package net.gepafin.tendermanagement.dao; 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.enums.ApplicationEvaluationStatusTypeEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.enums.AssignedApplicationEnum; 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.response.AmendmentFormFieldResponse; import net.gepafin.tendermanagement.model.response.ApplicationAmendmentRequestResponse; import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.util.DateTimeUtil; 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.temporal.ChronoUnit; import java.time.LocalDateTime; 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 FormRepository formRepository; @Autowired private UserService userService; @Autowired private DocumentService documentService; @Autowired private ApplicationFormRepository applicationFormRepository; @Autowired private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; @Autowired private ApplicationFormFieldRepository applicationFormFieldRepository; @Autowired private DocumentRepository documentRepository; @Autowired private ApplicationEvaluationService applicationEvaluationService; @Autowired private AssignedApplicationsService assignedApplicationsService; @Autowired private ApplicationEvaluationRepository applicationEvaluationRepository; @Autowired private ApplicationRepository applicationRepository; @Autowired private AssignedApplicationsRepository assignedApplicationsRepository; public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(HttpServletRequest request, 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); return applicationAmendmentRequestResponse; } public ApplicationAmendmentRequestEntity createApplicationAmendmentRequestEntity(ApplicationAmendmentRequest applicationAmendmentRequest,Long applicationEvaluationId){ ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = new ApplicationAmendmentRequestEntity(); applicationAmendmentRequestEntity.setNote(applicationAmendmentRequest.getNote()); applicationAmendmentRequestEntity.setResponseDays(applicationAmendmentRequest.getResponseDays()); ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluation(applicationEvaluationId); applicationAmendmentRequestEntity.setApplicationEvaluationEntity(applicationEvaluationEntity); Long applicationId = applicationEvaluationEntity.getApplicationId(); Long assignedApplicationId = applicationEvaluationEntity.getAssignedApplicationsEntity().getId(); applicationAmendmentRequestEntity.setApplicationId(applicationId); if (applicationAmendmentRequest.getFormFields() != null) { String fieldIdsString = applicationAmendmentRequest.getFormFields().stream() .filter(AmendmentFormFieldResponse::isSelected) .map(AmendmentFormFieldResponse::getFieldId) .collect(Collectors.joining(",")); applicationAmendmentRequestEntity.setFormFields(fieldIdsString); } applicationAmendmentRequestEntity.setIsEmail(false); applicationAmendmentRequestEntity.setIsNotification(false); 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.setApplicationEvaluationId(applicationAmendmentRequestEntity.getApplicationEvaluationEntity().getId()); applicationAmendmentRequestResponse.setNote(applicationAmendmentRequestEntity.getNote()); applicationAmendmentRequestResponse.setResponseDays(applicationAmendmentRequestEntity.getResponseDays()); LocalDateTime startDate = applicationAmendmentRequestEntity.getCreatedDate(); applicationAmendmentRequestResponse.setStartDate(startDate); LocalDateTime expirationDate = startDate.plus(expirationDays, ChronoUnit.DAYS); applicationAmendmentRequestResponse.setExpirationDate(expirationDate); applicationAmendmentRequestResponse.setSendEmail(applicationAmendmentRequestEntity.getIsEmail()); applicationAmendmentRequestResponse.setSendNotification(applicationAmendmentRequestEntity.getIsNotification()); 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.setCallName(callName); applicationAmendmentRequestResponse.setProtocolNumber(protocolNumber); applicationAmendmentRequestResponse.setBeneficiaryName(beneficiaryName); String formFieldsString = applicationAmendmentRequestEntity.getFormFields(); List storedFieldIds = (formFieldsString != null) ? Arrays.asList(formFieldsString.split(",")) : Collections.emptyList(); List applicationForms = applicationFormRepository.findByApplicationId(application.getId()); List formFields = new ArrayList<>(); for (ApplicationFormEntity formEntity : applicationForms) { String content = formEntity.getForm().getContent(); List> result = filterByName(content, "fileupload"); List matchingFields = getIdAndLabelFromResult(result).stream() .filter(field -> storedFieldIds.contains(field.getFieldId())) .collect(Collectors.toList()); formFields.addAll(matchingFields); } applicationAmendmentRequestResponse.setFormFields(formFields); List formField = formFields.stream() .map(field -> { AmendmentFormFieldResponse responseField = new AmendmentFormFieldResponse(); responseField.setFieldId(field.getFieldId()); responseField.setLabel(field.getLabel()); responseField.setSelected(true); return responseField; }) .collect(Collectors.toList()); applicationAmendmentRequestResponse.setFormFields(formField); return applicationAmendmentRequestResponse; } public ApplicationAmendmentRequestEntity validateApplicationAmendmentRequest(Long id){ ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id).orElseThrow(()-> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); return applicationAmendmentRequestEntity; } public void deleteById(Long id) { log.info("Deleting assigned application with ID: {}", id); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity= validateApplicationAmendmentRequest(id); applicationAmendmentRequestEntity.setIsDeleted(true); applicationAmendmentRequestEntity= 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(Long 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.getUpdatedFormFields() != null) { updateApplicationFormFields(existingApplicationAmendment, updateRequest.getUpdatedFormFields()); } 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) { List documentIds; // Check if fieldValue is an array if (updatedFormField.getFieldValue() instanceof List) { documentIds = ((List) updatedFormField.getFieldValue()).stream() .map(Object::toString) .collect(Collectors.toList()); } else { log.warn("Expected fieldValue as a list but got: {}", updatedFormField.getFieldValue()); return; } List validDocumentIds = new ArrayList<>(); for (String documentId : documentIds) { DocumentEntity documentEntity = documentService.validateDocument(Long.parseLong(documentId)); if (documentEntity != null) { validDocumentIds.add(documentId); } else { log.warn("Document with ID {} does not exist. Skipping this ID.", documentId); } } if (!validDocumentIds.isEmpty()) { 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(String.join(",", validDocumentIds)); applicationFormFieldRepository.save(formEntity); log.info("Updated field value for application ID {} and field ID {} with document IDs {}", applicationAmendment.getApplicationId(), updatedFormField.getFieldId(), String.join(",", validDocumentIds)); fieldUpdated = true; break; } } if (!fieldUpdated) { log.warn("No ApplicationFormFieldEntity found for application ID {} and field ID {}. Skipping update.", applicationAmendment.getApplicationId(), updatedFormField.getFieldId()); } } else { log.warn("No valid document IDs found for update. Skipping field ID {}", updatedFormField.getFieldId()); } } public List getAllAmendmentRequestByBeneficiaryId(Long beneficiaryId) { List entities = applicationAmendmentRequestRepository.findByUserId(beneficiaryId); return entities.stream() .map(this::convertEntityToResponse) .collect(Collectors.toList()); } }