Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grad release 1.12.0 #608

Merged
merged 18 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>ca.bc.gov.educ</groupId>
<artifactId>educ-grad-student-api</artifactId>
<version>1.8.52</version>
<version>1.8.53</version>
<name>educ-grad-student-api</name>
<description>Student Demographics API for GRAD team</description>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
import ca.bc.gov.educ.api.gradstudent.constant.Topics;
import ca.bc.gov.educ.api.gradstudent.exception.EntityNotFoundException;
import ca.bc.gov.educ.api.gradstudent.model.dc.Event;
import ca.bc.gov.educ.api.gradstudent.model.dc.GradStatusPayload;
import ca.bc.gov.educ.api.gradstudent.model.dto.GraduationStudentRecord;
import ca.bc.gov.educ.api.gradstudent.service.GraduationStatusService;
import ca.bc.gov.educ.api.gradstudent.util.EducGradStudentApiConstants;
import ca.bc.gov.educ.api.gradstudent.util.JsonUtil;
import ca.bc.gov.educ.api.gradstudent.util.LogHelper;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.nats.client.*;
import lombok.val;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand All @@ -22,14 +26,14 @@ public class FetchGradStatusSubscriber implements MessageHandler {
private Dispatcher dispatcher;
private final GraduationStatusService graduationStatusService;

private final EducGradStudentApiConstants constants;
private static final String TOPIC = Topics.GRAD_STUDENT_API_FETCH_GRAD_STATUS_TOPIC.toString();

private static final Logger log = LoggerFactory.getLogger(FetchGradStatusSubscriber.class);

@Autowired
public FetchGradStatusSubscriber(final Connection natsConnection, GraduationStatusService graduationStatusService, EducGradStudentApiConstants constants) {
this.natsConnection = natsConnection;
this.graduationStatusService = graduationStatusService;
this.constants = constants;
}

@PostConstruct
Expand All @@ -41,18 +45,40 @@ public void subscribe() {
@Override
public void onMessage(Message message) {
val eventString = new String(message.getData());
LogHelper.logMessagingEventDetails(eventString, constants.isSplunkLogHelperEnabled());
log.debug(eventString);
String response;
try {
Event event = JsonUtil.getJsonObjectFromString(Event.class, eventString);
UUID stdId = UUID.fromString(event.getEventPayload());
boolean hasStudentGraduated = graduationStatusService.hasStudentGraduated(stdId);
response = String.valueOf(hasStudentGraduated);
UUID stdId = JsonUtil.getJsonObjectFromString(UUID.class, event.getEventPayload());
GraduationStudentRecord graduationStatus = graduationStatusService.getGraduationStatus(stdId);
response = getResponse(graduationStatus);
} catch (Exception e) {
response = (e instanceof EntityNotFoundException) ? "not found" : "error";
LogHelper.logMessagingEventDetails("NATS message exception at FetchGradStatusSubscriber: " + response + " when processing: " + eventString, constants.isSplunkLogHelperEnabled());
response = getErrorResponse(e);
if(!(e instanceof EntityNotFoundException)){
log.error(String.format("NATS message exception at FetchGradStatusSubscriber: %s when processing: %s", e.getMessage(), eventString));
}
}
this.natsConnection.publish(message.getReplyTo(), response.getBytes());
}

private String getResponse(GraduationStudentRecord graduationStudentRecord) throws JsonProcessingException {
GradStatusPayload gradStatusPayload = GradStatusPayload.builder()
.program(graduationStudentRecord.getProgram())
.programCompletionDate(graduationStudentRecord.getProgramCompletionDate())
.build();
return JsonUtil.getJsonStringFromObject(gradStatusPayload);
}

private String getErrorResponse(Exception e) {
String ex = (e instanceof EntityNotFoundException) ? "not found" : "error";
GradStatusPayload gradStatusPayload = GradStatusPayload.builder()
.exception(ex)
.build();
try {
return JsonUtil.getJsonStringFromObject(gradStatusPayload);
} catch (JsonProcessingException exc) {
return "{\"program\": \"\", \"programCompletionDate\": \"\", \"exception\": \"JSON Parsing exception\"}";
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ca.bc.gov.educ.api.gradstudent.model.dc;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class GradStatusPayload {

private String program;
private String programCompletionDate;
private String exception;

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,21 @@ public class GraduationStatusTransformer {
@Autowired
GradValidation validation;

public GraduationStudentRecord transformToDTO (GraduationStudentRecordEntity gradStatusEntity) {
public GraduationStudentRecord transformToDTOWithModifiedProgramCompletionDate(GraduationStudentRecordEntity gradStatusEntity) {
GraduationStudentRecord gradStatus = modelMapper.map(gradStatusEntity, GraduationStudentRecord.class);
gradStatus.setProgramCompletionDate(EducGradStudentApiUtils.parseDateFromString(gradStatusEntity.getProgramCompletionDate() != null ?
EducGradStudentApiUtils.formatDate(gradStatusEntity.getProgramCompletionDate()) : null));
return gradStatus;
}

public GraduationStudentRecord transformToDTO ( Optional<GraduationStudentRecordEntity> gradStatusEntity ) {
public GraduationStudentRecord transformToDTO(GraduationStudentRecordEntity gradStatusEntity) {
GraduationStudentRecord gradStatus = modelMapper.map(gradStatusEntity, GraduationStudentRecord.class);
gradStatus.setProgramCompletionDate(gradStatusEntity.getProgramCompletionDate() != null ?
EducGradStudentApiUtils.formatDate(gradStatusEntity.getProgramCompletionDate()) : null);
return gradStatus;
}

public GraduationStudentRecord transformToDTOWithModifiedProgramCompletionDate(Optional<GraduationStudentRecordEntity> gradStatusEntity ) {
GraduationStudentRecordEntity cae = new GraduationStudentRecordEntity();
if (gradStatusEntity.isPresent())
cae = gradStatusEntity.get();
Expand All @@ -50,7 +57,7 @@ public GraduationStudentRecord transformToDTO ( Optional<GraduationStudentRecord
return gradStatus;
}

public List<GraduationStudentRecord> transformToDTO (Iterable<GraduationStudentRecordEntity> gradStatusEntities ) {
public List<GraduationStudentRecord> transformToDTOWithModifiedProgramCompletionDate(Iterable<GraduationStudentRecordEntity> gradStatusEntities ) {
List<GraduationStudentRecord> gradStatusList = new ArrayList<>();
for (GraduationStudentRecordEntity gradStatusEntity : gradStatusEntities) {
GraduationStudentRecord gradStatus = modelMapper.map(gradStatusEntity, GraduationStudentRecord.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import ca.bc.gov.educ.api.gradstudent.model.entity.GradStatusEvent;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
Expand Down Expand Up @@ -35,4 +39,9 @@ public interface GradStatusEventRepository extends JpaRepository<GradStatusEvent
* @return the list
*/
List<GradStatusEvent> findByEventStatusOrderByCreateDate(String eventStatus);

@Transactional
@Modifying
@Query("delete from GradStatusEvent where createDate <= :createDate")
void deleteByCreateDateBefore(LocalDateTime createDate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ca.bc.gov.educ.api.gradstudent.scheduler;

import ca.bc.gov.educ.api.gradstudent.repository.GradStatusEventRepository;
import ca.bc.gov.educ.api.gradstudent.util.EducGradStudentApiConstants;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.LockAssert;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@Slf4j
public class PurgeOldRecordsScheduler {
private final GradStatusEventRepository gradStatusEventRepository;
private final EducGradStudentApiConstants constants;

public PurgeOldRecordsScheduler(final GradStatusEventRepository gradStatusEventRepository,
final EducGradStudentApiConstants constants) {
this.gradStatusEventRepository = gradStatusEventRepository;
this.constants = constants;
}

@Scheduled(cron = "${cron.scheduled.process.purge-old-records.run}")
@SchedulerLock(name = "PurgeOldRecordsLock",
lockAtLeastFor = "PT1H", lockAtMostFor = "PT1H") //midnight job so lock for an hour
@Transactional
public void purgeOldRecords() {
LockAssert.assertLocked();
final LocalDateTime createDateToCompare = this.calculateCreateDateBasedOnStaleEventInDays();
this.gradStatusEventRepository.deleteByCreateDateBefore(createDateToCompare);
}

private LocalDateTime calculateCreateDateBasedOnStaleEventInDays() {
final LocalDateTime currentTime = LocalDateTime.now();
return currentTime.minusDays(this.constants.getRecordsStaleInDays());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ public GraduationStudentRecord saveGraduationStudentRecord(UUID studentID, Gradu
if (gradStatusOptional.isPresent()) {
GraduationStudentRecordEntity gradEntity = gradStatusOptional.get();
gradEntity = handleExistingGraduationStatus(sourceObject, gradEntity, graduationStatus.getPen(), ongoingUpdate);
return graduationStatusTransformer.transformToDTO(gradEntity);
return graduationStatusTransformer.transformToDTOWithModifiedProgramCompletionDate(gradEntity);
} else {
sourceObject = handleNewGraduationStatus(sourceObject, graduationStatus.getPen(), ongoingUpdate);
return graduationStatusTransformer.transformToDTO(sourceObject);
return graduationStatusTransformer.transformToDTOWithModifiedProgramCompletionDate(sourceObject);
}
}

Expand All @@ -116,7 +116,7 @@ public GraduationStudentRecord updateGraduationStatusByFields(OngoingUpdateReque
if (constants.isStudentGuidPenXrefEnabled() && StringUtils.isNotBlank(requestDTO.getPen())) {
saveStudentGuidPenXref(gradEntity.getStudentID(), requestDTO.getPen());
}
return graduationStatusTransformer.transformToDTO(gradEntity);
return graduationStatusTransformer.transformToDTOWithModifiedProgramCompletionDate(gradEntity);
}
return null;
}
Expand Down Expand Up @@ -275,21 +275,33 @@ private void populateOngoingUpdateFields(List<OngoingUpdateFieldDTO> fields, Gra
if (f.getName() == FieldName.GRAD_PROGRAM) {
String newProgram = (String) f.getValue();
String currentProgram = targetObject.getProgram();
if (!StringUtils.equalsIgnoreCase(currentProgram, newProgram)) {
if("SCCP".equalsIgnoreCase(currentProgram)) {
log.info(" {} ==> {}: Archive Student Achievements and SLP_DATE is set to null.", currentProgram, newProgram);
targetObject.setProgramCompletionDate(null);
graduationStatusService.archiveStudentAchievements(targetObject.getStudentID(),accessToken);
} else {
log.info(" {} ==> {}: Delete Student Achievements.", currentProgram, newProgram);
graduationStatusService.deleteStudentAchievements(targetObject.getStudentID(), accessToken);
}
}
handleStudentAchievements(currentProgram, newProgram, targetObject, accessToken);
resetAdultStartDate(currentProgram, newProgram, targetObject);
}
populate(f, targetObject);
});
}

private void handleStudentAchievements(String currentProgram, String newProgram, GraduationStudentRecordEntity targetObject, String accessToken) {
if (!StringUtils.equalsIgnoreCase(currentProgram, newProgram)) {
if("SCCP".equalsIgnoreCase(currentProgram)) {
log.info(" {} ==> {}: Archive Student Achievements and SLP_DATE is set to null.", currentProgram, newProgram);
targetObject.setProgramCompletionDate(null);
graduationStatusService.archiveStudentAchievements(targetObject.getStudentID(),accessToken);
} else {
log.info(" {} ==> {}: Delete Student Achievements.", currentProgram, newProgram);
graduationStatusService.deleteStudentAchievements(targetObject.getStudentID(), accessToken);
}
}
}

private void resetAdultStartDate(String currentProgram, String newProgram, GraduationStudentRecordEntity targetObject) {
// Only when 1950 adult program is channged to another, reset adultStartDate to null
if (!StringUtils.equalsIgnoreCase(currentProgram, newProgram) && "1950".equalsIgnoreCase(currentProgram)) {
targetObject.setAdultStartDate(null);
}
}

private void populate(OngoingUpdateFieldDTO field, GraduationStudentRecordEntity targetObject) {
switch (field.getName()) {
case SCHOOL_OF_RECORD -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ private GradSearchStudent populateGradSearchStudent(Student student, String acce
BeanUtils.copyProperties(student, gradStu);
GraduationStudentRecordEntity graduationStatusEntity = graduationStatusRepository.findByStudentID(UUID.fromString(student.getStudentID()));
if(graduationStatusEntity != null) {
GraduationStudentRecord gradObj = graduationStatusTransformer.transformToDTO(graduationStatusEntity);
GraduationStudentRecord gradObj = graduationStatusTransformer.transformToDTOWithModifiedProgramCompletionDate(graduationStatusEntity);
gradStu.setProgram(gradObj.getProgram());
gradStu.setStudentGrade(gradObj.getStudentGrade());
gradStu.setStudentStatus(gradObj.getStudentStatus());
Expand Down
Loading
Loading