package net.gepafin.tendermanagement.dao; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.Predicate; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequest; import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequestBean; import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean; import net.gepafin.tendermanagement.model.request.CloseAmendmentRequest; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Validator; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; import static net.gepafin.tendermanagement.util.Utils.log; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; @Component public class ApplicationAmendmentRequestDao { @Value("${application.amendment.expiration.days}") private long expirationDays; @Autowired private ApplicationService applicationService; @Autowired private UserService userService; @Autowired private DocumentService documentService; @Autowired private ApplicationFormRepository applicationFormRepository; @Autowired private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; @Autowired private ApplicationFormFieldRepository applicationFormFieldRepository; @Autowired private EmailNotificationDao emailNotificationDao; @Autowired private ApplicationEvaluationService applicationEvaluationService; @Autowired private ProtocolDao protocolDao; @Autowired private AssignedApplicationsService assignedApplicationsService; @Autowired private ApplicationEvaluationRepository applicationEvaluationRepository; @Autowired private ApplicationRepository applicationRepository; @Autowired private AssignedApplicationsRepository assignedApplicationsRepository; @Autowired private SystemEmailTemplatesService systemEmailTemplatesService; @Autowired private CallDao callDao; @Autowired private DocumentRepository documentRepository; @Autowired private HubService hubService; // @Autowired // private MailUtil mailUtil; @Autowired private Validator validator; public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(Long applicationEvaluationId) { log.info("Fetching the application data for the Amendment process {}", applicationEvaluationId); ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluation(applicationEvaluationId); Long applicationId = applicationEvaluationEntity.getApplicationId(); ApplicationEntity application = applicationService.validateApplication(applicationId); // Set common application-level details String callName = application.getCall().getName(); Long protocolNumber = (application.getProtocol() != null && application.getProtocol().getProtocolNumber() != null) ? application.getProtocol().getProtocolNumber() : null; UserEntity userEntity = userService.validateUser(application.getUserId()); String firstName = userEntity.getBeneficiary() != null ? userEntity.getBeneficiary().getFirstName() : ""; String lastName = userEntity.getBeneficiary() != null ? userEntity.getBeneficiary().getLastName() : ""; String beneficiaryName = (!firstName.isBlank() ? firstName : "") + (!lastName.isBlank() ? " " + lastName : ""); beneficiaryName = beneficiaryName.isBlank() ? "" : beneficiaryName; ApplicationAmendmentRequestResponse response = new ApplicationAmendmentRequestResponse(); response.setId(applicationEvaluationId); response.setProtocolNumber(protocolNumber); response.setCallName(callName); response.setBeneficiaryName(beneficiaryName); response.setApplicationId(applicationId); response.setApplicationEvaluationId(applicationEvaluationId); List forms = applicationFormRepository.findByApplicationId(applicationId); List allFormFields = new ArrayList<>(); for (ApplicationFormEntity form : forms) { String content = form.getForm().getContent(); List> result = filterByName(content, "fileupload"); allFormFields.addAll(getIdAndLabelFromResult(result)); } response.setFormFields(allFormFields); return response; } public List getIdAndLabelFromResult(List> result) { List formFieldResponses = new ArrayList<>(); for (Map item : result) { AmendmentFormFieldResponse formFieldResponse = new AmendmentFormFieldResponse(); formFieldResponse.setFieldId((String) item.get("id")); // Extract "label" value from the "settings" array List> settings = (List>) item.get("settings"); String label = settings.stream() .filter(setting -> "label".equals(setting.get("name"))) .map(setting -> (String) setting.get("value")) .findFirst() .orElse(""); // Default to empty string if not found if (label == null || label.trim().isEmpty()) { continue; } formFieldResponse.setLabel(label); // Set the label as fieldValue formFieldResponses.add(formFieldResponse); } return formFieldResponses; } public static List> filterByName(String content, String target) { ObjectMapper objectMapper = new ObjectMapper(); List> filteredList = new ArrayList<>(); try { List> dataList = objectMapper.readValue( content, new TypeReference>>() { }); for (Map data : dataList) { if (target.equals(data.get("name"))) { filteredList.add(data); } } } catch (Exception e) { e.printStackTrace(); } return filteredList; } public ApplicationAmendmentRequestResponse createApplicationAmendmentRequest(Long applicationEvaluationId, ApplicationAmendmentRequest applicationAmendmentRequest) { log.info("Submiting application data for amendment Process with details: {}", applicationEvaluationId); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = createApplicationAmendmentRequestEntity(applicationAmendmentRequest, applicationEvaluationId); ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = convertEntityToResponse(applicationAmendmentRequestEntity); log.info("Application submitted successfully for amendment", applicationAmendmentRequestResponse); if (Boolean.TRUE.equals(applicationAmendmentRequestResponse.getIsSendEmail())) { emailNotificationDao.sendMailToNotifyBeneficiaryRegardingNewAmendment(applicationAmendmentRequestEntity); } return applicationAmendmentRequestResponse; } public ApplicationAmendmentRequestEntity createApplicationAmendmentRequestEntity(ApplicationAmendmentRequest applicationAmendmentRequest,Long applicationEvaluationId) { ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = new ApplicationAmendmentRequestEntity(); applicationAmendmentRequestEntity.setNote(applicationAmendmentRequest.getNote()); applicationAmendmentRequestEntity.setResponseDays(applicationAmendmentRequest.getResponseDays()); applicationAmendmentRequestEntity.setIsEmail(applicationAmendmentRequest.getIsSendEmail()); applicationAmendmentRequestEntity.setIsNotification(applicationAmendmentRequest.getIsSendNotification()); applicationAmendmentRequestEntity.setStartDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); applicationAmendmentRequestEntity.setStatus(ApplicationAmendmentRequestEnum.AWAITING.getValue()); ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluation(applicationEvaluationId); applicationAmendmentRequestEntity.setApplicationEvaluationEntity(applicationEvaluationEntity); Long applicationId = applicationEvaluationEntity.getApplicationId(); Long assignedApplicationId = applicationEvaluationEntity.getAssignedApplicationsEntity().getId(); applicationAmendmentRequestEntity.setApplicationId(applicationId); if (applicationAmendmentRequest.getFormFields() != null) { List formFieldRequestBean = applicationAmendmentRequest.getFormFields().stream() .filter(AmendmentFormFieldResponse::isSelected) .map(amendmentFormFieldRequest -> { ApplicationFormFieldRequestBean formField = new ApplicationFormFieldRequestBean(); formField.setFieldId(amendmentFormFieldRequest.getFieldId()); formField.setFieldValue(null); return formField; }) .collect(Collectors.toList()); String formFieldsJson = Utils.convertObjectToJson(formFieldRequestBean); applicationAmendmentRequestEntity.setFormFields(formFieldsJson); } UserEntity userEntity = userService.validateUser(applicationEvaluationEntity.getUserId()); Long protocolNumber = protocolDao.getProtocolNumber(userEntity.getHub()); ProtocolEntity protocolEntity = protocolDao.createProtocolEntity( applicationEvaluationEntity.getAssignedApplicationsEntity().getApplication(), protocolNumber, userEntity.getHub().getId()); applicationAmendmentRequestEntity.setProtocol(protocolEntity); ApplicationAmendmentRequestEntity applicationAmendment = saveApplicationAmendmentRequestEntity(applicationAmendmentRequestEntity); //Set Status applicationEvaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue()); applicationEvaluationRepository.save(applicationEvaluationEntity); ApplicationEntity applicationEntity = applicationService.validateApplication(applicationId); applicationEntity.setStatus(ApplicationStatusTypeEnum.SOCCORSO.getValue()); applicationRepository.save(applicationEntity); AssignedApplicationsEntity assignedApplicationsEntity = assignedApplicationsService.validateAssignedApplication(assignedApplicationId); assignedApplicationsEntity.setStatus(AssignedApplicationEnum.SOCCORSO.getValue()); assignedApplicationsRepository.save(assignedApplicationsEntity); return applicationAmendment; } public ApplicationAmendmentRequestEntity saveApplicationAmendmentRequestEntity(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) { ApplicationAmendmentRequestEntity applicationAmendmentRequest = applicationAmendmentRequestRepository.save(applicationAmendmentRequestEntity); return applicationAmendmentRequest; } public ApplicationAmendmentRequestResponse convertEntityToResponse(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) { ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = new ApplicationAmendmentRequestResponse(); applicationAmendmentRequestResponse.setId(applicationAmendmentRequestEntity.getId()); Long applicationId = applicationAmendmentRequestEntity.getApplicationId(); ApplicationEntity application = applicationService.validateApplication(applicationId); applicationAmendmentRequestResponse.setApplicationId(applicationId); applicationAmendmentRequestResponse.setCallEmail(application.getCall().getEmail()); applicationAmendmentRequestResponse.setApplicationEvaluationId(applicationAmendmentRequestEntity.getApplicationEvaluationEntity().getId()); applicationAmendmentRequestResponse.setNote(applicationAmendmentRequestEntity.getNote()); applicationAmendmentRequestResponse.setStatus(ApplicationAmendmentRequestEnum.valueOf(applicationAmendmentRequestEntity.getStatus())); applicationAmendmentRequestResponse.setResponseDays(applicationAmendmentRequestEntity.getResponseDays()); applicationAmendmentRequestResponse.setInternalNote(applicationAmendmentRequestEntity.getInternalNote()); LocalDateTime startDate = applicationAmendmentRequestEntity.getStartDate(); applicationAmendmentRequestResponse.setStartDate(startDate); LocalDateTime expirationDate = startDate.plus(expirationDays, ChronoUnit.DAYS); applicationAmendmentRequestResponse.setExpirationDate(expirationDate); applicationAmendmentRequestResponse.setIsSendEmail(applicationAmendmentRequestEntity.getIsEmail()); applicationAmendmentRequestResponse.setIsSendNotification(applicationAmendmentRequestEntity.getIsNotification()); String callName = application.getCall().getName(); Long protocolNumber = (applicationAmendmentRequestEntity.getProtocol() != null && applicationAmendmentRequestEntity.getProtocol().getProtocolNumber() != null) ? applicationAmendmentRequestEntity.getProtocol().getProtocolNumber() : null; UserEntity userEntity = userService.validateUser(application.getUserId()); String firstName = userEntity.getBeneficiary() != null ? userEntity.getBeneficiary().getFirstName() : ""; String lastName = userEntity.getBeneficiary() != null ? userEntity.getBeneficiary().getLastName() : ""; String beneficiaryName = (!firstName.isBlank() ? firstName : "") + (!lastName.isBlank() ? " " + lastName : ""); beneficiaryName = beneficiaryName.isBlank() ? "" : beneficiaryName; applicationAmendmentRequestResponse.setCallName(callName); applicationAmendmentRequestResponse.setProtocolNumber(protocolNumber); applicationAmendmentRequestResponse.setBeneficiaryName(beneficiaryName); List forms = applicationFormRepository.findByApplicationId(applicationId); List allFormFields = new ArrayList<>(); for (ApplicationFormEntity form : forms) { String content = form.getForm().getContent(); List> result = filterByName(content, "fileupload"); allFormFields.addAll(getIdAndLabelFromResult(result)); } Map fieldIdToLabelMap = allFormFields.stream() .collect(Collectors.toMap(AmendmentFormFieldResponse::getFieldId, AmendmentFormFieldResponse::getLabel)); String formFieldsJson = applicationAmendmentRequestEntity.getFormFields(); List formFields = Utils.convertJsonToList( formFieldsJson, new TypeReference>() { }); for (AmendmentFormFieldResponse formField : formFields) { String label = fieldIdToLabelMap.get(formField.getFieldId()); formField.setLabel(label); formField.setSelected(true); } // Set the filtered formFields in the response applicationAmendmentRequestResponse.setFormFields(formFields); String applicationFormFieldsJson = applicationAmendmentRequestEntity.getFormFields(); List applicationFormFields = Utils.convertJsonToList( formFieldsJson, new TypeReference>() { }); List fileDetailResponses = new ArrayList<>(); for (ApplicationFormFieldResponseBean field : applicationFormFields) { ApplicationFormFieldResponseBean responseBean = new ApplicationFormFieldResponseBean(); responseBean.setFieldId(field.getFieldId()); Optional formFieldEntity = Optional.empty(); for (ApplicationFormEntity form : forms) { formFieldEntity = applicationFormFieldRepository .findByApplicationFormIdAndFieldId(form.getId(), field.getFieldId()); if (formFieldEntity.isPresent()) { // Set the applicationFormId from the matching form responseBean.setApplicationFormId(form.getId()); responseBean.setId(formFieldEntity.get().getId()); responseBean.setCreatedDate(formFieldEntity.get().getCreatedDate()); responseBean.setUpdatedDate(formFieldEntity.get().getUpdatedDate()); break; } } // Check if fieldValue is not null and is a String if (field.getFieldValue() instanceof String && field.getFieldValue() != null && !((String) field.getFieldValue()).isBlank()) { String fieldValueString = (String) field.getFieldValue(); String[] documentIds = fieldValueString.split(","); List documentResponseBeans = new ArrayList<>(); // Process each document ID for (String docId : documentIds) { try { Long documentId = Long.valueOf(docId.trim()); documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { DocumentResponseBean docBean = new DocumentResponseBean(); docBean.setId(documentEntity.getId()); docBean.setName(documentEntity.getFileName()); docBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); docBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); docBean.setSourceId(documentEntity.getSourceId()); docBean.setFilePath(documentEntity.getFilePath()); docBean.setCreatedDate(documentEntity.getCreatedDate()); docBean.setUpdatedDate(documentEntity.getUpdatedDate()); documentResponseBeans.add(docBean); }); } catch (NumberFormatException e) { // Handle the case where documentId is not a valid number // Log the error if necessary } } responseBean.setFieldValue(documentResponseBeans); } else { responseBean.setFieldValue(null); } fileDetailResponses.add(responseBean); } applicationAmendmentRequestResponse.setApplicationFormFields(fileDetailResponses); return applicationAmendmentRequestResponse; } public ApplicationAmendmentRequestEntity validateApplicationAmendmentRequest(Long id) { return applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); } public void deleteById(Long id) { log.info("Deleting assigned application with ID: {}", id); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id); applicationAmendmentRequestEntity.setIsDeleted(true); saveApplicationAmendmentRequestEntity(applicationAmendmentRequestEntity); log.info(" Application amendment deleted with ID: {}", id); } public ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(Long id) { log.info("Fetching application amendment with ID: {}", id); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id); ApplicationAmendmentRequestResponse response = convertEntityToResponse(applicationAmendmentRequestEntity); log.info("Application Amendment fetched successfully by ID: {}", response); return response; } public List getAllApplicationAmendmentRequest(HttpServletRequest request, Long userId) { if (validator.checkIsPreInstructor() && userId == null) { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.USER_ID_NOT_NULL_MSG)); } if (userId != null) { validator.validatePreInstructor(request, userId); } Specification spec = search(userId); List applicationAmendmentRequestEntities = applicationAmendmentRequestRepository.findAll(spec); return applicationAmendmentRequestEntities.stream() .map(this::convertEntityToResponse) .collect(Collectors.toList()); } private Specification search(Long userId) { return (root, query, builder) -> { Predicate predicate = builder.isFalse(root.get("isDeleted")); // Only non-deleted records if (userId != null) { Join evaluationJoin = root.join("applicationEvaluationEntity"); predicate = builder.and(predicate, builder.equal(evaluationJoin.get("userId"), userId)); } return predicate; // Return final predicate }; } public ApplicationAmendmentRequestResponse updateApplicationAmendment( Long id, ApplicationAmendmentRequestBean updateRequest) { log.info("Updating application amendement with ID: {}", id); ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id); setIfUpdated(existingApplicationAmendment::getNote, existingApplicationAmendment::setNote, updateRequest.getNote()); if (updateRequest.getApplicationFormFields() != null) { updateApplicationFormFields(existingApplicationAmendment, updateRequest.getApplicationFormFields()); updateFormFieldsJson(existingApplicationAmendment, updateRequest.getApplicationFormFields()); } existingApplicationAmendment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); ApplicationAmendmentRequestEntity updatedApplicationAmendment = saveApplicationAmendmentRequestEntity(existingApplicationAmendment); ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment); log.info("Application Amendment updated successfully: {}", response); return response; } private void updateApplicationFormFields(ApplicationAmendmentRequestEntity applicationAmendment, ApplicationFormFieldRequestBean updatedFormField) { if (updatedFormField.getFieldValue() == null || "".equals(updatedFormField.getFieldValue().toString().trim())) { List applicationForms = applicationFormRepository.findByApplicationId(applicationAmendment.getApplicationId()); boolean fieldUpdated = false; for (ApplicationFormEntity applicationForm : applicationForms) { Optional formFieldEntityOptional = applicationFormFieldRepository .findByApplicationFormIdAndFieldId(applicationForm.getId(), updatedFormField.getFieldId()); if (formFieldEntityOptional.isPresent()) { ApplicationFormFieldEntity formEntity = formFieldEntityOptional.get(); formEntity.setFieldValue(null); // Set field value to null applicationFormFieldRepository.save(formEntity); log.info("Set field value to null for application ID {} and field ID {}", applicationAmendment.getApplicationId(), updatedFormField.getFieldId()); fieldUpdated = true; break; } } if (!fieldUpdated) { throw new CustomValidationException(Status.NOT_FOUND, "No ApplicationFormField found for application ID " + applicationAmendment.getApplicationId() + " and field ID " + updatedFormField.getFieldId()); } return; } List documentIds; if (updatedFormField.getFieldValue() instanceof String && updatedFormField.getFieldValue() != null) { documentIds = Arrays.asList(((String) updatedFormField.getFieldValue()).split(",")); } else { log.warn("Expected fieldValue as a comma-separated String but got: {}", updatedFormField.getFieldValue()); return; } List validDocumentIds = new ArrayList<>(); for (String documentId : documentIds) { try { DocumentEntity documentEntity = documentService.validateDocument(Long.parseLong(documentId.trim())); if (documentEntity != null) { validDocumentIds.add(documentId.trim()); } else { log.warn("Document with ID {} does not exist. Skipping this ID.", documentId); } } catch (NumberFormatException e) { log.error("Invalid document ID format: {}. Error: {}", documentId, e.getMessage()); } } if (!validDocumentIds.isEmpty()) { List applicationForms = applicationFormRepository.findByApplicationId(applicationAmendment.getApplicationId()); boolean fieldUpdated = false; // Parse the formFields JSON string to get amendment field values String amendmentFieldValue = null; try { ObjectMapper mapper = new ObjectMapper(); List amendmentFields = mapper.readValue( applicationAmendment.getFormFields(), mapper.getTypeFactory().constructCollectionType(List.class, ApplicationFormFieldRequestBean.class) ); // Find the matching field value and convert to string if found Optional amendmentFieldObj = amendmentFields.stream() .filter(field -> updatedFormField.getFieldId().equals(field.getFieldId())) .map(ApplicationFormFieldRequestBean::getFieldValue) .findFirst(); if (amendmentFieldObj.isPresent() && amendmentFieldObj.get() instanceof String) { amendmentFieldValue = (String) amendmentFieldObj.get(); } } catch (JsonProcessingException e) { log.error("Error parsing formFields JSON: {}", e.getMessage()); return; } if (amendmentFieldValue == null) { log.warn("No matching field found in amendment for field ID {}", updatedFormField.getFieldId()); return; } List amendmentDocumentIds = Arrays.asList(amendmentFieldValue.split(",")); for (ApplicationFormEntity applicationForm : applicationForms) { Optional formFieldEntityOptional = applicationFormFieldRepository .findByApplicationFormIdAndFieldId(applicationForm.getId(), updatedFormField.getFieldId()); if (formFieldEntityOptional.isPresent()) { ApplicationFormFieldEntity formEntity = formFieldEntityOptional.get(); // Retrieve existing document IDs in ApplicationFormFieldTable String existingFieldValue = formEntity.getFieldValue(); Set existingDocumentIds = existingFieldValue != null ? new HashSet<>(Arrays.asList(existingFieldValue.split(","))) : new HashSet<>(); // Remove amendment documents from existing document IDs existingDocumentIds.removeAll(amendmentDocumentIds); // Add valid new document IDs from the request existingDocumentIds.addAll(validDocumentIds); // Set the combined document IDs back as the field value formEntity.setFieldValue(String.join(",", existingDocumentIds)); applicationFormFieldRepository.save(formEntity); log.info("Updated field value for application ID {} and field ID {} with document IDs {}", applicationAmendment.getApplicationId(), updatedFormField.getFieldId(), String.join(",", existingDocumentIds)); fieldUpdated = true; break; } } if (!fieldUpdated) { throw new CustomValidationException(Status.NOT_FOUND, String.format("No ApplicationFormField found for application ID %s and field ID %s. Skipping update.", applicationAmendment.getApplicationId(), updatedFormField.getFieldId())); } } else { log.warn("No valid document IDs found for update. Skipping field ID {}", updatedFormField.getFieldId()); } } private void updateFormFieldsJson(ApplicationAmendmentRequestEntity applicationAmendment, ApplicationFormFieldRequestBean updatedFormField) { if (updatedFormField != null) { try { // Step 1: Fetch the existing form fields JSON String existingFormFieldsJson = applicationAmendment.getFormFields(); List formFieldsList; if (existingFormFieldsJson == null || existingFormFieldsJson.isEmpty()) { formFieldsList = new ArrayList<>(); // If no existing data, start with an empty list } else { // Step 2: Deserialize the existing JSON into a list of objects formFieldsList = new ObjectMapper().readValue(existingFormFieldsJson, new TypeReference>() { }); } // Step 3: Check if the field ID already exists in the list and update it boolean fieldUpdated = false; for (ApplicationFormFieldRequestBean field : formFieldsList) { if (field.getFieldId().equals(updatedFormField.getFieldId())) { field.setFieldValue(updatedFormField.getFieldValue()); // Update field value fieldUpdated = true; break; } } // If field wasn't updated, log a warning message instead of adding a new field if (!fieldUpdated) { log.warn("Field ID {} does not exist in the form fields for application amendment ID {}", updatedFormField.getFieldId(), applicationAmendment.getId()); throw new CustomValidationException(Status.NOT_FOUND, "Field ID {} does not exist in the form fields for application amendment ID {}"); } // Step 4: Serialize the updated list back to JSON if the update was successful String updatedFormFieldsJson = new ObjectMapper().writeValueAsString(formFieldsList); applicationAmendment.setFormFields(updatedFormFieldsJson); // Update the form fields with the modified list log.info("Updated form fields JSON for application amendment ID {}: {}", applicationAmendment.getId(), updatedFormFieldsJson); } catch (JsonProcessingException e) { log.error("Error processing JSON for form fields for application amendment ID {}: {}", applicationAmendment.getId(), e.getMessage()); throw new CustomValidationException(Status.BAD_REQUEST, "Error processing JSON for form fields"); } } else { log.warn("No form field data to update for application amendment ID {}", applicationAmendment.getId()); throw new CustomValidationException(Status.NOT_FOUND, "No form field data to update for application amendment ID {}"); } } public List getAllAmendmentRequestByBeneficiaryId(Long beneficiaryId) { UserEntity userEntity = userService.validateUser(beneficiaryId); List entities = applicationAmendmentRequestRepository.findByUserId(beneficiaryId); return entities.stream() .map(this::convertEntityToResponse) .collect(Collectors.toList()); } public ApplicationAmendmentRequestResponse closeAmendmentRequest(Long id, CloseAmendmentRequest closeAmendmentRequest) { log.info("Closing application amendement with ID: {}", id); ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id); setIfUpdated(existingApplicationAmendment::getInternalNote, existingApplicationAmendment::setInternalNote, closeAmendmentRequest.getInternalNote()); setIfUpdated(existingApplicationAmendment::getStatus, existingApplicationAmendment::setStatus, ApplicationAmendmentRequestEnum.CLOSE.getValue()); ApplicationAmendmentRequestEntity updatedApplicationAmendment = saveApplicationAmendmentRequestEntity(existingApplicationAmendment); ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment); log.info("Application Amendment closed successfully: {}", response); return response; } public ApplicationAmendmentRequestResponse extendResponseDays(Long id, Long newResponseDays) { ApplicationAmendmentRequestEntity request = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); if (newResponseDays != null && newResponseDays > 0) { Long currentResponseDays = request.getResponseDays() != null ? request.getResponseDays() : 0L; request.setResponseDays(currentResponseDays + newResponseDays); applicationAmendmentRequestRepository.save(request); } return convertEntityToResponse(request); } public List getAmendmentByApplicationId(HttpServletRequest request, Long applicationId, List statuses) { log.info("Fetching the Amendment data from application id {}", applicationId); ApplicationEntity application = applicationService.validateApplication(applicationId); List applicationAmendmentRequestEntity = applicationAmendmentRequestRepository.findByApplicationIdAndIsDeletedFalse(applicationId); if (statuses != null && !statuses.isEmpty()) { List statusStrings = statuses.stream().map(Enum::name).collect(Collectors.toList()); applicationAmendmentRequestEntity = applicationAmendmentRequestRepository.findByApplicationIdAndStatusInAndIsDeletedFalse(application.getId(), statusStrings); } if (!applicationAmendmentRequestEntity.isEmpty()) { ApplicationAmendmentRequestEntity applicationAmendmentRequest = applicationAmendmentRequestEntity.get(0); Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(applicationAmendmentRequest.getApplicationEvaluationEntity().getId()); if (entityOptional.isPresent()) { if (Boolean.FALSE.equals(validator.checkIsBeneficiary())) { validator.validatePreInstructor(request, entityOptional.get().getUserId()); } else { validator.validateUserId(request, entityOptional.get().getAssignedApplicationsEntity().getApplication().getUserId()); } } } List response = new ArrayList<>(); if (applicationAmendmentRequestEntity != null) { response = applicationAmendmentRequestEntity.stream() .map(this::convertEntityToResponse) .collect(Collectors.toList()); } return response; } public ApplicationAmendmentRequestResponse updateApplicationAmendmentStatus( Long id, ApplicationAmendmentRequestEnum statusTypeEnum) { log.info("Updating application amendement with status: {}", id); ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id); if (Boolean.TRUE.equals(existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())) && Boolean.TRUE.equals(statusTypeEnum.equals(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED))) { existingApplicationAmendment.setStatus(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue()); existingApplicationAmendment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); applicationAmendmentRequestRepository.save(existingApplicationAmendment); } ApplicationAmendmentRequestResponse response = convertEntityToResponse(existingApplicationAmendment); log.info("Amendment status updated successfully: {}", response); return response; } public void sendReminderEmail(Long amendmentId) { ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(amendmentId) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(amendment.getApplicationEvaluationEntity().getId()); if (entityOptional.isPresent()) { ApplicationEntity applicationEntity = applicationService.validateApplication(entityOptional.get().getApplicationId()); UserEntity beneficiaryUser = userService.validateUser(applicationEntity.getUserId()); HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); SystemEmailTemplateResponse emailTemplate = systemEmailTemplatesService .retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.AMENDMENT_REMINDER, hub, null); String subject = prepareSubject(emailTemplate, amendment, beneficiaryUser); String body = prepareBody(emailTemplate, amendment, beneficiaryUser); String email = beneficiaryUser.getEmail(); if (Boolean.TRUE.equals(amendment.getIsEmail()) && email != null && !email.isEmpty()) { emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email)); } else { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.BENEFICIARY_EMAIL_NOT_FOUND_MSG)); } } } private String prepareSubject(SystemEmailTemplateResponse template, ApplicationAmendmentRequestEntity amendment, UserEntity beneficiary) { Map subjectPlaceholders = new HashMap<>(); String firstName = beneficiary.getFirstName() != null ? beneficiary.getFirstName() : ""; String lastName = beneficiary.getLastName() != null ? beneficiary.getLastName() : ""; String beneficiaryName = String.join(" ", firstName, lastName).trim(); subjectPlaceholders.put("{{amendment_id}}", amendment.getId().toString()); subjectPlaceholders.put("{{beneficiary_name}}", beneficiaryName); return Utils.replacePlaceholders(template.getSubject(), subjectPlaceholders); } private String prepareBody(SystemEmailTemplateResponse template, ApplicationAmendmentRequestEntity amendment, UserEntity beneficiary) { Map bodyPlaceholders = new HashMap<>(); bodyPlaceholders.put("{{amendment_id}}", amendment.getId().toString()); if (amendment.getStartDate() != null && amendment.getResponseDays() != null) { LocalDateTime dueDate = amendment.getStartDate().plusDays(amendment.getResponseDays()); bodyPlaceholders.put("{{amendment_due_date}}", DateTimeUtil.formatLocalDateTime(dueDate, GepafinConstant.DD_MM_YYYY)); } else { bodyPlaceholders.put("{{amendment_due_date}}", "Not available"); } return Utils.replacePlaceholders(template.getHtmlContent(), bodyPlaceholders); } }