From a1489ddeda4495d9e9f81a15656462b4e27b0720 Mon Sep 17 00:00:00 2001 From: "QSL\\SumathiT" Date: Fri, 11 Oct 2024 20:22:38 -0700 Subject: [PATCH] Changes to eliniate session status and normalization changes on assessment_student --- api/pom.xml | 6 +- .../v1/AssessmentStudentController.java | 9 ++- .../api/controller/v1/SessionController.java | 2 +- .../v1/AssessmentStudentEndpoint.java | 49 ++++++------ .../eas/api/mappers/v1/AssessmentMapper.java | 22 ++++++ .../mappers/v1/AssessmentStudentMapper.java | 24 ++++-- .../v1/AssessmentStudentSessionMapper.java | 50 ++++++++++++ .../api/mappers/{ => v1}/SessionMapper.java | 18 +---- .../eas/api/model/v1/AssessmentEntity.java | 49 ++++++++++++ .../api/model/v1/AssessmentStudentEntity.java | 15 ++-- .../educ/eas/api/model/v1/EasSagaEntity.java | 5 +- .../api/model/v1/SagaEventStatesEntity.java | 5 +- .../educ/eas/api/model/v1/SessionEntity.java | 5 +- ...tity.java => StudentStatusCodeEntity.java} | 9 ++- .../repository/v1/AssessmentRepository.java | 17 ++++ .../v1/AssessmentStudentRepository.java | 6 -- .../service/v1/AssessmentStudentService.java | 70 ++++++----------- .../educ/eas/api/service/v1/SagaService.java | 4 +- .../bc/gov/educ/eas/api/struct/OnCreate.java | 4 + .../bc/gov/educ/eas/api/struct/OnUpdate.java | 4 + .../educ/eas/api/struct/v1/Assessment.java | 30 +++++++ .../eas/api/struct/v1/AssessmentStudent.java | 58 ++++++++------ .../gov/educ/eas/api/struct/v1/Session.java | 3 - .../validator/AssessmentStudentValidator.java | 42 ++++++---- .../educ/eas/api/validator/EnumValidator.java | 27 +++++++ .../api/validator/constraint/IsValidEnum.java | 23 ++++++ .../db/migration/V1.0.1__EAS.API.sql | 37 +++++++++ .../bc/gov/educ/eas/api/BaseEasAPITest.java | 19 +++-- .../v1/AssessmentStudentControllerTest.java | 45 +++++++---- .../{ => v1}/SessionControllerTest.java | 4 +- .../v1/AssessmentStudentServiceTest.java | 78 ++++++++----------- 31 files changed, 499 insertions(+), 240 deletions(-) create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentMapper.java create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentSessionMapper.java rename api/src/main/java/ca/bc/gov/educ/eas/api/mappers/{ => v1}/SessionMapper.java (63%) create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentEntity.java rename api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/{CourseStatusCodeEntity.java => StudentStatusCodeEntity.java} (87%) create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentRepository.java create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnCreate.java create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnUpdate.java create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Assessment.java create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/validator/EnumValidator.java create mode 100644 api/src/main/java/ca/bc/gov/educ/eas/api/validator/constraint/IsValidEnum.java create mode 100644 api/src/main/resources/db/migration/V1.0.1__EAS.API.sql rename api/src/test/java/ca/bc/gov/educ/eas/api/controller/{ => v1}/SessionControllerTest.java (97%) diff --git a/api/pom.xml b/api/pom.xml index d75a857..c50126d 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -27,7 +27,7 @@ ${java.version} ${java.version} 1.6.2 - 4.20.0 + 5.16.0 1.6.9 2.11.0 42.7.3 @@ -87,6 +87,10 @@ org.flywaydb flyway-core + + org.flywaydb + flyway-database-postgresql + org.postgresql postgresql diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentController.java b/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentController.java index effc6b0..e74fd47 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentController.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentController.java @@ -27,13 +27,14 @@ public class AssessmentStudentController implements AssessmentStudentEndpoint { private final AssessmentStudentService studentService; private final AssessmentStudentValidator validator; private final AssessmentStudentSearchService searchService; + private final AssessmentStudentMapper mapper; - private static final AssessmentStudentMapper mapper = AssessmentStudentMapper.mapper; @Autowired - public AssessmentStudentController(AssessmentStudentService assessmentStudentService, AssessmentStudentValidator validator, AssessmentStudentSearchService searchService) { + public AssessmentStudentController(AssessmentStudentService assessmentStudentService, AssessmentStudentValidator validator, AssessmentStudentSearchService searchService, AssessmentStudentMapper mapper) { this.studentService = assessmentStudentService; this.validator = validator; this.searchService = searchService; + this.mapper = mapper; } @Override @@ -43,14 +44,14 @@ public AssessmentStudent readStudent(UUID assessmentStudentID) { @Override public AssessmentStudent updateStudent(AssessmentStudent assessmentStudent, UUID assessmentStudentID) { - ValidationUtil.validatePayload(() -> validator.validatePayload(assessmentStudent, false)); + ValidationUtil.validatePayload(() -> validator.validatePayload(mapper.mapAssessment(assessmentStudent), false)); RequestUtil.setAuditColumnsForUpdate(assessmentStudent); return mapper.toStructure(studentService.updateStudent(mapper.toModel(assessmentStudent))); } @Override public AssessmentStudent createStudent(AssessmentStudent assessmentStudent) { - ValidationUtil.validatePayload(() -> validator.validatePayload(assessmentStudent, true)); + ValidationUtil.validatePayload(() -> validator.validatePayload(mapper.mapAssessment(assessmentStudent), true)); RequestUtil.setAuditColumnsForCreate(assessmentStudent); return mapper.toStructure(studentService.createStudent(mapper.toModel(assessmentStudent))); } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/SessionController.java b/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/SessionController.java index 0c2c968..e133395 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/SessionController.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/controller/v1/SessionController.java @@ -1,7 +1,7 @@ package ca.bc.gov.educ.eas.api.controller.v1; import ca.bc.gov.educ.eas.api.endpoint.v1.SessionEndpoint; -import ca.bc.gov.educ.eas.api.mappers.SessionMapper; +import ca.bc.gov.educ.eas.api.mappers.v1.SessionMapper; import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; import ca.bc.gov.educ.eas.api.service.v1.SessionService; import ca.bc.gov.educ.eas.api.struct.v1.Session; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/endpoint/v1/AssessmentStudentEndpoint.java b/api/src/main/java/ca/bc/gov/educ/eas/api/endpoint/v1/AssessmentStudentEndpoint.java index c356e44..3a0997e 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/endpoint/v1/AssessmentStudentEndpoint.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/endpoint/v1/AssessmentStudentEndpoint.java @@ -1,9 +1,12 @@ package ca.bc.gov.educ.eas.api.endpoint.v1; import ca.bc.gov.educ.eas.api.constants.v1.URL; +import ca.bc.gov.educ.eas.api.struct.OnCreate; +import ca.bc.gov.educ.eas.api.struct.OnUpdate; import ca.bc.gov.educ.eas.api.struct.v1.AssessmentStudent; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.groups.Default; import org.springframework.data.domain.Page; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; @@ -16,28 +19,28 @@ @RequestMapping(URL.BASE_URL_STUDENT) public interface AssessmentStudentEndpoint { - @GetMapping("/{assessmentStudentID}") - @PreAuthorize("hasAuthority('SCOPE_READ_EAS_STUDENT')") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) - AssessmentStudent readStudent(@PathVariable UUID assessmentStudentID); - - @PutMapping("/{assessmentStudentID}") - @PreAuthorize("hasAuthority('SCOPE_WRITE_EAS_STUDENT')") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) - AssessmentStudent updateStudent(@Validated @RequestBody AssessmentStudent assessmentStudent, @PathVariable UUID assessmentStudentID); - - @PostMapping - @PreAuthorize("hasAuthority('SCOPE_WRITE_EAS_STUDENT')") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) - AssessmentStudent createStudent(@Validated @RequestBody AssessmentStudent assessmentStudent); - - @GetMapping(URL.PAGINATED) - @PreAuthorize("hasAuthority('SCOPE_READ_EAS_STUDENT')") - @Transactional(readOnly = true) - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) - CompletableFuture> findAll(@RequestParam(name = "pageNumber", defaultValue = "0") Integer pageNumber, - @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, - @RequestParam(name = "sort", defaultValue = "") String sortCriteriaJson, - @RequestParam(name = "searchCriteriaList", required = false) String searchCriteriaListJson); + @GetMapping("/{assessmentStudentID}") + @PreAuthorize("hasAuthority('SCOPE_READ_EAS_STUDENT')") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) + AssessmentStudent readStudent(@PathVariable UUID assessmentStudentID); + + @PutMapping("/{assessmentStudentID}") + @PreAuthorize("hasAuthority('SCOPE_WRITE_EAS_STUDENT')") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) + AssessmentStudent updateStudent(@Validated({Default.class, OnUpdate.class}) @RequestBody AssessmentStudent assessmentStudent, @PathVariable UUID assessmentStudentID); + + @PostMapping + @PreAuthorize("hasAuthority('SCOPE_WRITE_EAS_STUDENT')") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) + AssessmentStudent createStudent(@Validated({Default.class, OnCreate.class}) @RequestBody AssessmentStudent assessmentStudent); + + @GetMapping(URL.PAGINATED) + @PreAuthorize("hasAuthority('SCOPE_READ_EAS_STUDENT')") + @Transactional(readOnly = true) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")}) + CompletableFuture> findAll(@RequestParam(name = "pageNumber", defaultValue = "0") Integer pageNumber, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + @RequestParam(name = "sort", defaultValue = "") String sortCriteriaJson, + @RequestParam(name = "searchCriteriaList", required = false) String searchCriteriaListJson); } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentMapper.java b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentMapper.java new file mode 100644 index 0000000..f68a0aa --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentMapper.java @@ -0,0 +1,22 @@ +package ca.bc.gov.educ.eas.api.mappers.v1; + +import ca.bc.gov.educ.eas.api.mappers.LocalDateTimeMapper; +import ca.bc.gov.educ.eas.api.mappers.UUIDMapper; +import ca.bc.gov.educ.eas.api.model.v1.AssessmentEntity; +import ca.bc.gov.educ.eas.api.struct.v1.Assessment; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper(uses = {UUIDMapper.class, LocalDateTimeMapper.class}) +public interface AssessmentMapper { + + AssessmentMapper mapper = Mappers.getMapper(AssessmentMapper.class); + + @Mapping(target = "session.sessionID", source = "sessionEntity.sessionID") + Assessment toStructure(AssessmentEntity entity); + + @Mapping(target = "sessionEntity.sessionID", source = "session.sessionID") + AssessmentEntity toEntity(Assessment session); + +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentMapper.java b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentMapper.java index abd22ee..2b1098c 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentMapper.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentMapper.java @@ -4,18 +4,32 @@ import ca.bc.gov.educ.eas.api.mappers.UUIDMapper; import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; import ca.bc.gov.educ.eas.api.struct.v1.AssessmentStudent; +import ca.bc.gov.educ.eas.api.util.TransformUtil; +import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; import org.mapstruct.factory.Mappers; @Mapper(uses = {UUIDMapper.class, LocalDateTimeMapper.class}) public interface AssessmentStudentMapper { - AssessmentStudentMapper mapper = Mappers.getMapper(AssessmentStudentMapper.class); + AssessmentStudentMapper mapper = Mappers.getMapper(AssessmentStudentMapper.class); - @Mapping(target = "sessionID", source = "sessionEntity.sessionID") - AssessmentStudent toStructure(AssessmentStudentEntity entity); + @Mapping(target = "assessmentID", source = "assessmentEntity.assessmentID") + @Mapping(target = "sessionID", source = "assessmentEntity.sessionEntity.sessionID") + @Mapping(target = "assessmentTypeCode", source = "assessmentEntity.assessmentTypeCode") + AssessmentStudent toStructure(AssessmentStudentEntity entity); - @Mapping(target = "sessionEntity.sessionID", source = "sessionID") - AssessmentStudentEntity toModel(AssessmentStudent assessmentStudent); + AssessmentStudent mapAssessment(AssessmentStudent assessmentStudent); + + @Mapping(target = "assessmentEntity.assessmentID", source = "assessmentID") + @Mapping(target = "assessmentEntity.sessionEntity.sessionID", source = "sessionID") + @Mapping(target = "assessmentEntity.assessmentTypeCode", source = "assessmentTypeCode") + AssessmentStudentEntity toModel(AssessmentStudent assessmentStudent); + + @AfterMapping + default void transformToUpperCase(AssessmentStudentEntity assessmentStudentEntity, @MappingTarget AssessmentStudent.AssessmentStudentBuilder assessmentStudent) { + TransformUtil.uppercaseFields(assessmentStudentEntity); + } } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentSessionMapper.java b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentSessionMapper.java new file mode 100644 index 0000000..c066e95 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/AssessmentStudentSessionMapper.java @@ -0,0 +1,50 @@ +package ca.bc.gov.educ.eas.api.mappers.v1; + +import ca.bc.gov.educ.eas.api.model.v1.AssessmentEntity; +import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; +import ca.bc.gov.educ.eas.api.repository.v1.AssessmentRepository; +import ca.bc.gov.educ.eas.api.struct.v1.AssessmentStudent; +import io.micrometer.common.util.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Optional; +import java.util.UUID; + +@Component +public class AssessmentStudentSessionMapper implements AssessmentStudentMapper { + + private final AssessmentRepository assessmentRepository; + + @Autowired + public AssessmentStudentSessionMapper(AssessmentRepository assessmentRepository) { + this.assessmentRepository = assessmentRepository; + } + + @Override + public AssessmentStudent toStructure(AssessmentStudentEntity entity) { + return mapper.toStructure(entity); + } + + @Override + public AssessmentStudent mapAssessment(AssessmentStudent assessmentStudent) { + Optional assessmentEntity; + if (StringUtils.isNotEmpty(assessmentStudent.getAssessmentID())) { + assessmentEntity = assessmentRepository.findById(UUID.fromString(assessmentStudent.getAssessmentID())); + } else { + assessmentEntity = assessmentRepository.findBySessionIdAndAssessmentType(UUID.fromString(assessmentStudent.getSessionID()), assessmentStudent.getAssessmentTypeCode()); + } + if (assessmentEntity.isPresent()) { + assessmentStudent.setAssessmentID(assessmentEntity.get().getAssessmentID().toString()); + } else { + assessmentStudent.setAssessmentID(null); + } + return assessmentStudent; + } + + @Override + public AssessmentStudentEntity toModel(AssessmentStudent assessmentStudent) { + return mapper.toModel(assessmentStudent); + } + +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/SessionMapper.java b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/SessionMapper.java similarity index 63% rename from api/src/main/java/ca/bc/gov/educ/eas/api/mappers/SessionMapper.java rename to api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/SessionMapper.java index dae0894..6bc80e4 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/SessionMapper.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/mappers/v1/SessionMapper.java @@ -1,5 +1,7 @@ -package ca.bc.gov.educ.eas.api.mappers; +package ca.bc.gov.educ.eas.api.mappers.v1; +import ca.bc.gov.educ.eas.api.mappers.LocalDateTimeMapper; +import ca.bc.gov.educ.eas.api.mappers.UUIDMapper; import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; import ca.bc.gov.educ.eas.api.struct.v1.Session; import org.mapstruct.BeanMapping; @@ -8,28 +10,14 @@ import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.factory.Mappers; -/** - * Mapper for converting between SessionEntity and Session DTO. - */ @Mapper(uses = {UUIDMapper.class, LocalDateTimeMapper.class}) public interface SessionMapper { SessionMapper mapper = Mappers.getMapper(SessionMapper.class); - /** - * Conversion from Session Entity to DTO. - * @param entity SessionEntity - * @return Session - */ @Mapping(source = "courseSession", target = "courseSession") - @Mapping(source = "statusCode", target = "status") Session toStructure(SessionEntity entity); - /** - * Conversion from Session DTO to Entity. - * @param session Session - * @return SessionEntity - */ @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) SessionEntity toEntity(Session session); diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentEntity.java b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentEntity.java new file mode 100644 index 0000000..00f0261 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentEntity.java @@ -0,0 +1,49 @@ +package ca.bc.gov.educ.eas.api.model.v1; + +import jakarta.persistence.*; +import jakarta.validation.constraints.PastOrPresent; +import lombok.*; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.UuidGenerator; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@DynamicUpdate +@Entity +@Builder +@Table(name = "ASSESSMENT") +public class AssessmentEntity { + + @Id + @GeneratedValue(generator = "UUID") + @UuidGenerator + @Column(name = "ASSESSMENT_ID", unique = true, updatable = false, columnDefinition = "BINARY(16)") + private UUID assessmentID; + + @ToString.Exclude + @EqualsAndHashCode.Exclude + @ManyToOne(optional = false, targetEntity = SessionEntity.class) + @JoinColumn(name = "SESSION_ID", referencedColumnName = "SESSION_ID", updatable = false) + SessionEntity sessionEntity; + + @Column(name = "ASSESSMENT_TYPE_CODE", nullable = false, length = 10) + private String assessmentTypeCode; + + @Column(name = "CREATE_USER", updatable = false, length = 100) + private String createUser; + + @PastOrPresent + @Column(name = "CREATE_DATE", updatable = false) + private LocalDateTime createDate; + + @Column(name = "UPDATE_USER", nullable = false, length = 100) + private String updateUser; + + @PastOrPresent + @Column(name = "UPDATE_DATE", nullable = false) + private LocalDateTime updateDate; +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentStudentEntity.java b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentStudentEntity.java index a943255..adcacd5 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentStudentEntity.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/AssessmentStudentEntity.java @@ -5,8 +5,7 @@ import jakarta.validation.constraints.PastOrPresent; import lombok.*; import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Parameter; +import org.hibernate.annotations.UuidGenerator; import java.time.LocalDateTime; import java.util.UUID; @@ -23,19 +22,15 @@ public class AssessmentStudentEntity { @Id @GeneratedValue(generator = "UUID") - @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator", parameters = { - @Parameter(name = "uuid_gen_strategy_class", value = "org.hibernate.id.uuid.CustomVersionOneStrategy")}) + @UuidGenerator @Column(name = "ASSESSMENT_STUDENT_ID", unique = true, updatable = false, columnDefinition = "BINARY(16)") private UUID assessmentStudentID; @ToString.Exclude @EqualsAndHashCode.Exclude - @ManyToOne(optional = false, targetEntity = SessionEntity.class) - @JoinColumn(name = "SESSION_ID", referencedColumnName = "SESSION_ID", updatable = false) - SessionEntity sessionEntity; - - @Column(name = "ASSESSMENT_TYPE_CODE", nullable = false, length = 10) - private String assessmentTypeCode; + @ManyToOne(optional = false, targetEntity = AssessmentEntity.class) + @JoinColumn(name = "ASSESSMENT_ID", referencedColumnName = "ASSESSMENT_ID", updatable = false) + AssessmentEntity assessmentEntity; @Column(name = "SCHOOL_ID", nullable = false, columnDefinition = "BINARY(16)") private UUID schoolID; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/EasSagaEntity.java b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/EasSagaEntity.java index 9784072..57db35c 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/EasSagaEntity.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/EasSagaEntity.java @@ -9,7 +9,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.UuidGenerator; import java.time.LocalDateTime; import java.util.UUID; @@ -28,8 +28,7 @@ public class EasSagaEntity { @Id @GeneratedValue(generator = "UUID") - @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator", parameters = { - @org.hibernate.annotations.Parameter(name = "uuid_gen_strategy_class", value = "org.hibernate.id.uuid.CustomVersionOneStrategy")}) + @UuidGenerator @Column(name = "SAGA_ID", unique = true, updatable = false, columnDefinition = "BINARY(16)") UUID sagaId; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SagaEventStatesEntity.java b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SagaEventStatesEntity.java index f9d3d42..a1a62b8 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SagaEventStatesEntity.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SagaEventStatesEntity.java @@ -6,7 +6,7 @@ import jakarta.validation.constraints.Size; import lombok.*; import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.UuidGenerator; import java.time.LocalDateTime; import java.util.UUID; @@ -29,8 +29,7 @@ public class SagaEventStatesEntity { */ @Id @GeneratedValue(generator = "UUID") - @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator", parameters = { - @org.hibernate.annotations.Parameter(name = "uuid_gen_strategy_class", value = "org.hibernate.id.uuid.CustomVersionOneStrategy")}) + @UuidGenerator @Column(name = "SAGA_EVENT_ID", unique = true, updatable = false, columnDefinition = "BINARY(16)") UUID sagaEventId; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SessionEntity.java b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SessionEntity.java index 226c57c..630f425 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SessionEntity.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/SessionEntity.java @@ -18,7 +18,7 @@ @DynamicUpdate @Entity @Builder -@Table(name = "SESSION") +@Table(name = "ASSESSMENT_SESSION") public class SessionEntity { @Id @@ -36,9 +36,6 @@ public class SessionEntity { @Column(name = "COURSE_MONTH", nullable = false, length = 2) private String courseMonth; - @Column(name = "STATUS_CODE", nullable = false, length = 10) - private String statusCode; - @Column(name = "ACTIVE_FROM_DATE", nullable = false) private LocalDateTime activeFromDate; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/CourseStatusCodeEntity.java b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/StudentStatusCodeEntity.java similarity index 87% rename from api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/CourseStatusCodeEntity.java rename to api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/StudentStatusCodeEntity.java index d0e7c4a..a36668c 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/CourseStatusCodeEntity.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/model/v1/StudentStatusCodeEntity.java @@ -20,12 +20,13 @@ @Builder @DynamicUpdate @Entity -@Table(name = "COURSE_STATUS_CODE") +@Table(name = "STUDENT_STATUS_CODE") @JsonIgnoreProperties(ignoreUnknown = true) -public class CourseStatusCodeEntity { +public class StudentStatusCodeEntity { + @Id - @Column(name = "COURSE_STATUS_CODE", unique = true, length = 10) - private String courseStatusCode; + @Column(name = "STUDENT_STATUS_CODE", unique = true, length = 10) + private String studentStatusCode; @Column(name = "LABEL", length = 30) private String label; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentRepository.java b/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentRepository.java new file mode 100644 index 0000000..0003dcc --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentRepository.java @@ -0,0 +1,17 @@ +package ca.bc.gov.educ.eas.api.repository.v1; + +import ca.bc.gov.educ.eas.api.model.v1.AssessmentEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface AssessmentRepository extends JpaRepository { + + @Query(value = "SELECT ASST FROM AssessmentEntity ASST WHERE ASST.sessionEntity.sessionID=:sessionID AND ASST.assessmentTypeCode =:assessmentTypeCode") + Optional findBySessionIdAndAssessmentType(UUID sessionID, String assessmentTypeCode); + +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentStudentRepository.java b/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentStudentRepository.java index dc288f7..97a4050 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentStudentRepository.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/repository/v1/AssessmentStudentRepository.java @@ -2,19 +2,13 @@ import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; -import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; -import java.util.Optional; import java.util.UUID; -/** - * The interface Saga event repository. - */ @Repository public interface AssessmentStudentRepository extends JpaRepository, JpaSpecificationExecutor { - Optional findBySessionEntityAndStudentID(SessionEntity sessionEntity, UUID studentID); } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentService.java b/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentService.java index 8488e4c..4ef5407 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentService.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentService.java @@ -2,12 +2,9 @@ import ca.bc.gov.educ.eas.api.exception.EntityNotFoundException; import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; -import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; import ca.bc.gov.educ.eas.api.repository.v1.AssessmentStudentRepository; -import ca.bc.gov.educ.eas.api.repository.v1.SessionRepository; import ca.bc.gov.educ.eas.api.struct.v1.AssessmentStudent; import ca.bc.gov.educ.eas.api.util.TransformUtil; -import jakarta.persistence.EntityExistsException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -15,63 +12,40 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; import java.util.UUID; @Service @Slf4j public class AssessmentStudentService { - private final AssessmentStudentRepository assessmentStudentRepository; - private final SessionRepository sessionRepository; + private final AssessmentStudentRepository assessmentStudentRepository; - @Autowired - public AssessmentStudentService(final AssessmentStudentRepository assessmentStudentRepository, SessionRepository sessionRepository) { - this.assessmentStudentRepository = assessmentStudentRepository; - this.sessionRepository = sessionRepository; - } - - public AssessmentStudentEntity getStudentByID(UUID assessmentStudentID) { - return this.assessmentStudentRepository.findById(assessmentStudentID).orElseThrow(() -> - new EntityNotFoundException(AssessmentStudent.class, "assessmentStudentID", assessmentStudentID.toString()) - ); - } - - @Transactional(propagation = Propagation.REQUIRES_NEW) - public AssessmentStudentEntity updateStudent(AssessmentStudentEntity assessmentStudentEntity) { - AssessmentStudentEntity currentAssessmentStudentEntity = this.assessmentStudentRepository.findById(assessmentStudentEntity.getAssessmentStudentID()).orElseThrow(() -> - new EntityNotFoundException(AssessmentStudentEntity.class, "AssessmentStudent", assessmentStudentEntity.getAssessmentStudentID().toString()) - ); + @Autowired + public AssessmentStudentService(final AssessmentStudentRepository assessmentStudentRepository) { + this.assessmentStudentRepository = assessmentStudentRepository; + } - SessionEntity sessionEntity = this.sessionRepository.findById(assessmentStudentEntity.getSessionEntity().getSessionID()).orElseThrow(() -> - new EntityNotFoundException(SessionEntity.class, "sessionID", assessmentStudentEntity.getSessionEntity().getSessionID().toString()) - ); + public AssessmentStudentEntity getStudentByID(UUID assessmentStudentID) { + return assessmentStudentRepository.findById(assessmentStudentID).orElseThrow(() -> + new EntityNotFoundException(AssessmentStudent.class, "assessmentStudentID", assessmentStudentID.toString()) + ); + } - Optional optionalExistingStudent = assessmentStudentRepository.findBySessionEntityAndStudentID(sessionEntity, assessmentStudentEntity.getStudentID()); + @Transactional(propagation = Propagation.REQUIRES_NEW) + public AssessmentStudentEntity updateStudent(AssessmentStudentEntity assessmentStudentEntity) { + AssessmentStudentEntity currentAssessmentStudentEntity = assessmentStudentRepository.findById(assessmentStudentEntity.getAssessmentStudentID()).orElseThrow(() -> + new EntityNotFoundException(AssessmentStudentEntity.class, "AssessmentStudent", assessmentStudentEntity.getAssessmentStudentID().toString()) + ); - //If their already exists this student id in the session that is not the assessment student being updated - if(optionalExistingStudent.isPresent() && !optionalExistingStudent.get().getAssessmentStudentID().equals(assessmentStudentEntity.getAssessmentStudentID())) { - throw new EntityExistsException("Assessment student with StudentID::"+assessmentStudentEntity.getStudentID()+" and Session ID::"+sessionEntity.getSessionID()+" already exists"); - } else { - BeanUtils.copyProperties(assessmentStudentEntity, currentAssessmentStudentEntity, "createUser", "createDate"); - TransformUtil.uppercaseFields(currentAssessmentStudentEntity); - return assessmentStudentRepository.save(currentAssessmentStudentEntity); + BeanUtils.copyProperties(assessmentStudentEntity, currentAssessmentStudentEntity, "assessmentEntity", "createUser", "createDate"); + TransformUtil.uppercaseFields(currentAssessmentStudentEntity); + return assessmentStudentRepository.save(currentAssessmentStudentEntity); } - } - @Transactional(propagation = Propagation.REQUIRES_NEW) - public AssessmentStudentEntity createStudent(AssessmentStudentEntity assessmentStudentEntity) { - SessionEntity sessionEntity = this.sessionRepository.findById(assessmentStudentEntity.getSessionEntity().getSessionID()).orElseThrow(() -> - new EntityNotFoundException(SessionEntity.class, "sessionID", assessmentStudentEntity.getSessionEntity().getSessionID().toString()) - ); + @Transactional(propagation = Propagation.REQUIRES_NEW) + public AssessmentStudentEntity createStudent(AssessmentStudentEntity assessmentStudentEntity) { + return assessmentStudentRepository.save(assessmentStudentEntity); + } - Optional optionalExistingStudent = assessmentStudentRepository.findBySessionEntityAndStudentID(sessionEntity, assessmentStudentEntity.getStudentID()); - if(optionalExistingStudent.isEmpty()) { - TransformUtil.uppercaseFields(assessmentStudentEntity); - return assessmentStudentRepository.save(assessmentStudentEntity); - } else { - throw new EntityExistsException("Assessment student with StudentID::"+assessmentStudentEntity.getStudentID()+" and Session ID::"+sessionEntity.getSessionID()+" already exists"); - } - } } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/SagaService.java b/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/SagaService.java index 531d42d..820a5eb 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/SagaService.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/service/v1/SagaService.java @@ -156,12 +156,12 @@ public EasSagaEntity createSagaRecordInDB(final String sagaName, final String us .updateUser(userName) .updateDate(LocalDateTime.now()) .build(); - return this.createSagaRecord(saga); + return createSagaRecord(saga); } @Transactional(propagation = Propagation.REQUIRES_NEW) public List createSagaRecordsInDB(final List easSagaEntities) { - return this.createSagaRecords(easSagaEntities); + return createSagaRecords(easSagaEntities); } /** diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnCreate.java b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnCreate.java new file mode 100644 index 0000000..9f43bd7 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnCreate.java @@ -0,0 +1,4 @@ +package ca.bc.gov.educ.eas.api.struct; + +public interface OnCreate { +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnUpdate.java b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnUpdate.java new file mode 100644 index 0000000..e09bb93 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/OnUpdate.java @@ -0,0 +1,4 @@ +package ca.bc.gov.educ.eas.api.struct; + +public interface OnUpdate { +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Assessment.java b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Assessment.java new file mode 100644 index 0000000..f4b42d1 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Assessment.java @@ -0,0 +1,30 @@ +package ca.bc.gov.educ.eas.api.struct.v1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.springframework.data.annotation.ReadOnlyProperty; + +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class Assessment extends BaseRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @ReadOnlyProperty + private String assessmentID; + + @ReadOnlyProperty + private Session session; + + @ReadOnlyProperty + private String assessmentTypeCode; + +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/AssessmentStudent.java b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/AssessmentStudent.java index d892d01..3324254 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/AssessmentStudent.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/AssessmentStudent.java @@ -1,7 +1,12 @@ package ca.bc.gov.educ.eas.api.struct.v1; +import ca.bc.gov.educ.eas.api.constants.v1.AssessmentTypeCodes; +import ca.bc.gov.educ.eas.api.constants.v1.CourseStatusCodes; +import ca.bc.gov.educ.eas.api.constants.v1.ProvincialSpecialCaseCodes; +import ca.bc.gov.educ.eas.api.struct.OnUpdate; +import ca.bc.gov.educ.eas.api.validator.constraint.IsValidEnum; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,38 +21,43 @@ @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class AssessmentStudent extends BaseRequest implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private String assessmentStudentID; + @NotBlank(groups = OnUpdate.class, message = "assessmentStudentID cannot be null ") + private String assessmentStudentID; - @NotNull(message = "sessionID cannot be null") - private String sessionID; + @NotBlank(message = "sessionID cannot be null") + private String sessionID; - @NotNull(message = "assessmentTypeCode cannot be null") - @Size(max = 10) - private String assessmentTypeCode; + @Size(max = 10) + @IsValidEnum(enumClass = AssessmentTypeCodes.class, message = "Invalid assessment type code.") + private String assessmentTypeCode; - @NotNull(message = "schoolID cannot be null") - private String schoolID; + private String assessmentID; - @NotNull(message = "studentID cannot be null") - private String studentID; + @NotBlank(message = "schoolID cannot be null") + private String schoolID; - @NotNull(message = "pen cannot be null") - @Size(max = 9) - private String pen; + @NotBlank(message = "studentID cannot be null") + private String studentID; - @Size(max = 12) - private String localID; + @NotBlank(message = "pen cannot be null") + @Size(max = 9) + private String pen; - private Boolean isElectronicExam; + @Size(max = 12) + private String localID; - @Size(max = 3) - private String finalPercentage; + private Boolean isElectronicExam; - @Size(max = 1) - private String provincialSpecialCaseCode; + @Size(max = 3) + private String finalPercentage; - @Size(max = 1) - private String courseStatusCode; + @Size(max = 1) + @IsValidEnum(enumClass = ProvincialSpecialCaseCodes.class, message = "Invalid provincial special case code.") + private String provincialSpecialCaseCode; + + @Size(max = 1) + @IsValidEnum(enumClass = CourseStatusCodes.class, message = "Invalid course status code.") + private String courseStatusCode; } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Session.java b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Session.java index e5d9a35..e147157 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Session.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/struct/v1/Session.java @@ -35,9 +35,6 @@ public class Session extends BaseRequest implements Serializable { @ReadOnlyProperty private Integer courseYear; - @ReadOnlyProperty - private String status; - @NotNull(message = "activeFromDate cannot be null") private LocalDateTime activeFromDate; diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/validator/AssessmentStudentValidator.java b/api/src/main/java/ca/bc/gov/educ/eas/api/validator/AssessmentStudentValidator.java index 6a0ce63..3dfd0ff 100644 --- a/api/src/main/java/ca/bc/gov/educ/eas/api/validator/AssessmentStudentValidator.java +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/validator/AssessmentStudentValidator.java @@ -1,12 +1,8 @@ package ca.bc.gov.educ.eas.api.validator; -import ca.bc.gov.educ.eas.api.constants.v1.AssessmentTypeCodes; -import ca.bc.gov.educ.eas.api.constants.v1.CourseStatusCodes; -import ca.bc.gov.educ.eas.api.constants.v1.ProvincialSpecialCaseCodes; import ca.bc.gov.educ.eas.api.struct.v1.AssessmentStudent; import ca.bc.gov.educ.eas.api.util.PenUtil; import ca.bc.gov.educ.eas.api.util.ValidationUtil; -import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.validation.FieldError; @@ -14,31 +10,45 @@ import java.util.ArrayList; import java.util.List; + @Component public class AssessmentStudentValidator { public static final String ASSESSMENT_STUDENT = "assessmentStudent"; + public List validatePayload(AssessmentStudent assessmentStudent, boolean isCreateOperation) { final List apiValidationErrors = new ArrayList<>(); - if(isCreateOperation && StringUtils.isNotEmpty(assessmentStudent.getAssessmentStudentID())) { - apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "assessmentStudentID", assessmentStudent.getAssessmentStudentID(), "assessmentStudentID should be null for post operation.")); - } - if (!isCreateOperation && StringUtils.isEmpty(assessmentStudent.getAssessmentStudentID())) { - apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "assessmentStudentID", null, "assessmentStudentID cannot be null for put operation.")); - } if (StringUtils.isNotEmpty(assessmentStudent.getPen()) && !PenUtil.validCheckDigit(assessmentStudent.getPen())) { apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "pen", assessmentStudent.getPen(), "Invalid Student Pen.")); } - if (!EnumUtils.isValidEnum(AssessmentTypeCodes.class, assessmentStudent.getAssessmentTypeCode())) { - apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "assessmentTypeCode", assessmentStudent.getAssessmentTypeCode(), "Invalid assessment type code.")); + + if (StringUtils.isEmpty(assessmentStudent.getAssessmentID())) { + apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "session", assessmentStudent.getSessionID(), "Invalid assessment session.")); } - if (assessmentStudent.getProvincialSpecialCaseCode() != null && !EnumUtils.isValidEnum(ProvincialSpecialCaseCodes.class, assessmentStudent.getProvincialSpecialCaseCode())) { - apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "provincialSpecialCaseCode", assessmentStudent.getProvincialSpecialCaseCode(), "Invalid provincial special case code.")); + + if (isCreateOperation) { + apiValidationErrors.addAll(validateCreatePayload(assessmentStudent)); + } else { + apiValidationErrors.addAll(validateUpdatePayload(assessmentStudent)); + } + return apiValidationErrors; + } + + List validateCreatePayload(AssessmentStudent assessmentStudent) { + final List apiValidationErrors = new ArrayList<>(); + if (StringUtils.isNotEmpty(assessmentStudent.getAssessmentStudentID())) { + apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "assessmentStudentID", assessmentStudent.getAssessmentStudentID(), "assessmentStudentID should be null for post operation.")); } - if (assessmentStudent.getCourseStatusCode() != null && !EnumUtils.isValidEnum(CourseStatusCodes.class, assessmentStudent.getCourseStatusCode())) { - apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "courseStatusCode", assessmentStudent.getCourseStatusCode(), "Invalid course status code.")); + return apiValidationErrors; + } + + List validateUpdatePayload(AssessmentStudent assessmentStudent) { + final List apiValidationErrors = new ArrayList<>(); + if (StringUtils.isEmpty(assessmentStudent.getAssessmentStudentID())) { + apiValidationErrors.add(ValidationUtil.createFieldError(ASSESSMENT_STUDENT, "assessmentStudentID", null, "assessmentStudentID cannot be null for put operation.")); } return apiValidationErrors; } + } diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/validator/EnumValidator.java b/api/src/main/java/ca/bc/gov/educ/eas/api/validator/EnumValidator.java new file mode 100644 index 0000000..aa24f88 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/validator/EnumValidator.java @@ -0,0 +1,27 @@ +package ca.bc.gov.educ.eas.api.validator; + +import ca.bc.gov.educ.eas.api.validator.constraint.IsValidEnum; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.apache.commons.lang3.EnumUtils; + +public class EnumValidator implements ConstraintValidator { + + private Class enumClass; + + private EnumValidator() { + } + + @Override + public void initialize(IsValidEnum annotation) { + this.enumClass = annotation.enumClass(); + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null || value.isEmpty()) { + return true; + } + return EnumUtils.isValidEnum(enumClass, value); + } +} diff --git a/api/src/main/java/ca/bc/gov/educ/eas/api/validator/constraint/IsValidEnum.java b/api/src/main/java/ca/bc/gov/educ/eas/api/validator/constraint/IsValidEnum.java new file mode 100644 index 0000000..f8f9aba --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/eas/api/validator/constraint/IsValidEnum.java @@ -0,0 +1,23 @@ +package ca.bc.gov.educ.eas.api.validator.constraint; + +import ca.bc.gov.educ.eas.api.validator.EnumValidator; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = EnumValidator.class) +public @interface IsValidEnum { + String message() default "Invalid value"; + + Class enumClass(); + + Class[] groups() default {}; + + Class[] payload() default {}; +} \ No newline at end of file diff --git a/api/src/main/resources/db/migration/V1.0.1__EAS.API.sql b/api/src/main/resources/db/migration/V1.0.1__EAS.API.sql new file mode 100644 index 0000000..f3c01e2 --- /dev/null +++ b/api/src/main/resources/db/migration/V1.0.1__EAS.API.sql @@ -0,0 +1,37 @@ +ALTER TABLE SESSION RENAME TO ASSESSMENT_SESSION; + +ALTER TABLE COURSE_STATUS_CODE RENAME TO STUDENT_STATUS_CODE; +ALTER TABLE STUDENT_STATUS_CODE RENAME COLUMN COURSE_STATUS_CODE TO STUDENT_STATUS_CODE; + +CREATE TABLE ASSESSMENT +( + ASSESSMENT_ID UUID NOT NULL, + SESSION_ID UUID NOT NULL, + ASSESSMENT_TYPE_CODE VARCHAR(10) NOT NULL, + CREATE_USER VARCHAR(100) NOT NULL, + CREATE_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, + UPDATE_USER VARCHAR(100) NOT NULL, + UPDATE_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT ASSESSMENT_ID_PK PRIMARY KEY (ASSESSMENT_ID), + CONSTRAINT FK_ASSESSMENT_TYPE_CODE FOREIGN KEY (ASSESSMENT_TYPE_CODE) REFERENCES ASSESSMENT_TYPE_CODE(ASSESSMENT_TYPE_CODE), + CONSTRAINT FK_ASSESSMENT_SESSION FOREIGN KEY (SESSION_ID) REFERENCES ASSESSMENT_SESSION(SESSION_ID) +); + +ALTER TABLE ASSESSMENT_STUDENT DROP CONSTRAINT FK_ASSESSMENT_TYPE_CODE; +ALTER TABLE ASSESSMENT_STUDENT DROP CONSTRAINT FK_SESSION_ID; +ALTER TABLE ASSESSMENT_STUDENT DROP COLUMN SESSION_ID; +ALTER TABLE ASSESSMENT_STUDENT DROP COLUMN ASSESSMENT_TYPE_CODE; + +ALTER TABLE ASSESSMENT_STUDENT ADD COLUMN ASSESSMENT_ID UUID NOT NULL; +ALTER TABLE ASSESSMENT_STUDENT ADD CONSTRAINT FK_ASSESSMENT_ID FOREIGN KEY (ASSESSMENT_ID) REFERENCES ASSESSMENT(ASSESSMENT_ID); + +CREATE TABLE EAS_SHEDLOCK +( + NAME VARCHAR(64), + LOCK_UNTIL TIMESTAMP(3) NULL, + LOCKED_AT TIMESTAMP(3) NULL, + LOCKED_BY VARCHAR(255), + CONSTRAINT EAS_SHEDLOCK_PK PRIMARY KEY (NAME) +); + +COMMENT ON TABLE EAS_SHEDLOCK IS 'This table is used to achieve distributed lock between pods, for schedulers.'; diff --git a/api/src/test/java/ca/bc/gov/educ/eas/api/BaseEasAPITest.java b/api/src/test/java/ca/bc/gov/educ/eas/api/BaseEasAPITest.java index 307270c..a8b25ec 100644 --- a/api/src/test/java/ca/bc/gov/educ/eas/api/BaseEasAPITest.java +++ b/api/src/test/java/ca/bc/gov/educ/eas/api/BaseEasAPITest.java @@ -1,7 +1,7 @@ package ca.bc.gov.educ.eas.api; import ca.bc.gov.educ.eas.api.constants.v1.AssessmentTypeCodes; -import ca.bc.gov.educ.eas.api.constants.v1.StatusCodes; +import ca.bc.gov.educ.eas.api.model.v1.AssessmentEntity; import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; import ca.bc.gov.educ.eas.api.struct.external.institute.v1.*; @@ -54,7 +54,6 @@ public SessionEntity createMockSessionEntity() { .courseSession(Integer.toString(currentDate.getYear()) + Integer.toString(currentDate.getMonthValue())) .courseYear(Integer.toString(currentDate.getYear())) .courseMonth(Integer.toString(currentDate.getMonthValue())) - .statusCode(StatusCodes.OPEN.getCode()) .activeFromDate(currentDate.minusMonths(2)) .activeUntilDate(currentDate.plusMonths(2)) .createUser("ABC") @@ -64,6 +63,17 @@ public SessionEntity createMockSessionEntity() { .build(); } + public AssessmentEntity createMockAssessmentEntity(SessionEntity sessionEntity, String assessmentTypeCode) { + return AssessmentEntity.builder() + .sessionEntity(sessionEntity) + .assessmentTypeCode(assessmentTypeCode) + .createUser("ABC") + .createDate(LocalDateTime.now()) + .updateUser("ABC") + .updateDate(LocalDateTime.now()) + .build(); + } + public AssessmentStudent createMockStudent() { return AssessmentStudent.builder() .assessmentStudentID(UUID.randomUUID().toString()) @@ -76,11 +86,10 @@ public AssessmentStudent createMockStudent() { .build(); } - public AssessmentStudentEntity createMockStudentEntity(SessionEntity sessionEntity) { + public AssessmentStudentEntity createMockStudentEntity(AssessmentEntity assessmentEntity) { return AssessmentStudentEntity.builder() .assessmentStudentID(UUID.randomUUID()) - .sessionEntity(sessionEntity) - .assessmentTypeCode(AssessmentTypeCodes.LTP10.getCode()) + .assessmentEntity(assessmentEntity) .schoolID(UUID.randomUUID()) .studentID(UUID.randomUUID()) .pen("120164447") diff --git a/api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentControllerTest.java b/api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentControllerTest.java index 907b511..5478838 100644 --- a/api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentControllerTest.java +++ b/api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/AssessmentStudentControllerTest.java @@ -5,8 +5,10 @@ import ca.bc.gov.educ.eas.api.constants.v1.URL; import ca.bc.gov.educ.eas.api.filter.FilterOperation; import ca.bc.gov.educ.eas.api.mappers.v1.AssessmentStudentMapper; +import ca.bc.gov.educ.eas.api.model.v1.AssessmentEntity; import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; +import ca.bc.gov.educ.eas.api.repository.v1.AssessmentRepository; import ca.bc.gov.educ.eas.api.repository.v1.AssessmentStudentRepository; import ca.bc.gov.educ.eas.api.repository.v1.SessionRepository; import ca.bc.gov.educ.eas.api.struct.v1.*; @@ -44,11 +46,16 @@ class AssessmentStudentControllerTest extends BaseEasAPITest { @Autowired SessionRepository sessionRepository; + @Autowired + AssessmentRepository assessmentRepository; + @Autowired + AssessmentStudentMapper mapper; @AfterEach public void after() { this.studentRepository.deleteAll(); + this.assessmentRepository.deleteAll(); this.sessionRepository.deleteAll(); } @@ -58,7 +65,9 @@ void testReadStudent_GivenIDExists_ShouldReturnStudent() throws Exception { final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); SessionEntity session = sessionRepository.save(createMockSessionEntity()); - UUID assessmentStudentID = studentRepository.save(createMockStudentEntity(session)).getAssessmentStudentID(); + AssessmentEntity assessment = assessmentRepository.save(createMockAssessmentEntity(session, AssessmentTypeCodes.LTF12.getCode())); + + UUID assessmentStudentID = studentRepository.save(createMockStudentEntity(assessment)).getAssessmentStudentID(); this.mockMvc.perform( get(URL.BASE_URL_STUDENT + "/" + assessmentStudentID).with(mockAuthority)) @@ -84,7 +93,8 @@ void testReadStudent_GivenIncorrectScope_ShouldReturn403() throws Exception { final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); SessionEntity session = sessionRepository.save(createMockSessionEntity()); - UUID assessmentStudentID = studentRepository.save(createMockStudentEntity(session)).getAssessmentStudentID(); + AssessmentEntity assessment = assessmentRepository.save(createMockAssessmentEntity(session, AssessmentTypeCodes.LTF12.getCode())); + UUID assessmentStudentID = studentRepository.save(createMockStudentEntity(assessment)).getAssessmentStudentID(); this.mockMvc.perform( get(URL.BASE_URL_STUDENT + "/" + assessmentStudentID).with(mockAuthority)) @@ -107,7 +117,7 @@ void testUpdateStudent_GivenInvalidProvincialCaseCode_ShouldReturn400() throws E .with(mockAuthority)) .andDo(print()) .andExpect(status().isBadRequest()) - .andExpect(MockMvcResultMatchers.jsonPath("$.subErrors[0].field").value("provincialSpecialCaseCode")); + .andExpect(jsonPath("$.subErrors[?(@.field == 'provincialSpecialCaseCode')]").exists()); } @Test @@ -125,7 +135,7 @@ void testUpdateStudent_GivenNullID_ShouldReturn400() throws Exception { .with(mockAuthority)) .andDo(print()) .andExpect(status().isBadRequest()) - .andExpect(MockMvcResultMatchers.jsonPath("$.subErrors[0].field").value("assessmentStudentID")); + .andExpect(jsonPath("$.subErrors[?(@.field == 'assessmentStudentID')]").exists()); } @Test @@ -152,10 +162,15 @@ void testUpdateStudent_GivenValidPayload_ShouldReturnStudent() throws Exception final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); SessionEntity session = sessionRepository.save(createMockSessionEntity()); - AssessmentStudent student = AssessmentStudentMapper.mapper.toStructure(studentRepository.save(createMockStudentEntity(session))); + AssessmentEntity assessment = assessmentRepository.save(createMockAssessmentEntity(session, AssessmentTypeCodes.LTF12.getCode())); + AssessmentStudent student = mapper.toStructure(studentRepository.save(createMockStudentEntity(assessment))); + + student.setSessionID(assessment.getSessionEntity().getSessionID().toString()); + student.setAssessmentTypeCode(assessment.getAssessmentTypeCode()); student.setCreateDate(null); student.setUpdateDate(null); student.setUpdateUser(null); + student.setAssessmentID(null); this.mockMvc.perform( put(URL.BASE_URL_STUDENT + "/" + student.getAssessmentStudentID()) @@ -182,7 +197,7 @@ void testCreateStudent_GivenIDNotNull_ShouldReturn400() throws Exception { .with(mockAuthority)) .andDo(print()) .andExpect(status().isBadRequest()) - .andExpect(MockMvcResultMatchers.jsonPath("$.subErrors[0].field").value("assessmentStudentID")); + .andExpect(jsonPath("$.subErrors[?(@.field == 'assessmentStudentID')]").exists()); } @Test @@ -229,8 +244,11 @@ void testCreateStudent_GivenValidPayload_ShouldReturnStudent() throws Exception final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); SessionEntity session = sessionRepository.save(createMockSessionEntity()); - AssessmentStudent student = AssessmentStudentMapper.mapper.toStructure(createMockStudentEntity(session)); + assessmentRepository.save(createMockAssessmentEntity(session, AssessmentTypeCodes.LTF12.getCode())); + AssessmentStudent student = createMockStudent(); student.setAssessmentStudentID(null); + student.setSessionID(session.getSessionID().toString()); + student.setAssessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()); student.setCreateDate(null); student.setUpdateDate(null); student.setUpdateUser(null); @@ -253,16 +271,17 @@ void testFindAll_GivenAssessmentCodeAndSessionMonth_ShouldReturnStudent() throws SessionEntity session = createMockSessionEntity(); session.setCourseMonth("08"); SessionEntity sessionEntity = sessionRepository.save(session); - AssessmentStudentEntity student = createMockStudentEntity(sessionEntity); - student.setAssessmentTypeCode(AssessmentTypeCodes.LTP10.getCode()); + AssessmentEntity assessment = assessmentRepository.save(createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTP10.getCode())); + + AssessmentStudentEntity student = createMockStudentEntity(assessment); studentRepository.save(student); - AssessmentStudentEntity student2 = createMockStudentEntity(sessionEntity); - student2.setAssessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()); + AssessmentEntity assessment2 = assessmentRepository.save(createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTF12.getCode())); + AssessmentStudentEntity student2 = createMockStudentEntity(assessment2); studentRepository.save(student2); SearchCriteria criteriaAssessmentTypeCode = SearchCriteria.builder() - .key("assessmentTypeCode") + .key("assessmentEntity.assessmentTypeCode") .operation(FilterOperation.EQUAL) .value(AssessmentTypeCodes.LTP10.getCode()) .valueType(ValueType.STRING) @@ -270,7 +289,7 @@ void testFindAll_GivenAssessmentCodeAndSessionMonth_ShouldReturnStudent() throws SearchCriteria criteriaSessionMonth = SearchCriteria.builder() .condition(Condition.AND) - .key("sessionEntity.courseMonth") + .key("assessmentEntity.sessionEntity.courseMonth") .operation(FilterOperation.EQUAL) .value("08") .valueType(ValueType.STRING) diff --git a/api/src/test/java/ca/bc/gov/educ/eas/api/controller/SessionControllerTest.java b/api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/SessionControllerTest.java similarity index 97% rename from api/src/test/java/ca/bc/gov/educ/eas/api/controller/SessionControllerTest.java rename to api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/SessionControllerTest.java index 54197b4..e207eeb 100644 --- a/api/src/test/java/ca/bc/gov/educ/eas/api/controller/SessionControllerTest.java +++ b/api/src/test/java/ca/bc/gov/educ/eas/api/controller/v1/SessionControllerTest.java @@ -1,9 +1,7 @@ -package ca.bc.gov.educ.eas.api.controller; +package ca.bc.gov.educ.eas.api.controller.v1; import ca.bc.gov.educ.eas.api.BaseEasAPITest; -import ca.bc.gov.educ.eas.api.constants.v1.StatusCodes; import ca.bc.gov.educ.eas.api.constants.v1.URL; -import ca.bc.gov.educ.eas.api.controller.v1.SessionController; import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; import ca.bc.gov.educ.eas.api.repository.v1.SessionRepository; import ca.bc.gov.educ.eas.api.struct.v1.Session; diff --git a/api/src/test/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentServiceTest.java b/api/src/test/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentServiceTest.java index 727455d..c8a80c6 100644 --- a/api/src/test/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentServiceTest.java +++ b/api/src/test/java/ca/bc/gov/educ/eas/api/service/v1/AssessmentStudentServiceTest.java @@ -3,16 +3,19 @@ import ca.bc.gov.educ.eas.api.BaseEasAPITest; import ca.bc.gov.educ.eas.api.constants.v1.AssessmentTypeCodes; import ca.bc.gov.educ.eas.api.exception.EntityNotFoundException; +import ca.bc.gov.educ.eas.api.model.v1.AssessmentEntity; import ca.bc.gov.educ.eas.api.model.v1.AssessmentStudentEntity; import ca.bc.gov.educ.eas.api.model.v1.SessionEntity; +import ca.bc.gov.educ.eas.api.repository.v1.AssessmentRepository; import ca.bc.gov.educ.eas.api.repository.v1.AssessmentStudentRepository; import ca.bc.gov.educ.eas.api.repository.v1.SessionRepository; -import jakarta.persistence.EntityExistsException; import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; @@ -40,12 +43,23 @@ class AssessmentStudentServiceTest extends BaseEasAPITest { @Autowired SessionRepository sessionRepository; + @Autowired + AssessmentRepository assessmentRepository; + + @AfterEach + public void after() { + this.assessmentStudentRepository.deleteAll(); + this.assessmentRepository.deleteAll(); + this.sessionRepository.deleteAll(); + } + @Test void testGetStudentByID_WhenStudentExistInDB_ShouldReturnStudent() { //given student exists in db SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); + AssessmentEntity assessmentEntity = assessmentRepository.save(createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTP10.getCode())); - AssessmentStudentEntity assessmentStudentEntity = repository.save(AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(sessionEntity.getSessionID()).build()).build()); + AssessmentStudentEntity assessmentStudentEntity = repository.save(createMockStudentEntity(assessmentEntity)); //when retrieving the student AssessmentStudentEntity student = service.getStudentByID(assessmentStudentEntity.getAssessmentStudentID()); @@ -67,93 +81,63 @@ void testGetStudentByID_WhenStudentDoesNotExistInDB_Return404() { void testCreateStudent_WhenStudentDoesNotExistInDB_ShouldReturnStudent() { //given session exists SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); + AssessmentEntity assessmentEntity = assessmentRepository.save(createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTP12.getCode())); //when creating an assessment student - AssessmentStudentEntity student = service.createStudent(AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(sessionEntity.getSessionID()).build()).build()); + AssessmentStudentEntity student = service.createStudent(AssessmentStudentEntity.builder().pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).assessmentEntity(assessmentEntity).build()); //then assessment student is created assertNotNull(student); assertNotNull(repository.findById(student.getStudentID())); } - @Test - void testCreateStudent_WhenStudentAlreadyInThisSession_ShouldThrowError() { - //given studentID exists in db for a session - SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); - - AssessmentStudentEntity assessmentStudentEntity = repository.save(AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(sessionEntity.getSessionID()).build()).build()); - - //when attempting to create a new assessment student with same studentID and session - assessmentStudentEntity.setAssessmentStudentID(UUID.randomUUID()); - - //then throw exception - assertThrows(EntityExistsException.class, () -> service.createStudent(assessmentStudentEntity)); - } - @Test void testCreateStudent_WhenSessionIDDoesNotExistInDB_ShouldThrowError() { //when attempting to create student with invalid session id - AssessmentStudentEntity student = AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(UUID.randomUUID()).build()).build(); - + AssessmentStudentEntity student = AssessmentStudentEntity.builder().pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).build(); //then throw exception - assertThrows(EntityNotFoundException.class, () -> service.createStudent(student)); + assertThrows(DataIntegrityViolationException.class, () -> service.createStudent(student)); } @Test void testUpdateStudent_WhenStudentExistInDB_ShouldReturnUpdatedStudent() { //given student exists in db SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); + AssessmentEntity assessmentEntity = assessmentRepository.save(createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTP10.getCode())); - AssessmentStudentEntity assessmentStudentEntity = repository.save(AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(sessionEntity.getSessionID()).build()).build()); - + AssessmentStudentEntity assessmentStudentEntity = repository.save(AssessmentStudentEntity.builder().pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).assessmentEntity(assessmentEntity).build()); //when updating the student - assessmentStudentEntity.setAssessmentTypeCode(AssessmentTypeCodes.LTP10.getCode()); AssessmentStudentEntity student = service.updateStudent(assessmentStudentEntity); assertNotNull(student); //then student is updated and saved var updatedStudent = repository.findById(student.getAssessmentStudentID()); assertThat(updatedStudent).isPresent(); - assertThat(updatedStudent.get().getAssessmentTypeCode()).isEqualTo(AssessmentTypeCodes.LTP10.getCode()); + assertThat(updatedStudent.get().getAssessmentEntity().getAssessmentTypeCode()).isEqualTo(AssessmentTypeCodes.LTP10.getCode()); } @Test void testUpdateStudent_WhenStudentDoesNotExistInDB_ReturnError() { + SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); + AssessmentEntity assessmentEntity = assessmentRepository.save(createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTP10.getCode())); + //given student does not exist in database //when attempting to update student - AssessmentStudentEntity student = AssessmentStudentEntity.builder().assessmentStudentID(UUID.randomUUID()).assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(UUID.randomUUID()).build()).build(); + AssessmentStudentEntity student = AssessmentStudentEntity.builder().assessmentStudentID(UUID.randomUUID()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).assessmentEntity(assessmentEntity).build(); //then throw exception assertThrows(EntityNotFoundException.class, () -> service.updateStudent(student)); } - @Test - void testUpdateStudent_WhenStudentAlreadyInThisSession_ShouldThrowError() { - //given two existing students in the session - SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); - - UUID studentUUID = UUID.randomUUID(); - AssessmentStudentEntity studentEntity = repository.save(AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(studentUUID).sessionEntity(SessionEntity.builder().sessionID(sessionEntity.getSessionID()).build()).build()); - - //when updating one student to have the same studentID and sessionID as another student - studentEntity.setAssessmentStudentID(null); - studentEntity.setStudentID(UUID.randomUUID()); - AssessmentStudentEntity studentEntity2 = repository.save(studentEntity); - studentEntity2.setStudentID(studentUUID); - - //then exception thrown - assertThrows(EntityExistsException.class, () -> service.updateStudent(studentEntity2)); - } - @Test void testUpdateStudent_WhenSessionIDDoesNotExistInDB_ShouldThrowError() { //given student existing in db - SessionEntity sessionEntity = sessionRepository.save(createMockSessionEntity()); + SessionEntity sessionEntity = createMockSessionEntity(); + //assessment does not exist in db + AssessmentEntity assessmentEntity =createMockAssessmentEntity(sessionEntity, AssessmentTypeCodes.LTF12.getCode()); //when attempting to update to session id that does not exist - AssessmentStudentEntity student = repository.save(AssessmentStudentEntity.builder().assessmentTypeCode(AssessmentTypeCodes.LTF12.getCode()).pen("120164447").schoolID(UUID.randomUUID()).studentID(UUID.randomUUID()).sessionEntity(SessionEntity.builder().sessionID(sessionEntity.getSessionID()).build()).build()); - - student.setSessionEntity(SessionEntity.builder().sessionID(UUID.randomUUID()).build()); + AssessmentStudentEntity student = createMockStudentEntity(assessmentEntity); //then throw exception assertThrows(EntityNotFoundException.class, () -> service.updateStudent(student));