diff --git a/.github/workflows/build.from.main.branch.deploy.to.dev.yml b/.github/workflows/build.from.main.branch.deploy.to.dev.yml
index 33c1e04f..897ccd88 100644
--- a/.github/workflows/build.from.main.branch.deploy.to.dev.yml
+++ b/.github/workflows/build.from.main.branch.deploy.to.dev.yml
@@ -27,7 +27,7 @@ env:
MAX_CPU: "500m"
MIN_MEM: "1Gi"
MAX_MEM: "2Gi"
- MIN_REPLICAS: "3"
+ MIN_REPLICAS: "2"
MAX_REPLICAS: "3"
on:
diff --git a/.github/workflows/build.from.release.branch.deploy.to.dev.yml b/.github/workflows/build.from.release.branch.deploy.to.dev.yml
index d2e4cfd0..44ffffec 100644
--- a/.github/workflows/build.from.release.branch.deploy.to.dev.yml
+++ b/.github/workflows/build.from.release.branch.deploy.to.dev.yml
@@ -27,7 +27,7 @@ env:
MAX_CPU: "500m"
MIN_MEM: "1Gi"
MAX_MEM: "2Gi"
- MIN_REPLICAS: "3"
+ MIN_REPLICAS: "2"
MAX_REPLICAS: "3"
on:
diff --git a/.github/workflows/deploy.to.dev.jinil.yaml b/.github/workflows/deploy.to.dev.jinil.yaml
index 75ae69fe..76aa55c7 100644
--- a/.github/workflows/deploy.to.dev.jinil.yaml
+++ b/.github/workflows/deploy.to.dev.jinil.yaml
@@ -27,7 +27,7 @@ env:
MAX_CPU: "500m"
MIN_MEM: "1Gi"
MAX_MEM: "2Gi"
- MIN_REPLICAS: "3"
+ MIN_REPLICAS: "2"
MAX_REPLICAS: "3"
on:
diff --git a/.github/workflows/deploy_prod.yml b/.github/workflows/deploy_prod.yml
index 43d95365..55fc6cb5 100644
--- a/.github/workflows/deploy_prod.yml
+++ b/.github/workflows/deploy_prod.yml
@@ -23,7 +23,7 @@ env:
MIN_MEM: "1Gi"
MAX_MEM: "2Gi"
MIN_REPLICAS: "3"
- MAX_REPLICAS: "3"
+ MAX_REPLICAS: "4"
on:
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows
diff --git a/.github/workflows/deploy_test.yml b/.github/workflows/deploy_test.yml
index bd12442e..37f1265d 100644
--- a/.github/workflows/deploy_test.yml
+++ b/.github/workflows/deploy_test.yml
@@ -23,7 +23,7 @@ env:
MIN_MEM: "1Gi"
MAX_MEM: "2Gi"
MIN_REPLICAS: "3"
- MAX_REPLICAS: "3"
+ MAX_REPLICAS: "4"
on:
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows
diff --git a/api/pom.xml b/api/pom.xml
index 3c214f40..fa02a6b5 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -6,7 +6,7 @@
ca.bc.gov.educ
educ-grad-data-conversion-api
- 1.8.54
+ 1.8.55
educ-grad-data-conversion-api
Ministry of Education GRAD DATA CONVERSION API
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/config/WebSecurityConfiguration.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/config/WebSecurityConfiguration.java
index e89cd61d..283e9824 100644
--- a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/config/WebSecurityConfiguration.java
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/config/WebSecurityConfiguration.java
@@ -16,10 +16,6 @@
@EnableWebSecurity
public class WebSecurityConfiguration {
- public WebSecurityConfiguration() {
- SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
- }
-
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/JobLauncherController.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/JobLauncherController.java
index b12c8120..eb825922 100644
--- a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/JobLauncherController.java
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/JobLauncherController.java
@@ -26,7 +26,7 @@
import java.util.Date;
@RestController
-@RequestMapping(EducGradDataConversionApiConstants.GRAD_BATCH_API_ROOT_MAPPING)
+@RequestMapping(EducGradDataConversionApiConstants.GRAD_DATA_CONVERSION_API_ROOT_MAPPING)
@CrossOrigin
@OpenAPIDefinition(info = @Info(title = "API for Data Conversion & Ongoing Updates.",
description = "This API is for Reading TRAX data and Persisting GRAD data.", version = "1"))
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/StudentController.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/StudentController.java
new file mode 100644
index 00000000..4a1343a4
--- /dev/null
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/controller/StudentController.java
@@ -0,0 +1,59 @@
+package ca.bc.gov.educ.api.dataconversion.controller;
+
+import ca.bc.gov.educ.api.dataconversion.model.Student;
+import ca.bc.gov.educ.api.dataconversion.service.student.StudentService;
+import ca.bc.gov.educ.api.dataconversion.util.EducGradDataConversionApiConstants;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping(EducGradDataConversionApiConstants.GRAD_DATA_CONVERSION_API_ROOT_MAPPING)
+@CrossOrigin
+@OpenAPIDefinition(info = @Info(title = "API for Adhoc Student Operations",
+ description = "This API is for running adhoc student operations invoking the endpoints manually.", version = "1"))
+public class StudentController {
+
+ private static final Logger logger = LoggerFactory.getLogger(StudentController.class);
+
+ @Autowired
+ StudentService studentService;
+
+ @GetMapping(EducGradDataConversionApiConstants.GRAD_STUDENT_BY_PEN_STUDENT_API)
+ @PreAuthorize("hasAuthority('SCOPE_READ_GRAD_STUDENT_DATA')")
+ @Operation(summary = "Search For Student by PEN", description = "Search for Student Demographics by PEN", tags = { "Students" })
+ @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
+ public Student getGradStudentByPenFromStudentAPI(@PathVariable String pen, @RequestHeader(name="Authorization") String accessToken) {
+ logger.debug("Get Student by PEN [Controller]");
+ return studentService.getStudentByPen(pen, accessToken.replaceAll("Bearer ", ""));
+ }
+
+ @DeleteMapping(EducGradDataConversionApiConstants.GRAD_STUDENT_BY_PEN_STUDENT_API)
+ @PreAuthorize("hasAuthority('SCOPE_DELETE_GRAD_STUDENT_DATA')")
+ @Operation(summary = "Delete a Student by PEN", description = "Delete a Student and all related data by PEN", tags = { "Students" })
+ @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
+ public void cascadeDeleteStudent(@PathVariable String pen, @RequestHeader(name="Authorization") String accessToken) {
+ logger.debug("Cascade Delete a Student [Controller]");
+ studentService.cascadeDeleteStudent(pen, accessToken.replaceAll("Bearer ", ""));
+ }
+
+ @DeleteMapping(EducGradDataConversionApiConstants.GRAD_STUDENTS_BY_PENLIST_STUDENT_API)
+ @PreAuthorize("hasAuthority('SCOPE_DELETE_GRAD_STUDENT_DATA')")
+ @Operation(summary = "Delete multiple Students by PEN", description = "Delete a list of Students and all related data by PEN", tags = { "Students" })
+ @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
+ public void cascadeDeleteStudents(@RequestBody List penList, @RequestHeader(name="Authorization") String accessToken) {
+ logger.debug("Cascade Delete a Student [Controller]");
+ penList.forEach(pen -> {
+ studentService.cascadeDeleteStudent(pen, accessToken.replaceAll("Bearer ", ""));
+ });
+ }
+}
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/GradSearchStudent.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/GradSearchStudent.java
new file mode 100644
index 00000000..0c855c9c
--- /dev/null
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/GradSearchStudent.java
@@ -0,0 +1,52 @@
+package ca.bc.gov.educ.api.dataconversion.model;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+import java.sql.Date;
+
+@Data
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+public class GradSearchStudent {
+
+ private String studentID;
+ private String pen;
+ private String legalFirstName;
+ private String legalMiddleNames;
+ private String legalLastName;
+ private String dob;
+ private String sexCode;
+ private String genderCode;
+ private String studentCitizenship;
+ private String usualFirstName;
+ private String usualMiddleNames;
+ private String usualLastName;
+ private String email;
+ private String emailVerified;
+ private String deceasedDate;
+ private String postalCode;
+ private String mincode;
+ private String localID;
+ private String gradeCode;
+ private String gradeYear;
+ private String demogCode;
+ private String statusCode;
+ private String memo;
+ private String trueStudentID;
+ private String program;
+ private String schoolOfRecord;
+ private String schoolOfRecordName;
+ private String schoolOfRecordindependentAffiliation;
+ private String studentGrade;
+ private String studentStatus;
+ private String transcriptEligibility;
+ private String certificateEligibility;
+ @JsonFormat(pattern="yyyy-MM-dd")
+ private Date adultStartDate;
+
+}
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/Student.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/Student.java
index 547c7e66..db8405bd 100644
--- a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/Student.java
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/Student.java
@@ -13,35 +13,35 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class Student {
- String studentID;
- String pen;
- String legalFirstName;
- String legalMiddleNames;
- String legalLastName;
- String dob;
- String sexCode;
- String genderCode;
- String usualFirstName;
- String usualMiddleNames;
- String usualLastName;
- String email;
- String emailVerified;
- String deceasedDate;
- String postalCode;
- String mincode;
- String localID;
- String gradeCode;
- String gradeYear;
- String demogCode;
- String statusCode;
- String memo;
- String trueStudentID;
- String historyActivityCode;
+ String studentID;
+ String pen;
+ String legalFirstName;
+ String legalMiddleNames;
+ String legalLastName;
+ String dob;
+ String sexCode;
+ String genderCode;
+ String usualFirstName;
+ String usualMiddleNames;
+ String usualLastName;
+ String email;
+ String emailVerified;
+ String deceasedDate;
+ String postalCode;
+ String mincode;
+ String localID;
+ String gradeCode;
+ String gradeYear;
+ String demogCode;
+ String statusCode;
+ String memo;
+ String trueStudentID;
+ String historyActivityCode;
- public String createUser;
- public String updateUser;
- public String createDate;
- public String updateDate;
+ public String createUser;
+ public String updateUser;
+ public String createDate;
+ public String updateDate;
- String truePen;
+ String truePen;
}
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/StudentNote.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/StudentNote.java
new file mode 100644
index 00000000..c814be1b
--- /dev/null
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/model/StudentNote.java
@@ -0,0 +1,17 @@
+package ca.bc.gov.educ.api.dataconversion.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.UUID;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class StudentNote extends BaseModel {
+
+ private UUID id;
+ private String note;
+ private String studentID;
+}
\ No newline at end of file
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/service/student/StudentService.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/service/student/StudentService.java
new file mode 100644
index 00000000..fe82db82
--- /dev/null
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/service/student/StudentService.java
@@ -0,0 +1,100 @@
+package ca.bc.gov.educ.api.dataconversion.service.student;
+
+import ca.bc.gov.educ.api.dataconversion.model.*;
+import ca.bc.gov.educ.api.dataconversion.util.RestUtils;
+import io.github.resilience4j.retry.annotation.Retry;
+import jakarta.transaction.Transactional;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import java.util.List;
+import java.util.UUID;
+
+@Service
+@Slf4j
+public class StudentService {
+ private static final Logger logger = LoggerFactory.getLogger(StudentService.class);
+
+ private final RestUtils restUtils;
+ final WebClient webClient;
+
+ @Autowired
+ public StudentService(RestUtils restUtils, WebClient webClient) {
+ this.restUtils = restUtils;
+ this.webClient = webClient;
+ }
+
+ @Transactional
+ @Retry(name = "searchbypen")
+ public Student getStudentByPen(String pen, String accessToken) {
+ logger.debug("Get Student by PEN [Service]");
+
+ Student student;
+ List gradStudentList;
+
+ try {
+ gradStudentList = restUtils.getStudentsByPen(pen, accessToken);
+ student = gradStudentList.stream().filter(s -> s.getPen().compareTo(pen) == 0).findAny().orElse(null);
+ } catch (Exception e) {
+ log.error("Failed to retrieve PEN [{}] : {} ", pen, e.getLocalizedMessage());
+ return null;
+ }
+
+ if (student == null) {
+ log.error("PEN NOT FOUND [{}]", pen);
+ return null;
+ }
+ return student;
+ }
+
+ @Transactional
+ public String cascadeDeleteStudent(String pen, String accessToken) {
+ logger.debug("Cascade Delete a Student [Service]");
+
+ //GET Student by PEN
+ Student student = getStudentByPen(pen, accessToken);
+ logger.debug("After GET student");
+ String studentID;
+
+ if (student != null) {
+ studentID = student.getStudentID();
+ logger.debug("Student ID: [{}]", studentID);
+
+ /*
+ Delete All student related data ({STUDENT_API}/api/v1/student/conv/studentid/{studentID})
+ This will delete student data from the following tables:
+ STUDENT_RECORD_NOTE, STUDENT_CAREER_PROGRAMS, STUDENT_OPTIONAL_PROGRAM_HISTORY,
+ STUDENT_OPTIONAL_PROGRAM, GRADUATION_STUDENT_RECORD_HISTORY, GRADUATION_STUDENT_RECORD
+ */
+ try {
+ restUtils.removeAllStudentRelatedData(UUID.fromString(studentID), accessToken);
+ } catch (Exception e) {
+ logger.info("Exception thrown when trying to delete student related data from grad student API.");
+ }
+
+ /*
+ Delete all Student certificates, transcripts and reports from API_GRAD_REPORT schema
+ Tables: STUDENT_CERTIFICATE, STUDENT_TRANSCRIPT and STUDENT_REPORT
+ */
+ try {
+ restUtils.removeAllStudentAchievements(UUID.fromString(studentID), accessToken);
+ } catch (Exception e) {
+ logger.info("Exception thrown when trying to delete student achievements.");
+ }
+
+ /*
+ Update TRAX_STUDENT_NO status to NULL
+ */
+ try {
+ restUtils.updateTraxStudentNo(new TraxStudentNo(pen, null, null), accessToken);
+ } catch (Exception e) {
+ logger.info("Exception thrown when trying to update TraxStudentNo.");
+ }
+ }
+ return pen;
+ }
+}
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/EducGradDataConversionApiConstants.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/EducGradDataConversionApiConstants.java
index 28e9c623..76ed6d79 100644
--- a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/EducGradDataConversionApiConstants.java
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/EducGradDataConversionApiConstants.java
@@ -15,12 +15,14 @@ public class EducGradDataConversionApiConstants {
public static final String CORRELATION_ID = "correlationID";
public static final String API_ROOT_MAPPING = "";
public static final String API_VERSION = "v1";
- public static final String GRAD_BATCH_API_ROOT_MAPPING = "/api/" + API_VERSION + "/data-conversion";
+ public static final String GRAD_DATA_CONVERSION_API_ROOT_MAPPING = "/api/" + API_VERSION + "/data-conversion";
// Data Conversion
public static final String GRAD_STUDENT_PARALLEL_DATA_CONVERSION_BATCH_JOB = "/student/parallel";
public static final String GRAD_COURSE_RESTRICTION_DATA_CONVERSION_BATCH_JOB = "/courseRestriction";
public static final String GRAD_COURSE_REQUIREMENT_DATA_CONVERSION_BATCH_JOB = "/courseRequirement";
+ public static final String GRAD_STUDENT_BY_PEN_STUDENT_API = "/student/pen/{pen}";
+ public static final String GRAD_STUDENTS_BY_PENLIST_STUDENT_API = "/student/penlist";
// Util
public static final String PEN_UPDATES_PARALLEL_BATCH_JOB = "/penUpdates/parallel";
@@ -33,8 +35,6 @@ public class EducGradDataConversionApiConstants {
public static final String DEFAULT_CREATED_BY = "DATA_CONV";
public static final String DEFAULT_UPDATED_BY = "DATA_CONV";
- public static final String DEFAULT_END_DATE_FORMAT = "20991231"; // yyyyMMdd
-
@Value("${authorization.user}")
private String userName;
@@ -101,6 +101,12 @@ public class EducGradDataConversionApiConstants {
@Value("${endpoint.grad-student-api.remove-student-career-program}")
private String removeStudentCareerProgram;
+ @Value("${endpoint.grad-student-api.get-student-by-pen}")
+ private String gradStudentByPenUrl;
+
+ @Value("${endpoint.grad-student-api.get-student-notes-by-studentID}")
+ private String gradStudentNotesByStudentID;
+
@Value("${endpoint.grad-assessment-api.assessment-requirement.url}")
private String addAssessmentRequirementApiUrl;
@@ -155,6 +161,9 @@ public class EducGradDataConversionApiConstants {
@Value("${endpoint.grad-trax-api.student.save-trax-student-no.url}")
private String saveTraxStudentNoUrl;
+ @Value("${endpoint.grad-graduation-report-api.delete-student-achievements.url}")
+ private String deleteStudentAchievementsUrl;
+
// Incremental Grad Update
@Value("${grad.update.enabled}")
private boolean gradUpdateEnabled;
diff --git a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/RestUtils.java b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/RestUtils.java
index c3e5f840..7c2b8dc3 100644
--- a/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/RestUtils.java
+++ b/api/src/main/java/ca/bc/gov/educ/api/dataconversion/util/RestUtils.java
@@ -26,7 +26,7 @@ public class RestUtils {
private final EducGradDataConversionApiConstants constants;
- private ResponseObjCache responseObjCache;
+ private final ResponseObjCache responseObjCache;
private final WebClient webClient;
@@ -76,6 +76,20 @@ public List getStudentsByPen(String pen, String accessToken) {
.retrieve().bodyToMono(responseType).block();
}
+ public List getStudentNotesByStudentId(String studentID, String accessToken) {
+
+ log.debug("GET student Notes: {}", String.format(constants.getGradStudentNotesByStudentID(), studentID));
+ final ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() {
+ };
+ return this.webClient.get()
+ .uri(String.format(constants.getGradStudentNotesByStudentID(), studentID))
+ .headers(h -> {
+ h.setBearerAuth(accessToken);
+ h.set(EducGradDataConversionApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID());
+ })
+ .retrieve().bodyToMono(responseType).block();
+ }
+
public OptionalProgram getOptionalProgram(String programCode, String specialProgramCode, String accessToken) {
return this.webClient.get()
.uri(constants.getGradOptionalProgramUrl(), uri -> uri.path("/{programCode}/{specialProgramCode}").build(programCode, specialProgramCode))
@@ -346,6 +360,17 @@ public TraxStudentNo saveTraxStudentNo(TraxStudentNo traxStudentNo, String acces
.retrieve().bodyToMono(TraxStudentNo.class).block();
}
+ public TraxStudentNo updateTraxStudentNo(TraxStudentNo traxStudentNo, String accessToken) {
+ return webClient.put()
+ .uri(constants.getSaveTraxStudentNoUrl())
+ .headers(h -> {
+ h.setBearerAuth(accessToken);
+ h.set(EducGradDataConversionApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID());
+ })
+ .body(BodyInserters.fromValue(traxStudentNo))
+ .retrieve().bodyToMono(TraxStudentNo.class).block();
+ }
+
// Read GraduationStudentRecord - GET /student/studentid/{id}/algorithm
@Retry(name = "rt-getStudentGradStatus", fallbackMethod = "rtGetStudentGradStatusFallback")
public GraduationStudentRecord getStudentGradStatus(String studentID, String accessToken) {
@@ -380,13 +405,21 @@ public GraduationStudentRecord updateStudentGradStatusByFields(OngoingUpdateRequ
}).body(BodyInserters.fromValue(requestDTO)).retrieve().bodyToMono(GraduationStudentRecord.class).block();
}
+ public void removeAllStudentAchievements(UUID studentID, String accessToken) {
+ webClient.delete().uri(String.format(constants.getDeleteStudentAchievementsUrl(),studentID))
+ .headers(h -> {
+ h.setBearerAuth(accessToken);
+ h.set(EducGradDataConversionApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID());
+ }).retrieve().bodyToMono(Void.class).block();
+ }
+
// Remove All Student Related Data - DELETE /student/conv/studentid/{id}
public void removeAllStudentRelatedData(UUID studentID, String accessToken) {
webClient.delete().uri(String.format(constants.getSaveGraduationStudentRecord(),studentID))
.headers(h -> {
h.setBearerAuth(accessToken);
h.set(EducGradDataConversionApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID());
- }).retrieve().onStatus(p -> p.value() == 404, error -> Mono.error(new Exception("Student Data Not Found"))).bodyToMono(Void.class).block();
+ }).retrieve().bodyToMono(Void.class).block();
}
// READ StudentOptionalProgram - GET /student/optionalprogram/studentid/{id}
diff --git a/api/src/main/resources/application.yaml b/api/src/main/resources/application.yaml
index 2d03219e..ff295f55 100644
--- a/api/src/main/resources/application.yaml
+++ b/api/src/main/resources/application.yaml
@@ -210,6 +210,8 @@ endpoint:
remove-student-career-program: ${GRAD_STUDENT_API}api/v1/student/conv/studentcareerprogram/%s/%s
read-student-career-programs: ${GRAD_STUDENT_API}api/v1/student/studentcareerprogram/studentid/%s
save-grad-student-record-for-ongoing-updates: ${GRAD_STUDENT_API}api/v1/student/conv/ongoingupdate/gradstatus
+ get-student-by-pen: ${GRAD_STUDENT_API}api/v1/student/pen/%s
+ get-student-notes-by-studentID: ${GRAD_STUDENT_API}api/v1/student/studentnotes/studentid/%s
grad-assessment-api:
assessment-requirement:
url: ${GRAD_ASSESSMENT_API}api/v1/assessment/requirement
@@ -233,6 +235,10 @@ endpoint:
url: ${GRAD_TRAX_API}api/v1/trax/common/course-restrictions
get-course-requirements:
url: ${GRAD_TRAX_API}api/v1/trax/common/course-requirements
+ grad-graduation-report-api:
+ delete-student-achievements:
+ url: ${GRAD_GRADUATION_REPORT_API}api/v1/graduationreports/studentachievement/%s
+
#Incremental Grad Update
grad:
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/controller/StudentControllerTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/controller/StudentControllerTest.java
new file mode 100644
index 00000000..8d8358d7
--- /dev/null
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/controller/StudentControllerTest.java
@@ -0,0 +1,44 @@
+package ca.bc.gov.educ.api.dataconversion.controller;
+
+import ca.bc.gov.educ.api.dataconversion.model.Student;
+import ca.bc.gov.educ.api.dataconversion.service.student.StudentService;
+import org.junit.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
+public class StudentControllerTest {
+
+ @Mock
+ private StudentService studentService;
+
+ @Test
+ public void testGetGradStudentByPenFromStudentAPI() {
+
+ String pen = "123456789";
+ String accessToken = "Bearer accesstoken";
+ Student student = new Student();
+
+ Mockito.when(studentService.getStudentByPen(pen,accessToken.replaceAll("Bearer ", accessToken))).thenReturn(student);
+ studentService.getStudentByPen(pen,accessToken.replaceAll("Bearer ", accessToken));
+ Mockito.verify(studentService).getStudentByPen(pen, accessToken.replaceAll("Bearer ", accessToken));
+ }
+
+ @Test
+ public void testCascadeDeleteStudent() {
+
+ String pen = "123456789";
+ String accessToken = "Bearer accesstoken";
+ Student student = new Student();
+
+ Mockito.when(studentService.cascadeDeleteStudent(pen, accessToken.replaceAll("Bearer ", accessToken))).thenReturn(pen);
+ studentService.cascadeDeleteStudent(pen,accessToken.replaceAll("Bearer ", accessToken));
+ Mockito.verify(studentService).cascadeDeleteStudent(pen, accessToken.replaceAll("Bearer ", accessToken));
+
+ }
+}
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/NewStudentEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/NewStudentEventServiceTest.java
index 55d0e4a5..08363b3f 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/NewStudentEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/NewStudentEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Arrays;
import java.util.Optional;
@@ -45,6 +46,9 @@ public class NewStudentEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentAssessmentUpdateEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentAssessmentUpdateEventServiceTest.java
index 9b8c48d3..58fe1e1c 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentAssessmentUpdateEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentAssessmentUpdateEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Optional;
import java.util.UUID;
@@ -44,6 +45,9 @@ public class StudentAssessmentUpdateEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentCourseUpdateEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentCourseUpdateEventServiceTest.java
index d65d1258..9f9319f5 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentCourseUpdateEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentCourseUpdateEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Optional;
import java.util.UUID;
@@ -44,6 +45,9 @@ public class StudentCourseUpdateEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentDemographicsUpdateEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentDemographicsUpdateEventServiceTest.java
index 8c904691..9a858067 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentDemographicsUpdateEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentDemographicsUpdateEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Optional;
import java.util.UUID;
@@ -44,6 +45,9 @@ public class StudentDemographicsUpdateEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentFrenchImmersionEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentFrenchImmersionEventServiceTest.java
index 699a86d8..db7962ac 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentFrenchImmersionEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentFrenchImmersionEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Optional;
import java.util.UUID;
@@ -44,6 +45,9 @@ public class StudentFrenchImmersionEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentGraduationUpdateEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentGraduationUpdateEventServiceTest.java
index b99513c2..20a38f27 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentGraduationUpdateEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentGraduationUpdateEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Optional;
import java.util.UUID;
@@ -44,6 +45,9 @@ public class StudentGraduationUpdateEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentServiceTest.java
new file mode 100644
index 00000000..bb47f062
--- /dev/null
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentServiceTest.java
@@ -0,0 +1,113 @@
+package ca.bc.gov.educ.api.dataconversion.service;
+
+import ca.bc.gov.educ.api.dataconversion.constant.EventStatus;
+import ca.bc.gov.educ.api.dataconversion.constant.EventType;
+import ca.bc.gov.educ.api.dataconversion.entity.Event;
+import ca.bc.gov.educ.api.dataconversion.messaging.NatsConnection;
+import ca.bc.gov.educ.api.dataconversion.messaging.jetstream.Subscriber;
+import ca.bc.gov.educ.api.dataconversion.model.ConvGradStudent;
+import ca.bc.gov.educ.api.dataconversion.model.ConversionStudentSummaryDTO;
+import ca.bc.gov.educ.api.dataconversion.model.Student;
+import ca.bc.gov.educ.api.dataconversion.process.StudentProcess;
+import ca.bc.gov.educ.api.dataconversion.repository.EventRepository;
+import ca.bc.gov.educ.api.dataconversion.service.student.NewStudentEventService;
+import ca.bc.gov.educ.api.dataconversion.service.student.StudentService;
+import ca.bc.gov.educ.api.dataconversion.util.EducGradDataConversionApiConstants;
+import ca.bc.gov.educ.api.dataconversion.util.RestUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatException;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@ActiveProfiles("test")
+public class StudentServiceTest {
+
+ @Autowired
+ StudentService studentService;
+
+ @MockBean
+ RestUtils restUtils;
+
+ @MockBean
+ WebClient webClient;
+
+ // NATS
+ @MockBean
+ private NatsConnection natsConnection;
+ @MockBean
+ private Subscriber subscriber;
+
+ @Test
+ public void testGetStudentByPen_given_PEN_returnsAPICallSuccess() {
+ String pen = "123456789";
+ String accessToken = "Bearer accesstoken";
+
+ Student student = new Student();
+ student.setPen(pen);
+ List penList = List.of(student);
+
+ when(this.restUtils.getStudentsByPen(pen, accessToken)).thenReturn(penList);
+ studentService.getStudentByPen(pen, accessToken);
+
+ assertThat(penList).isNotNull();
+ }
+
+ @Test
+ public void testGetStudentByPen_given_PEN_returnsNULL() {
+ String pen = "123456789";
+ String accessToken = "Bearer accesstoken";
+
+ Student student = new Student();
+ student.setPen(pen);
+ List penList = List.of(student);
+
+ when(this.restUtils.getStudentsByPen(pen, accessToken)).thenReturn(new ArrayList());
+ Student s = studentService.getStudentByPen(pen, accessToken);
+
+ assertThat(s).isNull();
+ }
+
+ @Test(expected = Exception.class)
+ public void testGetStudentByPen_given_PEN_throws_exception() {
+ String pen = "123456789";
+ String accessToken = "Bearer accesstoken";
+
+ Student student = new Student();
+ student.setPen(pen);
+ List penList = List.of(student);
+
+ when(this.restUtils.getStudentsByPen(pen, accessToken)).thenThrow(Exception.class);
+ Student s = studentService.getStudentByPen(pen, accessToken);
+ }
+
+ @Test
+ public void testCascadeDeleteStudentBy_given_PEN_returnsAPICallSuccess() {
+ String pen = "123456789";
+ String studentID = "0a614e84-7e27-1815-817e-fad384090090";
+ String accessToken = "Bearer accesstoken";
+
+ Student student = new Student();
+ student.setPen(pen);
+ student.setStudentID(studentID);
+ List penList = List.of(student);
+
+ when(this.restUtils.getStudentsByPen(pen, accessToken)).thenReturn(penList);
+ studentService.cascadeDeleteStudent(pen, accessToken);
+ Mockito.verify(restUtils).removeAllStudentRelatedData(UUID.fromString(studentID), accessToken);
+ }
+}
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentStatusUpdateEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentStatusUpdateEventServiceTest.java
index d92072a1..8c944ab5 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentStatusUpdateEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentStatusUpdateEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.Arrays;
import java.util.Optional;
@@ -45,6 +46,9 @@ public class StudentStatusUpdateEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentXProgramEventServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentXProgramEventServiceTest.java
index 7a3aa9b2..ce36a69f 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentXProgramEventServiceTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/service/StudentXProgramEventServiceTest.java
@@ -18,6 +18,7 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.reactive.function.client.WebClient;
import java.util.ArrayList;
import java.util.Arrays;
@@ -46,6 +47,9 @@ public class StudentXProgramEventServiceTest {
@MockBean
RestUtils restUtils;
+ @MockBean
+ WebClient webClient;
+
// NATS
@MockBean
private NatsConnection natsConnection;
diff --git a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/util/RestUtilsTest.java b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/util/RestUtilsTest.java
index dbd49fbe..310c84ed 100644
--- a/api/src/test/java/ca/bc/gov/educ/api/dataconversion/util/RestUtilsTest.java
+++ b/api/src/test/java/ca/bc/gov/educ/api/dataconversion/util/RestUtilsTest.java
@@ -368,4 +368,31 @@ public void testUpdateStudentFallbackMethod_givenException_shouldReturnNull(){
val result = this.restUtils.rtUpdateStudentGradStatusFallback(new HttpServerErrorException(HttpStatus.I_AM_A_TEAPOT));
assertThat(result).isNull();
}
+
+ @Test
+ public void testGetStudentNotesByStudentId_returnsTrue_with_APICallSuccess() {
+
+ final String studentID = "0a614e84-7e27-1815-817e-fad384090090";
+ final String noteID = "0a614e84-7e27-1815-817e-fad384090090";
+ String accessToken = "Bearer accesstoken";
+ StudentNote note = new StudentNote();
+ note.setStudentID(studentID);
+ note.setNote("Sample Note");
+ note.setId(UUID.fromString(noteID));
+
+ when(this.webClient.get()).thenReturn(this.requestHeadersUriMock);
+ when(this.requestHeadersUriMock.uri(String.format(constants.getGradStudentNotesByStudentID(), studentID)))
+ .thenReturn(this.requestHeadersMock);
+ when(this.requestHeadersMock.headers(any(Consumer.class))).thenReturn(this.requestHeadersMock);
+ when(this.requestHeadersMock.retrieve()).thenReturn(this.responseMock);
+
+ final ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() {
+ };
+ when(this.responseMock.bodyToMono(responseType)).thenReturn(Mono.just(Arrays.asList(note)));
+
+ val result = this.restUtils.getStudentNotesByStudentId(studentID, accessToken);
+ assertThat(result).isNotNull();
+ assertThat(!result.isEmpty()).isTrue();
+ assertThat(result.get(0).getStudentID()).isEqualTo(studentID);
+ }
}
diff --git a/api/src/test/resources/application.yaml b/api/src/test/resources/application.yaml
index fee5931c..d36d6f55 100644
--- a/api/src/test/resources/application.yaml
+++ b/api/src/test/resources/application.yaml
@@ -137,6 +137,8 @@ endpoint:
remove-student-career-program: https://educ-grad-student-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/student/conv/studentcareerprogram/%s/%s
read-student-career-programs: https://educ-grad-student-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/student/studentcareerprogram/studentid/%s
save-grad-student-record-for-ongoing-updates: https://educ-grad-student-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/student/conv/ongoingupdate/gradstatus
+ get-student-by-pen: https://educ-grad-student-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/student/pen/%s
+ get-student-notes-by-studentID: https://educ-grad-student-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/student/studentnotes/studentid/%s
grad-assessment-api:
assessment-requirement:
url: https://educ-grad-assessment-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/assessment/requirement
@@ -160,6 +162,9 @@ endpoint:
url: https://educ-grad-trax-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/trax/common/course-restrictions
get-course-requirements:
url: https://educ-grad-trax-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/trax/common/course-requirements
+ grad-graduation-report-api:
+ delete-student-achievements:
+ url: https://educ-grad-graduation-report-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/graduationreports/studentachievement/%s
#Incremental Grad Update
grad:
diff --git a/tools/config/update-configmap.sh b/tools/config/update-configmap.sh
index ca30ca8c..baa14221 100644
--- a/tools/config/update-configmap.sh
+++ b/tools/config/update-configmap.sh
@@ -62,6 +62,7 @@ oc create -n "$BUSINESS_NAMESPACE"-"$envValue" configmap "$APP_NAME"-config-map
--from-literal=GRAD_PROGRAM_API="http://educ-grad-program-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \
--from-literal=GRAD_STUDENT_API="http://educ-grad-student-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \
--from-literal=GRAD_TRAX_API="http://educ-grad-trax-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \
+ --from-literal=GRAD_GRADUATION_REPORT_API="http://educ-grad-graduation-report-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \
--from-literal=IDLE_TIMEOUT="400000" \
--from-literal=KEYCLOAK_TOKEN_URL="https://soam-$envValue.apps.silver.devops.gov.bc.ca/" \
--from-literal=MAXIMUM_POOL_SIZE="40" \