package net.gepafin.tendermanagement.scheduler; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao; import net.gepafin.tendermanagement.dao.NotificationDao; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; import net.gepafin.tendermanagement.repositories.ApplicationRepository; import net.gepafin.tendermanagement.repositories.AssignedApplicationsRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.enums.AssignedApplicationEnum; import net.gepafin.tendermanagement.enums.NotificationTypeEnum; import net.gepafin.tendermanagement.enums.UserActionContextEnum; import net.gepafin.tendermanagement.enums.UserActionLogsEnum; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.UserActionRequest; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; @Component public class ApplicationAmendmentScheduler { @Autowired private HttpServletRequest httpServletRequest; @Autowired private ApplicationAmendmentRequestRepository applicationAmendmentRepository; @Autowired private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; @Autowired private LoggingUtil loggingUtil; @Autowired private NotificationDao notificationDao; @Autowired private AssignedApplicationsRepository assignedApplicationsRepository; @Autowired private ApplicationRepository applicationRepository; @Autowired private ApplicationEvaluationRepository applicationEvaluationRepository; private static final Logger log = LoggerFactory.getLogger(ApplicationAmendmentScheduler.class); @Scheduled(cron = "0 0 1 * * ?") public void processAmendmentExpirationScheduler() { log.info("Starting the Application Amendment Expiration scheduler."); try { Utils.setHttpServletRequestForScheduler(); /** This code is responsible for creating user action logs for the "Application Amendment Expiration scheduler" operation. **/ loggingUtil.logUserActionWithoutToken( UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.SCHEDULER).actionContext(UserActionContextEnum.AMENDMENT_EXPIRATION_SCHEDULER).build()); List amendmentRequestList = applicationAmendmentRepository .findAmendmentsDueForExpiration( DateTimeUtil.DateServerToUTC(LocalDateTime.now()).with(LocalTime.MIN).plusSeconds(5)); processAmendmentsForExpiration(amendmentRequestList); log.info("Application Amendment Expiration scheduler completed successfully."); } catch (Exception e) { log.error("An error occurred during the Application Amendment Expiration scheduler: {}", e.getMessage(), e); } Utils.clearHttpServletRequest(); } private void processAmendmentsForExpiration(List amendmentRequests) { log.info("Starting the process of expiring application amendments."); amendmentRequests.forEach(request -> { try { ApplicationAmendmentRequestEntity oldAmendmentRequestEntity = Utils.getClonedEntityForData(request); request.setStatus(ApplicationAmendmentRequestEnum.EXPIRED.getValue()); ApplicationEntity application=oldAmendmentRequestEntity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication(); request = applicationAmendmentRepository.save(request); Map placeHolders=notificationDao.sendNotificationToBeneficiary(application,NotificationTypeEnum.AMENDMENT_EXPIRED); notificationDao.sendNotificationToInstructor(placeHolders,oldAmendmentRequestEntity.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_EXPIRED); /** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAmendmentRequestEntity).newData(request).build()); // emailNotificationDao.sendApplicationFailureNotificationEmail(request); log.info("Updated status to EXPIRED for ApplicationAmendmentRequest with ID: {}", request.getId()); } catch (Exception e) { log.error("Error expiring ApplicationAmendmentRequest with ID {}: {}", request.getId(), e.getMessage(), e); } }); log.info("Completed the process of updating expiring application amendments."); log.info("Starting the process of updating EndDate in ApplicationEvaluations."); try { Set applicationEvaluationIds = amendmentRequests.stream() .map(request -> request.getApplicationEvaluationEntity().getId()).collect(Collectors.toSet()); Set evaluationsWithoutActiveAmendmentList = applicationAmendmentRepository .findEvaluationsWithoutActiveAmendmentsByIds(applicationEvaluationIds); evaluationsWithoutActiveAmendmentList.forEach(evaluation -> { try { applicationAmendmentRequestDao.calculateEndDateAndSuspensionDaysOnExpirationOrClosing(evaluation); updateEvaluationStatus(evaluation); // Update AssignedApplicationsEntity status updateAssignedApplicationStatus(evaluation.getAssignedApplicationsEntity()); // Update ApplicationEntity status updateApplicationStatus(evaluation.getAssignedApplicationsEntity().getApplication()); log.info("Updated EndDate and suspension days for ApplicationEvaluation with ID: {}", evaluation.getId()); } catch (Exception e) { log.error("Error updating EndDate for ApplicationEvaluation with ID {}: {}", evaluation.getId(), e.getMessage(), e); } }); log.info("Completed the process of updating EndDate in ApplicationEvaluations."); } catch (Exception e) { log.error("An error occurred while updating EndDate in ApplicationEvaluations: {}", e.getMessage(), e); } } public void updateAssignedApplicationStatus(AssignedApplicationsEntity assignedApplicationsEntity){ AssignedApplicationsEntity oldAssignedApplicationEntity = Utils.getClonedEntityForData(assignedApplicationsEntity); assignedApplicationsEntity.setStatus(AssignedApplicationEnum.OPEN.getValue()); assignedApplicationsRepository.save(assignedApplicationsEntity); log.info("Updated status to OPEN for Assigned Application with ID: {}", assignedApplicationsEntity.getId()); /** This code is responsible for adding a version history log for the "Update Assigned Application status" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApplicationEntity).newData(assignedApplicationsEntity).build()); } public void updateApplicationStatus(ApplicationEntity applicationEntity){ ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity); applicationEntity.setStatus(applicationEntity.getPreviousStatus()); applicationRepository.save(applicationEntity); log.info("Updated status to EVALUATION for Application with ID: {}",applicationEntity.getId()); /** This code is responsible for adding a version history log for the "Update Application Status" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntity).newData(applicationEntity).build()); } public void updateEvaluationStatus(ApplicationEvaluationEntity applicationEvaluationEntity){ ApplicationEvaluationEntity oldApplicationEvaluationEntity = Utils.getClonedEntityForData(applicationEvaluationEntity); applicationEvaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.OPEN.getValue()); applicationEvaluationRepository.save(applicationEvaluationEntity); log.info("Updated status to OPEN for ApplicationEvaluation with ID: {}", applicationEvaluationEntity.getId()); /** This code is responsible for adding a version history log for the "Update Application Status" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity).newData(applicationEvaluationEntity).build()); } }