diff --git a/README.md b/README.md index 5a99ac9..2d33f08 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,33 @@ Projet du groupe 01: - William Karpinski: Extension gestion des horaires - Léo Moulin: Extension inscription des étudiants +## Running + +Le projet peut être lancé grace à docker compose. + +```sh +$ docker compose up +``` + +Dans le cas ou vous modifiers des fichiers, pour éviter que les images de docker soient recrées avec les changement + +```sh +$ docker compose up --force-recreate --build +``` + ## Dévelopement -``` -$ ./gradlew backend:run frontend:run --parallel -``` +Dans le cas ou vous êtes dans une phase de développement, il est plus simple d'utiliser gradle pour lancer le backend et frontend dans un mode de développement. +**Attention**: Ce mode n'est pas fait pour être utilisé en production! +```sh +$ ./gradlew run --parallel +``` permet de lancer le frontend sur [http://localhost:5173](http://localhost:5173) ansi que le frontend sur [http://localhost:8080](http://localhost:8080) + +Ceci requière également docker pour lancer une instance de postgresql pris en charge par spring. + +Il est possible de se passer entièrement de docker en supprimant la dépendance dans le fichier `backend/build.gradle.kts`: ~~`developmentOnly("org.springframework.boot:spring-boot-docker-compose")`~~ +Il est alors nécéssaire d'avoir une instance de postgresql tournant sur `localhost:5432` avec une table `clyde`, utilisateur: `devel` et password: `devel` +(cette configuration peut également être changée dans le fichier resources/application.properties de spring) + diff --git a/backend/Dockerfile b/backend/Dockerfile index 5475dc9..1ed9969 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,6 +1,15 @@ +## Building phase +FROM gradle:jdk21-alpine AS BUILD +WORKDIR /backend + +COPY . . +RUN gradle build -x test + +## Running Phase FROM eclipse-temurin:21-jdk-alpine -VOLUME /tmp +WORKDIR /backend VOLUME /cdn -ENV SPRING_PROFILES_ACTIVE=prod -COPY build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar -ENTRYPOINT ["java", "-jar", "/app.jar"] +# ENV SPRING_PROFILES_ACTIVE=prod +COPY --from=BUILD /backend/build/libs/Clyde-0.0.1-SNAPSHOT.jar /backend/app.jar +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "/backend/app.jar"] diff --git a/backend/settings.gradle.kts b/backend/settings.gradle.kts new file mode 100644 index 0000000..7d39fc5 --- /dev/null +++ b/backend/settings.gradle.kts @@ -0,0 +1,13 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.6/userguide/multi_project_builds.html in the Gradle documentation. + */ + +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" +} + +rootProject.name = "Clyde" diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/ApplicationsController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/ApplicationsController.java index 8d1f1ca..d4fdaa0 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/ApplicationsController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/ApplicationsController.java @@ -64,8 +64,8 @@ public class ApplicationsController { if (!authServ.isNotIn(new Role[]{Role.Teacher,Role.Secretary,Role.Admin},token)) authorizedApps.add(Applications.ManageCourses); - if (!authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin},token)){ - authorizedApps.add(Applications.Inscription); + if (!authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin, Role.Teacher},token)){ + authorizedApps.add(Applications.Requests); authorizedApps.add(Applications.StudentsList);} if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)){ diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CourseController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CourseController.java index d5e87a8..474e2cb 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CourseController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CourseController.java @@ -135,4 +135,5 @@ public class CourseController { courseServ.delete(courseServ.findById(id)); return new ResponseEntity<>(HttpStatus.OK); } + } diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CurriculumController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CurriculumController.java index 409e269..efe34e6 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CurriculumController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/CurriculumController.java @@ -4,11 +4,13 @@ package ovh.herisson.Clyde.EndPoints; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; +import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository; import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Services.*; -import ovh.herisson.Clyde.Tables.Curriculum; -import ovh.herisson.Clyde.Tables.Role; +import ovh.herisson.Clyde.Tables.*; +import java.util.HashMap; import java.util.Map; @RestController @@ -21,12 +23,18 @@ public class CurriculumController { private final UserCurriculumService userCurriculumServ; private final CurriculumCourseService curriculumCourseServ; + private final InscriptionRepository ir; + private final UserService userServ; - public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ){ + private final ExternalCurriculumRepository ecr; + public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ, InscriptionRepository ir, UserService userServ, ExternalCurriculumRepository ecr){ this.curriculumServ = curriculumServ; this.authServ = authServ; this.userCurriculumServ = userCurriculumServ; this.curriculumCourseServ = curriculumCourseServ; + this.ir = ir; + this.userServ = userServ; + this.ecr = ecr; } @GetMapping("/curriculum/{id}") @@ -52,6 +60,22 @@ public class CurriculumController { return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(curriculum),HttpStatus.OK); } + + //Return the list of all curicullums of an user + @GetMapping("/onescurriculum/{userId}") + public ResponseEntity<Map<String ,Object>> findOnesCurriculum(@RequestHeader("Authorization") String token, @PathVariable String userId){ + if (authServ.getUserFromToken(token) == null) + return new UnauthorizedResponse<>(null); + + User u = userServ.getUserById(Long.parseLong(userId)); + HashMap<String,Object> toReturn = userCurriculumServ.findAllCurriculumByStudent(u); + + if (toReturn == null) + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + + return new ResponseEntity<>(toReturn,HttpStatus.OK); + } + @GetMapping("/curriculums") public ResponseEntity<Iterable<Map<String, Object>>> findAllIndDepth(){ return new ResponseEntity<>(curriculumCourseServ.getAllDepthCurriculum(),HttpStatus.OK); @@ -94,4 +118,5 @@ public class CurriculumController { curriculumServ.delete(toDelete); return new ResponseEntity<>(HttpStatus.OK); } + } diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/ExternalCurriculumController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/ExternalCurriculumController.java new file mode 100644 index 0000000..e88c759 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/ExternalCurriculumController.java @@ -0,0 +1,55 @@ +package ovh.herisson.Clyde.EndPoints.Inscription; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; +import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository; +import ovh.herisson.Clyde.Repositories.UserRepository; +import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; +import ovh.herisson.Clyde.Tables.User; + +import java.util.ArrayList; +import java.util.Map; + +@RestController +@CrossOrigin(originPatterns = "*", allowCredentials = "true") +public class ExternalCurriculumController { + + public final ExternalCurriculumRepository ecr; + public final InscriptionRepository inscriptionRepository; + public final UserRepository userRepository; + + public ExternalCurriculumController(ExternalCurriculumRepository ecr, InscriptionRepository inscriptionRepository, UserRepository userRepository) { + this.ecr = ecr; + this.inscriptionRepository = inscriptionRepository; + this.userRepository = userRepository; + } + + //everyone can post some externalcurriculums (the validity of the elements is assured by the inscription service) + @PostMapping("/externalcurriculum") + public ResponseEntity<ExternalCurriculum> postExternalCurriculum(@RequestBody Map<String, Object> externalCurrInfos){ + InscriptionRequest ir = inscriptionRepository.findById((Integer) externalCurrInfos.get("inscriptionRequestId")); + + ExternalCurriculum toSave = new ExternalCurriculum(ir, (String) externalCurrInfos.get("school"),(String) externalCurrInfos.get("formation"),(String) externalCurrInfos.get("completion"), (Integer)externalCurrInfos.get("startYear"), (Integer)externalCurrInfos.get("endYear"), (String)externalCurrInfos.get("justifDocUrl"), null); + + return new ResponseEntity<>(ecr.save(toSave), HttpStatus.OK); + } + + @GetMapping("/externalcurriculum/{inscReqId}") + public ResponseEntity<ArrayList<ExternalCurriculum>> getExternalCurrListByInscrReq(@PathVariable long inscReqId){ + InscriptionRequest ir = inscriptionRepository.findById(inscReqId); + + ArrayList<ExternalCurriculum> toReturn = ecr.getExternalCurriculumByInscriptionRequest(ir); + return new ResponseEntity<>(toReturn, HttpStatus.OK); + } + + @GetMapping("/externalcurriculumbyuser/{userId}") + public ResponseEntity<ArrayList<ExternalCurriculum>> getExternalCurrByUser(@PathVariable long userId){ + User user = userRepository.findById(userId); + + ArrayList<ExternalCurriculum> toReturn = ecr.getExternalCurriculumByUser(user); + return new ResponseEntity<>(toReturn, HttpStatus.OK); + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/InscriptionController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/InscriptionController.java similarity index 75% rename from backend/src/main/java/ovh/herisson/Clyde/EndPoints/InscriptionController.java rename to backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/InscriptionController.java index 35c4852..60f4585 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/InscriptionController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/InscriptionController.java @@ -1,13 +1,13 @@ -package ovh.herisson.Clyde.EndPoints; +package ovh.herisson.Clyde.EndPoints.Inscription; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Services.AuthenticatorService; -import ovh.herisson.Clyde.Services.InscriptionService; +import ovh.herisson.Clyde.Services.Inscription.InscriptionService; import ovh.herisson.Clyde.Services.ProtectionService; -import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; import ovh.herisson.Clyde.Tables.RequestState; import ovh.herisson.Clyde.Tables.Role; import java.util.Map; @@ -79,4 +79,22 @@ public class InscriptionController { return new ResponseEntity<>(HttpStatus.OK); } + + //Allow teacher or admin to accept or refuse the equivalence + @PatchMapping("/request/registerequiv/{id}/{newstate}") + public ResponseEntity<Object> editRegisterEquiv(@RequestHeader("Authorization") String token, @PathVariable long id, @PathVariable RequestState newstate){ + if (authServ.isNotIn(new Role[]{Role.Admin,Role.Teacher}, token)) + return new UnauthorizedResponse<>(null); + + InscriptionRequest toEdit = inscriptionServ.getById(id); + toEdit.setEquivalenceState(newstate); + + inscriptionServ.save(toEdit); + + if (toEdit.getState() == RequestState.Accepted && (toEdit.getEquivalenceState() == RequestState.Accepted || toEdit.getEquivalenceState() == RequestState.Unrequired)) + { + inscriptionServ.createUser(toEdit); + } + return new ResponseEntity<>(HttpStatus.OK); + } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/MinervalController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/MinervalController.java new file mode 100644 index 0000000..737f472 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/MinervalController.java @@ -0,0 +1,55 @@ +package ovh.herisson.Clyde.EndPoints.Inscription; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository; +import ovh.herisson.Clyde.Responses.UnauthorizedResponse; +import ovh.herisson.Clyde.Services.AuthenticatorService; +import ovh.herisson.Clyde.Tables.Inscription.Minerval; +import ovh.herisson.Clyde.Tables.Role; + +import java.util.*; + +@RestController +@CrossOrigin(originPatterns = "*", allowCredentials = "true") +public class MinervalController { + private final AuthenticatorService authServ; + private final MinervalRepository mr; + + public MinervalController(AuthenticatorService authServ, MinervalRepository mr) { + this.authServ = authServ; + this.mr = mr; + } + + //A new minerval entry is posted when the inscription service accept a registration request + @PostMapping("/minerval/{studentRegNo}") + public ResponseEntity<Object> postMinerval(@RequestHeader("Authorization") String token, @PathVariable long studentRegNo){ + if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token)) + return new UnauthorizedResponse<>(null); + + Calendar c = new GregorianCalendar(); + + mr.save(new Minerval(studentRegNo, 0, 835, c.get(Calendar.YEAR))); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/minerval/{studentRegNo}") + public ResponseEntity<Minerval> getCurrentMinervalbyRegNo(@PathVariable long studentRegNo){ + ArrayList<Minerval> mlist = mr.getMinervalsByStudentRegNoOrderByYearDesc(studentRegNo); + + //The list is ordered by year in descending order then the index 0 contains the actual minerval (for this year) + Minerval m = mlist.get(0); + return new ResponseEntity<>(m, HttpStatus.OK); + } + + @PatchMapping("/minerval") + public ResponseEntity<Object> updateMinerval(@RequestBody Minerval updatedMinerval){ + Minerval minerval = mr.findById(updatedMinerval.getId()); + + minerval.setPaidAmount(updatedMinerval.getPaidAmount()); + minerval.setToPay(updatedMinerval.getToPay()); + mr.save(minerval); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/PaymentController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/PaymentController.java new file mode 100644 index 0000000..b70ad59 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/PaymentController.java @@ -0,0 +1,37 @@ +package ovh.herisson.Clyde.EndPoints.Inscription; + + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Repositories.Inscription.PaymentRepository; +import ovh.herisson.Clyde.Tables.Inscription.Payment; + +import java.util.ArrayList; + +@RestController +@CrossOrigin(originPatterns = "*", allowCredentials = "true") +public class PaymentController { + + private final PaymentRepository paymentRepository; + + public PaymentController(PaymentRepository paymentRepository){ + this.paymentRepository = paymentRepository; + } + + //Post a payment record + @PostMapping("/payment") + public ResponseEntity<Object> postPayment(@RequestBody Payment payment){ + paymentRepository.save(payment); + return new ResponseEntity<>(HttpStatus.OK); + } + + + //Get all payment records of a student + @GetMapping("/payment/{studentRegNo}") + public ResponseEntity<ArrayList<Payment>> getPaymentsByUser(@PathVariable long studentRegNo){ + ArrayList<Payment> toReturn = paymentRepository.getPaymentsByStudentRegNo(studentRegNo); + return new ResponseEntity<>(toReturn, HttpStatus.OK); + } + +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/RequestsController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/RequestsController.java new file mode 100644 index 0000000..61489bf --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/Inscription/RequestsController.java @@ -0,0 +1,97 @@ +package ovh.herisson.Clyde.EndPoints.Inscription; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Repositories.CourseRepository; +import ovh.herisson.Clyde.Repositories.Inscription.ExemptionsRequestRepository; +import ovh.herisson.Clyde.Repositories.Inscription.ScholarshipRequestRepository; +import ovh.herisson.Clyde.Repositories.Inscription.UninscriptionRequestRepository; +import ovh.herisson.Clyde.Repositories.UserRepository; +import ovh.herisson.Clyde.Responses.UnauthorizedResponse; +import ovh.herisson.Clyde.Services.AuthenticatorService; +import ovh.herisson.Clyde.Tables.*; +import ovh.herisson.Clyde.Tables.Inscription.ExemptionsRequest; +import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest; +import ovh.herisson.Clyde.Tables.Inscription.UninscriptionRequest; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Map; + +@RestController +@CrossOrigin(originPatterns = "*", allowCredentials = "true") +public class RequestsController { + + public final ExemptionsRequestRepository err; + public final ScholarshipRequestRepository srr; + public final UserRepository userRepository; + public final AuthenticatorService authServ; + public final UninscriptionRequestRepository uninscriptionRequestRepository; + public final CourseRepository courseRepository; + + public RequestsController(ExemptionsRequestRepository err, ScholarshipRequestRepository srr, UserRepository userRepository, AuthenticatorService authServ, UninscriptionRequestRepository uninscriptionRequestRepository, CourseRepository courseRepository) { + this.err = err; + this.srr = srr; + this.userRepository = userRepository; + this.authServ = authServ; + this.uninscriptionRequestRepository = uninscriptionRequestRepository; + this.courseRepository = courseRepository; + } + + @PostMapping(value="/exemptionreq") + public ResponseEntity<String> createExemptionReq(@RequestBody Map<String, Object> exemptionsRequestInfo){ + User user = userRepository.findById((Integer) exemptionsRequestInfo.get("userRegNo")); + Course course = courseRepository.findById((Integer) exemptionsRequestInfo.get("courseId")); + + ExemptionsRequest exemptionsRequest = new ExemptionsRequest(user, course, (String) exemptionsRequestInfo.get("justifDocument"), RequestState.Pending, new Date()); + + err.save(exemptionsRequest); + + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PostMapping(value="/scholarshipreq") + public ResponseEntity<String> createScholarshipReq(@RequestBody Map<String, Object> scholarshipRequestInfo){ + User user = userRepository.findById((Integer)scholarshipRequestInfo.get("userId")); + ScholarshipRequest toCreate = new ScholarshipRequest(user, RequestState.Pending, 0, new Date(), (String) scholarshipRequestInfo.get("taxDocUrl"), (String) scholarshipRequestInfo.get("residencyDocUrl")); + + srr.save(toCreate); + + return new ResponseEntity<>(HttpStatus.CREATED); + } + + //Get all the exemptions Request + @GetMapping(value = "/exemptionsreq") + public ResponseEntity<ArrayList<ExemptionsRequest>> getAllExemptionsRequests(@RequestHeader("Authorization") String token){ + if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token)) + return new UnauthorizedResponse<>(null); + + ArrayList<ExemptionsRequest> toReturn = new ArrayList<>(); + + err.findAll().forEach(toReturn::add); + + return new ResponseEntity<>(toReturn, HttpStatus.OK); + } + + //Get all the scholarships requests + @GetMapping(value = "/scholarshipreq") + public ResponseEntity<ArrayList<ScholarshipRequest>> getAllScholarshipRequests(@RequestHeader("Authorization") String token){ + if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token)) + return new UnauthorizedResponse<>(null); + + ArrayList<ScholarshipRequest> toReturn = new ArrayList<>(); + + srr.findAll().forEach(toReturn::add); + + return new ResponseEntity<>(toReturn, HttpStatus.OK); + } + + @PostMapping(value = "/uninscriptionreq") + public ResponseEntity<String> postUnregReq(@RequestBody Map<String,Object> uninscr){ + User u = userRepository.findById((int) uninscr.get("userId")); + UninscriptionRequest ur = new UninscriptionRequest(RequestState.Pending, (String) uninscr.get("reason"), new Date(), u); + uninscriptionRequestRepository.save(ur); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java index ef3c559..7ab988d 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java @@ -5,10 +5,14 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Repositories.CurriculumRepository; import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.ProtectionService; -import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Curriculum; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; +import ovh.herisson.Clyde.Tables.RequestState; + import java.util.Date; import java.util.Map; @@ -16,7 +20,7 @@ import java.util.Map; @CrossOrigin(originPatterns = "*", allowCredentials = "true") public class LoginController { private final AuthenticatorService authServ; - + private final CurriculumRepository curriculumRepository; static public class RequestLogin{ private final String identifier; private final String password; @@ -29,8 +33,9 @@ public class LoginController { } } - public LoginController(AuthenticatorService authServ){ + public LoginController(AuthenticatorService authServ, CurriculumRepository curriculumRepository){ this.authServ = authServ; + this.curriculumRepository = curriculumRepository; } @PostMapping(value = "/login") @@ -48,9 +53,18 @@ public class LoginController { @PostMapping("/register") public ResponseEntity<Map<String,Object>> register(@RequestBody InscriptionRequest inscriptionRequest){ + //We ensure here that if the targeted cursus year is more than first grade then we need the teacher equivalence approval + Curriculum curr = curriculumRepository.findById(inscriptionRequest.getCurriculumId()); + + if (curr.getYear() > 1){ + inscriptionRequest.setEquivalenceState(RequestState.Pending); + }else{ + inscriptionRequest.setEquivalenceState(RequestState.Unrequired); + } InscriptionRequest returnedInscriptionRequest = authServ.register(inscriptionRequest); + return new ResponseEntity<>(ProtectionService.requestWithoutPassword(returnedInscriptionRequest), HttpStatus.CREATED); } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java index f9fe3f9..5c8a91b 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java @@ -2,8 +2,10 @@ package ovh.herisson.Clyde.EndPoints; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.bind.annotation.*; -import ovh.herisson.Clyde.Repositories.TokenRepository; -import ovh.herisson.Clyde.Repositories.UserRepository; +import ovh.herisson.Clyde.Repositories.*; +import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; +import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository; +import ovh.herisson.Clyde.Repositories.Inscription.ScholarshipRequestRepository; import ovh.herisson.Clyde.Services.*; import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService; import ovh.herisson.Clyde.Tables.*; @@ -11,6 +13,11 @@ import ovh.herisson.Clyde.Tables.ScientificPublications.Access; import ovh.herisson.Clyde.Tables.ScientificPublications.PaperType; import ovh.herisson.Clyde.Tables.ScientificPublications.Research; import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher; +import ovh.herisson.Clyde.Services.Inscription.InscriptionService; +import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Inscription.Minerval; +import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest; import java.util.ArrayList; import java.util.Arrays; @@ -18,7 +25,6 @@ import java.util.Date; @RestController @CrossOrigin(originPatterns = "*", allowCredentials = "true") - public class MockController { private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); @@ -28,22 +34,28 @@ public class MockController { public final CurriculumCourseService CurriculumCourseService; public final CurriculumService curriculumService; public final CourseService courseService; - + public final ExternalCurriculumRepository externalCurriculumRepository; public final InscriptionService inscriptionService; public final ResearchesService researchesService; + public final UserCurriculumRepository ucr; + public final MinervalRepository minervalRepository; + public final ScholarshipRequestRepository scholarshipRequestRepository; + ArrayList<User> mockUsers; - - - public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, InscriptionService inscriptionService, ResearchesService researchesService){ + public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, ExternalCurriculumRepository externalCurriculumRepository, ResearchesService researchesService, InscriptionService inscriptionService, UserCurriculumRepository ucr, MinervalRepository minervalRepository, ScholarshipRequestRepository scholarshipRequestRepository){ this.tokenRepo = tokenRepo; this.userRepo = userRepo; this.tokenService = tokenService; this.CurriculumCourseService = CurriculumCourseService; this.curriculumService = curriculumService; this.courseService = courseService; + this.externalCurriculumRepository = externalCurriculumRepository; this.inscriptionService = inscriptionService; this.researchesService = researchesService; + this.ucr = ucr; + this.minervalRepository = minervalRepository; + this.scholarshipRequestRepository = scholarshipRequestRepository; } /** Saves an example of each user type by : @@ -53,82 +65,99 @@ public class MockController { */ @PostMapping("/mock") - public void postMock(){ + public void postMock() { - // user part + // user part + User herobrine = new User("brine", "hero", "admin@admin.com", "behind", "ShadowsLand", new Date(0), null, Role.Admin, passwordEncoder.encode("admin")); + User joe = new User("Mama", "Joe", "student@student.com", "roundabout", "England", new Date(0), null, Role.Student, passwordEncoder.encode("student")); + User meh = new User("Polo", "Marco", "secretary@secretary.com", "a Box", "Monaco", new Date(0), null, Role.Secretary, passwordEncoder.encode("secretary")); + User joke = new User("Gaillard", "Corentin", "teacher@teacher.com", "lab", "faculty", new Date(0), null, Role.Teacher, passwordEncoder.encode("teacher")); + User jojo = new User("Bridoux", "Justin", "teacher2@teacher2.com", "lab", "faculty", new Date(0), null, Role.Teacher, passwordEncoder.encode("teacher")); + User lena = new User("Louille", "Lena", "inscriptionService@InscriptionService.com", "no", "yes", new Date(0), null, Role.InscriptionService, passwordEncoder.encode("inscriptionService")); + User popo = new User("Smith", "Paul", "paulsmith@gmail.com", "306 rue du poulet", "belgique", new Date(0), null, Role.Student, passwordEncoder.encode("jesuispaulleroi")); + mockUsers = new ArrayList<>(Arrays.asList(herobrine, joe, meh, joke, lena, jojo, popo)); + + userRepo.saveAll(mockUsers); + + Minerval minerval = new Minerval(joe.getRegNo(), 0, 852, 2023); + minervalRepository.save(minerval); + // Course / Curriculum part + + Curriculum infoBab1 = new Curriculum(1, "info"); + Curriculum chemistryBab1 = new Curriculum(1, "chemistry"); + Curriculum psychologyBab1 = new Curriculum(1, "psychology"); + Curriculum infoBab2 = new Curriculum(2, "info"); + Curriculum masterinfo1 = new Curriculum(4, "info"); + Curriculum masterinfo2 = new Curriculum(5, "info"); + + curriculumService.save(infoBab1); + curriculumService.save(chemistryBab1); + curriculumService.save(psychologyBab1); + curriculumService.save(infoBab2); + curriculumService.save(masterinfo1); + curriculumService.save(masterinfo2); + + ucr.save(new UserCurriculum(joe, infoBab1, 2022)); + ucr.save(new UserCurriculum(joe, chemistryBab1, 2023)); + ucr.save(new UserCurriculum(joe, infoBab1, 2023)); + ucr.save(new UserCurriculum(joe, psychologyBab1, 2020)); + ucr.save(new UserCurriculum(popo, infoBab1, 2022)); + ucr.save(new UserCurriculum(popo, infoBab2, 2023)); + + Course progra1 = new Course(5, "Programmation et algorithmique 1", joke); + Course chemistry1 = new Course(12, "Thermochimie", joke); + Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells", joke); + Course commun = new Course(2, "cours commun", joke); + + courseService.save(progra1); + courseService.save(chemistry1); + courseService.save(psycho1); + courseService.save(commun); + + ScholarshipRequest ssr1 = new ScholarshipRequest(joe, RequestState.Pending, 0, new Date(), "test", "test"); + scholarshipRequestRepository.save(ssr1); + + CurriculumCourseService.save(new CurriculumCourse(infoBab1, progra1)); + CurriculumCourseService.save(new CurriculumCourse(infoBab1, commun)); + CurriculumCourseService.save(new CurriculumCourse(infoBab1, psycho1)); + CurriculumCourseService.save(new CurriculumCourse(psychologyBab1, psycho1)); + CurriculumCourseService.save(new CurriculumCourse(psychologyBab1, commun)); - User herobrine = new User("brine","hero","admin@admin.com","behind","ShadowsLand",new Date(0), null,Role.Admin,passwordEncoder.encode("admin")); - User joe = new User("Mama","Joe","student@student.com","roundabout","England",new Date(0), null,Role.Student,passwordEncoder.encode("student")); - User meh = new User("Polo","Marco","secretary@secretary.com","a Box","Monaco",new Date(0), null,Role.Secretary,passwordEncoder.encode("secretary")); - User joke = new User("Gaillard","Corentin","teacher@teacher.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher")); - User jojo = new User("Bridoux","Justin","teacher2@teacher2.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher")); - User lena = new User("Louille","Lena","inscriptionService@InscriptionService.com","no","yes",new Date(0), null,Role.InscriptionService,passwordEncoder.encode("inscriptionService")); - mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke,lena,jojo)); - - userRepo.saveAll(mockUsers); - - // Course / Curriculum part - - Curriculum infoBab1 = new Curriculum(1,"info"); - Curriculum chemistryBab1 = new Curriculum(1,"chemistry"); - Curriculum psychologyBab1 = new Curriculum(1,"psychology"); - - curriculumService.save(infoBab1); - curriculumService.save(chemistryBab1); - curriculumService.save(psychologyBab1); + CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, commun)); + CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, chemistry1)); - Course progra1 = new Course(5,"Programmation et algorithmique 1",joke); - Course chemistry1 = new Course(12, "Thermochimie",joke); - Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells",joke); - Course commun = new Course(2, "cours commun",joke); + InscriptionRequest inscriptionRequest = new InscriptionRequest("helen", "prenom", "non", "helen@gmail.com", "america", new Date(), (long) 4, RequestState.Pending, "yes.png", "password", null, new Date(), RequestState.Pending); - courseService.save(progra1); - courseService.save(chemistry1); - courseService.save(psycho1); - courseService.save(commun); + inscriptionService.save(inscriptionRequest); + ExternalCurriculum externalCurriculum = new ExternalCurriculum(inscriptionRequest, "HEH", "Bachelier en informatique", "Completed", 2015, 2018, null, null); + externalCurriculumRepository.save(externalCurriculum); + + /////////////////////////// + // extension Publications Scientifiques + Researcher jojoResearcherAccount = new Researcher(jojo, "3363-22555-AB33-T", null, "IT"); + + Researcher output = researchesService.saveResearcher(jojoResearcherAccount); + + Research jojoResearch = new Research("Graphs : Advanced Search Algorithms", output, new Date(0), + PaperType.Article, "here.pdf", null, "english", + Access.OpenSource, "IT", "This Article's title speaks for itself \n We'll discuss about advanced Graph search Algorithms"); + + Research restrictedResearch = new Research("just another Name", output, new Date(1111111111), + PaperType.Article, "restricted", null, "english", + Access.Restricted, "Restricted", "This Article's title speaks for itself\n We'll discuss about advanced Graph search Algorithms"); + + Research privateResearch = new Research("the great Potato War", output, new Date(), + PaperType.Article, "private", null, "english", + Access.Private, "private", "This Article's title speaks for itself\n We'll discuss about advanced Graph search Algorithms"); - CurriculumCourseService.save(new CurriculumCourse(infoBab1,progra1)); - CurriculumCourseService.save(new CurriculumCourse(infoBab1,commun)); + researchesService.saveResearch(restrictedResearch); + researchesService.saveResearch(privateResearch); - CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,psycho1)); - CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,commun)); + researchesService.saveResearch(jojoResearch); - - CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,commun)); - CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,chemistry1)); - - - InscriptionRequest inscriptionRequest = new InscriptionRequest("helen","prenom","non","helen@gmail.com","america",new Date(),(long) 1,RequestState.Pending,"yes.png","password"); - - inscriptionService.save(inscriptionRequest); - - - /////////////////////////// - // extension Publications Scientifiques - Researcher jojoResearcherAccount = new Researcher(jojo,"3363-22555-AB33-T",null,"IT"); - - Researcher output = researchesService.saveResearcher(jojoResearcherAccount); - - Research jojoResearch = new Research("Graphs : Advanced Search Algorithms",output,new Date(0), - PaperType.Article,"here.pdf",null,"english", - Access.OpenSource,"IT","This Article's title speaks for itself \n We'll discuss about advanced Graph search Algorithms"); - - Research restrictedResearch = new Research("just another Name",output,new Date(1111111111), - PaperType.Article,"restricted",null,"english", - Access.Restricted,"Restricted","This Article's title speaks for itself\n We'll discuss about advanced Graph search Algorithms"); - - Research privateResearch = new Research("the great Potato War",output,new Date(), - PaperType.Article,"private",null,"english", - Access.Private,"private","This Article's title speaks for itself\n We'll discuss about advanced Graph search Algorithms"); - - - researchesService.saveResearch(restrictedResearch); - researchesService.saveResearch(privateResearch); - - researchesService.saveResearch(jojoResearch); } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java b/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java deleted file mode 100644 index 801e549..0000000 --- a/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package ovh.herisson.Clyde; - -import javax.sql.DataSource; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.scheduling.annotation.EnableScheduling; - -@Configuration -@EnableScheduling -public class JdbcConfig { - - @Bean - @Profile("!prod") - public DataSource psqlSource(){ - DriverManagerDataSource source = new DriverManagerDataSource(); - source.setDriverClassName("org.postgresql.Driver"); - source.setUrl("jdbc:postgresql://localhost:5442/clyde"); - source.setUsername("devel"); - source.setPassword("devel"); - - return source; - } - - @Bean - @Profile("prod") - public DataSource psqlSourceProd(){ - DriverManagerDataSource source = new DriverManagerDataSource(); - source.setDriverClassName("org.postgresql.Driver"); - source.setUrl("jdbc:postgresql:clyde?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432"); - source.setUsername("clyde"); - - return source; - } -} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ExemptionsRequestRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ExemptionsRequestRepository.java new file mode 100644 index 0000000..3f66e80 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ExemptionsRequestRepository.java @@ -0,0 +1,8 @@ +package ovh.herisson.Clyde.Repositories.Inscription; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.Inscription.ExemptionsRequest; + +public interface ExemptionsRequestRepository extends CrudRepository<ExemptionsRequest, Long> { + +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ExternalCurriculumRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ExternalCurriculumRepository.java new file mode 100644 index 0000000..7b4ee4e --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ExternalCurriculumRepository.java @@ -0,0 +1,15 @@ +package ovh.herisson.Clyde.Repositories.Inscription; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; +import ovh.herisson.Clyde.Tables.User; + +import java.util.ArrayList; + +public interface ExternalCurriculumRepository extends CrudRepository<ExternalCurriculum, Long> { + ArrayList<ExternalCurriculum> getExternalCurriculumByInscriptionRequest(InscriptionRequest ir); + + ArrayList<ExternalCurriculum> getExternalCurriculumByUser(User user); + ExternalCurriculum getExternalCurriculumById(long id); +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/InscriptionRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/InscriptionRepository.java similarity index 62% rename from backend/src/main/java/ovh/herisson/Clyde/Repositories/InscriptionRepository.java rename to backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/InscriptionRepository.java index 0d83e6b..6564377 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Repositories/InscriptionRepository.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/InscriptionRepository.java @@ -1,7 +1,7 @@ -package ovh.herisson.Clyde.Repositories; +package ovh.herisson.Clyde.Repositories.Inscription; import org.springframework.data.repository.CrudRepository; -import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; public interface InscriptionRepository extends CrudRepository<InscriptionRequest,Long> { diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/MinervalRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/MinervalRepository.java new file mode 100644 index 0000000..475ac3c --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/MinervalRepository.java @@ -0,0 +1,12 @@ +package ovh.herisson.Clyde.Repositories.Inscription; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.Inscription.Minerval; + +import java.util.ArrayList; + +public interface MinervalRepository extends CrudRepository<Minerval, Long> { + public ArrayList<Minerval> getMinervalsByStudentRegNoOrderByYearDesc(Long studentRegNo); + + public Minerval findById(long id); +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/PaymentRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/PaymentRepository.java new file mode 100644 index 0000000..c479a4e --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/PaymentRepository.java @@ -0,0 +1,10 @@ +package ovh.herisson.Clyde.Repositories.Inscription; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.Inscription.Payment; + +import java.util.ArrayList; + +public interface PaymentRepository extends CrudRepository<Payment, Long> { + public ArrayList<Payment> getPaymentsByStudentRegNo(long regNo); +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ScholarshipRequestRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ScholarshipRequestRepository.java new file mode 100644 index 0000000..5550937 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/ScholarshipRequestRepository.java @@ -0,0 +1,8 @@ +package ovh.herisson.Clyde.Repositories.Inscription; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest; + +public interface ScholarshipRequestRepository extends CrudRepository<ScholarshipRequest, Long> { + +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/UninscriptionRequestRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/UninscriptionRequestRepository.java new file mode 100644 index 0000000..6d38b8c --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/Inscription/UninscriptionRequestRepository.java @@ -0,0 +1,7 @@ +package ovh.herisson.Clyde.Repositories.Inscription; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.Inscription.UninscriptionRequest; + +public interface UninscriptionRequestRepository extends CrudRepository<UninscriptionRequest, Long> { +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/UserCurriculumRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/UserCurriculumRepository.java index 32f207a..2f1c2a3 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Repositories/UserCurriculumRepository.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/UserCurriculumRepository.java @@ -6,8 +6,12 @@ import ovh.herisson.Clyde.Tables.Curriculum; import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.UserCurriculum; +import java.util.ArrayList; + public interface UserCurriculumRepository extends CrudRepository<UserCurriculum, Long> { @Query("select uc.curriculum from UserCurriculum uc where uc.user = ?1") Curriculum findByUser(User student); + + ArrayList<UserCurriculum> findByUserOrderByCurriculum(User student); } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java index 25c127f..9e517b7 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java @@ -1,7 +1,10 @@ package ovh.herisson.Clyde.Services; import org.springframework.stereotype.Service; +import ovh.herisson.Clyde.Services.Inscription.InscriptionService; import ovh.herisson.Clyde.Tables.*; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; + import java.util.Date; @Service diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/CurriculumService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/CurriculumService.java index af04d78..790c51f 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/CurriculumService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/CurriculumService.java @@ -18,7 +18,6 @@ public class CurriculumService { public Curriculum findById(long id){ return curriculumRepo.findById(id); } - public void delete(Curriculum curriculum) { curriculumRepo.delete(curriculum); } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/Inscription/InscriptionService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/Inscription/InscriptionService.java new file mode 100644 index 0000000..c80e2d9 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/Inscription/InscriptionService.java @@ -0,0 +1,105 @@ +package ovh.herisson.Clyde.Services.Inscription; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import ovh.herisson.Clyde.Repositories.*; +import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; +import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository; +import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository; +import ovh.herisson.Clyde.Tables.*; +import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Inscription.Minerval; + +import java.util.ArrayList; + +@Service +public class InscriptionService { + + private final InscriptionRepository inscriptionRepo; + + private final UserRepository userRepo; + + private final UserCurriculumRepository userCurriculumRepo; + + private final CurriculumRepository curriculumRepo; + + private final MinervalRepository minervalRepository; + private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + private final ExternalCurriculumRepository externalCurriculumRepository; + + public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo, MinervalRepository minervalRepository, ExternalCurriculumRepository externalCurriculumRepository){ + this.inscriptionRepo = inscriptionRepo; + this.userRepo = userRepo; + this.userCurriculumRepo = userCurriculumRepo; + this.curriculumRepo = curriculumRepo; + this.minervalRepository = minervalRepository; + this.externalCurriculumRepository = externalCurriculumRepository; + } + + public InscriptionRequest save(InscriptionRequest inscriptionRequest){ + inscriptionRequest.setPassword(passwordEncoder.encode(inscriptionRequest.getPassword())); + return inscriptionRepo.save(inscriptionRequest); + } + + public InscriptionRequest getById(long id){ + return inscriptionRepo.findById(id); + } + + public Iterable<InscriptionRequest> getAll(){ + return inscriptionRepo.findAll(); + } + + public boolean modifyState(long id, RequestState requestState) { + InscriptionRequest inscrRequest = getById(id); + + if (inscrRequest == null) + return false; + + inscrRequest.setState(requestState); + save(inscrRequest); + + //saves the user from the request if accepted from teacher and inscription services + if (requestState == RequestState.Accepted && (inscrRequest.getEquivalenceState() == RequestState.Accepted || inscrRequest.getEquivalenceState() == RequestState.Unrequired)) + { + return createUser(inscrRequest); + } + return true; + } + + public boolean createUser(InscriptionRequest inscrRequest){ + //We must send an email here + + if (curriculumRepo.findById(inscrRequest.getCurriculumId()) == null) + return false; + + User userFromRequest = new User( + inscrRequest.getLastName(), + inscrRequest.getFirstName(), + inscrRequest.getEmail(), + inscrRequest.getAddress(), + inscrRequest.getCountry(), + inscrRequest.getBirthDate(), + inscrRequest.getProfilePicture(), + inscrRequest.getPassword() + ); + + userRepo.save(userFromRequest); + userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId()),0)); + + //Create a minerval for the new student + Minerval minerval = new Minerval(userFromRequest.getRegNo(), 0, 852, 2023); + minervalRepository.save(minerval); + + //Assign the externals curriculums from the inscription request to newly created student + ArrayList<ExternalCurriculum> extCurrList = externalCurriculumRepository.getExternalCurriculumByInscriptionRequest(inscrRequest); + for (int i = 0; i < extCurrList.size(); i++){ + extCurrList.get(i).setUser(userFromRequest); + externalCurriculumRepository.save(extCurrList.get(i)); + } + return true; + } + public void delete(InscriptionRequest toDelete) { + inscriptionRepo.delete(toDelete); + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/InscriptionService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/InscriptionService.java deleted file mode 100644 index 311dbf2..0000000 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/InscriptionService.java +++ /dev/null @@ -1,94 +0,0 @@ -package ovh.herisson.Clyde.Services; - -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.stereotype.Service; -import ovh.herisson.Clyde.Repositories.CurriculumRepository; -import ovh.herisson.Clyde.Repositories.InscriptionRepository; -import ovh.herisson.Clyde.Repositories.UserCurriculumRepository; -import ovh.herisson.Clyde.Repositories.UserRepository; -import ovh.herisson.Clyde.Tables.InscriptionRequest; -import ovh.herisson.Clyde.Tables.RequestState; -import ovh.herisson.Clyde.Tables.User; -import ovh.herisson.Clyde.Tables.UserCurriculum; - -@Service -public class InscriptionService { - - private final InscriptionRepository inscriptionRepo; - - private final UserRepository userRepo; - - private final UserCurriculumRepository userCurriculumRepo; - - private final CurriculumRepository curriculumRepo; - - private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - - - public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo){ - this.inscriptionRepo = inscriptionRepo; - this.userRepo = userRepo; - this.userCurriculumRepo = userCurriculumRepo; - this.curriculumRepo = curriculumRepo; - } - - public InscriptionRequest save(InscriptionRequest inscriptionRequest){ - inscriptionRequest.setPassword(passwordEncoder.encode(inscriptionRequest.getPassword())); - return inscriptionRepo.save(inscriptionRequest); - } - - public InscriptionRequest getById(long id){ - return inscriptionRepo.findById(id); - } - - public Iterable<InscriptionRequest> getAll(){ - return inscriptionRepo.findAll(); - } - - public boolean modifyState(long id, RequestState requestState) { - InscriptionRequest inscrRequest = getById(id); - - if (inscrRequest == null) - return false; - - // if th state is the same we don't send an email - if (requestState == inscrRequest.getState()) - return false; - - /** todo send an email to tell the poster of the inscrRequest (inscrRequest.getEmail()) - * to notify them that the state of their request changed - * FooEmailFormat toSend = (String.format("Your request state changed from %s to %s"), - * inscrRequest.getState(), requestState) - * FooEmailSender.send(toSend, inscrRequest.getEmail()) - */ - - - //saves the user from the request if accepted - if (requestState == RequestState.Accepted) - { - if (curriculumRepo.findById(inscrRequest.getCurriculumId()) == null) - return false; - - User userFromRequest = new User( - inscrRequest.getLastName(), - inscrRequest.getFirstName(), - inscrRequest.getEmail(), - inscrRequest.getAddress(), - inscrRequest.getCountry(), - inscrRequest.getBirthDate(), - inscrRequest.getProfilePicture(), - inscrRequest.getPassword() - ); - - userRepo.save(userFromRequest); - userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId()))); - } - inscrRequest.setState(requestState); - save(inscrRequest); - return true; - } - - public void delete(InscriptionRequest toDelete) { - inscriptionRepo.delete(toDelete); - } -} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/ProtectionService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/ProtectionService.java index 44e53a7..1c9b944 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/ProtectionService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/ProtectionService.java @@ -1,7 +1,7 @@ package ovh.herisson.Clyde.Services; import ovh.herisson.Clyde.Tables.Course; -import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest; import ovh.herisson.Clyde.Tables.User; import java.util.ArrayList; @@ -87,7 +87,9 @@ public class ProtectionService { toReturn.put("curriculum", inscriptionRequest.getCurriculumId()); toReturn.put("state", inscriptionRequest.getState()); toReturn.put("profilePictureUrl", inscriptionRequest.getProfilePicture()); - + toReturn.put("identityCard", inscriptionRequest.getIdentityCard()); + toReturn.put("submissionDate", inscriptionRequest.getSubmissionDate()); + toReturn.put("equivalenceState", inscriptionRequest.getEquivalenceState()); return toReturn; } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/UserCurriculumService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/UserCurriculumService.java index 6484e2b..8b446df 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/UserCurriculumService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/UserCurriculumService.java @@ -1,20 +1,52 @@ package ovh.herisson.Clyde.Services; import org.springframework.stereotype.Service; +import ovh.herisson.Clyde.Repositories.CurriculumRepository; +import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; import ovh.herisson.Clyde.Repositories.UserCurriculumRepository; -import ovh.herisson.Clyde.Tables.Curriculum; -import ovh.herisson.Clyde.Tables.User; +import ovh.herisson.Clyde.Tables.*; + +import java.util.ArrayList; +import java.util.HashMap; @Service public class UserCurriculumService { private final UserCurriculumRepository userCurriculumRepository; + private final CurriculumRepository curriculumRepo; - public UserCurriculumService(UserCurriculumRepository userCurriculumRepository) { + private final ExternalCurriculumRepository externalCurriculumRepo; + public UserCurriculumService(UserCurriculumRepository userCurriculumRepository, CurriculumRepository curriculumRepo, ExternalCurriculumRepository externalCurriculumRepo) { this.userCurriculumRepository = userCurriculumRepository; + this.curriculumRepo = curriculumRepo; + this.externalCurriculumRepo = externalCurriculumRepo; } public Curriculum findByUser(User student){ return userCurriculumRepository.findByUser(student); } + + public HashMap<String,Object> findAllCurriculumByStudent(User student) { + ArrayList<UserCurriculum> list = userCurriculumRepository.findByUserOrderByCurriculum(student); + + ArrayList<HashMap<String, Object>> curriculumlist = new ArrayList<HashMap<String, Object>>(); + + for (int i = 0; i < list.size(); i++) { + HashMap<String, Object> element = new HashMap<>(); + Curriculum c = list.get(i).getCurriculum(); + + + element.put("curriculumId", c.getCurriculumId()); + element.put("year", c.getYear()); + element.put("option", c.getOption()); + element.put("dateyear", list.get(i).getYear()); + curriculumlist.add(element); + } + + HashMap<String, Object> toReturn = new HashMap<String, Object>(); + toReturn.put("curriculumList", curriculumlist); + return toReturn; + } + + } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Applications.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Applications.java index 3dadcec..5c39891 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/Applications.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Applications.java @@ -18,6 +18,6 @@ public enum Applications { UsersList, // InscriptionService authorization - Inscription, + Requests, StudentsList } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java index a89de1f..8730c05 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java @@ -1,10 +1,8 @@ package ovh.herisson.Clyde.Tables; public enum FileType { - ProfilePicture, - EducationCertificate, - Article, + JustificationDocument } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ExemptionsRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ExemptionsRequest.java new file mode 100644 index 0000000..75ee926 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ExemptionsRequest.java @@ -0,0 +1,83 @@ +package ovh.herisson.Clyde.Tables.Inscription; + + +import jakarta.persistence.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; +import ovh.herisson.Clyde.Tables.Course; +import ovh.herisson.Clyde.Tables.RequestState; +import ovh.herisson.Clyde.Tables.User; + +import java.util.Date; + +@Entity +public class ExemptionsRequest { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @JoinColumn(name = "Users") + @ManyToOne(fetch = FetchType.EAGER) + private User user; + + @JoinColumn(name = "Course") + @ManyToOne(fetch = FetchType.EAGER) + private Course course; + private String justifDocument; + + private RequestState state; + + private Date date; + + public ExemptionsRequest(User user, Course course, String justifDocument, RequestState state, Date date){ + this.user = user; + this.course = course; + this.justifDocument = justifDocument; + this.state = state; + this.date = date; + } + + + public ExemptionsRequest(){} + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Course getCourse() { + return course; + } + + public void setCourse(Course course) { + this.course = course; + } + + public String getJustifDocument() { + return justifDocument; + } + + public void setJustifDocument(String justifDocument) { + this.justifDocument = justifDocument; + } + + + public RequestState getState() { + return state; + } + + public void setState(RequestState state) { + this.state = state; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ExternalCurriculum.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ExternalCurriculum.java new file mode 100644 index 0000000..893971b --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ExternalCurriculum.java @@ -0,0 +1,114 @@ +package ovh.herisson.Clyde.Tables.Inscription; + + +import jakarta.persistence.*; +import ovh.herisson.Clyde.Tables.User; + +//This table stores a student's curriculum from another university +@Entity +public class ExternalCurriculum { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + //An external curriculum is first linked to an inscription request and when it is accepted and the user is created we link it to the user + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name="InscriptionRequest") + private InscriptionRequest inscriptionRequest; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name="Users") + private User user; + + private String school; + + private String formation; + + //This string denotes the completion of the external formation or the last year completed by the student in this formation + private String completion; + + private int startYear; + private int endYear; + private String justifdocUrl; + + public ExternalCurriculum(){} + + public ExternalCurriculum(InscriptionRequest ir, String school, String formation, String completion, int startYear, int endYear, String justifdocUrl,User user){ + this.inscriptionRequest = ir; + this.school = school; + this.formation = formation; + this.completion = completion; + this.startYear = startYear; + this.endYear = endYear; + this.justifdocUrl = justifdocUrl; + this.user = user; + } + + public int getId() { + return id; + } + + public InscriptionRequest getInscriptionRequest() { + return inscriptionRequest; + } + + public void setInscriptionRequest(InscriptionRequest inscriptionRequest) { + this.inscriptionRequest = inscriptionRequest; + } + + public String getSchool() { + return school; + } + + public void setSchool(String school) { + this.school = school; + } + + public String getFormation() { + return formation; + } + + public void setFormation(String formation) { + this.formation = formation; + } + + public String getCompletion(){ + return completion; + } + + public void setCompletion(String completion) { + this.completion = completion; + } + + public int getStartYear() { + return startYear; + } + + public void setStartYear(int startYear) { + this.startYear = startYear; + } + + public int getEndYear() { + return endYear; + } + + public void setEndYear(int endYear) { + this.endYear = endYear; + } + + public void setJustifdocUrl(String justifdocUrl) { + this.justifdocUrl = justifdocUrl; + } + + public String getJustifdocUrl() { + return justifdocUrl; + } + + public void setUser(User user) { + this.user = user; + } + + public User getUser() { + return user; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/InscriptionRequest.java similarity index 72% rename from backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java rename to backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/InscriptionRequest.java index 18e20d0..07c720f 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/InscriptionRequest.java @@ -1,6 +1,8 @@ -package ovh.herisson.Clyde.Tables; +package ovh.herisson.Clyde.Tables.Inscription; import jakarta.persistence.*; +import ovh.herisson.Clyde.Tables.RequestState; + import java.util.Date; @@ -15,14 +17,16 @@ public class InscriptionRequest { private String email; private String country; private Date birthDate; - private Long curriculumId; private RequestState state; private String profilePicture; - private String password; + private String identityCard; + private Date submissionDate; + private RequestState equivalenceState; public InscriptionRequest(){} - public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate,Long curriculumId, RequestState state, String profilePicture, String password){ + + public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate,Long curriculumId, RequestState state, String profilePicture, String password, String identityCard, Date submissionDate, RequestState equivalenceState){ this.lastName = lastName; this.firstName = firstName; this.address = address; @@ -33,6 +37,9 @@ public class InscriptionRequest { this.state = state; this.profilePicture = profilePicture; this.password = password; + this.identityCard = identityCard; + this.submissionDate = submissionDate; + this.equivalenceState = equivalenceState; } public int getId() { @@ -118,4 +125,28 @@ public class InscriptionRequest { public void setPassword(String password) { this.password = password; } + + public String getIdentityCard() { + return identityCard; + } + + public void setIdentityCard(String identityCard) { + this.identityCard = identityCard; + } + + public Date getSubmissionDate() { + return submissionDate; + } + + public void setSubmissionDate(Date submissionDate) { + this.submissionDate = submissionDate; + } + + public RequestState getEquivalenceState() { + return equivalenceState; + } + + public void setEquivalenceState(RequestState equivalenceState) { + this.equivalenceState = equivalenceState; + } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/Minerval.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/Minerval.java new file mode 100644 index 0000000..dac5799 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/Minerval.java @@ -0,0 +1,64 @@ +package ovh.herisson.Clyde.Tables.Inscription; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Minerval { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private long studentRegNo; + private int paidAmount; + private int toPay; + + //If the academic year is 2023-2024 then 2023 will be stored here (we take the lowest year) + private int year; + public Minerval(){} + + public Minerval(long studentRegNo, int paidAmount, int toPay, int year){ + this.studentRegNo = studentRegNo; + this.paidAmount = paidAmount; + this.toPay = toPay; + this.year = year; + } + + public long getStudentRegNo() { + return studentRegNo; + } + + public void setStudentRegNo(long studentRegNo) { + this.studentRegNo = studentRegNo; + } + + public int getPaidAmount() { + return paidAmount; + } + + public void setPaidAmount(int paidAmount) { + this.paidAmount = paidAmount; + } + + public int getToPay() { + return toPay; + } + + public void setToPay(int toPay) { + this.toPay = toPay; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + + public long getId() { + return id; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/Payment.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/Payment.java new file mode 100644 index 0000000..48626e1 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/Payment.java @@ -0,0 +1,84 @@ +package ovh.herisson.Clyde.Tables.Inscription; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +import java.util.Date; + +@Entity +public class Payment { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private long studentRegNo; + private String card; + private String client; + private Date expDate; + private int amount; + private Date date; + public Payment(){} + + public Payment(long studentRegNo, String card, String client, Date expDate, int amount, Date date){ + this.studentRegNo = studentRegNo; + this.card = card; + this.client = client; + this.expDate = expDate; + this.amount = amount; + this.date = date; + } + + public long getStudentRegNo() { + return studentRegNo; + } + + public void setStudentRegNo(long studentRegNo) { + this.studentRegNo = studentRegNo; + } + + public String getCard() { + return card; + } + + public void setCard(String card) { + this.card = card; + } + + public String getClient() { + return client; + } + + public void setClient(String client) { + this.client = client; + } + + public Date getExpDate() { + return expDate; + } + + public void setExpDate(Date expDate) { + this.expDate = expDate; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public long getId() { + return id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/ReInscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ReInscriptionRequest.java similarity index 91% rename from backend/src/main/java/ovh/herisson/Clyde/Tables/ReInscriptionRequest.java rename to backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ReInscriptionRequest.java index b96ed42..cafffe6 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/ReInscriptionRequest.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ReInscriptionRequest.java @@ -1,8 +1,11 @@ -package ovh.herisson.Clyde.Tables; +package ovh.herisson.Clyde.Tables.Inscription; import jakarta.persistence.*; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; +import ovh.herisson.Clyde.Tables.Curriculum; +import ovh.herisson.Clyde.Tables.RequestState; +import ovh.herisson.Clyde.Tables.User; @Entity public class ReInscriptionRequest { diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ScholarshipRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ScholarshipRequest.java new file mode 100644 index 0000000..18ebee6 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/ScholarshipRequest.java @@ -0,0 +1,88 @@ +package ovh.herisson.Clyde.Tables.Inscription; + +import jakarta.persistence.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; +import ovh.herisson.Clyde.Tables.RequestState; +import ovh.herisson.Clyde.Tables.User; + +import java.util.Date; + +@Entity +public class ScholarshipRequest { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @JoinColumn(name="Users") + @ManyToOne(fetch = FetchType.EAGER) + private User user; + private RequestState state; + private Date date; + private int amount; + private String taxDocUrl; + private String residencyDocUrl; + + public ScholarshipRequest(User user, RequestState state, int amount, Date date, String taxDocUrl, String residencyDocUrl){ + this.user = user; + this.state = state; + this.amount = amount; + this.date = date; + this.taxDocUrl = taxDocUrl; + this.residencyDocUrl = residencyDocUrl; + } + + public ScholarshipRequest(){} + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public RequestState getState() { + return state; + } + + public void setState(RequestState state) { + this.state = state; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public long getId() { + return id; + } + + public String getResidencyDocUrl() { + return residencyDocUrl; + } + + public void setResidencyDocUrl(String residencyDocUrl) { + this.residencyDocUrl = residencyDocUrl; + } + + public String getTaxDocUrl() { + return taxDocUrl; + } + + public void setTaxDocUrl(String taxDocUrl) { + this.taxDocUrl = taxDocUrl; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/UninscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/UninscriptionRequest.java new file mode 100644 index 0000000..e7858c6 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Inscription/UninscriptionRequest.java @@ -0,0 +1,67 @@ +package ovh.herisson.Clyde.Tables.Inscription; + +import jakarta.persistence.*; +import ovh.herisson.Clyde.Tables.RequestState; +import ovh.herisson.Clyde.Tables.User; + +import java.util.Date; + +@Entity +public class UninscriptionRequest { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + private RequestState state; + private String reason; + private Date date; + + @JoinColumn(name = "Users") + @ManyToOne(fetch = FetchType.EAGER) + private User user; + + public UninscriptionRequest(RequestState state,String reason, Date date, User user){ + this.state = state; + this.reason = reason; + this.date = date; + this.user = user; + } + + public UninscriptionRequest(){} + + public RequestState getState() { + return state; + } + + public void setState(RequestState state) { + this.state = state; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public long getId() { + return id; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public void setDate(Date date) { + this.date = date; + } + + public Date getDate() { + return date; + } +} + diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java index d52f1c9..fd2eeb0 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java @@ -3,5 +3,6 @@ package ovh.herisson.Clyde.Tables; public enum RequestState { Accepted, Refused, - Pending + Pending, + Unrequired } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCurriculum.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCurriculum.java index f42e588..b79295b 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCurriculum.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCurriculum.java @@ -21,9 +21,12 @@ public class UserCurriculum { @OnDelete(action = OnDeleteAction.CASCADE) private Curriculum curriculum; - public UserCurriculum(User user, Curriculum curriculum){ + private int year; + + public UserCurriculum(User user, Curriculum curriculum, int year){ this.user = user; this.curriculum = curriculum; + this.year = year; } public UserCurriculum() {} @@ -47,4 +50,12 @@ public class UserCurriculum { public void setCurriculum(Curriculum curriculum) { this.curriculum = curriculum; } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 5d00d8e..190c76b 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,3 +1,12 @@ spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect -spring.sql.init.mode=always \ No newline at end of file +spring.sql.init.mode=always + +# spring.datasource.url=jdbc:postgresql://localhost:5442/clyde +spring.datasource.url=jdbc:postgresql://db:5432/clyde +spring.datasource.username=devel +spring.datasource.password=devel + +# spring.config.activate.on-profile=prod +# spring.datasource.url=jdbc:postgresql:clyde?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432 +# spring.datasource.username=clyde diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..ec5f6bc --- /dev/null +++ b/compose.yaml @@ -0,0 +1,29 @@ +services: + db: + image: 'postgres:16' + environment: + - 'POSTGRES_DB=clyde' + - 'POSTGRES_USER=devel' + - 'POSTGRES_PASSWORD=devel' + # Uncomment this to allow connections to the db from outside the container + # ports: + # - '5442:5432' + back: + build: backend/. + ports: + - "8080:8080" + volumes: + - cdn:/backend/cdn + ulimits: + nofile: + soft: 65536 + hard: 65536 + front: + build: frontend/. + volumes: + - cdn:/app/front/dist/cdn + ports: + - "8000:8080" + +volumes: + cdn: diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..2df53ae --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,11 @@ +# https://v2.vuejs.org/v2/cookbook/dockerize-vuejs-app +FROM node:lts-alpine +RUN npm install -g http-server +WORKDIR /app/front +COPY package*.json ./ +RUN npm install +COPY . . +ENV VITE_CLYDE_MODE=container +RUN npm run build +EXPOSE 8080 +CMD [ "http-server", "dist" ] diff --git a/frontend/src/Apps/Inscription.vue b/frontend/src/Apps/Inscription.vue deleted file mode 100644 index 95581ce..0000000 --- a/frontend/src/Apps/Inscription.vue +++ /dev/null @@ -1,111 +0,0 @@ -<script setup> - import i18n from "@/i18n.js" - import {ref} from 'vue' - import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js' - - const requests = ref(await getAllRegisters()); - console.log(requests); - - async function upPage(id,review){ - await validateRegister(id,review); - requests.value = await getAllRegisters(); - - } -</script> - - - -<template> - <div style='display:flex; justify-content:center; min-width:1140px;' v-for="item of requests"> - <div class="bodu" v-if="item.state === 'Pending'"> - <div class="container"> - <div class="id"><a>{{item.id}}</a></div> - <div class="surname"><a>{{item.lastName}}</a></div> - <div class="firstname"><a>{{item.firstName}}</a></div> - <div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}}</button></div> - <div class="accept"><button @click="upPage(item.id,'Accepted')" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div> - <div class="refuse"><button @click="upPage(item.id,'Refused')" style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div> - </div> - </div> - </div> -</template> - -<style scoped> - .container{ - color:white; - height:100px; - font-size:20px; - display:grid; - grid-template-columns:10% 14.2% 19% 14.2% 14.2% 14.2% 14.2%; - grid-template-areas: - "id type surname firstname infos accept refuse"; - - } - - .infos { - grid-area:infos; - align-self:center; - } - - .accept{ - grid-area:accept; - align-self:center; - } - - .refuse{ - grid-area:refuse; - align-self:center; - } - - .titles { - grid-area:titles; - background-color:rgb(215,215,215); - } - .id{ - grid-area:id; - margin-left:40px; - align-self:center; - } - - .type{ - grid-area:type; - align-self:center; - } - - .surname{ - grid-area:surname; - align-self:center; - white-space: nowrap; - overflow: hidden; - text-overflow:ellipsis; - } - - .firstname{ - grid-area:firstname; - align-self:center; - white-space: nowrap; - overflow: hidden; - text-overflow:ellipsis; - } - - button{ - font-size:15px; - height:50px; - width:100px; - border:none; - border-radius:20px; - - } - - .bodu { - margin-top:2%; - width:66%; - border:2px solid black; - border-radius:9px; - background-color:rgb(50,50,50); - } - - -</style> - - diff --git a/frontend/src/Apps/Inscription/AboutRequest.vue b/frontend/src/Apps/Inscription/AboutRequest.vue new file mode 100644 index 0000000..15c72f5 --- /dev/null +++ b/frontend/src/Apps/Inscription/AboutRequest.vue @@ -0,0 +1,132 @@ +<script setup> +import i18n from "@/i18n.js" +import {getSelf, getUser} from '../../rest/Users.js' +import {getcurriculum,getSomeonesCurriculumList} from "@/rest/curriculum.js"; +import {getRegisters} from "@/rest/ServiceInscription.js"; +import {get} from "jsdom/lib/jsdom/named-properties-tracker.js"; +import {getExternalCurriculumByInscrReq} from "@/rest/externalCurriculum.js"; +import {ref} from "vue"; +import ExternalCurriculumList from "@/Apps/Inscription/ExternalCurriculumList.vue"; +import {editEquivalenceState} from "@/rest/requests.js"; + +const props = defineProps(['target']); +const request = await getRegisters(props.target); +const cursus = await getcurriculum(request.curriculum); +const user = await getSelf(); +const list = ref(false); +const externalCurriculum = await getExternalCurriculumByInscrReq(request.id) + +function getPP(){ + if(request.profilePictureUrl === null){ + return "/Clyde.png" + } + return request.profilePictureUrl; +} + +async function editEquivalence(id, newstate){ + await editEquivalenceState(id, newstate) +} +</script> + +<template> + <div class="body" v-if="list == false"> + <div class="container"> + <div class="profilPic"> + <img class="subContainter" :src=getPP()> + </div> + <div class = "globalInfos"> + <div class="infosContainer"> + <div> + FirstName/Name : {{request.firstName}} {{request.lastName}} + </div> + <div> + E-mail: {{request.email}} + </div> + <div> + Adresse : {{request.address}} + </div> + <div> + Pays : {{request.country}} + </div> + <div> + Date de naissance : {{request.birthDate}} + </div> + <div> + Cursus voulu : BAB {{cursus.year}} {{cursus.option}} + </div> + <div v-if="cursus.year > 1"> + <button style="background-color:rgb(105,05,105);margin-left: 5%" @click="list=!list" v-if="(user.role == 'Teacher' || user.role == 'Admin')&& request.equivalenceState == 'Pending'">See external curriculums</button> + </div> + </div> + </div> + </div> + </div> + <div v-if="list==true"> + <ExternalCurriculumList :ext-curr-list="externalCurriculum" :inscr-req-id="request.id"></ExternalCurriculumList> + <div style="margin-left: 15%;margin-top: 5%;"> + <button style="margin-left: 2%" @click="list = false;editEquivalence(request.id, 'Accepted'); request.equivalenceState='Accepted'">Accept Equivalence</button> + <button style="margin-left: 2%" @click="list = false;editEquivalence(request.id, 'Refused'); request.equivalenceState='Refused'">Refuse Equivalence</button> + <button style="margin-left: 2%" @click="list=false">Return to profile</button> + </div> + </div> +</template> + + +<style scoped> +.container{ + min-width:675px; + display:grid; + grid-template-columns:10vw 50vw; + grid-template-rows:200px auto; + column-gap:2.7%; + row-gap:45px; + grid-template-areas: + "profilPic globalInfos" + "minfos minfos"; +} + +.profilPic{ + grid-area:profilPic; + width:100%; +} + +.globalInfos { + grid-area:globalInfos; + align-self :center; + +} + +.body { + min-width:960px; + width:100%; + display:flex; + align-items:center; + justify-content:center; + margin-top:5%; +} + +.subContainter{ + width:100%; + background-color:rgb(50,50,50); + border-radius:20px; + border:4px solid black; +} + +.infosContainer { + padding-bottom:50px; + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px; +} + +button{ + font-size:15px; + height:50px; + width:100px; + border:none; + border-radius:20px; +} +</style> \ No newline at end of file diff --git a/frontend/src/Apps/Inscription/AboutStudent.vue b/frontend/src/Apps/Inscription/AboutStudent.vue new file mode 100644 index 0000000..03368c2 --- /dev/null +++ b/frontend/src/Apps/Inscription/AboutStudent.vue @@ -0,0 +1,192 @@ +<script setup> + import i18n from "@/i18n.js" + import {getUser} from '../../rest/Users.js' + import {getSomeonesCurriculumList} from "@/rest/curriculum.js"; + import {ref} from "vue"; + import ExternalCurriculumList from "@/Apps/Inscription/ExternalCurriculumList.vue"; + import {getExternalCurriculumByUser} from "@/rest/externalCurriculum.js"; + + const props = defineProps(['target']) + const user = await getUser(props.target) + const UserCurriculum = await getSomeonesCurriculumList(props.target) + const externalcurrlist = await getExternalCurriculumByUser(user.regNo) + const extercurrlist = ref(false) + + function getPP(){ + if(user.profilePictureUrl === null){ + return "/Clyde.png" + } + return user.profilePictureUrl + } + + //Cette function renvoie l'année académique concernée si on est dans l'année 2023-2024 elle renvoie 2023 + //car dans la db l'année scolaire 2023-2024 est representée juste par 2023 (le même système s'applique pour chaque années on prend la borne inférieure + function getYear(){ + let date = new Date(); + if (date.getMonth() <= 6){ + return date.getFullYear()-1 + } + return date.getFullYear() + } + +</script> + +<template> + <div class="body" v-if="extercurrlist==false"> + <div class="container"> + <div class="profilPic"> + <img class="subContainter" :src=getPP()> + </div> + <div class = "globalInfos"> + <div class="infosContainer"> + <div> + FirstName/Name : {{user.firstName}} {{user.lastName}} + </div> + <div> + E-mail: {{user.email}} + </div> + <div> + Adresse : {{user.address}} + </div> + <div> + Pays : {{user.country}} + </div> + <div> + Date de naissance : {{user.birthDate}} + </div> + <div> + <button @click="extercurrlist=!extercurrlist">See external curriculums</button> + </div> + </div> + </div> + <div class="moreInfos"> + <div class = "oldcursus"> + <div class="listTitle"> + Anciens Cursus + </div> + <div class="listElement"> + <div class=" containerElement" v-for="item in UserCurriculum.curriculumList"> + <div class="year" v-if="parseInt(item.dateyear) !== getYear()">Bac {{item.year}}</div> + <div class="option" v-if="parseInt(item.dateyear) !== getYear()">{{item.option}}</div> + <div class="dateyear" v-if="parseInt(item.dateyear) !== getYear()">Année {{item.dateyear}}-{{item.dateyear+1}}</div> + </div> + </div> + </div> + <div class="newcursus"> + <div class="listTitle"> + Cursus Actuel + </div> + <div class="listElement"> + <div class=" containerElement" v-for="item in UserCurriculum.curriculumList" > + <div class="year" v-if="parseInt(item.dateyear) === getYear()">Bac {{item.year}}</div> + <div class="option" v-if="parseInt(item.dateyear) === getYear()">{{item.option}}</div> + <div class="dateyear" v-if="parseInt(item.dateyear) === getYear()">Année {{item.dateyear}}-{{item.dateyear+1}}</div> + </div> + </div> + </div> + </div> + </div> + </div> + <div v-if="extercurrlist==true"> + <ExternalCurriculumList :ext-curr-list="externalcurrlist"></ExternalCurriculumList> + </div> +</template> + + +<style scoped> +.container{ + min-width:675px; + display:grid; + grid-template-columns:10vw 50vw; + grid-template-rows:200px auto; + column-gap:2.7%; + row-gap:45px; + grid-template-areas: + "profilPic globalInfos" + "minfos minfos"; +} + +.profilPic{ + grid-area:profilPic; +} + +.globalInfos { + grid-area:globalInfos; + align-self :center; + +} + +.body { + min-width:960px; + width:100%; + display:flex; + align-items:center; + justify-content:center; + margin-top:5%; +} + +.subContainter{ + width:100%; + background-color:rgb(50,50,50); + border-radius:20px; + border:4px solid black; +} + +.infosContainer { + padding-bottom:50px; + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px; +} + +.moreInfos { + display:grid; + grid-template-rows:200px auto; + column-gap:50px; + row-gap:45px; + grid-template-areas: + "minfos minfos"; + grid-template-columns:600px 600px; + align-items:center; + justify-content:center; + margin-left: 320%; +} + +.listTitle{ + display: flex; + justify-content: center; + align-items: center; + width:250px; + margin-left:auto; + margin-right:auto; + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px;margin-bottom:10px; +} + +.listElement{ + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px; + margin-bottom:10px; +} + +.containerElement{ + justify-content:center; + display:grid; + grid-template-columns:100px 100px 300px; + grid-template-areas: + "year option dateyear"; + column-gap:40px; + padding-left: 25px; +} +</style> \ No newline at end of file diff --git a/frontend/src/Apps/Inscription/CourseList.vue b/frontend/src/Apps/Inscription/CourseList.vue new file mode 100644 index 0000000..7442076 --- /dev/null +++ b/frontend/src/Apps/Inscription/CourseList.vue @@ -0,0 +1,139 @@ +<script setup> + +import {reactive, ref} from "vue"; +import i18n from "@/i18n.js"; +import {getCourse} from "@/rest/courses.js"; +import {getcurriculum} from "@/rest/curriculum.js"; +import {uploadFile, uploadProfilePicture} from "@/rest/uploads.js"; +import {createExemptionsRequest} from "@/rest/requests.js"; +import {getSelf} from "@/rest/Users.js"; + +const props = defineProps(["cursuslist"]) +const selectedCurriculum = ref(props.cursuslist[0]) +const user = await getSelf() + +const courseslist = ref(await getcurriculum(selectedCurriculum.value.curriculumId)) +const list = ref(true) + +const ppData = ref({}) +async function updateCourseList(){ + courseslist.value = await getcurriculum(selectedCurriculum.value.curriculumId) +} + +async function postExemptionRequest(file, type){ + const a = await uploadFile(file, type); + exemptReq.justifDocument = a.url + await createExemptionsRequest(exemptReq) +} +const exemptReq = reactive({ + userRegNo : user.regNo, + courseId : null, + justifDocument : "", +}) +</script> + +<template style="margin-top:5%;"> + <div v-if="list == true"> + <span>Selected Cursus : </span> + <select v-model="selectedCurriculum" @change="updateCourseList"> + <option v-for="item in props.cursuslist" :value="item">Bac {{item.year}} {{item.option}}</option> + </select> + <div style="display:flex; justify-content:center;" v-for="item in courseslist.courses"> + <div class="bodu"> + <div class="container"> + <div class="title">{{item.title}}</div> + <div class="firstname">{{item.owner.firstName}}</div> + <div class="lastname">{{item.owner.lastName}}</div> + <div class="credits">credits : {{item.credits}}</div> + <div class="askexemption"><button style="background-color:rgb(105,0,0);" @click="list= !list;exemptReq.courseId=item.courseId">Ask exemption</button></div> + </div> + </div> + </div> + </div> + <div v-else> + <p>Please upload the justification document for the exemption </p> + <label class="browser"> + <input type="file" @change="ppData.value = $event.target.files" accept="image/*" ref="filepath"> + </label> + <button style="width:15%; margin-top: 5%;" @click="postExemptionRequest(ppData.value, 'JustificationDocument');"> + Submit exemption request + </button> + </div> +</template> + +<style scoped> +.container{ + color:white; + height:100px; + font-size:30px; + display:grid; + grid-template-columns:30% 20% 15% 15% 15%; + grid-template-areas:"title firstname lastname credits askexemption"; + column-gap:10px; +} + +.title { + grid-area:title; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + font-size: 50%; + margin-left:30px; +} + +.credits { + grid-area:credits; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + font-size: 50%; +} + +.askexemption { + grid-area:askexemption; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; +} +.lastname{ + grid-area:lastname; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + font-size: 50%; +} + + +.firstname{ + grid-area:firstname; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + font-size: 50%; + padding-left: 30%; +} + + +.bodu { + margin-top:2%; + width:100%; + border:2px solid black; + border-radius:9px; + background-color:rgb(50,50,50); +} + +button{ + border:none; + background-color:rgb(239, 60, 168); + border-radius:10px; + height:35px; + margin-top:10px; + +} +</style> + diff --git a/frontend/src/Apps/Inscription/ExternalCurriculumList.vue b/frontend/src/Apps/Inscription/ExternalCurriculumList.vue new file mode 100644 index 0000000..a642840 --- /dev/null +++ b/frontend/src/Apps/Inscription/ExternalCurriculumList.vue @@ -0,0 +1,87 @@ +<script setup> + import i18n from "@/i18n.js"; + import {ref} from "vue"; + + const props = defineProps(["extCurrList"]) + + const extCurrList = ref(props.extCurrList) + console.log(extCurrList) +</script> + +<template style="margin-top:5%;"> + <div style="display:flex; justify-content:center; " v-for="item in extCurrList"> + <div class="bodu"> + <div class="container"> + <div class="status"><a style="margin-left:30px">{{item.state}}</a></div> + <div class="school"><a>{{item.school}}</a></div> + <div class="formation"><a>{{item.formation}}</a></div> + <div class="completion"><a>{{item.completion}}</a></div> + <div class="download"><button>Download document</button></div> + </div> + </div> + </div> +</template> + +<style scoped> +.container{ + color:white; + height:100px; + font-size:30px; + display:grid; + grid-template-columns:15% 10% 20% 15% 13.1%; + grid-template-areas: + "status school formation completion download"; + column-gap:10px; +} + +.status { + grid-area:status; + align-self:center; + font-size: 70%; +} + +.school{ + grid-area:school; + align-self:center; + font-size: 70%; +} + +.formation{ + grid-area:formation; + align-self:center; + font-size: 70%; +} + +.completion{ + grid-area:completion; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + font-size: 70%; +} + +.download{ + grid-area: download; + align-self:center; +} +button{ + font-size:15px; + height:50px; + width:75%; + border:none; + border-radius:20px; + +} + +.bodu { + margin-top:2%; + width:66%; + border:2px solid black; + border-radius:9px; + background-color:rgb(50,50,50); +} + + +</style> + diff --git a/frontend/src/Apps/Inscription/ManageRequests.vue b/frontend/src/Apps/Inscription/ManageRequests.vue new file mode 100644 index 0000000..e45a1a5 --- /dev/null +++ b/frontend/src/Apps/Inscription/ManageRequests.vue @@ -0,0 +1,196 @@ +<script setup> + import i18n from "@/i18n.js" + import {ref} from 'vue' + import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js' + import AboutRequest from "@/Apps/Inscription/AboutRequest.vue"; + import {getAllExemptionsRequest, getAllScholarShipsRequest} from "@/rest/requests.js"; + + const requests = ref(await getAllRegisters()); + let targetId = ""; + + const requestType = ref("inscription"); + const filterType = ref("None"); + + //0 = liste, 1 = détails, 2 = sure? + let windowsState = ref(0); + + async function upPage(id,review){ + await validateRegister(id,review); + + requests.value = await getAllRegisters(); + } + + async function loadRequests(){ + if (requestType.value === "inscription"){ + requests.value = await getAllRegisters(); + } + if (requestType.value === "scholarship"){ + requests.value = await getAllScholarShipsRequest(); + } + if(requestType.value === "exemption"){ + requests.value = await getAllExemptionsRequest(); + } + } +</script> + + + +<template> + <div v-if="windowsState === 1"> + <AboutRequest :target="targetId"></AboutRequest> + </div> + <div v-if="windowsState === 0"> + <div style="margin-top: 2%;margin-left: 2%"> + <span>Request type : </span> + <select v-model="requestType" @change="loadRequests()"> + <option>inscription</option> + <option>scholarship</option> + <option>exemption</option> + </select> + <span style="margin-left: 5%"> + Filter : + <select v-model="filterType"> + <option>None</option> + <option>Pending</option> + <option>Accepted</option> + <option>Refused</option> + </select> + </span> + </div> + <div style='display:flex; justify-content:center; min-width:1140px;' v-for="item of requests"> + <div class="bodu" style="width: 95%" v-if="filterType == 'None' || filterType == item.state"> + <div class="container" style="grid-template-columns:11% 15% 20% 10% 10% 9% 9%;grid-template-areas:'date state equivalencestate surname firstname accept refuse infos';" v-if="requestType === 'inscription'"> + <!-- + The condition below avoids an error occuring because loadRequests() finishes after the vue refresh + then submissionDate is undefined an it triggers an error in the console despite the fact that it is working + properly at the end. + --> + <div class="date" v-if="item.submissionDate !== undefined">{{item.submissionDate.slice(0, 10)}}</div> + <div class="state" style="font-size: 80%">Approval : {{item.state}}</div> + <div class="equivalencestate" style="font-size: 80%">Teacher approval : {{item.equivalenceState}}</div> + <div class="surname">{{item.lastName}}</div> + <div class="firstname">{{item.firstName}}</div> + <div class="accept" v-if="item.state === 'Pending'"><button @click="windowsState=2;targetId=item.id;" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div> + <div class="refuse" v-if="item.state === 'Pending'"><button @click="upPage(item.id,'Refused')" style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div> + <div class="infos"><button style="background-color:rgb(105,05,105);" @click="targetId=item.id;windowsState=1;">{{i18n("request.moreInfos")}}</button></div> + </div> + <div class="container" style="grid-template-columns:25% 15% 15% 25% 14.2%;grid-template-areas:'date reqState studentfirstname studentlastname infos';" v-if="requestType === 'scholarship'"> + <div class="date" v-if="item.date !== undefined"> {{item.date.slice(0,10)}}</div> + <div class="studentfirstname">{{item.user.firstName}}</div> + <div class="studentlastname">{{item.user.lastName}}</div> + <div class="reqState">{{item.state}}</div> + <div class="infos"><button>More infos</button></div> + </div> + <div class="container" style="grid-template-columns:17% 15% 12% 15% 25%;grid-template-areas:'date reqState studentfirstname studentlastname course infos';"v-if="requestType === 'exemption'"> + <div class="date" v-if="item.date != undefined">{{item.date.slice(0,10)}}</div> + <div class="studentfirstname">{{item.user.firstName}}</div> + <div class="studentlastname">{{item.user.lastName}}</div> + <div class="course">{{item.course.title}}</div> + <div class="reqState">{{item.state}}</div> + <div class="infos"><button>More infos</button></div> + </div> + </div> + </div> + </div> + <div style='display:flex; justify-content:center; min-width:1140px;margin-top: 10%' v-if="windowsState === 2"> + <p>Etes vous sur de vouloir accepter cette demande ?</p> + <button style="background-color:rgb(105,05,105);" @click="upPage(targetId,'Accepted');windowsState=0;">Valider</button> + <button style="background-color:rgb(105,05,105);" @click="windowsState=0;">Retour</button> + </div> +</template> + +<style scoped> + .container{ + color:white; + height:100px; + font-size:20px; + display:grid; + column-gap:10px; + } + + .equivalencestate{ + grid-area: equivalencestate; + align-self: center; + } + .studentfirstname{ + grid-area: studentfirstname; + align-self: center; + } + + .studentlastname{ + grid-area: studentlastname; + align-self: center; + } + + .course{ + grid-area: course; + align-self: center; + } + .reqState{ + grid-area: reqState; + align-self: center; + } + .infos { + grid-area:infos; + align-self:center; + } + + .accept{ + grid-area:accept; + align-self:center; + } + + .refuse{ + grid-area:refuse; + align-self:center; + } + + .date{ + grid-area:date; + margin-left:40px; + align-self:center; + } + + .state{ + grid-area:state; + margin-left:40px; + align-self:center; + } + + .surname{ + grid-area:surname; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + } + + .firstname{ + grid-area:firstname; + align-self:center; + white-space: nowrap; + overflow: hidden; + text-overflow:ellipsis; + } + + button{ + font-size:15px; + height:50px; + width:100px; + border:none; + border-radius:20px; + + } + + .bodu { + margin-top:2%; + width:66%; + border:2px solid black; + border-radius:9px; + background-color:rgb(50,50,50); + } + + +</style> + + diff --git a/frontend/src/Apps/Login.vue b/frontend/src/Apps/Login.vue index 82caa80..5b0a807 100644 --- a/frontend/src/Apps/Login.vue +++ b/frontend/src/Apps/Login.vue @@ -1,16 +1,16 @@ <script setup> import {reactive, ref } from 'vue' import i18n from '@/i18n.js' - import { login , register , disconnect, isLogged} from '@/rest/Users.js' - import { getAllCurriculums } from '@/rest/curriculum.js' + import {login, register, disconnect, isLogged} from '@/rest/Users.js' + import {getAllCurriculums, getcurriculum} from '@/rest/curriculum.js' import { uploadProfilePicture } from '@/rest/uploads.js' import {toast} from 'vue3-toastify' import 'vue3-toastify/dist/index.css'; - + import {createExternalCurriculum} from "@/rest/externalCurriculum.js"; const loginPage= ref(true) const page = ref(0) - + const outputs = reactive({ surname:null, firstname:null, @@ -20,13 +20,32 @@ address:null, country:null, curriculum:null, + equivalenceState: "Unrequired" }) + const notcompletedCheck = ref(false); + + const externalCurr = reactive({ + inscriptionRequestId : null, + school:null, + formation :null, + completion : null, + startYear : null, + endYear: null, + justifdocUrl : null + }) + + //Stores some externalCurriculums in order to upload them all at the confirmation of the registration request + const externalCurrTab = ref([]); + const submitValue= ref(i18n("login.guest.submit")) const passwordConfirm=ref("") const imageSaved = ref(false) - const ppData = ref(false) + let ppData = "" + + //Contains the id of the newly created request (useful to link the student's formations informations to the request) + let requestId = "" const curricula= await getAllCurriculums(); @@ -50,8 +69,39 @@ disconnect(); window.location.reload();} - + async function uploadPP(arg){ + const data = await uploadProfilePicture(arg); + ppData = data.url; + } + //This functions makes the distinction between a master cursus (year 4 or more) and a bachelor cursus (year 3 or less) + function getCursusDisplay(cursus){ + if (cursus.year <= 3){ + return "BAB " + cursus.year + " " + cursus.option; + }else{ + return "MA" + (parseInt(cursus.year)-3).toString() + " " + cursus.option; + } + } + + async function getCurriculumYear(curriculumId){ + const curriculum = await getcurriculum(curriculumId); + return parseInt(curriculum.year); + } + + + + //Post the register request and return the id of the newly created request and also post the external curriculum list in the database + async function postRegisterReq(){ + const val = await register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, ppData, null, new Date(), outputs.equivalenceState); + for (let item in externalCurrTab.value){ + await createExternalCurriculum(val.id, externalCurrTab.value[item].school, externalCurrTab.value[item].formation, externalCurrTab.value[item].completion, externalCurrTab.value[item].startYear, externalCurrTab.value[item].endYear, externalCurrTab.value[item].justifdocUrl); + } + } + + + function deleteExtCursus(extcursus){ + externalCurrTab.value.splice(externalCurrTab.value.indexOf(extcursus),1) + } </script> @@ -116,7 +166,7 @@ <a>{{i18n("login.guest.alregister")}}</a> </div> </div> - <div v-else> + <div v-if="page === 1"> <div class="inputBox"> <p>{{i18n("login.guest.email")}}</p> <input type="mail" v-model="outputs.email"> @@ -129,23 +179,30 @@ <p>{{i18n("login.guest.country")}}</p> <input type="text" v-model="outputs.country"> </div> - <form class="inputBox"novalidate enctype="multipart/form-data"> + <form class="inputBox" novalidate enctype="multipart/form-data"> <p>{{i18n("profile.picture").toUpperCase()}}</p> + </form> <label class="browser"> Parcourir . . . <input type="file" :disabled="imageSaved" @change="ppData = uploadProfilePicture($event.target.files); imageSaved = true;" accept="image/*"> </label> + <form novalidate enctype="multipart/form-data" class="inputBox"> + <p>{{i18n("profile.picture").toUpperCase()}}</p> + <input type="file" @change="uploadPP($event.target.files); imageSaved = true;" accept="image/*"> </form> <div class="inputBox"> <p>{{i18n("Curriculum").toUpperCase()}}</p> <select v-model="outputs.curriculum"> - <option v-for="item in curricula">{{item.curriculumId}}</option> - + <option v-for="item in curricula" :value="item.curriculumId">{{getCursusDisplay(item)}}</option> </select> </div> + <p style="color:rgb(239,60,168);"> + Si vous êtes déja inscrits dans cette université veuillez vous connecter a votre compte et utilisez les fonctions + changer de cursus/réinscription sinon continuez ici. + </p> <div style="align-self:center;" class="inputBox"> - <button style="margin-top:25px;" @click="register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, ppData);"> - {{i18n("login.guest.submit")}} + <button style="margin-top:25px;" @click="page++;"> + {{i18n("login.guest.nextpage")}} </button> </div> <div class="switchpage"> @@ -155,10 +212,69 @@ <a>{{i18n("login.guest.alregister")}}</a> </div> </div> + <div v-if="page === 2"> + <form novalidate enctype="multipart/form-data" class="inputBox"> + Carte d'identité : + </form> + <button @click="page++">{{i18n("login.guest.nextpage")}}</button> + </div> + <div v-if="page === 3"> + <p> + Vous avez séléctionné un cursus qui possède des prérequis veuillez ajouter vos formations antérieures + dans l'enseignement supérieur, votre dossier sera vérifié par un membre du service d'inscription. + </p> + <button @click="page++">Ajouter une formation</button> + <button @click="postRegisterReq();">Envoyer la demande d'inscription</button> + </div> + <div v-if="page===4"> + <form @submit.prevent=""class="form"> + <div class="inputBox"> + <p>Ecole</p> + <input type="text" v-model="externalCurr.school"> + </div> + <div class="inputBox"> + <p>Formation</p> + <input type="text" v-model="externalCurr.formation"> + </div> + <div class="inputBox"> + <p>Cochez la case si vous n'avez terminé cette formation</p> + <input v-model="notcompletedCheck" type="checkbox" id="checkboxformation"> + <div v-if="notcompletedCheck"> + <p>En quelle année de la formation vous êtes vous arrété (exemple: 3ème) ?</p> + <input type="text" v-model="externalCurr.completion"> + </div> + </div> + <div class="inputBox"> + <p>Année de début</p> + <input type="text" v-model="externalCurr.startYear"> + </div> + <div class="inputBox"> + <p>Année de fin</p> + <input type="text" v-model="externalCurr.endYear"> + </div> + <div class="inputBox" style="margin-bottom:35px;"> + <input type="submit" v-model="submitValue" @click="externalCurrTab.push({inscriptionReqId:null, school:externalCurr.school, formation:externalCurr.formation, completion:externalCurr.completion, startYear:externalCurr.startYear, endYear:externalCurr.endYear, justifdocUrl:externalCurr.justifdocUrl});console.log(externalCurrTab);page--;"> + </div> + </form> + </div> </form> </div> </div> </div> + <div style="display:flex; justify-content:center; " v-for="item in externalCurrTab" v-if="page===3"> + <div class="bodu"> + <div class="container"> + <div class="school"><a style="margin-left:30px;">{{item.school}}</a></div> + <div class="formation"><a>{{item.formation}}</a></div> + <div class="edit"> + <button style="background-color:rgb(105,05,105);font-size:15px;height:50px;width:75%;border:none;border-radius:20px;" @click="externalCurr.school=item.school; externalCurr.completion=item.completion; externalCurr.formation=item.formation;externalCurr.endYear=item.endYear; externalCurr.startYear=item.startYear; externalCurr.justifdocUrl;page++;">Edit </button> + </div> + <div class="remove"> + <button style="background-color:rgb(105,05,105);font-size:15px;height:50px;width:75%;border:none;border-radius:20px;" @click="deleteExtCursus(item)">Remove </button> + </div> + </div> + </div> + </div> </template> <style scoped> @@ -167,13 +283,14 @@ margin-left: auto; margin-right:auto; min-width:400px; - width:25%; - height:60%; + height:50%; } + .loginBox { background-color: rgb(24,24,24); + width: 400px; display:flex; justify-content: center; border-radius: 5%; @@ -208,7 +325,7 @@ z-index: 100; font-family:sans-serif ; color:rgb(239,60,168); - transition:0.5; + transition: 0.5; } @@ -220,9 +337,16 @@ cursor: pointer; } +.bodu { + margin-top:2%; + width:50%; + border:2px solid black; + border-radius:9px; + background-color:rgb(50,50,50); +} + .switchpage{ width:100px; - background:rgb(255, 0 255); border: none; padding-right:0; padding-top:10px; @@ -230,7 +354,7 @@ outline:none; border-radius: 4px; font-size:0.8em; - align-self:right; + align-self: right; } @@ -260,11 +384,22 @@ input[type=file]{ background:#FFFFFF; } +.container{ + margin-top: 2%; + color:white; + height:60px; + font-size:30px; + display:grid; + grid-template-columns:30% 30% 20% 20%; + grid-template-areas: + "school formation completion edit remove"; + column-gap:10px; +} + button:active ,.switchpage:active{ opacity:0.8; } - </style> diff --git a/frontend/src/Apps/Profil.vue b/frontend/src/Apps/Profil.vue index 643cc7d..f0a7c2b 100644 --- a/frontend/src/Apps/Profil.vue +++ b/frontend/src/Apps/Profil.vue @@ -1,16 +1,22 @@ <script setup> import {reactive, ref } from 'vue' import {getSelf,alterSelf,disconnect,deleteUser} from '../rest/Users.js' - import {getSelfCurriculum, getAllCurriculums} from '../rest/curriculum.js' + import {getSelfCurriculum, getAllCurriculums, getSomeonesCurriculumList} from '../rest/curriculum.js' import {getCourses} from "../rest/courses.js" import i18n from "@/i18n.js" - import { uploadProfilePicture } from '@/rest/uploads.js' + import {uploadFile, uploadProfilePicture} from '@/rest/uploads.js' + import CourseList from "@/Apps/Inscription/CourseList.vue"; + import {editMinerval, getCurrentMinerval} from "@/rest/minerval.js"; + import {postPayment} from "@/rest/payment.js"; + import {addUninscReq, createScholarshipRequest} from "@/rest/requests.js"; const user = ref(await getSelf()); const UserCurriculum = ref(""); const curricula = ref (await getAllCurriculums()); + const minerv = ref({}); if(user.value.role === "Student"){ - UserCurriculum.value = await getSelfCurriculum(); + minerv.value = ref(await getCurrentMinerval(user.value.regNo)); + UserCurriculum.value = await getSomeonesCurriculumList(user.value.regNo); } if(user.role === "Teacher"){ @@ -19,6 +25,13 @@ const modif = ref(false); const curric = ref(false); const reg = ref(false); + const courseslist = ref(false); + const minerval = ref(false); + const paymentPage = ref(false); + const scholarship = ref(false); + const scholarshipinfos = ref(false); + const uninscr = ref(false); + const sure = ref(0); const pattern = { profilPictureUrl:null, @@ -34,7 +47,32 @@ id:null, } - + //Used to modelize a payment + const paymentData={ + studentRegNo: user.value.regNo, + date:null, + card:null, + client:null, + expDate:null, + amount: null + } + + //Used to modelize a scholarship request + const scholarshipData=reactive({ + userId: user.value.regNo, + state:null, + date:null, + amount:0, + taxDocUrl : "", + residencyDocUrl : "" + }) + + //Used to post a uninscription request + const uninscriptionData = reactive({ + reason : null, + userId : user.value.regNo + }) + const paymentAmount = ref(0); let toModify= Object.assign({}, pattern); let personnalInfos = Object.assign({}, patternInfos); @@ -86,17 +124,47 @@ } return user.profilePictureUrl } + + function getYear(){ + let date = new Date(); + if (date.getMonth() <= 6){ + return date.getFullYear()-1 + } + return date.getFullYear() + } + + //This function travels through the student cursus array and extract the current cursus of the student + function getActualCurriculumList(){ + let actualCurriculumList = []; + for (let i = 0; i < UserCurriculum.value.curriculumList.length; i++){ + if (UserCurriculum.value.curriculumList[i].dateyear === getYear()){ + actualCurriculumList.push(UserCurriculum.value.curriculumList[i]); + } + } + return actualCurriculumList + } + + async function postScholarshipRequest(file1, type1, file2, type2){ + const a = await uploadFile(file1, type1) + scholarshipData.taxDocUrl = a.url; + + const b = await uploadFile(file2, type2) + scholarshipData.residencyDocUrl = b.url; + + scholarshipData.date = Date.now(); + + await createScholarshipRequest(scholarshipData) + } </script> <template> <div class="body"> - <div class="container"> + <div class="container" v-if="courseslist == false"> <div class="profilPic"> <img class="subContainter" :src=getPP()> - </div> <div class="globalInfos"> - <div v-if="modif==false && curric==false && reg==false " class="infosContainer" > + <div v-if="modif==false && curric==false && reg==false && minerval==false && paymentPage == false && scholarship==false && uninscr == false" class="infosContainer"> <div> {{user.firstName}} {{user.lastName}} </div> @@ -114,11 +182,87 @@ </div> <div v-if="(user.role==='Student')"> <button @click="reg=!reg">{{i18n("profile.reRegister")}}</button> - <button @click="unRegister()" style="float:right;background-color:rgb(150,0,0);">{{i18n("profile.unRegister")}}</button> + <button @click="uninscr = !uninscr" style="float:right;background-color:rgb(150,0,0);">{{i18n("profile.unRegister")}}</button> </div> <div v-if="(user.role==='Student')"> <button @click="curric=!curric">{{i18n("profile.change.curriculum")}}</button> </div> + <div v-if="(user.role==='Student')"> + <button @click="courseslist=!courseslist">Manage Courses</button> + <button @click="minerval = !minerval" style="margin-left: 2%">Manage minerval</button> + </div> + </div> + <div v-else-if="uninscr" class="infosContainer"> + <div v-if="sure != 2">Please enter the reason you leave the university</div> + <textarea v-if="sure != 2" v-model="uninscriptionData.reason"></textarea> + <div v-if="sure != 2"> + <button @click="sure++">Submit</button> + </div> + <div v-if="sure==1"> + Are you sure that you want to unregister ? + <button @click="addUninscReq(uninscriptionData.userId, uninscriptionData.reason);sure++">Yes</button> + <button @click="sure=0">No</button> + </div> + <p v-if="sure==2">You request has been send !</p> + </div> + <div v-else-if="minerval" class="infosContainer"> + <div v-if="minerv.value.toPay != 0"> + Payment : {{minerv.value.toPay}}€ left to pay + <div v-if="minerv.value.paidAmount <= 50"> + <button @click="minerval = !minerval; paymentPage = !paymentPage; paymentAmount = 50">Pay deposit (50€)</button> + </div> + <div> + <button @click="minerval = !minerval; paymentPage = !paymentPage; paymentAmount = minerv.value.toPay">Pay all the rest ({{minerv.value.toPay}}€)</button> + </div> + </div> + <div v-else> + Payment : School fees have already been paid this year + </div> + <div> + <button @click="scholarship=!scholarship; minerval=!minerval">Ask for a scholarship</button> + </div> + </div> + <div v-else-if="scholarship && !scholarshipinfos" class="infosContainer"> + <p>Please upload the required documents</p> + <div> + Tax justification document : + <input type="file" @change="scholarshipData.taxDocUrl = $event.target.files"> + </div> + <div> + Residency justification document : + <input type="file" style="margin-top:2%" @change="scholarshipData.residencyDocUrl = $event.target.files"> + </div> + <button style="margin-top: 5%" @click="scholarshipinfos = !scholarshipinfos;postScholarshipRequest(scholarshipData.taxDocUrl, 'JustificationDocument',scholarshipData.residencyDocUrl, 'JustificationDocument');">Submit scholarship request</button> + </div> + <div v-else-if="scholarship && scholarshipinfos" class="infosContainer"> + <div> + Your request has been sent to the inscription service you will get notified when + the request is reviewed. + </div> + <button @click="scholarshipinfos=!scholarshipinfos; scholarship=!scholarship"> + Go back to profile + </button> + </div> + <div v-else-if="paymentPage" class="infosContainer"> + Proceed to payment of {{paymentAmount}}€ + <div style="margin-top: 1%"> + Client: + <input type="text" v-model="paymentData.client"> + </div> + <div style="margin-top: 1%"> + Card: + <input type="text" v-model="paymentData.card"> + </div> + <div style="margin-top: 1%"> + ExpDate: + <input type="date" v-model="paymentData.expDate"> + </div> + <div style="margin-top: 1%"> + <button @click="paymentPage=!paymentPage;minerval=!minerval;paymentData.amount=paymentAmount;paymentData.date=new Date();postPayment(paymentData);minerv.value.toPay -= paymentAmount; minerv.value.paidAmount += paymentAmount; editMinerval(minerv.value)">Process Payment</button> + </div> + <div> + <button @click="minerval = !minerval; paymentPage = !paymentPage;">Back</button> + </div> </div> <div v-else-if="modif" class="infosContainer"> <div> @@ -182,29 +326,38 @@ <button @click=" reg=!reg; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button> </div> </div> - </div> - - <div v-if="modif==false && curric==false && reg==false "class="moreInfos"> - - <div v-if="(user.role ==='Student')"> - <div class="listTitle"> - {{i18n("profile.course.list")}} + <div v-if="user.role == 'Student' && modif==false && curric==false && reg==false && minerval==false && scholarship == false && uninscr == false" class="moreInfos"> + <div class = "oldcursus"> + <div class="listTitle"> + Anciens Cursus + </div> + <div class="listElement"> + <div class=" containerElement" v-for="item in UserCurriculum.curriculumList"> + <div class="year" v-if="parseInt(item.dateyear) !== getYear()">Bac {{item.year}}</div> + <div class="option" v-if="parseInt(item.dateyear) !== getYear()">{{item.option}}</div> + <div class="dateyear" v-if="parseInt(item.dateyear) !== getYear()">Année {{item.dateyear}}-{{item.dateyear+1}}</div> + </div> + </div> </div> - <div class="listElement" v-for="item in UserCurriculum.courses"> - <div class=" containerElement"> - <div class="name"> {{item.title}} </div> - <div class="teacher">{{item.owner.lastName}}</div> - <div class="credits">Credits:{{item.credits}}</div> + <div class="actualcursus"> + <div class="listTitle"> + Cursus Actuel + </div> + <div class="listElement"> + <div class=" containerElement" v-for="item in UserCurriculum.curriculumList" > + <div class="year" v-if="parseInt(item.dateyear) === getYear()">Bac {{item.year}}</div> + <div class="option" v-if="parseInt(item.dateyear) === getYear()">{{item.option}}</div> + <div class="dateyear" v-if="parseInt(item.dateyear) === getYear()">Année {{item.dateyear}}-{{item.dateyear+1}}</div> + </div> + </div> </div> - </div> - </div> - - <div> - </div> - </div> </div> + <div v-if="courseslist === true" style="width: 80%"> + <CourseList :cursuslist="getActualCurriculumList()"/> + <button style="width: 10%; margin-top: 5%" @click="courseslist = false">Return to profile</button> + </div> </div> </template> <style scoped> @@ -240,7 +393,32 @@ } .moreInfos { - grid-area:minfos; + margin-top: 50%; + display:grid; + grid-template-rows:200px auto; + column-gap:50px; + row-gap:45px; + grid-template-areas: + "minfos minfos"; + grid-template-columns:600px 600px; + align-items:center; + justify-content:center; + margin-left: 320%; +} + +.listTitle{ + display: flex; + justify-content: center; + align-items: center; + width:250px; + margin-left:auto; + margin-right:auto; + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px;margin-bottom:10px; } .body { min-width:960px; @@ -248,18 +426,19 @@ display:flex; align-items:center; justify-content:center; - margin-top:5%; + margin-top:7%; } - .containerElement{ + .containerElement{ justify-content:center; - display:grid; - grid-template-columns:38.8% 38.8% 22.4%; - grid-template-areas: - "name teacher credits"; - column-gap:10px; + display:grid; + grid-template-columns:100px 100px 300px; + grid-template-areas: + "year option dateyear"; + column-gap:40px; + padding-left: 25px; } - + .name { grid-area:name; align-self:center; @@ -275,24 +454,8 @@ align-self:center; } -.listTitle{ - min-width:197px; - display: flex; - justify-content: center; - align-items: center; - width:8vw; - margin-left:auto; - margin-right:auto; - border:2px solid black; - font-size:25px; - color:white; - padding:20px; - background-color:rgb(50,50,50); - border-radius:20px;margin-bottom:10px; -} .listElement{ - min-width:625px; border:2px solid black; font-size:25px; color:white; diff --git a/frontend/src/Apps/StudentsList.vue b/frontend/src/Apps/StudentsList.vue index 1ab3ff8..c6adea8 100644 --- a/frontend/src/Apps/StudentsList.vue +++ b/frontend/src/Apps/StudentsList.vue @@ -1,19 +1,29 @@ <script setup> import i18n from "@/i18n.js" - import { reactive } from 'vue' + import {provide, reactive, ref} from 'vue' import { getStudents } from '../rest/Users.js' - + import AboutStudent from "@/Apps/Inscription/AboutStudent.vue"; const users = await getStudents(); -</script> + + let targetRegNo = ""; + let list = ref(true); +</script> + <template style="margin-top:5%;"> - <div style="display:flex; justify-content:center; " v-for="item in users"> + <div v-if="list === false"> + <AboutStudent :target=targetRegNo /> + <button style="background-color:rgb(105,05,105);width:5%; margin-left: 10%;" @click="list = true;">Back</button> + </div> + <div style="display:flex; justify-content:center; " v-for="item in users" v-if="list === true"> <div class="bodu"> <div class="container"> <div class="status"><a style="margin-left:30px">{{item.status}}</a></div> <div class="option"><a>{{item.role}}</a></div> <div class="surname"><a>{{item.lastName}}</a></div> <div class="firstname"><a>{{item.firstName}}</a></div> - <div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}} </button></div> + <div class="infos"> + <button style="background-color:rgb(105,05,105);" @click="list = false; targetRegNo = item.regNo;">{{i18n("request.moreInfos")}} </button> + </div> </div> </div> </div> @@ -25,10 +35,10 @@ height:100px; font-size:30px; display:grid; - grid-template-columns:21.7% 21.7% 21.7% 21.7% 13.1%; + grid-template-columns:21.7% 21.7% 21.7% 20% 13.1%; grid-template-areas: "status option surname firstname infos"; - + column-gap:10px; } .infos { @@ -64,8 +74,8 @@ button{ font-size:15px; - height:50px; - width:75%; + height:50px; + width:75%; border:none; border-radius:20px; diff --git a/frontend/src/rest/ServiceInscription.js b/frontend/src/rest/ServiceInscription.js index 5489713..5c10fde 100644 --- a/frontend/src/rest/ServiceInscription.js +++ b/frontend/src/rest/ServiceInscription.js @@ -3,7 +3,7 @@ * * TODO: On time of writing, the backend doesn't support these endpoints so it could be modified in the future. */ -import {restGet, restPatch} from './restConsumer.js' +import {restGet, restPatch, restPost} from './restConsumer.js' /** * create a new register requests that can be recovered by the registering service @@ -43,3 +43,4 @@ export async function getAllRegisters(){ export async function validateRegister(id, state){ return restPatch("/request/register/" + id, state); } + diff --git a/frontend/src/rest/Users.js b/frontend/src/rest/Users.js index 760bfc7..7daa99b 100644 --- a/frontend/src/rest/Users.js +++ b/frontend/src/rest/Users.js @@ -26,7 +26,7 @@ export function disconnect(){ * @param curriculum * @param imageId id of the image in database returned when uploaded */ -export async function register(firstname, lastname, birthDate, password, email, address, country, curriculumId, imageId){ +export async function register(firstname, lastname, birthDate, password, email, address, country, curriculumId, imageId, identityCardId, submissionDate, equivalence){ return restPost("/register", { firstName: firstname, lastName: lastname, @@ -36,7 +36,10 @@ export async function register(firstname, lastname, birthDate, password, email, address: address, country: country, curriculumId: curriculumId, - profilePictureUrl: imageId, + profilePicture: imageId, + identityCard : identityCardId, + submissionDate : submissionDate, + equivalenceState : equivalence }); } @@ -52,7 +55,7 @@ export async function register(firstname, lastname, birthDate, password, email, * @param country * @param imageId id of the image in database returned when uploaded * - * PS: the password is not is not required as it is generated by the backend and sent to the user + * PS: the password is not required as it is generated by the backend and sent to the user * by mail. it's up to the user to change it if he cares about security */ export async function createUser(firstname, lastname, birthDate, email, address, country, role, imageId){ diff --git a/frontend/src/rest/apps.js b/frontend/src/rest/apps.js index 0105112..59d3c76 100644 --- a/frontend/src/rest/apps.js +++ b/frontend/src/rest/apps.js @@ -4,17 +4,19 @@ import i18n from '@/i18n.js' // Liste des apps import LoginPage from '@/Apps/Login.vue' -import Inscription from "@/Apps/Inscription.vue" +import Inscription from "@/Apps/Inscription/ManageRequests.vue" import Profil from "@/Apps/Profil.vue" import Courses from "@/Apps/ManageCourses.vue" import Users from "@/Apps/UsersList.vue" import Students from "@/Apps/StudentsList.vue" import ResearcherProfile from "@/Apps/ScientificPublications/ResearcherProfile.vue"; +import AboutStudent from "@/Apps/Inscription/AboutStudent.vue"; import Msg from "@/Apps/Msg.vue" +import ManageRequests from "@/Apps/Inscription/ManageRequests.vue"; const apps = { '/login': LoginPage, - '/inscription': Inscription, + '/requests': ManageRequests, '/profil': Profil, '/manage-courses' : Courses, '/users-list' : Users, @@ -28,7 +30,7 @@ const appsList = { 'Notification': { path: '#/notifs', icon: 'fa-bell', text: i18n("app.notifications") }, 'Forum': { path: '#/forum', icon: 'fa-envelope', text: i18n("app.forum") }, 'Schedule': { path: '#/schedule', icon: 'fa-calendar-days', text: i18n("app.schedules") }, - 'Inscription': { path: '#/inscription', icon: 'fa-users', text: i18n("app.inscription.requests") }, + 'Requests': { path: '#/requests', icon: 'fa-users', text: "Requests" }, 'ManageCourses': { path: '#/manage-courses', icon: 'fa-book', text: i18n("app.manage.courses") }, 'StudentsList':{ path: '#/students-list',icon: 'fa-users',text: i18n("app.studentList")}, 'UsersList':{ path: '#/users-list',icon: 'fa-users',text: i18n("app.users")}, diff --git a/frontend/src/rest/curriculum.js b/frontend/src/rest/curriculum.js index b13c2ed..a34328c 100644 --- a/frontend/src/rest/curriculum.js +++ b/frontend/src/rest/curriculum.js @@ -48,3 +48,9 @@ export async function altercurriculum(id, courses){ export async function getSelfCurriculum(){ return restGet("/curriculum"); } + +export async function getSomeonesCurriculumList(user){ + return restGet("/onescurriculum/"+user) +} + + diff --git a/frontend/src/rest/externalCurriculum.js b/frontend/src/rest/externalCurriculum.js new file mode 100644 index 0000000..f1b403d --- /dev/null +++ b/frontend/src/rest/externalCurriculum.js @@ -0,0 +1,23 @@ +import {restGet, restPatch, restPost} from "@/rest/restConsumer.js"; +import {parseInteger} from "jsdom/lib/jsdom/living/helpers/strings.js"; + +export async function createExternalCurriculum(inscriptionRequestId,school, formation, completion, startYear, endYear, justifdocUrl){ + return restPost("/externalcurriculum", { + inscriptionRequestId: inscriptionRequestId, + school:school, + formation :formation, + completion : completion, + startYear : parseInteger(startYear), + endYear: parseInteger(endYear), + justifdocUrl : justifdocUrl + }) +} + +export async function getExternalCurriculumByInscrReq(inscrReqId){ + return restGet("/externalcurriculum/"+inscrReqId) +} + +export async function getExternalCurriculumByUser(userId){ + return restGet("/externalcurriculumbyuser/"+userId) +} + diff --git a/frontend/src/rest/minerval.js b/frontend/src/rest/minerval.js new file mode 100644 index 0000000..1606678 --- /dev/null +++ b/frontend/src/rest/minerval.js @@ -0,0 +1,9 @@ +import {restGet, restPatch, restPost} from "@/rest/restConsumer.js"; + +export async function getCurrentMinerval(userRegNo){ + return restGet("/minerval/"+userRegNo) +} + +export async function editMinerval(updatedMinerval){ + return restPatch("/minerval", updatedMinerval) +} diff --git a/frontend/src/rest/payment.js b/frontend/src/rest/payment.js new file mode 100644 index 0000000..a194457 --- /dev/null +++ b/frontend/src/rest/payment.js @@ -0,0 +1,6 @@ +import {restPost} from "@/rest/restConsumer.js"; + +export async function postPayment(payment){ + return restPost("/payment", payment) +} + diff --git a/frontend/src/rest/requests.js b/frontend/src/rest/requests.js new file mode 100644 index 0000000..9df8a1c --- /dev/null +++ b/frontend/src/rest/requests.js @@ -0,0 +1,25 @@ +import {restGet, restPatch, restPost} from "@/rest/restConsumer.js"; + +export async function createExemptionsRequest(exempReq){ + return restPost("/exemptionreq", exempReq) +} + +export async function createScholarshipRequest(reqInfo){ + return restPost("/scholarshipreq", reqInfo) +} + +export async function getAllScholarShipsRequest(){ + return restGet("/scholarshipreq") +} + +export async function getAllExemptionsRequest(){ + return restGet("/exemptionsreq") +} + +export async function editEquivalenceState(id, newstate){ + return restPatch("/request/registerequiv/"+id+"/"+newstate) +} + +export async function addUninscReq(userId, reason){ + return restPost("/uninscriptionreq", {"userId" : userId, "reason" : reason}) +} \ No newline at end of file diff --git a/frontend/src/rest/restConsumer.js b/frontend/src/rest/restConsumer.js index 2ac4cc3..1af979e 100644 --- a/frontend/src/rest/restConsumer.js +++ b/frontend/src/rest/restConsumer.js @@ -1,7 +1,7 @@ import { getCookie } from '../utils.js' import { toast } from 'vue3-toastify' -const restURL = import.meta.env.PROD ? "https://clyde.herisson.ovh/api" : "http://localhost:8080" +const restURL = import.meta.env.VITE_CLYDE_MODE === 'container' ? "http://localhost:8080": import.meta.env.DEV ? "http://localhost:8080" : "https://clyde.herisson.ovh/api" export async function restGet(endPoint) { return await _rest(endPoint, {method: "GET"}); diff --git a/frontend/src/rest/uploads.js b/frontend/src/rest/uploads.js index 48623cf..856024d 100644 --- a/frontend/src/rest/uploads.js +++ b/frontend/src/rest/uploads.js @@ -7,5 +7,17 @@ import { restPostFile } from '@/rest/restConsumer.js' export async function uploadProfilePicture(file){ const formData = new FormData(); formData.append("file", file[0]); - return restPostFile("/upload/ProfilePicture", formData) + + return restPostFile("/upload/ProfilePicture", formData); } + + +/** + * More generic version of the upload method + */ + +export async function uploadFile(file, type){ + const formData = new FormData(); + formData.append("file", file[0]); + return restPostFile("/upload/"+type, formData) +} \ No newline at end of file