diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 45418554..3a160d09 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -233,7 +233,16 @@ public class GepafinConstant { public static final String CANNOT_DELETE_COMPANY_WITH_APPLICATION_SUBMITT = "application.in.submit.status.cannot.delete.company"; public static final String GET_USERS_SUCCESS_MSG = "get.users.success.msg"; public static final String CANNOT_CREATE_BENEFICIARY_USER="cannot.create.beneficiary.user"; - + public static final String EVALUATION_CREATED_SUCCESSFULLY = "evaluation.created.successfully"; + public static final String EVALUATION_UPDATED_SUCCESSFULLY = "evaluation.updated.successfully"; + public static final String EVALUATION_FETCHED_SUCCESSFULLY = "evaluation.fetched.successfully"; + public static final String EVALUATION_DELETED_SUCCESSFULLY = "evaluation.deleted.successfully"; + public static final String EVALUATIONS_FETCHED_SUCCESSFULLY = "evaluations.fetched.successfully"; + public static final String APPLICATION_EVALUATION_NOT_FOUND = "application.evaluation.not.found"; + public static final String APPLICATION_EVALUATION_STATUS_UPDATED_SUCCESSFULLY = "application.evaluation.status.updated.successfully"; + public static final String ASSIGNED_APPLICATION_NOT_FOUND_WITH_ID_MSG = "assigned.application.not.found.with.id"; + public static final String EITHER_APPLICATION_OR_ASSIGNED_APPLICATION_ID_REQUIRED_MSG = "either.application.or.assigned.application.id.required"; + public static final String EVALUATION_ALREADY_EXISTS_MSG = "evaluation.already.exists"; public static final String APPLICATION_ASSIGNED= "application.assigned.success.msg"; public static final String APPLICATION_ALREADY_ASSIGNED = "application.already.assigned.msg"; public static final String ASSIGNED_APPLICATION_NOT_FOUND_MSG="aasigned.application.not.found"; @@ -250,8 +259,7 @@ public class GepafinConstant { public static final String EVALUATIONCRITERIA_INVALID = "evaluationCriteria.invalid"; public static final String APPLICATION_NOT_IN_DRAFT_STATUS="application.not.in.draft.status"; public static final String GET_ERROR_S3 = "get.error.s3"; - public static final String INVALID_APPLICATION_STATUS = "invalid.application.status"; - + public static final String BENEFICIARY_EMAIL_NOT_FOUND_MSG = "beneficiary.email.not.found.msg"; public static final String ADDED_S3_PATH_STRUCTURE ="added.s3.path.structure"; public static final String S3_PATH_STRUCTURE_BY_TYPE ="fetched.s3.path.structure.by.type.successfully"; public static final String S3_PATH_STRUCTURE_NOT_FOUND_BY_TYPE_MSG ="s3.path.not.found.by.type"; @@ -260,5 +268,27 @@ public class GepafinConstant { public static final String S3_PATH_CONFIG_UPDATE_MSG ="s3.path.config.updated.successfully"; public static final String S3_PATH_CONFIG_DUPLICATE_TYPE_ALREADY_EXIST ="s3.path.config.already.exist."; public static final String S3_PATH_GENERATION_ERROR_MSG ="s3.path.config.already.exist."; + public static final String INVALID_APPLICATION_STATUS = "invalid.application.status"; + + public static final String APPLICATION_DATA_FOR_AMENDMENT_SUCCESS_MSG = "application.data.amendment.success"; + public static final String DELETE_APPLICATION_AMENDMENT_SUCCESS_MSG = "delete.application.amendment.success"; + public static final String CREATE_APPLICATION_DATA_FOR_AMENDMENT_MSG = "create.application.data.amendment.msg"; + public static final String APPLICATION_AMENDMENT_NOT_FOUND_MSG = "application.amendment.not.found"; + public static final String GET_APPLICATION_AMENDMENT_SUCCESS_MSG = "application.amendment.get.success"; + public static final String APPLICATION_AMENDMENT_UPDATE_SUCCESSFULLY_MSG = "application.amendment.update.successfully"; + public static final String APPLICATION_AMENDMENT_CLOSED_SUCCESFULLY = "application.amendment.closed.successfully"; + + public static final String RESPONSE_DAYS_EXTENDED_SUCCESS_MSG = "response.days.extended.success"; + public static final String COMMUNICATION_ADDED_TO_AMENDMENT_REQUEST_SUCCESS = "added.comment.to.amendment.request.success"; + public static final String COMMENT_NOT_FOUND = "comment.not.found"; + public static final String COMMENT_UPDATED_SUCCESS_MSG = "comment.updated.successfully"; + public static final String COMMENT_DELETED_SUCCESS_MSG = "comment.deleted.successfully"; + public static final String COMMENT_NOT_ASSOCIATE_WITH_AMENDMENT_ID_ERROR_MSG = "comment.not.associate.with.amendment"; + public static final String AMENDMENT_FOUND_SUCCESS = "amendment.found.success"; + public static final String INVALID_AMENDMENT_FOR_COMMENT = "invalid.amendment.for.comment"; + public static final String DD_MM_YYYY_HH_MM = "DD_MM_YYYY_HH_MM"; + public static final String REMINDER_EMAIL_SENT_SUCCESS_MSG = "reminder.email.sent.success.msg"; + public static final String ENCRYPT_INIT_VECTOR = "IG8*(*@&)*#biVVD"; + public static final String ENCRYPT_KEY = "U2VjdXJlRW5jcnlwdEtleQ=="; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java new file mode 100644 index 00000000..b522354d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java @@ -0,0 +1,634 @@ +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.*; +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.Validator; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; +import net.gepafin.tendermanagement.util.Utils; +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.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 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.isSendEmail())){ + 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) { + String fieldIdsString = applicationAmendmentRequest.getFormFields().stream() + .filter(AmendmentFormFieldResponse::isSelected) + .map(AmendmentFormFieldResponse::getFieldId) + .collect(Collectors.joining(",")); + applicationAmendmentRequestEntity.setFormFields(fieldIdsString); + } + 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.setSendEmail(applicationAmendmentRequestEntity.getIsEmail()); + applicationAmendmentRequestResponse.setSendNotification(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); + + 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); + + List formFieldEntities = applicationFormFieldRepository.findByApplicationFormIdIn( + applicationForms.stream().map(ApplicationFormEntity::getId).collect(Collectors.toList()) + ); + + List fileDetailResponses = new ArrayList<>(); + for (AmendmentFormFieldResponse field : formFields) { + for (ApplicationFormFieldEntity formFieldEntity : formFieldEntities) { + if (formFieldEntity.getFieldId().equals(field.getFieldId()) && formFieldEntity.getFieldValue() != null) { + ApplicationFormFieldResponseBean responseBean = new ApplicationFormFieldResponseBean(); + responseBean.setFieldId(formFieldEntity.getFieldId()); + + String[] documentIds = formFieldEntity.getFieldValue().split(","); + List documentResponseBeans = new ArrayList<>(); + + for (String docId : documentIds) { + 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); + }); + } + + responseBean.setFieldValue(documentResponseBeans); + 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()); + } + 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; + + 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) { + throw new CustomValidationException(Status.NOT_FOUND,"No ApplicationFormField found for application ID {} and field ID {}. Skipping update."); + } + } else { + log.warn("No valid document IDs found for update. Skipping field ID {}", updatedFormField.getFieldId()); + } + } + + + + 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); + } + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 4a83b837..716c1d11 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -25,14 +25,12 @@ import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.FieldValidator; -import net.gepafin.tendermanagement.util.MailUtil; 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.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -46,7 +44,6 @@ import jakarta.servlet.http.HttpServletRequest; import java.text.MessageFormat; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.*; import java.util.stream.Collectors; @@ -93,16 +90,10 @@ public class ApplicationDao { @Autowired private CompanyService companyService; - - @Autowired - private ProtocolRepository protocolRepository; @Autowired private SystemEmailTemplatesService systemEmailTemplatesService; - @Autowired - private MailUtil mailUtil; - @Value("${default_System_Receiver_Email}") private String defaultSystemReceiverEmail; @@ -136,9 +127,18 @@ public class ApplicationDao { @Autowired private S3PathConfig s3ConfigBean; + @Autowired + private ProtocolDao protocolDao; + @Autowired private HubService hubService; + @Autowired + private EmailNotificationDao emailNotificationDao; + + @Autowired + private FormDao formDao; + public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); @@ -211,8 +211,10 @@ public class ApplicationDao { ApplicationFormEntity applicationFormEntity, List applicationFormFieldResponseBeans) { - List contentResponseBeans = Utils.convertJsonStringToList( - applicationFormEntity.getForm().getContent(), ContentResponseBean.class); +// List contentResponseBeans = Utils.convertJsonStringToList( +// applicationFormEntity.getForm().getContent(), ContentResponseBean.class); + + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(applicationFormEntity.getForm()).getContent(); for (ApplicationFormFieldEntity applicationFormFieldEntity : applicationFormFieldEntities) { @@ -296,11 +298,11 @@ public class ApplicationDao { // return applicationResponses; // } - public List getAllApplications(UserEntity userEntity, Long callId, Long companyId,String status) { + public List getAllApplications(UserEntity userEntity, Long callId, Long companyId,List statusList) { log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType()); - Specification spec = search(userEntity, callId, companyId,status); + Specification spec = search(userEntity, callId, companyId,statusList); List applicationEntities = applicationRepository.findAll(spec); @@ -310,7 +312,7 @@ public class ApplicationDao { } - private Specification search(UserEntity userEntity, Long callId, Long companyId,String status) { + private Specification search(UserEntity userEntity, Long callId, Long companyId,List statusList) { return (root, query, builder) -> { Boolean isBeneficiary = validator.checkIsBeneficiary(); Predicate predicate = builder.isFalse(root.get("isDeleted")); @@ -323,8 +325,11 @@ public class ApplicationDao { if (companyId != null) { predicate = builder.and(predicate, builder.equal(root.get("company").get("id"), companyId)); } - if (status != null) { - predicate = builder.and(predicate, builder.equal(root.get("status"), status)); + if (statusList != null && !statusList.isEmpty()) { + List statusNames = statusList.stream() + .map(Enum::name) + .collect(Collectors.toList()); + predicate = builder.and(predicate, root.get("status").in(statusNames)); } predicate = builder.and(predicate, builder.equal(root.get("hubId"), userEntity.getHub().getId())); return predicate; @@ -429,7 +434,8 @@ public class ApplicationDao { private List validateFileUploadDocuments(ApplicationFormFieldRequestBean applicationFormFieldRequestBean, FormEntity formEntity) { List documentIds=null; - List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); +// List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); + List contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); for (ContentResponseBean contentResponseBean:contentResponseBeans){ if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload"))) { if (contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) { @@ -514,10 +520,63 @@ public class ApplicationDao { } else { List applicationFormEntities = applicationFormRepository.findByApplicationId(applicationEntity.getId()); - for (ApplicationFormEntity applicationFormEntity : applicationFormEntities) { - FormEntity form = formService.validateForm(applicationFormEntity.getForm().getId()); - formEntities.add(form); - addFormApplication(form, applicationEntity, formApplicationResponses); + List sequencedApplicationFormEntity = new ArrayList<>(); + Long formIdMiddle = null; + List flowEdgesList = flowEdgesRepository.findBySourceIdAndCallId( + applicationEntity.getCall().getInitialForm(), applicationEntity.getCall().getId()); + + if (!flowEdgesList.isEmpty()) { + if (flowEdgesList.size() == 1) { + formIdMiddle = flowEdgesList.get(0).getTargetId(); + } else { + List nextFormIds = flowEdgesList.stream() + .map(FlowEdgesEntity::getTargetId) + .toList(); + + FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndCallId( + applicationEntity.getCall().getInitialForm(), applicationEntity.getCall().getId()); + + ApplicationFormFieldEntity applicationFormFieldEntity = applicationFormFieldRepository + .findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId( + flowDataEntity.getChoosenField(), applicationEntity.getCall().getInitialForm(), applicationEntity.getId()) + .orElse(null); + + if (applicationFormFieldEntity != null) { + formIdMiddle = flowDataRepository.findByChoosenValueAndFormIdIn( + applicationFormFieldEntity.getFieldValue(), nextFormIds) + .map(FlowDataEntity::getFormId) + .orElse(null); + } + } + } + List applicationFormIds = new ArrayList<>(); + applicationFormIds.add(applicationEntity.getCall().getInitialForm()); + if (formIdMiddle != null && formIdMiddle > 0) { + applicationFormIds.add(formIdMiddle); + } + applicationFormIds.add(applicationEntity.getCall().getFinalForm()); + if (applicationFormEntities.size() == 3) { + for (Long applicationFormId : applicationFormIds) { + for (ApplicationFormEntity applicationFormEntity : applicationFormEntities) { + if (applicationFormEntity.getForm().getId().equals(applicationFormId)) { + sequencedApplicationFormEntity.add(applicationFormEntity); + FormEntity form = formService.validateForm(applicationFormId); + formEntities.add(form); + addFormApplication(form, applicationEntity, formApplicationResponses); + } + } + } + }else { + ApplicationFormEntity applicationFormEntity1=applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),applicationEntity.getCall().getInitialForm()); + sequencedApplicationFormEntity.add(applicationFormEntity1); + FormEntity form1 = formService.validateForm(applicationFormEntity1.getForm().getId()); + formEntities.add(form1); + addFormApplication(form1, applicationEntity, formApplicationResponses); + ApplicationFormEntity applicationFormEntity2=applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),applicationEntity.getCall().getFinalForm()); + sequencedApplicationFormEntity.add(applicationFormEntity2); + FormEntity form2= formService.validateForm(applicationFormEntity2.getForm().getId()); + formEntities.add(form2); + addFormApplication(form2, applicationEntity, formApplicationResponses); } } @@ -579,7 +638,8 @@ public class ApplicationDao { formApplicationResponse.setId(formEntity.getId()); formApplicationResponse.setLabel(formEntity.getLabel()); formApplicationResponse.setCallId(formEntity.getCall().getId()); - formApplicationResponse.setContent(Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class)); +// formApplicationResponse.setContent(Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class) + formApplicationResponse.setContent(formDao.convertFormEntityToFormResponseBean(formEntity).getContent()); return formApplicationResponse; } @@ -614,13 +674,13 @@ public class ApplicationDao { } if (status.equals(ApplicationStatusTypeEnum.SUBMIT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.READY.getValue()))) { callService.validatePublishedCall(applicationEntity.getCall().getId(), userEntity.getHub().getId()); - Long protocolNumber = getProtocolNumber(userEntity.getHub()); - ProtocolEntity protocolEntity = createProtocolEntity(applicationEntity,protocolNumber, userEntity.getHub().getId()); + Long protocolNumber = protocolDao.getProtocolNumber(userEntity.getHub()); + ProtocolEntity protocolEntity = protocolDao.createProtocolEntity(applicationEntity,protocolNumber, userEntity.getHub().getId()); applicationEntity.setProtocol(protocolEntity); applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue()); applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); applicationEntity = saveApplicationEntity(applicationEntity); - //sendMailToUserAndCompany(userEntity, applicationEntity); + sendMailToUserAndCompany(userEntity, applicationEntity); sendMailTodefaultSystemAndGepafin(userEntity, applicationEntity); applicationEntity.setStatus(status.getValue()); } @@ -633,14 +693,7 @@ public class ApplicationDao { return getApplicationResponse(applicationEntity); } - private Long getProtocolNumber(HubEntity hubEntity) { - Long maxProtocolNumber = protocolRepository.findMaxProtocolNumberAndHubId(hubEntity.getId()); - Long startNumber = 10000001L; - if(Boolean.FALSE.equals(defaultHubUuid.equals(hubEntity.getUniqueUuid()))) { - startNumber = 20000001L; - } - return (maxProtocolNumber != null) ? maxProtocolNumber + 1 : startNumber; - } + public Integer calculateProgress(Long totalSteps, Long completedSteps) { if (FieldValidator.isNullOrZero(totalSteps)) { throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.TOTAL_STEPS_NOT_BE_ZERO)); @@ -655,7 +708,8 @@ public class ApplicationDao { } public void validateFormFields(ApplicationRequestBean request, FormEntity formEntity) { - List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); +// List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); + List contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); List requestFields = request.getFormFields(); @@ -714,18 +768,6 @@ public class ApplicationDao { } } - public ProtocolEntity createProtocolEntity(ApplicationEntity applicationEntity,Long protocolNumber, Long hubId){ - ProtocolEntity protocolEntity=new ProtocolEntity(); - protocolEntity.setCall(applicationEntity.getCall().getId()); - LocalDateTime utcDateTime = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); - protocolEntity.setYear(utcDateTime.getYear()); - protocolEntity.setProtocolNumber(protocolNumber); - protocolEntity.setTime(LocalTime.now()); - protocolEntity.setApplicationId(applicationEntity.getId()); - protocolEntity.setHubId(hubId); - protocolRepository.save(protocolEntity); - return protocolEntity; - } private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) { CallEntity call =applicationEntity.getCall(); CompanyEntity company = applicationEntity.getCompany(); @@ -750,17 +792,26 @@ public class ApplicationDao { // Replace placeholders in the subject and body String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - /** + String email = userEntity.getEmail(); if (userEntity.getBeneficiary() != null) { email = userEntity.getBeneficiary().getEmail(); } - mailUtil.sendByMailGun(subject, body, List.of(email), null); - mailUtil.sendByMailGun(subject, body, List.of(applicationEntity.getCompany().getEmail()), null); - **/ - - } + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email)); + List recipientEmails = new ArrayList<>(); +// recipientEmails.add(email); + String companyEmail = company.getEmail(); + String contactEmail = company.getContactEmail(); + if (companyEmail != null && !companyEmail.isEmpty()) { + recipientEmails.add(companyEmail); + } + + if (contactEmail != null && !contactEmail.isEmpty() && !contactEmail.equals(companyEmail)) { + recipientEmails.add(contactEmail); + } + emailNotificationDao.sendMail(hub.getId(), subject, body, recipientEmails); + } private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) { CallEntity call = applicationEntity.getCall(); CompanyEntity company = applicationEntity.getCompany(); @@ -787,12 +838,16 @@ public class ApplicationDao { String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null); - //mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null); - mailUtil.sendByMailGun(subject, body, List.of(rinaldoEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(rinaldoEmail), null); if(validator.isProductionProfileActivated()) { - mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(carloEmail)); } + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(gepafinEmail)); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(defaultSystemReceiverEmail)); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(rinaldoEmail)); } public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId, diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java new file mode 100644 index 00000000..29d198fd --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -0,0 +1,1323 @@ +package net.gepafin.tendermanagement.dao; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.*; +import net.gepafin.tendermanagement.enums.*; +import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.request.ChecklistRequest; +import net.gepafin.tendermanagement.model.request.CriteriaRequest; +import net.gepafin.tendermanagement.model.request.FieldRequest; +import net.gepafin.tendermanagement.model.response.*; +import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.util.Utils; +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.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; +import static org.apache.commons.lang3.StringUtils.isNumeric; + +@Component +public class ApplicationEvaluationDao { + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Autowired + private ApplicationService applicationService; + + @Autowired + private CallRepository callRepository; + + @Autowired + private ApplicationRepository applicationRepository; + + @Autowired + private UserService userService; +// @Autowired +// private CallService callService; + + @Autowired + private EvaluationCriteriaRepository evaluationCriteriaRepository; + + @Autowired + private FormRepository formRepository; + @Autowired + private CallTargetAudienceChecklistRepository callTargetAudienceChecklistRepository; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private ApplicationFormRepository applicationFormRepository; + + @Autowired + private ApplicationFormFieldRepository applicationFormFieldRepository; + + @Autowired + private AssignedApplicationsRepository assignedApplicationsRepository; + + @Autowired + private CriteriaFormFieldRepository criteriaFormFieldRepository; + + @Autowired + private EmailNotificationDao emailNotificationDao; + + @Autowired + ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + + @Autowired + private FormDao formDao; + + private ApplicationEvaluationEntity convertToEntity(UserEntity user, ApplicationEvaluationRequest req, Long assignedApplciationId) { + + ApplicationEvaluationEntity entity = new ApplicationEvaluationEntity(); + + AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository.findByIdAndIsDeletedFalse(assignedApplciationId).orElse(null); + ApplicationEntity application = applicationService.validateApplication(assignedApplications.getApplication().getId()); + entity.setApplicationId(application.getId()); + entity.setAssignedApplicationsEntity(assignedApplications); + entity.setUserId(user.getId()); + entity.setCriteria(Utils.convertObjectToJson(req.getCriteria())); + entity.setChecklist(Utils.convertObjectToJson(req.getChecklist())); + entity.setFile(Utils.convertObjectToJson(req.getFiles())); + entity.setNote(req.getNote()); + entity.setIsDeleted(false); + entity.setStatus(ApplicationEvaluationStatusTypeEnum.OPEN.getValue()); + return entity; + } + + private ApplicationEvaluationResponse convertToResponse(ApplicationEvaluationEntity entity) { + + ApplicationEvaluationResponse response = new ApplicationEvaluationResponse(); + populateBasicDetails(entity, response); + + CallEntity call = callRepository.findCallEntityByApplicationId(entity.getApplicationId()); + List evaluationCriterias = evaluationCriteriaRepository.findByCallId(call.getId()); + List checklistEntities = callTargetAudienceChecklistRepository.findByCallId(call.getId()); + List applicationFormEntities = applicationFormRepository.findByApplicationId(entity.getApplicationId()); + + setCriteriaResponses(entity, response, evaluationCriterias); + setChecklistResponses(entity, response, checklistEntities); + setFieldResponses(entity, response, applicationFormEntities); + + setApplicationDetails(response, entity); + + return response; + } + + private void populateBasicDetails(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response) { + + response.setId(entity.getId()); + response.setApplicationId(entity.getApplicationId()); + AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository.findByIdAndIsDeletedFalse(entity.getAssignedApplicationsEntity().getId()).orElse(null); + response.setAssignedApplicationId(assignedApplications.getId()); + response.setNote(entity.getNote()); + response.setStatus(ApplicationEvaluationStatusTypeEnum.valueOf(entity.getStatus())); + response.setCreatedDate(entity.getCreatedDate()); + response.setUpdatedDate(entity.getUpdatedDate()); + } + + + + private void setCriteriaResponses(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response, List evaluationCriterias) { + + List criteriaResponsesFromEntity = entity.getCriteria() != null ? + Utils.convertJsonToList(entity.getCriteria(), new TypeReference>() { + }) : + new ArrayList<>(); + + List criteriaResponsesFromDB = getCriteriaResponse(entity.getApplicationId()); + addMissingCriteriaResponses(criteriaResponsesFromEntity, criteriaResponsesFromDB, entity.getApplicationId()); + criteriaResponsesFromEntity.forEach(criteriaResponse -> { + EvaluationCriteriaEntity matchingEvaluationCriteria = evaluationCriterias.stream() + .filter(evaluationCriteria -> evaluationCriteria.getId().equals(criteriaResponse.getId())).findFirst().orElse(null); + + if (matchingEvaluationCriteria != null) { + criteriaResponse.setLabel(matchingEvaluationCriteria.getLookupData().getValue()); + criteriaResponse.setMaxScore(matchingEvaluationCriteria.getScore()); + + List mappedFields = getMappedFieldsForCriteria(matchingEvaluationCriteria.getId(), entity.getApplicationId()); + criteriaResponse.setCriteriaMappedFields(mappedFields); + } + }); + + response.setCriteria(criteriaResponsesFromEntity); + } + + private void addMissingCriteriaResponses(List criteriaResponsesFromEntity, List criteriaResponsesFromDB, Long applicationId) { + + Set existingCriteriaIds = criteriaResponsesFromEntity.stream().map(CriteriaResponse::getId).collect(Collectors.toSet()); + + for (CriteriaResponse dbResponse : criteriaResponsesFromDB) { + if (!existingCriteriaIds.contains(dbResponse.getId())) { + List mappedFields = getMappedFieldsForCriteria(dbResponse.getId(), applicationId); + dbResponse.setCriteriaMappedFields(mappedFields); + criteriaResponsesFromEntity.add(dbResponse); + } + } + } + + private List getMappedFieldsForCriteria(Long evaluationCriteriaId, Long applicationId) { + List criteriaFormFields = criteriaFormFieldRepository.findByEvaluationCriteriaIdAndIsDeletedFalse(evaluationCriteriaId); + List mappedFields = new ArrayList<>(); + List applicationForms = applicationFormRepository.findByApplicationId(applicationId); + + for (ApplicationFormEntity applicationForm : applicationForms) { + Set uniqueFieldIds = new HashSet<>(); + + for (CriteriaFormFieldEntity formField : criteriaFormFields) { + String formFieldId = formField.getFormFieldId(); + + FormEntity formEntity = applicationForm.getForm(); + if (formEntity == null || !formEntity.getId().equals(formField.getFormId())) { + continue; + } + if (!uniqueFieldIds.contains(formFieldId)) { + CriteriaMappedField mappedField = new CriteriaMappedField(); + mappedField.setId(formFieldId); + + List contentBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + contentBeans.stream() + .filter(contentBean -> contentBean.getId().equals(formFieldId)) + .findFirst() + .ifPresent(contentBean -> { + mappedField.setFieldLabel(getLabelForField(contentBean)); + mappedField.setFieldName(contentBean.getName()); + switch (contentBean.getName()) { + case "fileupload": + mapFileFieldDetails(mappedField, formFieldId, applicationForm.getId(), applicationId); + break; + case "checkboxes": + populateOptionFieldsAsFieldValue(mappedField, formFieldId, applicationForm, applicationId, contentBean); + break; + case "paragraph": + handleParagraphField(applicationId, formField, contentBean, mappedField); + break; + case "table": + handleTableField(applicationId, formField, contentBean, mappedField); + break; + default: + populateOptionFieldsAsFieldValue(mappedField, formFieldId, applicationForm, applicationId, contentBean); + } + }); + + mappedFields.add(mappedField); + uniqueFieldIds.add(formFieldId); + } + } + } + return mappedFields; + } + + private FormEntity getFormEntity(Long formId) { + return formRepository.findById(formId).orElse(null); + } + + private String getLabelForField(ContentResponseBean contentBean) { + String label = contentBean.getLabel(); + if (contentBean.getSettings() != null) { + for (SettingResponseBean setting : contentBean.getSettings()) { + if ("label".equals(setting.getName())) { + label = setting.getValue() != null ? setting.getValue().toString() : label; + break; + } + } + } + return label; + } + + private void mapFileFieldDetails(CriteriaMappedField mappedField, String formFieldId, Long applicationFormId, Long applicationId) { + Optional formFieldEntityOptional = applicationFormFieldRepository + .findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId(formFieldId, applicationFormId, applicationId); + + if (formFieldEntityOptional.isPresent()) { + String[] documentIds = formFieldEntityOptional.get().getFieldValue().split(","); + List documentResponseBeans = new ArrayList<>(); + + for (String docId : documentIds) { + Long documentId = Long.valueOf(docId.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + documentResponseBeans.add(responseBean); + }); + } + mappedField.setFieldValue(documentResponseBeans); + } + } + + + private void mapNonFileFieldDetails(CriteriaMappedField mappedField, String formFieldId, Long applicationFormId, Long applicationId) { + applicationFormFieldRepository + .findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId(formFieldId, applicationFormId, applicationId) + .ifPresent(field -> mappedField.setFieldValue(field.getFieldValue())); + } + + + private void setChecklistResponses(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response, List checklistEntities) { + + List checklistResponsesFromEntity = entity.getChecklist() != null ? + Utils.convertJsonToList(entity.getChecklist(), new TypeReference>() { + }) : + new ArrayList<>(); + + List checklistResponsesFromDB = getChecklistResponse(entity.getApplicationId()); + addMissingChecklistResponses(checklistResponsesFromEntity, checklistResponsesFromDB); + + checklistResponsesFromEntity.forEach(checklistResponse -> { + CallTargetAudienceChecklistEntity matchingChecklist = checklistEntities.stream().filter(checklistEntity -> checklistEntity.getId().equals(checklistResponse.getId())) + .findFirst().orElse(null); + + if (matchingChecklist != null) { + checklistResponse.setLabel(matchingChecklist.getLookupData().getValue()); + } + }); + + response.setChecklist(checklistResponsesFromEntity); + } + + private void addMissingChecklistResponses(List checklistResponsesFromEntity, List checklistResponsesFromDB) { + + Set existingChecklistIds = checklistResponsesFromEntity.stream().map(ChecklistResponse::getId).collect(Collectors.toSet()); + + for (ChecklistResponse dbResponse : checklistResponsesFromDB) { + if (!existingChecklistIds.contains(dbResponse.getId())) { + checklistResponsesFromEntity.add(dbResponse); + } + } + } + + private void setFieldResponses(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response, List applicationFormEntities) { + + List fieldResponsesFromEntity = entity.getFile() != null ? Utils.convertJsonToList(entity.getFile(), new TypeReference>() { + }) : new ArrayList<>(); + List fieldResponsesFromDB = getFieldResponses(entity.getApplicationId()); + addMissingFieldResponses(fieldResponsesFromEntity, fieldResponsesFromDB); + + Set processedFieldIds = new HashSet<>(); + + fieldResponsesFromEntity.forEach(fieldResponse -> { + if (processedFieldIds.contains(fieldResponse.getId())) { + return; + } + + applicationFormEntities.forEach(applicationForm -> { + FormEntity formEntity = applicationForm.getForm(); + if (formEntity != null) { +// List contentResponseBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + contentResponseBeans.forEach(contentResponseBean -> { + if ("fileupload".equals(contentResponseBean.getName()) && contentResponseBean.getId().equals(fieldResponse.getId())) { + String label = null; + if (contentResponseBean.getSettings() != null) { + for (SettingResponseBean setting : contentResponseBean.getSettings()) { + if ("label".equals(setting.getName())) { + label = setting.getValue() != null ? setting.getValue().toString() : label; + break; + } + } + } + fieldResponse.setLabel(label); + + Optional optionalFormField = + applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + fieldResponse.getId(), applicationForm.getId(), entity.getApplicationId()); + + if (optionalFormField.isPresent()) { + ApplicationFormFieldEntity formField = optionalFormField.get(); + if (formField.getFieldValue() != null) { + String[] documentIds = formField.getFieldValue().split(","); + List documentResponseBeans = new ArrayList<>(); + + for (String docId : documentIds) { + Long documentId = Long.valueOf(docId.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + documentResponseBeans.add(responseBean); + }); + } + + fieldResponse.setFileDetail(documentResponseBeans); + } + } + processedFieldIds.add(fieldResponse.getId()); + } + }); + } + }); + }); + response.setFiles(fieldResponsesFromEntity); + } + + private void addMissingFieldResponses(List fieldResponsesFromEntity, List fieldResponsesFromDB) { + + Set existingFieldIds = fieldResponsesFromEntity.stream().map(FieldResponse::getId).collect(Collectors.toSet()); + + for (FieldResponse dbResponse : fieldResponsesFromDB) { + if (!existingFieldIds.contains(dbResponse.getId())) { + fieldResponsesFromEntity.add(dbResponse); + } + } + } + + private void setApplicationDetails(ApplicationEvaluationResponse response, ApplicationEvaluationEntity entity) { + + ApplicationEntity application = applicationService.validateApplication(entity.getApplicationId() != null ? entity.getApplicationId() : null); + UserEntity user = userService.validateUser(application.getUserId()); + + CallEntity call = callRepository.findCallEntityByApplicationId(entity.getApplicationId()); + + String firstName = user.getFirstName() != null ? user.getFirstName() : ""; + String lastName = user.getLastName() != null ? user.getLastName() : ""; + String beneficiary = String.join(" ", firstName, lastName).trim(); + response.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(application.getStatus())); + response.setBeneficiary(beneficiary); + response.setMinScore(call.getThreshold() != null ? call.getThreshold() : null); + response.setCallName(application.getCall().getName() != null ? application.getCall().getName() : null); + response.setProtocolNumber(application.getProtocol() != null ? application.getProtocol().getProtocolNumber() : null); + response.setSubmissionDate(application.getSubmissionDate() != null ? application.getSubmissionDate() : null); + response.setEvaluationDate(application.getSubmissionDate() != null ? application.getSubmissionDate().plusDays(30) : null); + LocalDateTime callEndDate = application.getCall().getEndDate(); + response.setCallEndDate(callEndDate); + } + + + public ApplicationEvaluationResponse createOrUpdateApplicationEvaluation( + UserEntity user, + ApplicationEvaluationRequest req, + Long assignedApplicationId) { + + Optional existingEntityOptional = + applicationEvaluationRepository.findByAssignedApplicationsEntity_IdAndIsDeletedFalse(assignedApplicationId); + ApplicationEvaluationEntity entity; + Optional assignedApplications = + assignedApplicationsRepository.findByIdAndIsDeletedFalse(assignedApplicationId); + + if (existingEntityOptional.isPresent()) { + entity = existingEntityOptional.get(); + entity.setCriteria(Utils.convertObjectToJson(filterNonNullCriteria(processCriteria(entity, req)))); + entity.setChecklist(Utils.convertObjectToJson(filterNonNullChecklist(processChecklist(entity, req)))); + entity.setFile(Utils.convertObjectToJson(filterNonNullFields(processField(entity, req)))); + entity.setIsDeleted(false); + setIfUpdated(entity::getNote, entity::setNote, req.getNote()); + } else { + entity = convertToEntity(user, req, assignedApplicationId); + } + ApplicationStatusForEvaluation status = req.getApplicationStatus(); + + ApplicationEvaluationEntity savedEntity = applicationEvaluationRepository.save(entity); + if (status != null) { + ApplicationEntity application = applicationService.validateApplication(assignedApplications.get().getApplication().getId()); + AssignedApplicationsEntity assignedApplicationsEntity = assignedApplications.get(); + return updateApplicationEvaluationStatus(application, assignedApplicationsEntity, status); + } else { + return convertToResponse(savedEntity); + } + } + + + private List filterNonNullChecklist(List checklistRequests) { + + return checklistRequests.stream().filter(request -> request.getValid() != null).collect(Collectors.toList()); + } + + private List filterNonNullCriteria(List criteriaRequests) { + + return criteriaRequests.stream().filter(request -> request.getScore() != null && request.getValid() != null).collect(Collectors.toList()); + } + + private List filterNonNullFields(List fieldRequests) { + + return fieldRequests.stream().filter(request -> request.getValid() != null).collect(Collectors.toList()); + } + + private List processCriteria(ApplicationEvaluationEntity entity, ApplicationEvaluationRequest req) { + + List incomingCriteriaList = Optional.ofNullable(req.getCriteria()).orElse(new ArrayList<>()); + + List existingCriteriaList = entity.getCriteria() != null ? + Utils.convertJsonToList(entity.getCriteria(), new TypeReference>() {}) : + new ArrayList<>(); + + Map existingCriteriaMap = existingCriteriaList.stream() + .collect(Collectors.toMap(CriteriaResponse::getId, criteria -> criteria)); + + List updatedCriteriaList = incomingCriteriaList.stream().map(incoming -> { + CriteriaRequest request = new CriteriaRequest(); + request.setId(incoming.getId()); + request.setScore(incoming.getScore()); + request.setValid(incoming.getValid()); + + CriteriaResponse existingCriteria = existingCriteriaMap.get(incoming.getId()); + if (existingCriteria != null) { + request.setScore(incoming.getScore() != null ? incoming.getScore() : existingCriteria.getScore()); + request.setValid(incoming.getValid() != null ? incoming.getValid() : existingCriteria.getValid()); + } + return request; + }).collect(Collectors.toList()); + + List missingCriteriaRequests = existingCriteriaList.stream() + .filter(existing -> !updatedCriteriaList.stream().map(CriteriaRequest::getId).toList().contains(existing.getId())) + .map(existing -> { + CriteriaRequest request = new CriteriaRequest(); + request.setId(existing.getId()); + request.setScore(existing.getScore()); + request.setValid(existing.getValid()); + return request; + }).toList(); + + updatedCriteriaList.addAll(missingCriteriaRequests); + return updatedCriteriaList; + } + + private List processChecklist(ApplicationEvaluationEntity entity, ApplicationEvaluationRequest req) { + + List incomingChecklistList = Optional.ofNullable(req.getChecklist()).orElse(new ArrayList<>()); + + List existingChecklistList = entity.getChecklist() != null ? + Utils.convertJsonToList(entity.getChecklist(), new TypeReference>() {}) : + new ArrayList<>(); + + Map existingChecklistMap = existingChecklistList.stream() + .collect(Collectors.toMap(ChecklistResponse::getId, checklist -> checklist)); + + List updatedChecklistList = incomingChecklistList.stream().map(incoming -> { + ChecklistRequest request = new ChecklistRequest(); + request.setId(incoming.getId()); + request.setValid(incoming.getValid()); + + ChecklistResponse existingChecklist = existingChecklistMap.get(incoming.getId()); + if (existingChecklist != null && incoming.getValid() == null) { + request.setValid(existingChecklist.getValid()); + } + return request; + }).collect(Collectors.toList()); + + List missingChecklistRequests = existingChecklistList.stream() + .filter(existing -> !updatedChecklistList.stream().map(ChecklistRequest::getId).toList().contains(existing.getId())) + .map(existing -> { + ChecklistRequest request = new ChecklistRequest(); + request.setId(existing.getId()); + request.setValid(existing.getValid()); + return request; + }).toList(); + + updatedChecklistList.addAll(missingChecklistRequests); + return updatedChecklistList; + } + private List processField(ApplicationEvaluationEntity entity, ApplicationEvaluationRequest req) { + + List incomingFieldList = Optional.ofNullable(req.getFiles()).orElse(new ArrayList<>()); + + List existingFieldList = entity.getFile() != null ? + Utils.convertJsonToList(entity.getFile(), new TypeReference>() {}) : + new ArrayList<>(); + + Map existingFieldMap = existingFieldList.stream() + .collect(Collectors.toMap(FieldResponse::getId, field -> field)); + + List updatedFieldList = incomingFieldList.stream().map(incoming -> { + FieldRequest request = new FieldRequest(); + request.setId(incoming.getId()); + request.setValid(incoming.getValid()); + + FieldResponse existingField = existingFieldMap.get(incoming.getId()); + if (existingField != null) { + request.setValid(incoming.getValid() != null ? incoming.getValid() : existingField.getValid()); + } + return request; + }).collect(Collectors.toList()); + + List missingFieldRequests = existingFieldList.stream() + .filter(existing -> !updatedFieldList.stream().map(FieldRequest::getId).toList().contains(existing.getId())) + .map(existing -> { + FieldRequest request = new FieldRequest(); + request.setId(existing.getId()); + request.setValid(existing.getValid()); + return request; + }).toList(); + + updatedFieldList.addAll(missingFieldRequests); + return updatedFieldList; + } + + public ApplicationEvaluationEntity validateApplicationEvaluation(Long id) { + + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(id); + if (entityOptional.isEmpty()) { + throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_EVALUATION_NOT_FOUND, id)); + } + return entityOptional.get(); + } + + + public ApplicationEvaluationResponse getApplicationEvaluationByApplicationId(UserEntity user, Long applicationId, Long assignedApplicationId) { + + applicationService.validateApplication(applicationId); + + Optional entityOptional; + + if (applicationId != null && assignedApplicationId != null) { + entityOptional = applicationEvaluationRepository.findByApplicationIdAndAssignedApplicationsEntity_IdAndIsDeletedFalse(applicationId, assignedApplicationId); + } else if (applicationId != null) { + entityOptional = applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationId); + } else if (assignedApplicationId != null) { + entityOptional = applicationEvaluationRepository.findByAssignedApplicationsEntity_IdAndIsDeletedFalse(assignedApplicationId); + } else { + entityOptional = applicationEvaluationRepository.findFirstByIsDeletedFalseOrderByCreatedDateDesc(); + } + return entityOptional.map(this::convertToResponse) + .orElseGet(() -> { + return getEvaluationResponseByApplicationid(user, applicationId, assignedApplicationId); + }); + } + + public ApplicationEvaluationResponse getEvaluationResponseByApplicationid(UserEntity user, Long applicationId, Long assignedApplicationId) { + + ApplicationEvaluationEntity entity = new ApplicationEvaluationEntity(); + ApplicationEvaluationResponse response = new ApplicationEvaluationResponse(); + CallEntity call = null; + ApplicationEntity application = null; + AssignedApplicationsEntity assignedApplications = null; + if (applicationId != null && assignedApplicationId == null) { + application = applicationService.validateApplication(applicationId); + call = callRepository.findCallEntityByApplicationId(applicationId); + assignedApplications = assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null); + } else if (assignedApplicationId != null) { + assignedApplications = assignedApplicationsRepository.findByIdAndIsDeletedFalse(assignedApplicationId) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.ASSIGNED_APPLICATION_NOT_FOUND_MSG))); + application = applicationService.validateApplication(assignedApplications.getApplication().getId()); + call = callRepository.findCallEntityByApplicationId(application.getId()); + + } else { + call = callRepository.findCallEntityByApplicationId(applicationId); + assignedApplications = assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null); + } + List evaluationCriterias = evaluationCriteriaRepository.findByCallId(call.getId()); + List checklistEntities = callTargetAudienceChecklistRepository.findByCallId(call.getId()); + List applicationFormEntities = applicationFormRepository.findByApplicationId(applicationId); + response.setApplicationId(application.getId()); + response.setAssignedApplicationId(assignedApplications.getId()); + response.setNote(null); + response.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(application.getStatus())); + response.setStatus(ApplicationEvaluationStatusTypeEnum.valueOf(ApplicationEvaluationStatusTypeEnum.OPEN.getValue())); + response.setMinScore(call.getThreshold()!=null?call.getThreshold():null); + LocalDateTime callEndDate = application.getCall().getEndDate(); + response.setCallEndDate(callEndDate); + setCriteriaResponses(entity, application.getId(), response, evaluationCriterias); + setChecklistResponses(entity, application.getId(), response, checklistEntities); + setFileResponses(entity, application.getId(), response, applicationFormEntities); + + setApplicationDetails(response, application.getId(), user); + + return response; + } + + private void setCriteriaResponses(ApplicationEvaluationEntity entity, Long applicationId, + ApplicationEvaluationResponse response, + List evaluationCriterias) { + + List criteriaResponses = getInitialCriteriaResponses(entity, applicationId); + + criteriaResponses.forEach(criteriaResponse -> { + EvaluationCriteriaEntity matchingEvaluationCriteria = + findMatchingEvaluationCriteria(criteriaResponse, evaluationCriterias); + + if (matchingEvaluationCriteria != null) { + List applicationForms = applicationFormRepository.findByApplicationId(applicationId); + Map mappedFieldMap = populateMappedFields( + matchingEvaluationCriteria, applicationForms, applicationId); + + criteriaResponse.setLabel(matchingEvaluationCriteria.getLookupData().getValue()); + criteriaResponse.setMaxScore(matchingEvaluationCriteria.getScore()); + criteriaResponse.setCriteriaMappedFields(new ArrayList<>(mappedFieldMap.values())); + } + }); + + response.setCriteria(criteriaResponses); + } + + private List getInitialCriteriaResponses(ApplicationEvaluationEntity entity, Long applicationId) { + return entity.getCriteria() != null + ? Utils.convertJsonToList(entity.getCriteria(), new TypeReference>() {}) + : getCriteriaResponse(applicationId); + } + + private EvaluationCriteriaEntity findMatchingEvaluationCriteria(CriteriaResponse criteriaResponse, + List evaluationCriterias) { + return evaluationCriterias.stream() + .filter(evaluationCriteria -> evaluationCriteria.getId().equals(criteriaResponse.getId())) + .findFirst() + .orElse(null); + } + + private Map populateMappedFields(EvaluationCriteriaEntity matchingEvaluationCriteria, + List applicationForms, + Long applicationId) { + Map mappedFieldMap = new HashMap<>(); + List criteriaFormFields = criteriaFormFieldRepository + .findByEvaluationCriteriaIdAndIsDeletedFalse(matchingEvaluationCriteria.getId()); + + for (ApplicationFormEntity applicationForm : applicationForms) { + for (CriteriaFormFieldEntity criteriaFormField : criteriaFormFields) { + String formFieldId = criteriaFormField.getFormFieldId(); + if (!mappedFieldMap.containsKey(formFieldId)) { +// CriteriaMappedField mappedField = new CriteriaMappedField(); + CriteriaMappedField mappedField = populateMappedField(formFieldId, criteriaFormField, applicationForm, applicationId); + if(mappedField != null) { + mappedFieldMap.put(formFieldId, mappedField); + } + } + } + } + + return mappedFieldMap; + } + + private CriteriaMappedField populateMappedField(String formFieldId, + CriteriaFormFieldEntity criteriaFormField, + ApplicationFormEntity applicationForm, Long applicationId) { + CriteriaMappedField mappedField = new CriteriaMappedField(); + mappedField.setId(formFieldId); + if(Boolean.FALSE.equals(criteriaFormField.getFormId().equals(applicationForm.getForm().getId()))) { + return null; + } + formRepository.findById(criteriaFormField.getFormId()).ifPresent(formEntity -> { +// List contentResponseBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + contentResponseBeans.stream().filter(bean -> bean.getId().equals(formFieldId)).findFirst().ifPresent(contentResponseBean -> { + String label = getLabel(contentResponseBean); + mappedField.setFieldName(contentResponseBean.getName()); + mappedField.setFieldLabel(label); + switch (contentResponseBean.getName()) { + case "fileupload": + populateFileDetailsAsFieldValue(mappedField, formFieldId, applicationForm, applicationId); + break; + + case "checkboxes": + populateOptionFieldsAsFieldValue(mappedField, formFieldId, applicationForm, applicationId, contentResponseBean); + break; + + case "paragraph": + handleParagraphField(applicationId, criteriaFormField, contentResponseBean, mappedField); + break; + case "table": + handleTableField(applicationId, criteriaFormField, contentResponseBean, mappedField); + break; + + default: + populateOptionFieldsAsFieldValue(mappedField, formFieldId, applicationForm, applicationId, contentResponseBean); + } + }); + }); + return mappedField; + } + + + private void populateFileDetailsAsFieldValue(CriteriaMappedField mappedField, String formFieldId, + ApplicationFormEntity applicationForm, Long applicationId) { + applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + formFieldId, applicationForm.getId(), applicationId) + .ifPresent(formField -> { + if (formField.getFieldValue() != null) { + List documentResponseBeans = new ArrayList<>(); + for (String docId : formField.getFieldValue().split(",")) { + Long documentId = Long.valueOf(docId.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { + DocumentResponseBean responseBean = createDocumentResponseBean(documentEntity); + documentResponseBeans.add(responseBean); + }); + } + // Set the list of DocumentResponseBean directly + mappedField.setFieldValue(documentResponseBeans); + } + }); + } + + private String getLabel(ContentResponseBean contentResponseBean) { + String label = contentResponseBean.getLabel(); + if (contentResponseBean.getSettings() != null) { + for (SettingResponseBean setting : contentResponseBean.getSettings()) { + if ("label".equals(setting.getName())) { + label = setting.getValue() != null ? setting.getValue().toString() : label; + break; + } + } + } + return label; + } + private void populateOptionFieldsAsFieldValue(CriteriaMappedField mappedField, String formFieldId, ApplicationFormEntity applicationForm, Long applicationId, ContentResponseBean contentBean) { + ObjectMapper objectMapper = new ObjectMapper(); + findFormFieldValue(applicationId, formFieldId).ifPresent(formField -> { + Object value = formField.getFieldValue(); + List labels = new ArrayList<>(); + if (value instanceof String) { + String fieldValue = (String) value; + if (fieldValue.contains(",")) { + try { + List parsedValue = objectMapper.readValue(fieldValue, new TypeReference>() {}); + parsedValue.forEach(item -> addLabelToList(labels, item, contentBean)); + } catch (JsonProcessingException e) { + + String[] fallbackValues = fieldValue.split(","); + for (String item : fallbackValues) { + addLabelToList(labels, item.trim(), contentBean); + } + } + mappedField.setFieldValue(!labels.isEmpty() ? labels : null); + } else { + + addLabelToList(labels, fieldValue.trim(), contentBean); + mappedField.setFieldValue(!labels.isEmpty() ? labels.get(0) : null); + } + } else if (value instanceof List) { + + List parsedValue = (List) value; + parsedValue.forEach(item -> addLabelToList(labels, item, contentBean)); + mappedField.setFieldValue(!labels.isEmpty() ? labels : null); + } + }); + } + + private void addLabelToList(List labels, Object item, ContentResponseBean contentBean) { + if (item instanceof String) { + Object label = PdfDao.findLabelInOptions(contentBean.getSettings(), item); + if (label != null) { + labels.add(label.toString()); + } + } + } + + + private DocumentResponseBean createDocumentResponseBean(DocumentEntity documentEntity) { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + return responseBean; + } + + private void setChecklistResponses(ApplicationEvaluationEntity entity, Long applicationId, ApplicationEvaluationResponse response, + List checklistEntities) { + + List checklistResponses = entity.getChecklist() != null ? Utils.convertJsonToList(entity.getChecklist(), new TypeReference>() { + }) : getChecklistResponse(applicationId); + + checklistResponses.forEach(checklistResponse -> { + CallTargetAudienceChecklistEntity matchingChecklist = checklistEntities.stream().filter(checklistEntity -> checklistEntity.getId().equals(checklistResponse.getId())) + .findFirst().orElse(null); + + if (matchingChecklist != null) { + checklistResponse.setLabel(matchingChecklist.getLookupData().getValue()); + } + }); + + response.setChecklist(checklistResponses); + } + + private void setFileResponses(ApplicationEvaluationEntity entity, Long applicationId, ApplicationEvaluationResponse response, + List applicationFormEntities) { + + List fieldResponses = entity.getFile() != null ? Utils.convertJsonToList(entity.getFile(), new TypeReference>() { + }) : getFieldResponses(applicationId); + Set processedFieldIds = new HashSet<>(); + + fieldResponses.forEach(fieldResponse -> { + if (processedFieldIds.contains(fieldResponse.getId())) { + return; + } + + applicationFormEntities.forEach(applicationForm -> { + FormEntity formEntity = applicationForm.getForm(); + if (formEntity != null) { +// List contentResponseBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + contentResponseBeans.forEach(contentResponseBean -> { + if ("fileupload".equals(contentResponseBean.getName()) && contentResponseBean.getId().equals(fieldResponse.getId())) { + String label = null; + if (contentResponseBean.getSettings() != null) { + for (SettingResponseBean setting : contentResponseBean.getSettings()) { + if ("label".equals(setting.getName())) { + label = setting.getValue() != null ? setting.getValue().toString() : label; + break; + } + } + } + fieldResponse.setLabel(label); + + Optional optionalFormField = + applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + fieldResponse.getId(), applicationForm.getId(), applicationId); + + if (optionalFormField.isPresent() && optionalFormField.get().getFieldValue() != null) { + String[] documentIds = optionalFormField.get().getFieldValue().split(","); + List documentResponseBeans = new ArrayList<>(); + + for (String docId : documentIds) { + Long documentId = Long.valueOf(docId.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + documentResponseBeans.add(responseBean); + }); + } + + fieldResponse.setFileDetail(documentResponseBeans); + } + processedFieldIds.add(fieldResponse.getId()); + } + }); + } + }); + }); + + response.setFiles(fieldResponses); + } + + private void setApplicationDetails(ApplicationEvaluationResponse response, Long applicationId, UserEntity user) { + + ApplicationEntity application = applicationService.validateApplication(applicationId); + userService.validateUser(application.getUserId()); + String firstName = user.getFirstName() != null ? user.getFirstName() : ""; + String lastName = user.getLastName() != null ? user.getLastName() : ""; + + String beneficiary = String.join(" ", firstName, lastName).trim(); + response.setBeneficiary(beneficiary); + + response.setCallName(application.getCall().getName() != null ? application.getCall().getName() : null); + response.setProtocolNumber(application.getProtocol() != null ? application.getProtocol().getProtocolNumber() : null); + response.setSubmissionDate(application.getSubmissionDate() != null ? application.getSubmissionDate() : null); + response.setEvaluationDate(application.getSubmissionDate() != null ? application.getSubmissionDate().plusDays(30) : null); + + } + private Optional findFormFieldValue(Long applicationId, String formFieldId) { + return applicationFormRepository.findByApplicationId(applicationId).stream() + .flatMap(applicationForm -> applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + formFieldId, applicationForm.getId(), applicationId).stream()) + .findFirst(); + } + + List getCriteriaResponse(Long applicationId) { + CallEntity call = getCallEntityByApplicationId(applicationId); + List evaluationCriterias = getEvaluationCriterias(call); + + return evaluationCriterias.stream() + .map(criteria -> buildCriteriaResponse(applicationId, criteria)) + .collect(Collectors.toList()); + } + + private CallEntity getCallEntityByApplicationId(Long applicationId) { + return callRepository.findCallEntityByApplicationId(applicationId); + } + + private List getEvaluationCriterias(CallEntity call) { + return evaluationCriteriaRepository.findByCallId(call.getId()); + } + + private CriteriaResponse buildCriteriaResponse(Long applicationId, EvaluationCriteriaEntity criteria) { + CriteriaResponse response = new CriteriaResponse(); + response.setId(criteria.getId()); + response.setLabel(criteria.getLookupData().getValue()); + response.setScore(null); + response.setMaxScore(criteria.getScore()); + response.setValid(null); + + List mappedFields = getMappedFields(applicationId, criteria); + response.setCriteriaMappedFields(mappedFields); + return response; + } + + private List getMappedFields(Long applicationId, EvaluationCriteriaEntity criteria) { + List criteriaFormFields = getCriteriaFormFields(criteria); + + List mappedFields = new ArrayList<>(); + Set processedFormFieldIds = new HashSet<>(); + + for (CriteriaFormFieldEntity criteriaFormField : criteriaFormFields) { + if (processedFormFieldIds.contains(criteriaFormField.getFormFieldId())) { + continue; + } + + CriteriaMappedField mappedField = mapField(applicationId, criteriaFormField); + mappedFields.add(mappedField); + processedFormFieldIds.add(criteriaFormField.getFormFieldId()); + } + + return mappedFields; + } + + private List getCriteriaFormFields(EvaluationCriteriaEntity criteria) { + return criteriaFormFieldRepository.findByEvaluationCriteriaIdAndIsDeletedFalse(criteria.getId()); + } + + private CriteriaMappedField mapField(Long applicationId, CriteriaFormFieldEntity criteriaFormField) { + CriteriaMappedField mappedField = new CriteriaMappedField(); + mappedField.setId(criteriaFormField.getFormFieldId()); + + FormEntity formEntity = formRepository.findById(criteriaFormField.getFormId()).orElse(null); + if (formEntity != null) { +// List contentResponseBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + contentResponseBeans.stream() + .filter(bean -> bean.getId().equals(criteriaFormField.getFormFieldId())) + .findFirst() + .ifPresent(contentResponseBean -> processFieldValue(applicationId, criteriaFormField, contentResponseBean, mappedField)); + } + + return mappedField; + } + + private void processFieldValue(Long applicationId, CriteriaFormFieldEntity criteriaFormField, ContentResponseBean contentResponseBean, CriteriaMappedField mappedField) { + String label = getLabelFromSettings(contentResponseBean); + + mappedField.setFieldLabel(label); + mappedField.setFieldName(contentResponseBean.getName()); + boolean isCheckbox = "checkboxes".equals(contentResponseBean.getName()); + boolean isFileUpload = "fileupload".equals(contentResponseBean.getName()); + boolean isParagraph = "paragraph".equals(contentResponseBean.getName()); + boolean isTable = "table".equals(contentResponseBean.getName()); + if (isFileUpload) { + handleFileUpload(applicationId, criteriaFormField, mappedField); + } else if (isCheckbox) { + handleCheckbox(applicationId, criteriaFormField, contentResponseBean, mappedField); + } + else if (isParagraph) { + handleParagraphField(applicationId, criteriaFormField, contentResponseBean, mappedField); + } else if (isTable) { + handleTableField(applicationId, criteriaFormField, contentResponseBean, mappedField); + } + else { + handleOtherFields(applicationId, criteriaFormField, contentResponseBean, mappedField); + } + } + private void handleTableField(Long applicationId, CriteriaFormFieldEntity criteriaFormField, + ContentResponseBean contentResponseBean, CriteriaMappedField mappedField) { + Map stateFieldMap = new HashMap<>(); + Map stateFieldBoolean = new HashMap<>(); + + contentResponseBean.getSettings().stream() + .filter(setting -> "table_columns".equals(setting.getName())) + .map(SettingResponseBean::getValue) + .filter(Objects::nonNull) + .filter(settingValue -> settingValue instanceof Map) + .map(settingValue -> (Map) settingValue) + .map(valueMap -> (List>) valueMap.get("stateFieldData")) + .filter(Objects::nonNull) + .flatMap(List::stream) + .forEach(fieldData -> { + String fieldName = (String) fieldData.get("name"); + String fieldLabel = (String) fieldData.get("label"); + Boolean predefined = (Boolean) fieldData.getOrDefault("predefined", false); + + if (fieldName != null) { + stateFieldMap.put(fieldName, fieldLabel); + stateFieldBoolean.put(fieldName, predefined); + } + }); + + findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { + String fieldValue1 = formField.getFieldValue(); + ObjectMapper objectMapper = new ObjectMapper(); + + try { + List> rowsData = objectMapper.readValue(fieldValue1, new TypeReference>>() {}); + + List> tableData = new ArrayList<>(); + for (Map rowData : rowsData) { + Map mappedRow = new HashMap<>(); + rowData.forEach((fieldKey, fieldValue) -> { + String columnLabel = stateFieldMap.getOrDefault(fieldKey, fieldKey); + mappedRow.put(columnLabel, fieldValue); + }); + tableData.add(mappedRow); + } + + mappedField.setFieldValue(tableData); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + + private void handleParagraphField(Long applicationId, CriteriaFormFieldEntity criteriaFormField, ContentResponseBean contentResponseBean, CriteriaMappedField mappedField) { + findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { + String paragraph = contentResponseBean.getSettings().stream() + .filter(setting -> "text".equals(setting.getName())) + .map(SettingResponseBean::getValue) + .map(Object::toString) + .findFirst() + .orElse(null); + if (paragraph != null) { + mappedField.setFieldValue(paragraph.trim()); + } + + }); + } + + private String getLabelFromSettings(ContentResponseBean contentResponseBean) { + String label = contentResponseBean.getLabel(); + if (contentResponseBean.getSettings() != null) { + for (SettingResponseBean setting : contentResponseBean.getSettings()) { + if ("label".equals(setting.getName())) { + label = setting.getValue() != null ? setting.getValue().toString() : label; + break; + } + } + } + return label; + } + + private void handleFileUpload(Long applicationId, CriteriaFormFieldEntity criteriaFormField, CriteriaMappedField mappedField) { + List documentResponseBeans = new ArrayList<>(); + findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { + String fieldValue = formField.getFieldValue(); + if (fieldValue != null) { + String[] fieldValues = fieldValue.split(","); + for (String value : fieldValues) { + Long documentId = Long.valueOf(value.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { + DocumentResponseBean responseBean = mapDocumentEntityToResponse(documentEntity); + documentResponseBeans.add(responseBean); + }); + } + } + mappedField.setFieldValue(!documentResponseBeans.isEmpty() ? documentResponseBeans : null); + }); + } + + private DocumentResponseBean mapDocumentEntityToResponse(DocumentEntity documentEntity) { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + return responseBean; + } + + private void handleCheckbox(Long applicationId, CriteriaFormFieldEntity criteriaFormField, ContentResponseBean contentResponseBean, CriteriaMappedField mappedField) { + ObjectMapper objectMapper = new ObjectMapper(); + findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { + Object value = formField.getFieldValue(); + List labels = new ArrayList<>(); + + if (value instanceof String) { + List parsedValue = parseJsonValue((String) value, objectMapper); + addLabelsFromParsedValues(parsedValue, contentResponseBean, labels); + } else if (value instanceof List) { + List parsedValue = (List) value; + addLabelsFromParsedValues(parsedValue, contentResponseBean, labels); + } + + mappedField.setFieldValue(!labels.isEmpty() ? (labels.size() == 1 ? labels.get(0) : labels) : null); + }); + } + + private List parseJsonValue(String value, ObjectMapper objectMapper) { + try { + return objectMapper.readValue(value, new TypeReference>() {}); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private void addLabelsFromParsedValues(List parsedValue, ContentResponseBean contentResponseBean, List labels) { + for (Object item : parsedValue) { + if (item instanceof String) { + Object label = PdfDao.findLabelInOptions(contentResponseBean.getSettings(), item); + if (label != null) { + labels.add(label.toString()); + } + } + } + } + + private void handleOtherFields(Long applicationId, CriteriaFormFieldEntity criteriaFormField, ContentResponseBean contentResponseBean, CriteriaMappedField mappedField) { + findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { + String fieldValue = formField.getFieldValue() != null ? formField.getFieldValue().trim() : null; + Object label = PdfDao.findLabelInOptions(contentResponseBean.getSettings(), fieldValue); + if (label != null) { + mappedField.setFieldValue(fieldValue != null && !fieldValue.isEmpty() && !fieldValue.contains(",") + ? label.toString() + : Arrays.asList(label.toString())); + } + }); + } + + + List getChecklistResponse(Long applicationId) { + + CallEntity call = callRepository.findCallEntityByApplicationId(applicationId); + List checklistEntities = callTargetAudienceChecklistRepository.findByCallId(call.getId()); + List checklistResponses = checklistEntities.stream().map(checklist -> { + ChecklistResponse response = new ChecklistResponse(); + response.setId(checklist.getId()); + response.setLabel(checklist.getLookupData().getValue()); + response.setValid(null); + + return response; + }).collect(Collectors.toList()); + + return checklistResponses; + } + + public List getFieldResponses(Long applicationId) { + + List applicationFormEntities = applicationFormRepository.findByApplicationId(applicationId); + List fieldResponses = new ArrayList<>(); + + for (ApplicationFormEntity applicationForm : applicationFormEntities) { + FormEntity formEntity = applicationForm.getForm(); + + if (formEntity != null) { +// List contentResponseBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + + for (ContentResponseBean contentResponseBean : contentResponseBeans) { + if ("fileupload".equals(contentResponseBean.getName())) { + String fieldId = contentResponseBean.getId(); + Long applicationFormId = applicationForm.getId(); + + Optional optionalFormField = applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + fieldId, applicationFormId, applicationId); + + if (optionalFormField.isPresent()) { + ApplicationFormFieldEntity formField = optionalFormField.get(); + + if (formField.getFieldValue() != null) { + FieldResponse fieldResponse = new FieldResponse(); + fieldResponse.setId(fieldId); + String label = null; + if (contentResponseBean.getSettings() != null) { + for (SettingResponseBean setting : contentResponseBean.getSettings()) { + if ("label".equals(setting.getName())) { + label = setting.getValue() != null ? setting.getValue().toString() : label; + break; + } + } + } + fieldResponse.setLabel(label); + fieldResponse.setValid(null); + String[] documentIds = formField.getFieldValue().split(","); + List documentResponseBeans = new ArrayList<>(); + + for (String docId : documentIds) { + Long documentId = Long.valueOf(docId.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + documentResponseBeans.add(responseBean); + }); + } + + fieldResponse.setFileDetail(documentResponseBeans); + fieldResponses.add(fieldResponse); + } + } + } + } + } + } + return fieldResponses; + } + + public void deleteById(Long id) { + + ApplicationEvaluationEntity applicationEvaluationEntity = validateApplicationEvaluation(id); + applicationEvaluationEntity.setIsDeleted(true); + saveApplicationEvaluationEntity(applicationEvaluationEntity); + } + + public ApplicationEvaluationEntity saveApplicationEvaluationEntity(ApplicationEvaluationEntity applicationEvaluationEntityData) { + + return applicationEvaluationRepository.save(applicationEvaluationEntityData); + } + + public ApplicationEvaluationResponse updateApplicationEvaluationStatus(ApplicationEntity application, AssignedApplicationsEntity assignedApplicationsEntity, + ApplicationStatusForEvaluation newStatus) { + + Optional existingEntityOptional = applicationEvaluationRepository.findByAssignedApplicationsEntity_IdAndIsDeletedFalse( + assignedApplicationsEntity.getId()); + ApplicationEvaluationEntity entity; + + + if (existingEntityOptional.isPresent()) { + ApplicationEvaluationEntity existingEntity = existingEntityOptional.get(); +// UserEntity userEntity = userService.validateUser(application.getUserId()); +// callService.validatePublishedCall(application.getCall().getId(), userEntity.getHub().getId()); + application.setStatus(newStatus.getValue()); + application = applicationRepository.save(application); + String statusType = application.getStatus(); + if (application.getStatus().equals(ApplicationStatusTypeEnum.APPROVED.getValue()) || application.getStatus().equals(ApplicationStatusTypeEnum.REJECTED.getValue())) { + existingEntity.setStatus(ApplicationEvaluationStatusTypeEnum.CLOSE.getValue()); + assignedApplicationsEntity.setStatus(AssignedApplicationEnum.CLOSE.getValue()); + } + entity = applicationEvaluationRepository.save(existingEntity); + assignedApplicationsRepository.save(assignedApplicationsEntity); + + ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestRepository.findByApplicationEvaluationIdAndIsDeletedFalse(entity.getId()); + if(amendmentRequest!=null){ + if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.APPROVED.getValue())))) { + emailNotificationDao.sendAdmissibilityNotificationEmailForApprovedApplication(amendmentRequest); + } + if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.REJECTED.getValue())))) { + emailNotificationDao.sendInadmissibilityEmailForRejectedApplication(amendmentRequest); + }} + return convertToResponse(entity); + } + return null; + } +} + diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java index f04b5e98..b3e27da5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java @@ -79,7 +79,7 @@ public class AssignedApplicationsDao { assignApplication.setApplication(application); assignApplication.setAssignedBy(assignedByUser.getId()); assignApplication.setUserId(userId); - assignApplication.setStatus(AssignedApplicationEnum.ASSIGNED.getValue()); + assignApplication.setStatus(AssignedApplicationEnum.OPEN.getValue()); if(assignedApplicationsRequest.getStatus() != null) { assignApplication.setStatus(assignedApplicationsRequest.getStatus().getValue()); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CommunicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CommunicationDao.java new file mode 100644 index 00000000..afe7e21e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/CommunicationDao.java @@ -0,0 +1,102 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.entities.CommunicationEntity; +import net.gepafin.tendermanagement.model.request.CommunicationRequestBean; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse; +import net.gepafin.tendermanagement.model.response.CommunicationResponseBean; +import net.gepafin.tendermanagement.repositories.CommunicationRepository; +import net.gepafin.tendermanagement.service.ApplicationAmendmentRequestService; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; + +@Component +public class CommunicationDao { + private static final Logger log = LoggerFactory.getLogger(CommunicationDao.class); + + @Autowired + private CommunicationRepository communicationRepository; + + @Autowired + ApplicationAmendmentRequestService applicationAmendmentRequestService; + + public CommunicationResponseBean addCommentToAmendmentRequest(CommunicationRequestBean communicationReq, Long amendmentId) { + + log.info("Adding communication request..."); + CommunicationEntity communicationEntity = convertToCommunicationCommentEntity(communicationReq, amendmentId); + communicationEntity = communicationRepository.save(communicationEntity); + log.info("Added comment: {}", communicationEntity); + return convertToCommunicationResponseBean(communicationEntity); + } + + public String deleteComment(Long amendmentId, Long commentId) { + + CommunicationEntity data = communicationRepository.findById(commentId) + .orElseThrow(() -> new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.COMMENT_NOT_FOUND))); + if (!data.getApplicationAmendmentRequest().getId().equals(amendmentId)) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.INVALID_AMENDMENT_FOR_COMMENT)); + } + data.setIsDeleted(true); + communicationRepository.save(data); + return "Deleted Comment Successfully."; + } + + public ApplicationAmendmentResponse getAmendmentComments(Long amendmentId) { + + ApplicationAmendmentRequestEntity amendmentData = applicationAmendmentRequestService.validateApplicationAmendmentRequest(amendmentId); + List commentsList = communicationRepository.findCommentDetailsByAmendmentId(amendmentId); + if (commentsList == null) { + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.COMMENT_NOT_FOUND)); + } + return new ApplicationAmendmentResponse(amendmentData, commentsList); + } + + public CommunicationResponseBean updateAmendmentComment(CommunicationRequestBean communicationRequestBean, Long amendmentId, Long commentId) { + + log.info("Updating communication comment..."); + CommunicationEntity existingComment = communicationRepository.findById(commentId) + .orElseThrow(() -> new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.COMMENT_NOT_FOUND))); + if (!existingComment.getApplicationAmendmentRequest().getId().equals(amendmentId)) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.COMMENT_NOT_ASSOCIATE_WITH_AMENDMENT_ID_ERROR_MSG)); + } + existingComment.setCommunicationTitle(communicationRequestBean.getTitle()); + existingComment.setCommunicationComment(communicationRequestBean.getComment()); + existingComment.setCommentedDate(LocalDateTime.now()); + existingComment = communicationRepository.save(existingComment); + log.info("Updated Comment: {}", existingComment); + return convertToCommunicationResponseBean(existingComment); + } + + private CommunicationResponseBean convertToCommunicationResponseBean(CommunicationEntity entity) { + + CommunicationResponseBean response = new CommunicationResponseBean(); + response.setComment(entity.getCommunicationComment()); + response.setCommentedDate(entity.getCommentedDate()); + response.setAmendmentId(entity.getApplicationAmendmentRequest().getId()); + response.setCreatedDate(entity.getCreatedDate()); + response.setUpdatedDate(entity.getUpdatedDate()); + response.setTitle(entity.getCommunicationTitle()); + return response; + } + + private CommunicationEntity convertToCommunicationCommentEntity(CommunicationRequestBean communicationReq, Long amendmentId) { + + ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestService.validateApplicationAmendmentRequest(amendmentId); + CommunicationEntity communicationEntity = new CommunicationEntity(); + communicationEntity.setApplicationAmendmentRequest(amendmentRequest); + communicationEntity.setCommunicationTitle(communicationReq.getTitle()); + communicationEntity.setCommunicationComment(communicationReq.getComment()); + communicationEntity.setIsDeleted(false); + communicationEntity.setCommentedDate(LocalDateTime.now()); + return communicationEntity; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java index ffcbad26..2d84b831 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java @@ -97,6 +97,7 @@ public class DocumentDao { private Long resolveSourceId(Long sourceId, DocumentSourceTypeEnum sourceType) { if (sourceType == DocumentSourceTypeEnum.CALL) { CallEntity callEntity = callService.validateCall(sourceId); + callDao.validateUpdate(callEntity); return callEntity.getId(); } // else if (sourceType == SourceTypeEnum.APPLICATION) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java new file mode 100644 index 00000000..1cac5feb --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java @@ -0,0 +1,199 @@ +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 net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.HubEntity; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.model.request.EmailConfig; +import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse; +import net.gepafin.tendermanagement.repositories.HubRepository; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.service.HubService; +import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; +import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.service.impl.EmailService; +import net.gepafin.tendermanagement.service.impl.EmailServiceFactory; +import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class EmailNotificationDao { + + private static final Logger log = LoggerFactory.getLogger(EmailNotificationDao.class); + + @Autowired + private SystemEmailTemplatesService systemEmailTemplatesService; + + @Autowired + private ApplicationService applicationService; + + @Autowired + private UserService userService; + + @Autowired + private HubService hubService; + + @Autowired + EmailServiceFactory emailServiceFactory; + + @Autowired + HubRepository hubRepository; + + + private void sendEmail(ApplicationAmendmentRequestEntity amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum templateType, + Map bodyPlaceholders, List additionalRecipients) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); + HubEntity hubEntity = hubService.valdateHub(applicationEntity.getHubId()); + String service = determineService(applicationEntity.getHubId()); + String legalMail = service.equals("Gepafin S.p.a.") ? "bandi.gepafin@legalmail.it" : "bandi.sviluppumbria@legalmail.it"; + + SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall(templateType, hubEntity, null); + Map subjectPlaceholders = new HashMap<>(); + subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); + subjectPlaceholders.put("{{company_name}}", applicationEntity.getCompany().getCompanyName()); + bodyPlaceholders.put("{{legal_mail}}", legalMail); + String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); + String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); + + UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); + List recipientEmails = getRecipientEmails(applicationEntity, userEntity, additionalRecipients); + sendMail(applicationEntity.getHubId(), subject, body, recipientEmails); + } + private List getRecipientEmails(ApplicationEntity applicationEntity, UserEntity userEntity, List additionalRecipients) { + List recipientEmails = new ArrayList<>(); + String companyEmail = applicationEntity.getCompany().getEmail(); + String contactEmail = applicationEntity.getCompany().getContactEmail(); + + if (companyEmail != null && !companyEmail.isEmpty()) { + recipientEmails.add(companyEmail); + } + if (contactEmail != null && !contactEmail.isEmpty() && !contactEmail.equals(companyEmail)) { + recipientEmails.add(contactEmail); + } + + if (userEntity.getBeneficiary().getEmail() != null) { + recipientEmails.add(userEntity.getBeneficiary().getEmail()); + } + if (additionalRecipients != null) { + recipientEmails.addAll(additionalRecipients); + } + + return recipientEmails; + } + + + private String determineService(Long hubId) { + + HubEntity hub = hubRepository.findById(hubId).orElseThrow(() -> new IllegalArgumentException("Invalid Hub ID: " + hubId)); + return hub.getEmailServiceType().equalsIgnoreCase("MAILGUN_SERVICE") ? "Gepafin S.p.a." : "Sviluppumbria"; + } + + public void sendMailToNotifyBeneficiaryRegardingNewAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequest) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(applicationAmendmentRequest.getApplicationId()); + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); + bodyPlaceholders.put("{{protocol_number}}", applicationAmendmentRequest.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatLocalDateTime(applicationAmendmentRequest.getProtocol().getCreatedDate(), GepafinConstant.DD_MM_YYYY)); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationAmendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + String formFieldsJson = applicationAmendmentRequest.getFormFields(); + ObjectMapper objectMapper = new ObjectMapper(); + + try { + List> formFields = objectMapper.readValue(formFieldsJson, new TypeReference>>() { + }); + //• + StringBuilder bulletPoints = new StringBuilder(); + for (Map field : formFields) { + String label = (String) field.get("label"); + boolean selected = (boolean) field.get("selected"); + if (!selected) { + bulletPoints.append("• ").append(label).append("\n"); + } + } + bodyPlaceholders.put("{{form_dataInput}}", bulletPoints.toString()); + } catch (Exception e) { + log.error("Failed to parse form fields JSON: ", e); + } + bodyPlaceholders.put("{{note}}", applicationAmendmentRequest.getNote()); + sendEmail(applicationAmendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, bodyPlaceholders, null); + } + + public void sendApplicationFailureNotificationEmail(ApplicationAmendmentRequestEntity amendmentRequest) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); + bodyPlaceholders.put("{{date_time_emailSend}}", DateTimeUtil.formatLocalDateTime(amendmentRequest.getCreatedDate(), GepafinConstant.DD_MM_YYYY_HH_MM)); + + sendEmail(amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE, bodyPlaceholders, null); + } + + public void sendAdmissibilityNotificationEmailForApprovedApplication(ApplicationAmendmentRequestEntity amendmentRequest) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); + bodyPlaceholders.put("{{protocol_number}}", amendmentRequest.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatCreatedDate(amendmentRequest.getProtocol().getCreatedDate())); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(amendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + + sendEmail(amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.ADMISSIBILITY_NOTIFICATION, bodyPlaceholders, null); + } + + public void sendInadmissibilityEmailForRejectedApplication(ApplicationAmendmentRequestEntity amendmentRequest) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); + bodyPlaceholders.put("{{protocol_number}}", amendmentRequest.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatCreatedDate(amendmentRequest.getProtocol().getCreatedDate())); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(amendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + bodyPlaceholders.put("{{form_text}}", amendmentRequest.getNote()); + + sendEmail(amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.INADMISSIBILITY_TEMPLATE, bodyPlaceholders, null); + } + + public void sendMail(Long hubId, String subject, String body, List recipientEmails) { + + EmailConfig emailConfig = retrieveEmailConfig(hubId); + EmailService emailService = emailServiceFactory.getEmailService(emailConfig.getEmailServiceType()); + emailService.sendEmail(subject, body, recipientEmails, emailConfig); + } + + public EmailConfig retrieveEmailConfig(Long hubId) { + + HubEntity hubEntity = hubRepository.findById(hubId).orElseThrow(() -> new IllegalArgumentException("Invalid Hub ID: " + hubId)); + String emailServiceType = hubEntity.getEmailServiceType(); + String encryptedConfigJson = hubEntity.getEmailServiceConfig(); + String decryptedConfigJson = Utils.decryptCredential(encryptedConfigJson); + EmailConfig emailConfig = parseEmailConfig(decryptedConfigJson); + emailConfig.setEmailServiceType(emailServiceType); + return emailConfig; + } + + private EmailConfig parseEmailConfig(String configJson) { + + ObjectMapper objectMapper = new ObjectMapper(); + try { + return objectMapper.readValue(configJson, EmailConfig.class); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("Failed to parse email configuration JSON", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index 550bd240..456a614b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -230,10 +230,10 @@ public class PdfDao { // PdfPCell valueCell = new PdfPCell(new Phrase(item, valueFont)); PdfPCell valueCell = PdfUtils.htmlToPdfPCell(item, valueFont); - valueCell.setFixedHeight(30f); // Set a fixed height for the cell valueCell.setPaddingLeft(10f); // Adjust left padding as needed valueCell.setPaddingTop(0f); // Remove padding from top to allow vertical centering valueCell.setPaddingBottom(6f); + valueCell.setMinimumHeight(30f); // Set a fixed height for the cell valueCell.setPaddingLeft(leftMargin); // Increase left margin for value valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE); @@ -306,7 +306,7 @@ public class PdfDao { } // PdfPCell valueCell = new PdfPCell(new Phrase(fieldValue1, valueFont)); PdfPCell valueCell = PdfUtils.htmlToPdfPCell(fieldValue1, valueFont); - valueCell.setFixedHeight(30f); // Set a fixed height for the cell + valueCell.setMinimumHeight(30f); // Set a fixed height for the cell valueCell.setPaddingLeft(10f); // Adjust left padding as needed valueCell.setPaddingTop(0f); // Remove padding from top to allow vertical centering valueCell.setPaddingBottom(6f); @@ -393,7 +393,7 @@ public class PdfDao { headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE); headerCell.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header - headerCell.setFixedHeight(30f); // Set a fixed height for the cell + headerCell.setMinimumHeight(30f); // Set a fixed height for the cell headerCell.setPaddingLeft(10f); // Adjust left padding as needed headerCell.setPaddingTop(0f); // Remove padding from top to allow vertical centering headerCell.setPaddingBottom(6f); @@ -415,6 +415,7 @@ public class PdfDao { // PdfPCell dataCell = new PdfPCell(new Phrase(fieldValue != null ?fieldValue: "", textFont)); PdfPCell dataCell = PdfUtils.htmlToPdfPCell(fieldValue != null ? fieldValue : "", textFont); dataCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell + dataCell.setMinimumHeight(30f); dataCell.setPaddingLeft(10f); // Adjust left padding as needed dataCell.setPaddingTop(0f); // Remove padding from top to allow vertical centering dataCell.setPaddingBottom(6f); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java new file mode 100644 index 00000000..97ecde18 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java @@ -0,0 +1,48 @@ +package net.gepafin.tendermanagement.dao; + +import java.time.LocalDateTime; +import java.time.LocalTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.HubEntity; +import net.gepafin.tendermanagement.entities.ProtocolEntity; +import net.gepafin.tendermanagement.repositories.ProtocolRepository; +import net.gepafin.tendermanagement.util.DateTimeUtil; + +@Component +public class ProtocolDao { + + @Autowired + private ProtocolRepository protocolRepository; + + + @Value("${default.hub.uuid}") + private String defaultHubUuid; + + + public Long getProtocolNumber(HubEntity hubEntity) { + Long maxProtocolNumber = protocolRepository.findMaxProtocolNumberAndHubId(hubEntity.getId()); + Long startNumber = 10000001L; + if(Boolean.FALSE.equals(defaultHubUuid.equals(hubEntity.getUniqueUuid()))) { + startNumber = 20000001L; + } + return (maxProtocolNumber != null) ? maxProtocolNumber + 1 : startNumber; + } + + public ProtocolEntity createProtocolEntity(ApplicationEntity applicationEntity,Long protocolNumber, Long hubId){ + ProtocolEntity protocolEntity=new ProtocolEntity(); + protocolEntity.setCall(applicationEntity.getCall().getId()); + LocalDateTime utcDateTime = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + protocolEntity.setYear(utcDateTime.getYear()); + protocolEntity.setProtocolNumber(protocolNumber); + protocolEntity.setTime(LocalTime.now()); + protocolEntity.setApplicationId(applicationEntity.getId()); + protocolEntity.setHubId(hubId); + protocolRepository.save(protocolEntity); + return protocolEntity; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 33f235a2..53d21fc5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -5,10 +5,7 @@ import jakarta.servlet.http.HttpServletResponse; import net.gepafin.tendermanagement.config.SamlSuccessHandler; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; -import net.gepafin.tendermanagement.entities.BeneficiaryEntity; -import net.gepafin.tendermanagement.entities.HubEntity; -import net.gepafin.tendermanagement.entities.RoleEntity; -import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; @@ -80,6 +77,9 @@ public class UserDao { @Autowired private HubService hubService; + @Autowired + private AuthenticationService authenticationService; + public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { if(StringUtils.isEmpty(userReq.getHubUuid())) { @@ -92,6 +92,14 @@ public class UserDao { BeneficiaryEntity beneficiary = createBeneficiary(roleEntity, userReq, hub); UserEntity userEntity = convertUserRequestToUserEntity(beneficiary, roleEntity, userReq, hub); log.info("User created with ID: {}", userEntity.getId()); + LoginReq loginReq=new LoginReq(); + loginReq.setEmail(userEntity.getEmail()); + if(userEntity!=null){ + LoginAttemptEntity loginAttemptEntity =authenticationService.prepareLoginAttemptEntity(loginReq, request); + log.info("Authentication failed for email: {}", loginReq.getEmail()); + loginAttemptEntity.setUserId(userEntity.getId()); + authenticationService.createSuccessLoginAttempt(loginAttemptEntity); + } return authService.getJWTTokenBean(userEntity, Boolean.TRUE); } @@ -403,8 +411,8 @@ public class UserDao { return userResponseBeans; } - public JWTToken validateExistingUserToken(String token) { - return authService.validateExistingUserToken(token); + public JWTToken validateExistingUserToken(HttpServletRequest request,String token) { + return authService.validateExistingUserToken(request,token); } public UserSamlResponse validateNewUserToken(String token) { diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java new file mode 100644 index 00000000..4d2dabf6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java @@ -0,0 +1,50 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import java.time.LocalDateTime; + +@Entity +@Table(name="application_amendment_request") +@Data +public class ApplicationAmendmentRequestEntity extends BaseEntity { + + @Column(name = "NOTE") + private String note; + + @Column(name ="RESPONSE_DAYS") + private Long responseDays; + + @Column(name = "IS_NOTIFICATION") + private Boolean isNotification = false; + + @Column(name = "IS_EMAIL") + private Boolean isEmail=false; + + @Column(name = "APPLICATION_ID") + private Long applicationId; + + @Column(name = "START_DATE") + private LocalDateTime startDate; + + @Column(name = "FORM_FIELDS") + private String formFields; + + @Column(name="IS_DELETED") + private Boolean isDeleted=false; + + @Column(name = "STATUS") + private String status; + + @Column(name = "INTERNAL_NOTE") + private String internalNote; + + @ManyToOne + @JoinColumn(name = "APPLICATION_EVALUATION_ID", nullable = false) + private ApplicationEvaluationEntity applicationEvaluationEntity; + + @OneToOne + @JoinColumn(name = "PROTOCOL_Id") + private ProtocolEntity protocol; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java index 5ddebe5c..68c433e2 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java @@ -8,9 +8,6 @@ import java.time.LocalDateTime; @Entity @Table(name = "APPLICATION") @Data -@NoArgsConstructor -@AllArgsConstructor -@Builder public class ApplicationEntity extends BaseEntity { @Column(name = "USER_ID") diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java new file mode 100644 index 00000000..dae9a3fb --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java @@ -0,0 +1,39 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name = "application_evaluation") +public class ApplicationEvaluationEntity extends BaseEntity{ + + @Column(name = "application_Id") + private Long applicationId; + + @Column(name = "user_id") + private Long userId; + + @Column(name = "criteria") + private String criteria; + + @Column(name = "checklist") + private String checklist; + + @Column(name = "file") + private String file; + + @Column(name = "note") + private String note; + + @Column(name = "status") + private String status; + + @Column(name="IS_DELETED") + private Boolean isDeleted; + + @ManyToOne + @JoinColumn(name = "assigned_applications_id", nullable = true) + private AssignedApplicationsEntity assignedApplicationsEntity; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CommunicationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CommunicationEntity.java new file mode 100644 index 00000000..7aa43acd --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/CommunicationEntity.java @@ -0,0 +1,33 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Data; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "communication") +@Data +public class CommunicationEntity extends BaseEntity { + + @Column(name = "COMMUNICATION_TITLE") + private String communicationTitle; + + @Column(name = "COMMUNICATION_COMMENT") + private String communicationComment; + + @Column(name = "IS_DELETED") + private Boolean isDeleted = false; + + @Column(name = "COMMENTED_DATE") + private LocalDateTime commentedDate; + + @ManyToOne + @JoinColumn(name = "AMENDMENT_ID", referencedColumnName = "id", nullable = false) + private ApplicationAmendmentRequestEntity applicationAmendmentRequest; + +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java index b8ae74a9..2e219acf 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java @@ -42,10 +42,16 @@ public class HubEntity extends BaseEntity{ @Column(name = "UNIQUE_UUID") private String uniqueUuid; - - @Column(name = "EMAIL_SIGNATURE") - private String emailSignature; @Column(name="PDF_BANNER") private String pdfBanner; + + @Column(name = "EMAIL_SIGNATURE") + private String emailSignature; + + @Column(name = "EMAIL_SERVICE_TYPE") + private String emailServiceType; + + @Column(name = "EMAIL_SERVICE_CONFIG") + private String emailServiceConfig; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java index 9ae12cbf..1440e00d 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java @@ -39,7 +39,12 @@ public class SystemEmailTemplatesEntity extends BaseEntity { public enum SystemEmailTemplatesEntityTypeEnum { APPLICATION_SUBMISSION_TO_USER_AND_COMPANY("APPLICATION_SUBMISSION_TO_USER_AND_COMPANY"), - APPLICATION_SUBMISSION_TO_GEPAFIN("APPLICATION_SUBMISSION_TO_GEPAFIN"); + APPLICATION_SUBMISSION_TO_GEPAFIN("APPLICATION_SUBMISSION_TO_GEPAFIN"), + DOCUMENTATION_INTEGRATION_REQUEST("DOCUMENTATION_INTEGRATION_REQUEST"), + INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE("INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE"), + ADMISSIBILITY_NOTIFICATION("ADMISSIBILITY_NOTIFICATION"), + AMENDMENT_REMINDER("AMENDMENT_REMINDER"), + INADMISSIBILITY_TEMPLATE("INADMISSIBILITY_NOTIFICATION"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationAmendmentRequestEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationAmendmentRequestEnum.java new file mode 100644 index 00000000..d25ef71d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationAmendmentRequestEnum.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ApplicationAmendmentRequestEnum { + AWAITING("AWAITING"), + RESPONSE_RECEIVED("RESPONSE_RECEIVED"), + CLOSE("CLOSE"), + EXPIRED("EXPIRED"); + + private String value; + + ApplicationAmendmentRequestEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java new file mode 100644 index 00000000..18cfc30d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ApplicationEvaluationStatusTypeEnum { + OPEN ("OPEN"), + SOCCORSO("SOCCORSO"), + CLOSE("CLOSE"); + + private String value; + + ApplicationEvaluationStatusTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusForEvaluation.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusForEvaluation.java new file mode 100644 index 00000000..61c39b8e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusForEvaluation.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ApplicationStatusForEvaluation { + APPROVED("APPROVED"), + REJECTED("REJECTED"); + + private String value; + + ApplicationStatusForEvaluation(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java index fe44af47..db6fe287 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java @@ -9,6 +9,9 @@ public enum ApplicationStatusTypeEnum { AWAITING("AWAITING"), READY("READY"), DISCARD("DISCARD"), + SOCCORSO("SOCCORSO"), + APPROVED("APPROVED"), + REJECTED("REJECTED"), EVALUATION("EVALUATION"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/AssignedApplicationEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/AssignedApplicationEnum.java index e0cba98f..59f8ae1d 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/AssignedApplicationEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/AssignedApplicationEnum.java @@ -3,9 +3,9 @@ package net.gepafin.tendermanagement.enums; import com.fasterxml.jackson.annotation.JsonValue; public enum AssignedApplicationEnum { - ASSIGNED("ASSIGNED"), - APPROVED("APPROVED"), - REJECTED("REJECTED"); + OPEN ("OPEN"), + SOCCORSO("SOCCORSO"), + CLOSE("CLOSE"); private final String value; diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequest.java new file mode 100644 index 00000000..ade4c676 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequest.java @@ -0,0 +1,14 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; +import net.gepafin.tendermanagement.model.response.AmendmentFormFieldResponse; +import java.util.List; + +@Data +public class ApplicationAmendmentRequest { + private String note; + private List formFields; + private Long responseDays; + private Boolean isSendNotification; + private Boolean isSendEmail; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java new file mode 100644 index 00000000..c3c5aeb5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class ApplicationAmendmentRequestBean { + private String note; + private ApplicationFormFieldRequestBean applicationFormFields; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java new file mode 100644 index 00000000..9563f00b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; + +import java.util.List; +@Data +public class ApplicationEvaluationRequest { + + private List criteria; + private List checklist; + private List files; + private String note; + private ApplicationStatusForEvaluation applicationStatus; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ChecklistRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/ChecklistRequest.java new file mode 100644 index 00000000..2d760ec2 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ChecklistRequest.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class ChecklistRequest { + private Long id; + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CloseAmendmentRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CloseAmendmentRequest.java new file mode 100644 index 00000000..3d05c676 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CloseAmendmentRequest.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class CloseAmendmentRequest { + private String InternalNote; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CommunicationRequestBean.java b/src/main/java/net/gepafin/tendermanagement/model/request/CommunicationRequestBean.java new file mode 100644 index 00000000..d44e7eaa --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CommunicationRequestBean.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class CommunicationRequestBean { + private String title; + private String comment; +} + diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CriteriaRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CriteriaRequest.java new file mode 100644 index 00000000..ada0d83c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CriteriaRequest.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class CriteriaRequest { + private Long id; + private Long score; + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/EmailConfig.java b/src/main/java/net/gepafin/tendermanagement/model/request/EmailConfig.java new file mode 100644 index 00000000..5a94b325 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/EmailConfig.java @@ -0,0 +1,18 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class EmailConfig { + private String emailServiceType; + private String authToken; + private String apiKey; + private String username; + private String password; + private String sender; + private String domain; + private String mailgunApiUrl; + private String pecApiUrl; +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/FieldRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/FieldRequest.java new file mode 100644 index 00000000..b3b5b3e1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/FieldRequest.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class FieldRequest { + private String id; + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/PecEmailRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/PecEmailRequest.java new file mode 100644 index 00000000..a066dce0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/PecEmailRequest.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +import java.util.List; + +@Data +public class PecEmailRequest { + private String sender; + private List recipient; + private String subject; + private String body; + private String username; + private String password; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateApplicationEvaluationRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateApplicationEvaluationRequest.java new file mode 100644 index 00000000..16654fff --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateApplicationEvaluationRequest.java @@ -0,0 +1,2 @@ +package net.gepafin.tendermanagement.model.request;public class UpdateApplicationEvaluationRequest { +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentFormFieldResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentFormFieldResponse.java new file mode 100644 index 00000000..d3fdda8f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentFormFieldResponse.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class AmendmentFormFieldResponse { + private String fieldId; + private String label; + private boolean isSelected = false; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java new file mode 100644 index 00000000..be03d36b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java @@ -0,0 +1,30 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class ApplicationAmendmentRequestResponse { + private Long id; + private String callEmail; + private String note; + private Long responseDays; + private LocalDateTime startDate; + private boolean isSendNotification; + private boolean isSendEmail; + private Long protocolNumber; + private String callName; + private String beneficiaryName; + private List formFields; + private List applicationFormFields; + private Long applicationId; + private Long applicationEvaluationId; + private LocalDateTime expirationDate; + private List commentsList; + private String internalNote; + private ApplicationAmendmentRequestEnum status; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentResponse.java new file mode 100644 index 00000000..52ae7285 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentResponse.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; + +import java.util.List; + +@Data +public class ApplicationAmendmentResponse { + private ApplicationAmendmentRequestEntity amendment; + private List commentsList; + public ApplicationAmendmentResponse(ApplicationAmendmentRequestEntity amendment, List comments) { + this.amendment = amendment; + this.commentsList = comments; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java new file mode 100644 index 00000000..f0be1236 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java @@ -0,0 +1,32 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class ApplicationEvaluationResponse { + + + private Long id; + private Long applicationId; + private ApplicationStatusTypeEnum applicationStatus; + private Long assignedApplicationId; + private String note; + private ApplicationEvaluationStatusTypeEnum status; + private Long minScore; + private List criteria; + private List checklist; + private List files; + private LocalDateTime createdDate; + private LocalDateTime updatedDate; + private String beneficiary; + private Long protocolNumber; + private String callName; + private LocalDateTime submissionDate; + private LocalDateTime evaluationDate; + private LocalDateTime callEndDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ChecklistResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ChecklistResponse.java new file mode 100644 index 00000000..a07bfb52 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ChecklistResponse.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +public class ChecklistResponse { + private Long id; + private String label; + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CommunicationResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/CommunicationResponseBean.java new file mode 100644 index 00000000..d1405dd8 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CommunicationResponseBean.java @@ -0,0 +1,33 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class CommunicationResponseBean { + private LocalDateTime commentedDate; + + private String comment; + + private String title; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + + private Long amendmentId; + public CommunicationResponseBean(LocalDateTime commentedDate, String comment, String title, LocalDateTime createdDate, LocalDateTime updatedDate, Long amendmentId) { + + this.commentedDate = commentedDate; + this.comment = comment; + this.title = title; + this.createdDate = createdDate; + this.updatedDate = updatedDate; + this.amendmentId = amendmentId; + } + + public CommunicationResponseBean() { + + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CriteriaMappedField.java b/src/main/java/net/gepafin/tendermanagement/model/response/CriteriaMappedField.java new file mode 100644 index 00000000..d730d308 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CriteriaMappedField.java @@ -0,0 +1,12 @@ +package net.gepafin.tendermanagement.model.response; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Data; + +@Data +public class CriteriaMappedField { + private String id; + private String fieldName; + private String fieldLabel; + private Object fieldValue; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CriteriaResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CriteriaResponse.java new file mode 100644 index 00000000..ebbb2f2c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CriteriaResponse.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.util.List; + +@Data +public class CriteriaResponse { + private Long id; + private String label; + private Long score; + private Long maxScore; + private List criteriaMappedFields; + private Boolean valid; +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/FieldResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/FieldResponse.java new file mode 100644 index 00000000..07469d6c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/FieldResponse.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +public class FieldResponse { + private String id; + private String label; + private Boolean valid; + private List fileDetail ; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java new file mode 100644 index 00000000..88561517 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java @@ -0,0 +1,32 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface ApplicationAmendmentRequestRepository extends JpaRepository, JpaSpecificationExecutor { + Optional findByIdAndIsDeletedFalse(Long id); + + @Query(value = "SELECT ar.* FROM application_amendment_request ar " + + "JOIN application app ON ar.application_id = app.id " + + "WHERE app.user_id = :userId AND ar.is_deleted = false", + nativeQuery = true) + List findByUserId(@Param("userId") Long userId); + + List findByIsDeletedFalse(); + + @Query(value = "SELECT amr FROM ApplicationAmendmentRequestEntity amr " + "WHERE amr.applicationEvaluationEntity.id = :id " + "AND amr.applicationEvaluationEntity.isDeleted = false") + ApplicationAmendmentRequestEntity findByApplicationEvaluationIdAndIsDeletedFalse(Long id); + +// ApplicationAmendmentRequestEntity findByApplicationIdAndIsDeletedFalse(Long applicationId); + + List findByApplicationIdAndIsDeletedFalse(Long applicationId); + + List findByApplicationIdAndStatusInAndIsDeletedFalse(Long applicationId, List statuses); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java new file mode 100644 index 00000000..9ec88ffa --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java @@ -0,0 +1,25 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface ApplicationEvaluationRepository extends JpaRepository { + + Optional findByApplicationIdAndIsDeletedFalse(Long applicationId); + Optional findByIdAndIsDeletedFalse(Long id); + Optional findByAssignedApplicationsEntity_IdAndIsDeletedFalse(Long assignedApplicationId); + + Optional findByApplicationIdAndAssignedApplicationsEntity_IdAndIsDeletedFalse(Long applicationId, Long assignedApplicationId); + + Optional findFirstByIsDeletedFalseOrderByCreatedDateDesc(); + boolean existsByApplicationIdAndIsDeletedFalse(Long applicationId); + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormFieldRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormFieldRepository.java index 89c70488..b989e2dd 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormFieldRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormFieldRepository.java @@ -23,5 +23,19 @@ public interface ApplicationFormFieldRepository extends JpaRepository findByFieldValueInAndApplicationFormApplicationId( List fieldValue, Long applicationId); + /** + * Find ApplicationFormField entity by Field ID, Form ID, and Application ID. + * + * @param fieldId The Field ID to search. + * @param formId The Form ID to search. + * @param applicationId The Application ID to search. + * @return Optional of ApplicationFormFieldEntity + */ + Optional findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + String fieldId, Long formId, Long applicationId); + + public ApplicationFormFieldEntity findByFieldId(String FieldId); + + Optional findByApplicationFormIdAndFieldId(Long id, String fieldId); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 158c43fd..38d73e8d 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -29,15 +29,15 @@ public interface ApplicationRepository extends JpaRepository findByIdAndUserIdAndCallIdAndIsDeletedFalse(Long applicationId, Long userId, Long callId); - @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.userId = :userId AND a.company.id = :companyId AND a.status = 'SUBMIT' ") + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.userId = :userId AND a.company.id = :companyId AND a.status = 'SUBMIT' AND a.isDeleted = false") Long countSubmittedApplicationsByUserId(@Param("userId") Long userId, @Param("companyId") Long companyId); List findByCompanyIdAndUserIdAndIsDeletedFalse(Long companyId,Long userId); - @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'SUBMIT' And a.hubId = :hubId") + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'SUBMIT' And a.hubId = :hubId AND a.isDeleted = false") public Long countSubmittedApplicationsByHubId(@Param("hubId") Long hubId); - @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'DRAFT' And a.hubId = :hubId") + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'DRAFT' And a.hubId = :hubId AND a.isDeleted = false") public Long countDraftApplicationsByHubId(@Param("hubId") Long hubId); @Query("SELECT a.call.id FROM ApplicationEntity a WHERE a.id = :id") diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/AssignedApplicationsRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/AssignedApplicationsRepository.java index 076b93a9..164dcb0a 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/AssignedApplicationsRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/AssignedApplicationsRepository.java @@ -2,12 +2,24 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; + +import java.util.List; import java.util.Optional; @Repository public interface AssignedApplicationsRepository extends JpaRepository, JpaSpecificationExecutor{ Optional findByApplicationIdAndIsDeletedFalse(Long applicationId); Optional findByIdAndIsDeletedFalse(Long id); + @Query("SELECT aa FROM AssignedApplicationsEntity aa WHERE aa.isDeleted = false " + + "AND (:applicationId IS NULL OR aa.application.id = :applicationId) " + + "AND (:id IS NULL OR aa.id = :id) ") + Optional findByApplicationIdOrIdAndIsDeletedFalse( + @Param("applicationId") Long applicationId, + @Param("id") Long id); + + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java index 12934e36..27ab57b4 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java @@ -22,6 +22,14 @@ public interface CallRepository extends JpaRepository { // @Query("SELECT COALESCE(SUM(c.amount), 0) FROM CallEntity c WHERE c.status = 'PUBLISH'") // BigDecimal findTotalAmountOfPublishedCalls(); + @Query("SELECT c.name, COUNT(a.id) " + + "FROM CallEntity c LEFT JOIN ApplicationEntity a ON c.id = a.call.id " + + "GROUP BY c.name") + List findApplicationsPerCall(); + + + @Query("SELECT c FROM CallEntity c JOIN ApplicationEntity a ON c.id = a.call.id WHERE a.id = :applicationId") + CallEntity findCallEntityByApplicationId(Long applicationId); // @Query("SELECT c.name, COUNT(a.id) " + // "FROM CallEntity c LEFT JOIN ApplicationEntity a ON c.id = a.call.id " + // "GROUP BY c.name") diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java index 62da59a7..d092ea4a 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java @@ -17,4 +17,5 @@ public interface CallTargetAudienceChecklistRepository extends JpaRepository findById(@Param("id") Long id); List findByCallIdAndLookupDataTypeAndIsDeletedFalse(Long id, String type); + List findByCallId(Long callId); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CommunicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CommunicationRepository.java new file mode 100644 index 00000000..0e9d8d9c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CommunicationRepository.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.CommunicationEntity; +import net.gepafin.tendermanagement.model.response.CommunicationResponseBean; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface CommunicationRepository extends JpaRepository { + + @Query("Select new net.gepafin.tendermanagement.model.response.CommunicationResponseBean(c.commentedDate, c.communicationComment, c.communicationTitle, c.createdDate, c.updatedDate, c.applicationAmendmentRequest.id) " + + "from CommunicationEntity c Where c.applicationAmendmentRequest.id = :applicationAmendmentRequestId") + List findCommentsByApplicationAmendmentRequestId(@Param("applicationAmendmentRequestId") Long amendmentRequestId); + + @Query("SELECT new net.gepafin.tendermanagement.model.response.CommunicationResponseBean( " + "c.commentedDate, c.communicationComment, c.communicationTitle, c.createdDate, c" + + ".updatedDate, c.applicationAmendmentRequest.id) " + "FROM CommunicationEntity c " + "WHERE c.applicationAmendmentRequest.id = :amendmentId AND c.isDeleted = false") + List findCommentDetailsByAmendmentId(@Param("amendmentId") Long amendmentId); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index b7fc2923..d3eb3058 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -13,14 +13,14 @@ import org.springframework.stereotype.Repository; public interface DocumentRepository extends JpaRepository { @Query("SELECT d FROM DocumentEntity d WHERE d.id = :id AND d.isDeleted = false") - Optional findById(@Param("id") Long id); + Optional findByIdAndNotDeleted(@Param("id") Long id); // List findBySourceIdAndTypeAndIsDeletedFalse(Long sourceId, String type); // Optional findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId); List findBySource(String source); - + List findBySourceIdAndSourceAndTypeAndIsDeletedFalse(Long sourceId, String source, String type); Optional findByIdAndSourceIdAndSourceAndIsDeletedFalse(Long id, Long sourceId, String source); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java index b5b9a231..8b25fc1f 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java @@ -16,4 +16,6 @@ public interface EvaluationCriteriaRepository extends JpaRepository findById(@Param("id") Long id); List findByCallIdAndLookupDataTypeAndIsDeletedFalse(Long callId, String type); + List findByCallId(Long callId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java new file mode 100644 index 00000000..93d41c98 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java @@ -0,0 +1,61 @@ +package net.gepafin.tendermanagement.scheduler; + +import net.gepafin.tendermanagement.dao.EmailNotificationDao; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; + +@Component +public class NotificationScheduler { + + @Autowired + UserRepository userRepository; + + @Autowired + ApplicationRepository applicationRepository; + + @Autowired + ApplicationAmendmentRequestRepository applicationAmendmentRepository; + + @Autowired + EmailNotificationDao emailNotificationDao; + + @Scheduled(cron = "0 0 1 * * ?") + void sendNotificationForRejectedApplicationToBeneficiary() { + + List applicationsList = applicationRepository.findByIsDeletedFalse(); + List amendmentRequestList = applicationAmendmentRepository.findByIsDeletedFalse(); + + LocalDateTime today = LocalDateTime.now(); + + for (ApplicationEntity application : applicationsList) { + ApplicationAmendmentRequestEntity amendmentRequest = getAmendmentRequestForApplication(application, amendmentRequestList); + + if (amendmentRequest != null) { + LocalDateTime requestDate = amendmentRequest.getCreatedDate(); + if (requestDate.plusDays(amendmentRequest.getResponseDays()).isAfter(today)) { + // Update the application status to REJECTED + application.setStatus("REJECTED"); + applicationRepository.save(application); + amendmentRequest.setStatus("CLOSE"); + applicationAmendmentRepository.save(amendmentRequest); + emailNotificationDao.sendApplicationFailureNotificationEmail(amendmentRequest); + } + } + } + } + + private ApplicationAmendmentRequestEntity getAmendmentRequestForApplication(ApplicationEntity application, List amendmentRequestList) { + + return amendmentRequestList.stream().filter(request -> request.getId().equals(application.getId())).findFirst().orElse(null); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java new file mode 100644 index 00000000..678ff913 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java @@ -0,0 +1,29 @@ +package net.gepafin.tendermanagement.service; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequest; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequestBean; +import net.gepafin.tendermanagement.model.request.CloseAmendmentRequest; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentRequestResponse; + +import java.util.List; + +public interface ApplicationAmendmentRequestService { + public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(HttpServletRequest request,Long applicationEvaluationId); + public ApplicationAmendmentRequestResponse createApplicationAmendmentRequest(HttpServletRequest request, Long applicationEvaluationId , ApplicationAmendmentRequest applicationAmendmentRequest); + void deleteApplicationAmendmentRequest(HttpServletRequest request, Long id); + ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(HttpServletRequest request,Long id); + List getAllApplicationAmendmentRequest(HttpServletRequest request,Long userId); + ApplicationAmendmentRequestResponse updateApplicationAmendment(HttpServletRequest request, Long id, ApplicationAmendmentRequestBean applicationAmendmentRequestBean); + ApplicationAmendmentRequestEntity validateApplicationAmendmentRequest(Long applicationAmendmentId); + List getAllAmendmentRequestByBeneficiaryId(HttpServletRequest request,Long beneficiaryId); + ApplicationAmendmentRequestResponse closeAmendmentRequest(HttpServletRequest request, Long id, CloseAmendmentRequest closeAmendmentRequest); + ApplicationAmendmentRequestResponse extendResponseDays(HttpServletRequest request, Long id, Long addedDays); + public List getAmendmentByApplicationId(HttpServletRequest request,Long applicationId,List statuses); + public ApplicationAmendmentRequestResponse updateApplicationAmendmentStatus(HttpServletRequest request, Long applicationAmendmentId, ApplicationAmendmentRequestEnum status); + + void sendReminderEmail(HttpServletRequest request,Long amendmentId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java new file mode 100644 index 00000000..c9f72e6a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.service; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; +import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; + +public interface ApplicationEvaluationService { + ApplicationEvaluationResponse createOrUpdateApplicationEvaluation( + HttpServletRequest request, + ApplicationEvaluationRequest applicationEvaluationRequest, + Long assignedApplicationsId); + + void deleteApplicationEvaluation(HttpServletRequest request,Long id); + + ApplicationEvaluationResponse getApplicationEvaluationByApplicationId(HttpServletRequest request,Long applicationId,Long assignedApplicationId); + ApplicationEvaluationEntity validateApplicationEvaluation(Long applicationEvaluationId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java index c9a65fef..9ef06c48 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java @@ -22,11 +22,11 @@ public interface ApplicationService { ApplicationGetResponseBean getApplicationByFormId(HttpServletRequest request, Long applicationId,Long formId); - List getAllApplications(HttpServletRequest request,Long callId, Long companyId,String status); + List getAllApplications(HttpServletRequest request,Long callId, Long companyId,List statusList); void deleteApplication(HttpServletRequest request, Long applicationId); - public ApplicationEntity validateApplication(Long userId); + public ApplicationEntity validateApplication(Long applicationId); public ApplicationResponse createApplication(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId); diff --git a/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java b/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java index 166e9180..f1670687 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.service; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; @@ -16,4 +17,5 @@ public interface AssignedApplicationsService { List getAllAssignedApplications(HttpServletRequest request, Long userId); AssignedApplicationsResponse updateAssignedApplication(HttpServletRequest request, Long id, AssignedApplicationsRequest assignedApplicationsRequest); AssignedApplicationsResponse getAssignedApplicationById(HttpServletRequest request, Long id); + AssignedApplicationsEntity validateAssignedApplication(Long assignedApplicationId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CommunicationService.java b/src/main/java/net/gepafin/tendermanagement/service/CommunicationService.java new file mode 100644 index 00000000..5f8f1cd3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/CommunicationService.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.model.request.CommunicationRequestBean; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse; +import net.gepafin.tendermanagement.model.response.CommunicationResponseBean; + +public interface CommunicationService { + CommunicationResponseBean addCommentToAmendmentRequest(CommunicationRequestBean communicationRequestBean, Long amendmentId); + + String deleteComment(Long amendmentId, Long commentId); + + CommunicationResponseBean updateAmendmentComment(CommunicationRequestBean communicationRequestBean, Long amendmentId, Long commentId); + + ApplicationAmendmentResponse getAmendmentComments(Long id); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/MailgunFeignClient.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/MailgunFeignClient.java new file mode 100644 index 00000000..eb9c50d1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/MailgunFeignClient.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.service.feignClient; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = "mailgunClient", url = "${mailGun_base_url}") +public interface MailgunFeignClient { + @PostMapping("/v3/{domain}/messages") + ResponseEntity sendEmail( + @PathVariable("domain") String domain, + @RequestParam("from") String from, + @RequestParam("to") List to, + @RequestParam("subject") String subject, + @RequestParam("html") String htmlBody, + @RequestHeader("Authorization") String authorizationHeader); +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/PecFeignClient.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/PecFeignClient.java new file mode 100644 index 00000000..d251e644 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/PecFeignClient.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.service.feignClient; + +import feign.Headers; +import net.gepafin.tendermanagement.model.request.PecEmailRequest; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; + +@FeignClient(name = "pecClient", url = "${api.pecUrl}") +public interface PecFeignClient { + @PostMapping("/send") + ResponseEntity sendEmail(@RequestHeader("Authorization") String token, + @RequestBody PecEmailRequest emailRequest); +} + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java new file mode 100644 index 00000000..1f6f2f84 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java @@ -0,0 +1,153 @@ +package net.gepafin.tendermanagement.service.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequest; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequestBean; +import net.gepafin.tendermanagement.model.request.CloseAmendmentRequest; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentRequestResponse; +import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; +import net.gepafin.tendermanagement.service.ApplicationAmendmentRequestService; +import net.gepafin.tendermanagement.util.Validator; +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.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendmentRequestService { + + @Autowired + private Validator validator; + + @Autowired + private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; + @Autowired + private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Override + public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(HttpServletRequest request, Long applicationEvaluationId) { + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(applicationEvaluationId); + entityOptional.ifPresent(applicationEvaluationEntity -> validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId())); + return applicationAmendmentRequestDao.getApplicationDataForAmendment(applicationEvaluationId); + } + + @Override + public ApplicationAmendmentRequestResponse createApplicationAmendmentRequest(HttpServletRequest request, Long applicationEvaluationId , ApplicationAmendmentRequest applicationAmendmentRequest) { + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(applicationEvaluationId); + entityOptional.ifPresent(applicationEvaluationEntity -> validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId())); + return applicationAmendmentRequestDao.createApplicationAmendmentRequest(applicationEvaluationId,applicationAmendmentRequest); + } + + @Override + public void deleteApplicationAmendmentRequest(HttpServletRequest request, Long id) { + ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); + + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(amendment.getApplicationEvaluationEntity().getId()); + if (entityOptional.isPresent()) { + UserEntity user = validator.validatePreInstructor(request, entityOptional.get().getUserId()); + + applicationAmendmentRequestDao.deleteById(id); + } + } + + @Override + public ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(HttpServletRequest request,Long id) { + ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); + + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(amendment.getApplicationEvaluationEntity().getId()); + if (entityOptional.isPresent()) { + UserEntity user = validator.validatePreInstructor(request, entityOptional.get().getUserId()); + } + return applicationAmendmentRequestDao.getApplicationAmendmentRequestById(id); + + } + + @Override + public List getAllApplicationAmendmentRequest(HttpServletRequest request,Long userId) { + UserEntity user = validator.validatePreInstructor(request, userId); + return applicationAmendmentRequestDao.getAllApplicationAmendmentRequest(request,userId); + } + + @Override + public ApplicationAmendmentRequestResponse updateApplicationAmendment(HttpServletRequest request, Long id, ApplicationAmendmentRequestBean applicationAmendmentRequestBean) { + ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); + + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(amendment.getApplicationEvaluationEntity().getId()); + if (entityOptional.isPresent()) { + UserEntity user = validator.validatePreInstructor(request, entityOptional.get().getUserId()); + } + return applicationAmendmentRequestDao.updateApplicationAmendment(id,applicationAmendmentRequestBean); + } + + @Override + public ApplicationAmendmentRequestEntity validateApplicationAmendmentRequest(Long applicationAmendmentId) { + + return applicationAmendmentRequestDao.validateApplicationAmendmentRequest(applicationAmendmentId); + } + + @Override + public List getAllAmendmentRequestByBeneficiaryId(HttpServletRequest request, Long beneficiaryId) { + UserEntity user= validator.validateUser(request); + return applicationAmendmentRequestDao.getAllAmendmentRequestByBeneficiaryId(beneficiaryId); + } + + @Override + public ApplicationAmendmentRequestResponse closeAmendmentRequest(HttpServletRequest request, Long id, CloseAmendmentRequest closeAmendmentRequest) { + ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); + + Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(amendment.getApplicationEvaluationEntity().getId()); + if (entityOptional.isPresent()) { + UserEntity user = validator.validatePreInstructor(request, entityOptional.get().getUserId()); + } + return applicationAmendmentRequestDao.closeAmendmentRequest(id,closeAmendmentRequest); + } + + @Override + public ApplicationAmendmentRequestResponse extendResponseDays(HttpServletRequest request, Long id, Long addedDays) { + UserEntity user= validator.validateUser(request); + return applicationAmendmentRequestDao.extendResponseDays(id, addedDays); + + } + public List getAmendmentByApplicationId(HttpServletRequest request, Long applicationId,List statuses) { + return applicationAmendmentRequestDao.getAmendmentByApplicationId(request,applicationId,statuses); + } + @Override + public ApplicationAmendmentRequestResponse updateApplicationAmendmentStatus(HttpServletRequest request, Long applicationAmendmentId, ApplicationAmendmentRequestEnum status) { + return applicationAmendmentRequestDao.updateApplicationAmendmentStatus(applicationAmendmentId, status); + + } + @Override + public void sendReminderEmail(HttpServletRequest request,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()) { + UserEntity user = validator.validatePreInstructor(request, entityOptional.get().getUserId()); + + applicationAmendmentRequestDao.sendReminderEmail(amendmentId); + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java new file mode 100644 index 00000000..6ccee608 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java @@ -0,0 +1,98 @@ +package net.gepafin.tendermanagement.service.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.dao.ApplicationEvaluationDao; + +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; +import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; + +import net.gepafin.tendermanagement.repositories.AssignedApplicationsRepository; +import net.gepafin.tendermanagement.service.ApplicationEvaluationService; +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.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +public class ApplicationEvaluationServiceImpl implements ApplicationEvaluationService { + + @Autowired + private ApplicationEvaluationDao applicationEvaluationDao; + @Autowired + private Validator validator; + @Autowired + private AssignedApplicationsRepository assignedApplicationsRepository; + + @Override + @Transactional(rollbackFor = Exception.class) + public ApplicationEvaluationResponse createOrUpdateApplicationEvaluation( + HttpServletRequest request, + ApplicationEvaluationRequest req, + Long assignedApplicationsId) { + + AssignedApplicationsEntity assignedApplication = assignedApplicationsRepository + .findByIdAndIsDeletedFalse(assignedApplicationsId) + .orElseThrow(() -> new ResourceNotFoundException( + Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.ASSIGNED_APPLICATION_NOT_FOUND_MSG))); + + UserEntity user = validator.validatePreInstructor(request, assignedApplication.getUserId()); + + return applicationEvaluationDao.createOrUpdateApplicationEvaluation(user, req, assignedApplication.getId()); + } + + @Override + @Transactional(readOnly = true) + public ApplicationEvaluationResponse getApplicationEvaluationByApplicationId( + HttpServletRequest request, Long applicationId, Long assignedApplicationId) { + + if (applicationId == null && assignedApplicationId == null) { + throw new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.EITHER_APPLICATION_OR_ASSIGNED_APPLICATION_ID_REQUIRED_MSG) + ); + } + UserEntity preInstructor = validator.validateUser(request); + Optional assignedApplicationsOptional = + assignedApplicationsRepository.findByApplicationIdOrIdAndIsDeletedFalse(applicationId,assignedApplicationId); + + if (assignedApplicationId != null) { + assignedApplicationsOptional = assignedApplicationsOptional.filter(a -> a.getId().equals(assignedApplicationId)); + } + AssignedApplicationsEntity assignedApplications = assignedApplicationsOptional + .orElseThrow(() -> new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.ASSIGNED_APPLICATION_NOT_FOUND_WITH_ID_MSG) + )); + validator.validatePreInstructor(request, assignedApplications.getUserId()); + + return applicationEvaluationDao.getApplicationEvaluationByApplicationId( + preInstructor, + assignedApplications.getApplication().getId(), + assignedApplications.getId() + ); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteApplicationEvaluation(HttpServletRequest request,Long id) { + validator.getUserIdFromToken(request); + applicationEvaluationDao.deleteById(id); + } + + @Override + public ApplicationEvaluationEntity validateApplicationEvaluation(Long applicationEvaluationId) { + return applicationEvaluationDao.validateApplicationEvaluation(applicationEvaluationId); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index 779a3d09..886b91c1 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -56,8 +56,8 @@ public class ApplicationServiceImpl implements ApplicationService { } @Override - public ApplicationEntity validateApplication(Long id) { - return applicationDao.validateApplication(id); + public ApplicationEntity validateApplication(Long applicationId) { + return applicationDao.validateApplication(applicationId); } @Override @@ -86,12 +86,12 @@ public class ApplicationServiceImpl implements ApplicationService { @Override @Transactional(readOnly = true) - public List getAllApplications(HttpServletRequest request, Long callId, Long companyId , String status) { + public List getAllApplications(HttpServletRequest request, Long callId, Long companyId ,List statusList) { UserEntity userEntity = validator.validateUser(request); if (companyId != null) { validator.validateUserWithCompany(request, companyId); } - return applicationDao.getAllApplications(userEntity, callId, companyId , status); + return applicationDao.getAllApplications(userEntity, callId, companyId , statusList); } @Override @Transactional(rollbackFor = Exception.class) diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java index e0301dec..154e342a 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java @@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.service.impl; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.AssignedApplicationsDao; +import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; @@ -54,4 +55,9 @@ public class AssignedApplicationsServiceImpl implements AssignedApplicationsServ return assignedApplicationsDao.getAssignedApplicationById(request, id); } + @Override + public AssignedApplicationsEntity validateAssignedApplication(Long assignedApplicationId) { + return assignedApplicationsDao.validateAssignedApplication(assignedApplicationId); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 5a2d9ded..ddd74035 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -79,6 +79,7 @@ public class AuthenticationService { UserEntity user=null; LoginAttemptEntity loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request); + try { log.info("Attempting login for email: {}", loginReq.getEmail()); String emailWithHubId = loginReq.getEmail()+":"+loginReq.getHubUuid(); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( @@ -94,11 +95,18 @@ public class AuthenticationService { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); } + loginAttemptEntity.setUserId(user.getId()); createSuccessLoginAttempt(loginAttemptEntity); + } catch (Exception e) { + log.info("Authentication failed for email: {}", loginReq.getEmail()); + loginAttemptEntity.setUserId(user.getId()); + createFailedLoginAttempt(loginAttemptEntity, e.getMessage()); + throw e; + } return getJWTTokenBean(user, loginReq.getRememberMe()); } - private LoginAttemptEntity prepareLoginAttemptEntity(LoginReq loginUserReq, HttpServletRequest request) { + public LoginAttemptEntity prepareLoginAttemptEntity(LoginReq loginUserReq, HttpServletRequest request) { String ipAddress = Utils.getClientIpAddress(request); String userAgent = request.getHeader("user-agent"); LoginAttemptEntity loginAttemptEntity = new LoginAttemptEntity(); @@ -109,11 +117,11 @@ public class AuthenticationService { return loginAttemptEntity; } - private void createSuccessLoginAttempt(LoginAttemptEntity loginAttemptEntity) { + public void createSuccessLoginAttempt(LoginAttemptEntity loginAttemptEntity) { loginAttemptEntity.setResult(LoginAttemptResultEnum.SUCCESS.getValue()); loginAttemptDao.createLoginAttempt(loginAttemptEntity); } - private void createFailedLoginAttempt(LoginAttemptEntity loginAttemptEntity, String errorMsg) { + public void createFailedLoginAttempt(LoginAttemptEntity loginAttemptEntity, String errorMsg) { loginAttemptEntity.setResult(LoginAttemptResultEnum.FAILED.getValue()); loginAttemptEntity.setErrorMsg(errorMsg); loginAttemptDao.createLoginAttempt(loginAttemptEntity); @@ -184,13 +192,17 @@ public class AuthenticationService { SecurityContextHolder.clearContext(); } - public JWTToken validateExistingUserToken(String token) { + public JWTToken validateExistingUserToken(HttpServletRequest request,String token) { SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token); if (samlResponseLogEntity == null) { log.info("Invalid spid login token : {}", token); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); } + LoginReq loginReq=new LoginReq(); + Long userId=null; + LoginAttemptEntity loginAttemptEntity =new LoginAttemptEntity(); + try { HubEntity hub = hubService.getHubByUuid(samlResponseLogEntity.getHubUuid()); Map> userAttributes = Utils .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); @@ -198,9 +210,18 @@ public class AuthenticationService { UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscaleAndHubId(cf, hub.getId()) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + userId=userEntity.getId(); //samlResponseLogRepository.delete(samlResponseLogEntity); - - return getJWTTokenBean(userEntity, Boolean.TRUE); + loginReq.setEmail(userEntity.getEmail()); + loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request); + loginAttemptEntity.setUserId(userEntity.getId()); + return getJWTTokenBean(userEntity, Boolean.TRUE); + } catch (Exception e) { + log.info("Authentication login failed for email: {}",e.getMessage()); + loginAttemptEntity.setUserId(userId); + createFailedLoginAttempt(loginAttemptEntity, e.getMessage()); + throw e; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CommunicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CommunicationServiceImpl.java new file mode 100644 index 00000000..5a9b9c06 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CommunicationServiceImpl.java @@ -0,0 +1,43 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.dao.CommunicationDao; +import net.gepafin.tendermanagement.model.request.CommunicationRequestBean; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse; +import net.gepafin.tendermanagement.model.response.CommunicationResponseBean; +import net.gepafin.tendermanagement.service.CommunicationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +public class CommunicationServiceImpl implements CommunicationService { + + @Autowired + CommunicationDao communicationDao; + + @Override + @Transactional(rollbackFor = Exception.class) + public CommunicationResponseBean addCommentToAmendmentRequest(CommunicationRequestBean communicationRequestBean, Long amendmentId) { + + return communicationDao.addCommentToAmendmentRequest(communicationRequestBean, amendmentId); + } + @Override + @Transactional(rollbackFor = Exception.class) + public String deleteComment(Long amendmentId, Long commentId) { + + return communicationDao.deleteComment(amendmentId, commentId); + } + @Override + @Transactional(rollbackFor = Exception.class) + public CommunicationResponseBean updateAmendmentComment(CommunicationRequestBean communicationRequestBean, Long amendmentId, Long commentId) { + + return communicationDao.updateAmendmentComment(communicationRequestBean, amendmentId, commentId); + } + @Override + @Transactional(readOnly = true) + public ApplicationAmendmentResponse getAmendmentComments(Long id) { + + return communicationDao.getAmendmentComments(id); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/EmailService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailService.java new file mode 100644 index 00000000..6b7b91cc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailService.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.model.request.EmailConfig; + +import java.util.List; + +public interface EmailService { + void sendEmail(String subject, String body, List recipientEmails, EmailConfig emailConfig); +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/EmailServiceFactory.java b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailServiceFactory.java new file mode 100644 index 00000000..6ab6b270 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailServiceFactory.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class EmailServiceFactory { + + @Autowired + private PecEmailService pecEmailService; + + @Autowired + private MailgunEmailService mailgunEmailService; + + public EmailService getEmailService(String serviceType) { + if ("MAILGUN_SERVICE".equals(serviceType)) { + return mailgunEmailService; + } else if ("PEC_SERVICE".equals(serviceType)) { + return pecEmailService; + } else { + throw new IllegalArgumentException("Invalid email service type: " + serviceType); + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/MailgunEmailService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/MailgunEmailService.java new file mode 100644 index 00000000..03d1344c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/MailgunEmailService.java @@ -0,0 +1,49 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.model.request.EmailConfig; +import net.gepafin.tendermanagement.service.feignClient.MailgunFeignClient; +import net.gepafin.tendermanagement.util.Validator; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.Base64; +import java.util.List; + +@Service +public class MailgunEmailService implements EmailService { + + @Autowired + private MailgunFeignClient mailgunFeignClient; + + @Value("${isMailSendingEnabled}") + private String isEmailSendingEnabled; + + @Autowired + private Validator validator; + + @Override + public void sendEmail(String subject, String body, List recipientEmails, EmailConfig emailConfig) { + + if (Boolean.FALSE.equals(Boolean.parseBoolean(isEmailSendingEnabled))) { + return; + } + + String domain = emailConfig.getDomain(); + String from = emailConfig.getSender(); + String apiKey = emailConfig.getApiKey(); + String authHeader = "Basic " + Base64.getEncoder().encodeToString(("api:" + apiKey).getBytes()); + + // Send email via Mailgun API + if (Boolean.FALSE.equals(validator.isTestProfileActivated())) { + ResponseEntity response = mailgunFeignClient.sendEmail(domain, from, List.of("rajeshkhoreupwork@gmail.com"), subject, body, authHeader); + if (!response.getStatusCode().is2xxSuccessful()) { + throw new RuntimeException("Failed to send email via Mailgun: " + response.getStatusCode()); + } + } + } +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/PecEmailService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/PecEmailService.java new file mode 100644 index 00000000..38f94613 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/PecEmailService.java @@ -0,0 +1,58 @@ +package net.gepafin.tendermanagement.service.impl; + +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.model.request.EmailConfig; +import net.gepafin.tendermanagement.model.request.PecEmailRequest; +import net.gepafin.tendermanagement.service.feignClient.PecFeignClient; +import net.gepafin.tendermanagement.util.Validator; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +public class PecEmailService implements EmailService { + private final PecFeignClient pecFeignClient; + + public PecEmailService(PecFeignClient pecFeignClient) { + + this.pecFeignClient = pecFeignClient; + } + + @Value("${isMailSendingEnabled}") + private String isEmailSendingEnabled; + + @Autowired + private Validator validator; + + @Override + public void sendEmail(String subject, String body, List recipientEmails, EmailConfig emailConfig) { + + if (Boolean.FALSE.equals(Boolean.parseBoolean(isEmailSendingEnabled))) { + return; + } + + PecEmailRequest emailRequest = new PecEmailRequest(); + emailRequest.setSender(emailConfig.getSender()); + emailRequest.setRecipient(List.of("rajeshkhoreupwork@gmail.com")); + emailRequest.setSubject(subject); + emailRequest.setBody(body); + emailRequest.setUsername(emailConfig.getUsername()); + emailRequest.setPassword(emailConfig.getPassword()); + + String authToken = emailConfig.getAuthToken(); + if (Boolean.FALSE.equals(validator.isTestProfileActivated())) { + ResponseEntity response = pecFeignClient.sendEmail("Bearer " + authToken, emailRequest); + log.info("Mail response status: {}, headers: {}, body: {}", response.getStatusCode(), response.getHeaders(), response.getBody()); + if (!response.getStatusCode().is2xxSuccessful()) { + throw new RuntimeException("Failed to send email via PEC: " + response.getStatusCode()); + } + } + } +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java index 5d3640f9..d0b8a716 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -103,7 +103,7 @@ public class UserServiceImpl implements UserService { @Override @Transactional(rollbackFor = Exception.class) public JWTToken validateExistingUserToken(HttpServletRequest request, String token) { - return userDao.validateExistingUserToken(token); + return userDao.validateExistingUserToken(request,token); } @Override public UserSamlResponse validateNewUserToken(HttpServletRequest request, String token) { diff --git a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java index 1fdf6c1a..ec7fe7d9 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java @@ -108,4 +108,12 @@ public class DateTimeUtil { return null; } } + public static String formatCreatedDate(LocalDateTime createdDate) { + + if (createdDate == null) { + return ""; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + return createdDate.format(formatter); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index cb8aa153..26f049ef 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -1,5 +1,6 @@ package net.gepafin.tendermanagement.util; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; @@ -19,6 +20,7 @@ import java.util.stream.Collectors; import com.itextpdf.styledxmlparser.jsoup.Jsoup; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.constants.GepafinConstant; import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,6 +41,10 @@ import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientNotFoundExcep import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientUnauthorizedException; import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientValidationException; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + import static org.apache.commons.lang3.StringUtils.isEmpty; @@ -318,6 +324,23 @@ public class Utils { return new StringTokenizer(header, ",").nextToken().trim(); } + public static List convertJsonToList(String json, TypeReference> typeRef) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + return objectMapper.readValue(json, typeRef); + } catch (IOException e) { + e.printStackTrace(); + return Collections.emptyList(); + } + } + + public static String convertObjectToJson(Object obj) { + try { + if(obj == null){return null;} + return new ObjectMapper().writeValueAsString(obj); + } catch (JsonProcessingException e) { + log.error("Failed to convert object to JSON: {}", e.getMessage(), e); + throw new RuntimeException("Failed to convert object to JSON", e);}} public static String replaceSpacesWithUnderscores(String content) { if (content == null) { @@ -449,4 +472,47 @@ public class Utils { return sanitizedInput.matches(wholeNumberPattern); } + + public static String encryptCredential(String value) { + try { + if(Boolean.FALSE.equals(isEmpty(value))) { + + IvParameterSpec iv = new IvParameterSpec(GepafinConstant.ENCRYPT_INIT_VECTOR.getBytes("UTF-8")); + SecretKeySpec skeySpec = new SecretKeySpec(Base64.getDecoder().decode(GepafinConstant.ENCRYPT_KEY), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); + + byte[] encrypted = cipher.doFinal(value.getBytes()); + + return Base64.getEncoder().encodeToString(encrypted); + } + + } catch (Exception ex) { + log.error("Exception occured while encrypt credential :- {0}", ex); + } + return null; + } + + public static String decryptCredential(String encrypted) { + try { + if(Boolean.FALSE.equals(isEmpty(encrypted))) { + + IvParameterSpec iv = new IvParameterSpec(GepafinConstant.ENCRYPT_INIT_VECTOR.getBytes("UTF-8")); + SecretKeySpec skeySpec = new SecretKeySpec(Base64.getDecoder().decode(GepafinConstant.ENCRYPT_KEY), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + + cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); + + byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted)); + + return new String(original); + } + } catch (Exception ex) { + // log.error("Exception occured while decrypt credential :- {0}", ex); + return encrypted; + } + return null; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index f4f2e2bd..e0814305 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -135,11 +135,10 @@ public class Validator { return requestedUser; } - private Long getUserIdFromToken(HttpServletRequest request) { + public Long getUserIdFromToken(HttpServletRequest request) { Map userInfo= tokenProvider.getUserInfoAndUserIdFromToken(request); return Long.parseLong(userInfo.get("userId").toString()); } - public CallEntity validateUserWithCall(UserEntity user, Long callId) { CallEntity callEntity = callService.validateCall(callId); if(Boolean.FALSE.equals(user.getHub().getId().equals(callEntity.getHub().getId()))) { @@ -152,6 +151,11 @@ public class Validator { String[] activeProfiles = environment.getActiveProfiles(); return Arrays.stream(activeProfiles).anyMatch("production"::equals); } + + public Boolean isTestProfileActivated() { + String[] activeProfiles = environment.getActiveProfiles(); + return Arrays.stream(activeProfiles).anyMatch("test"::equals); + } public UserEntity validatePreInstructor(HttpServletRequest request, Long preInstructorUserId) { UserEntity preInstructorUser = userService.validateUser(preInstructorUserId); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java new file mode 100644 index 00000000..651680ff --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java @@ -0,0 +1,191 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequest; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequestBean; +import net.gepafin.tendermanagement.model.request.CloseAmendmentRequest; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentRequestResponse; +import net.gepafin.tendermanagement.model.response.ApplicationResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Validated +public interface ApplicationAmendmentRequestApi { + @Operation(summary = "Api to get application data for the Amendment process", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "applicationEvaluation/{id}", produces = "application/json") + ResponseEntity> getApplicationDataForAmendment(HttpServletRequest request, @Parameter(description = "The Application Evaluation id", required = true) @PathVariable(value = "id", required = true) Long applicationEvaluationId); + + @Operation(summary = "Api to submit the application data for the Amendment", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "", produces = "application/json") + ResponseEntity> createApplicationAmendmentRequest(HttpServletRequest request, + @Parameter(description = "Application Evaluation Id", required = true) @RequestParam Long applicationEvaluationId, + @Valid @RequestBody ApplicationAmendmentRequest applicationAmendmentRequest); + + @Operation(summary = "Api to delete application amendment request", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @DeleteMapping(value = "/{id}") + ResponseEntity> deleteApplicationAmendmentRequest(HttpServletRequest request, + @Parameter(description = "The application Amendment id", required = true) @PathVariable("id") Long id); + + @Operation(summary = "Api to get an application amendment by id", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "", produces = "application/json") + ResponseEntity> getApplicationAmendmentRequestById(HttpServletRequest request,@Parameter(description = "The application amendment id", required = true) @RequestParam(value = "id", required = true) Long id); + + @Operation(summary = "Api to get all applications amendment request by preInstructor user Id", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/user/{id}", produces = "application/json") + ResponseEntity>> getAllApplicationAmendmentRequest(HttpServletRequest request, + @Parameter(description = "The User ID", required = false) @PathVariable(value = "id",required = false) Long userId); + + @Operation(summary = "Api to update application amendment", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) + }) + @PutMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> updateApplicationAmendment(HttpServletRequest request, + @Parameter(description = "The Application Amendment id", required = true) @PathVariable("id") Long id, + @Parameter(description = "Assigned Application request object", required = true) @Valid @RequestBody ApplicationAmendmentRequestBean applicationAmendmentRequestBean); + + @Operation(summary = "Api to get all applications amendment request by beneficary user Id", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/beneficiary/user/{id}", produces = "application/json") + ResponseEntity>> getAllAmendmentRequestByBeneficiaryId(HttpServletRequest request, + @Parameter(description = "Id", required = false) @PathVariable(value = "id",required = false) Long beneficiaryId); + @Operation(summary = "Api to extend response days for an amendment request", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) + }) + @PutMapping(value = "/{id}/extendExpiration", produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> extendResponseDays( + HttpServletRequest request, + @Parameter( required = true) @PathVariable("id") Long id, + @Parameter( required = true) @RequestParam("extendedDays") Long extendedDays); + + @Operation(summary = "Api to close the application amendment request", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "", produces = "application/json") + ResponseEntity> closeApplicationAmendmentRequest(HttpServletRequest request, + @Parameter(description = "The Application Amendment id", required = true) @RequestParam("id") Long id, + @Valid @RequestBody CloseAmendmentRequest closeAmendmentRequest); + @Operation(summary = "Api to get amendment process list by application id", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "application/{applicationId}", produces = "application/json") + ResponseEntity>> getAmendmentByApplicationId(HttpServletRequest request, @Parameter(description = "The Application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId, + @Parameter(description = "List of amendment statuses") @RequestParam(value = "statuses", required = false) List statuses + ); + + @Operation(summary = "Api to update application amendment status", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "/{applicationAmendmentId}/status", produces = { "application/json" }) + ResponseEntity> updateApplicationAmendmentStatus(HttpServletRequest request, + @Parameter(description = "The application amendment id", required = true) @PathVariable("applicationAmendmentId") Long applicationAmendmentId, + @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) ApplicationAmendmentRequestEnum status); + + @Operation(summary = "Send reminder email for the specified amendment", + responses = { + @ApiResponse(responseCode = "200", description = "Email sent successfully"), + @ApiResponse(responseCode = "404", description = "Amendment not found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })) + }) + @PostMapping(value = "/{amendmentId}/reminder", produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> sendReminderEmail(HttpServletRequest request, + @Parameter( required = true) + @PathVariable(value = "amendmentId") Long amendmentId); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index fcfbe2ff..700bf353 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -72,7 +72,7 @@ public interface ApplicationApi { ResponseEntity>> getAllApplications(HttpServletRequest request, @Parameter(description = "The call id", required = false) @RequestParam(value = "callId", required = false) Long callId, @Parameter(description = "The company id", required = false) @RequestParam(value = "companyId", required = false) Long companyId, - @Parameter(description = "Application status" ,required = false) @RequestParam(value = "status",required = false)String status); + @Parameter(description = "Application statuses" ,required = false) @RequestParam(value = "statuses",required = false) List statusList); @Operation(summary = "Api to delete application", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java new file mode 100644 index 00000000..bc17e345 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java @@ -0,0 +1,57 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; +import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +public interface ApplicationEvaluationApi { + + @Operation(summary = "API to create or update ApplicationEvaluation", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) + }) + @PutMapping(value = "/{assignedApplicationsId}", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> createOrUpdateApplicationEvaluation( + HttpServletRequest request, + @Parameter(description = "Assigned Application ID", required = true) @PathVariable("assignedApplicationsId") Long assignedApplicationsId, + @Parameter(description = "Application Evaluation Request Body", required = true) @Valid @RequestBody ApplicationEvaluationRequest evaluationRequest); + + @Operation(summary = "API to get ApplicationEvaluation data for evaluation process", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })) + }) + @GetMapping(value = "/application", produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> getApplicationEvaluationByApplicationId( + HttpServletRequest request, + @Parameter(required = false) @RequestParam(value = "applicationId", required = false) Long applicationId, + @Parameter( required = false) @RequestParam(value = "assignedApplicationId", required = false) Long assignedApplicationId); + @Operation(summary = "API to delete ApplicationEvaluation", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })) + }) + @DeleteMapping(value = "/{id}") + ResponseEntity> deleteApplicationEvaluation(HttpServletRequest request, + @Parameter( required = true) @PathVariable("id") Long id); + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java new file mode 100644 index 00000000..eb1351c9 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java @@ -0,0 +1,69 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.request.CommunicationRequestBean; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse; +import net.gepafin.tendermanagement.model.response.CommunicationResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.data.repository.query.Param; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@Validated +public interface CommunicationApi { + @Operation(summary = "Api to create communication amendment comment", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "/{amendmentId}", produces = { "application/json" }) + ResponseEntity> addCommentToAmendmentRequest(HttpServletRequest request, + @RequestBody @Parameter CommunicationRequestBean communicationResponseBean, @PathVariable(value = "amendmentId") Long amendmentId); + + @Operation(summary = "API to Get Amendment Request Comment", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value = + ErrorConstants.NOTFOUND_ERROR_EXAMPLE))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value = + ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE))), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value = + ErrorConstants.BADREQUEST_ERROR_EXAMPLE))) }) + @GetMapping(value = "/{amendmentId}", produces = "application/json") + public ResponseEntity> getAmendmentComments(@PathVariable(value = "amendmentId") Long amendmentId); + + @Operation(summary = "Api to update communication comments", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "/{amendmentId}/{commentId}", produces = { "application/json" }) + ResponseEntity> updateCommunicationAmendment(HttpServletRequest request, + @RequestBody @Parameter CommunicationRequestBean communicationResponseBean, @PathVariable(value = "amendmentId") Long amendmentId, @PathVariable(value = "commentId") Long commentId); + + @Operation(summary = "Api to delete communication comments", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @DeleteMapping(value = "/{amendmentId}/{commentId}", produces = { "application/json" }) + ResponseEntity> deleteApplicationAmendmentComment(HttpServletRequest request, @PathVariable(value = "amendmentId") Long amendmentId, + @Param(value = "commentId") Long commentId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java index fd7ba455..cec3c224 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java @@ -51,6 +51,8 @@ public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity> handleResourceNotFoundException(ResourceNotFoundException ex) { + log.error(ex.getMessage()); + log.error(ex.getLocalizedMessage(), ex); return ResponseEntity.status(HttpStatus.NOT_FOUND) .body(new Response<>(null, ex.getStatus(), ex.getMessage())); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java new file mode 100644 index 00000000..bd66efd1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java @@ -0,0 +1,132 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.log4j.Log4j2; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequest; +import net.gepafin.tendermanagement.model.request.ApplicationAmendmentRequestBean; +import net.gepafin.tendermanagement.model.request.CloseAmendmentRequest; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentRequestResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.ApplicationAmendmentRequestService; +import net.gepafin.tendermanagement.web.rest.api.ApplicationAmendmentRequestApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.List; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/amendments}") +@Log4j2 +public class ApplicationAmendmentRequestController implements ApplicationAmendmentRequestApi { + + @Autowired + ApplicationAmendmentRequestService applicationAmendmentRequestService; + + @Override + public ResponseEntity> getApplicationDataForAmendment(HttpServletRequest request, Long applicationEvaluationId) { + ApplicationAmendmentRequestResponse applicationAmendmentBean = applicationAmendmentRequestService.getApplicationDataForAmendment(request,applicationEvaluationId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationAmendmentBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_DATA_FOR_AMENDMENT_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> createApplicationAmendmentRequest(HttpServletRequest request, Long applicationEvaluationId, ApplicationAmendmentRequest applicationAmendmentRequest) { + ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = applicationAmendmentRequestService.createApplicationAmendmentRequest(request,applicationEvaluationId,applicationAmendmentRequest); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationAmendmentRequestResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.CREATE_APPLICATION_DATA_FOR_AMENDMENT_MSG))); + } + + @Override + public ResponseEntity> deleteApplicationAmendmentRequest(HttpServletRequest request, Long id) { + log.info("Delete Application Amendment Request- Application Amendment ID: {}", id); + applicationAmendmentRequestService.deleteApplicationAmendmentRequest(request,id); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_APPLICATION_AMENDMENT_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> getApplicationAmendmentRequestById(HttpServletRequest request,Long id) { + log.info("Get Application Amendment Request By Id"); + ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = applicationAmendmentRequestService.getApplicationAmendmentRequestById(request,id); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationAmendmentRequestResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_AMENDMENT_SUCCESS_MSG))); + } + + @Override + public ResponseEntity>> getAllApplicationAmendmentRequest(HttpServletRequest request,Long userId) { + log.info("Get All Applications Amendment Request"); + List applicationAmendmentRequestResponses = applicationAmendmentRequestService.getAllApplicationAmendmentRequest(request,userId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationAmendmentRequestResponses, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_AMENDMENT_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> updateApplicationAmendment(HttpServletRequest request, Long id, ApplicationAmendmentRequestBean applicationAmendmentRequestBean) { + log.info("Update Application Amendment"); + ApplicationAmendmentRequestResponse updateApplicationAmendment = applicationAmendmentRequestService.updateApplicationAmendment(request, id, applicationAmendmentRequestBean); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(updateApplicationAmendment, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_UPDATE_SUCCESSFULLY_MSG))); + } + + @Override + public ResponseEntity>> getAllAmendmentRequestByBeneficiaryId(HttpServletRequest request, Long beneficiaryId) { + log.info("Get All Application Amendment Request By Beneficiary ID"); + List applicationAmendmentRequestResponseList = applicationAmendmentRequestService.getAllAmendmentRequestByBeneficiaryId(request, beneficiaryId); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(applicationAmendmentRequestResponseList, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_AMENDMENT_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> closeApplicationAmendmentRequest(HttpServletRequest request, Long id, CloseAmendmentRequest closeAmendmentRequest) { + log.info("Closing Amendment Request"); + ApplicationAmendmentRequestResponse amendmentRequestResponse = applicationAmendmentRequestService.closeAmendmentRequest(request, id,closeAmendmentRequest); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(amendmentRequestResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_CLOSED_SUCCESFULLY))); + } + + @Override + public ResponseEntity> extendResponseDays( + HttpServletRequest request, + Long id, + Long addedDays) { + + log.info("Extending response days for Amendment Request ID: {}", id); + + ApplicationAmendmentRequestResponse response = applicationAmendmentRequestService.extendResponseDays(request, id, addedDays); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.RESPONSE_DAYS_EXTENDED_SUCCESS_MSG))); + } + @Override + public ResponseEntity>> getAmendmentByApplicationId(HttpServletRequest request, Long applicationId,List statuses) { + List applicationAmendmentBean = applicationAmendmentRequestService.getAmendmentByApplicationId(request,applicationId,statuses); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationAmendmentBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_DATA_FOR_AMENDMENT_SUCCESS_MSG))); + } + @Override + public ResponseEntity> updateApplicationAmendmentStatus(HttpServletRequest request, Long applicationAmendmentId, + ApplicationAmendmentRequestEnum status) { + ApplicationAmendmentRequestResponse applicationResponse = applicationAmendmentRequestService.updateApplicationAmendmentStatus(request, applicationAmendmentId, status); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_UPDATE_SUCCESSFULLY_MSG))); + } + @Override + public ResponseEntity> sendReminderEmail( + HttpServletRequest request, + Long amendmentId) { + + log.info("Sending reminder email for Amendment ID: {}", amendmentId); + applicationAmendmentRequestService.sendReminderEmail(request,amendmentId); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.REMINDER_EMAIL_SENT_SUCCESS_MSG))); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index 71dc2421..27ea0bb7 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -76,8 +76,8 @@ public class ApplicationApiController implements ApplicationApi { } @Override - public ResponseEntity>> getAllApplications(HttpServletRequest request, Long callId, Long companyId, String status) { - List applications = applicationService.getAllApplications(request, callId, companyId,status); + public ResponseEntity>> getAllApplications(HttpServletRequest request, Long callId, Long companyId, List statusList) { + List applications = applicationService.getAllApplications(request, callId, companyId,statusList); log.info("Get All Applications"); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(applications, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java new file mode 100644 index 00000000..f56a85fb --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java @@ -0,0 +1,59 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; +import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.ApplicationEvaluationService; +import net.gepafin.tendermanagement.web.rest.api.ApplicationEvaluationApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/applicationEvaluation}") +public class ApplicationEvaluationApiController implements ApplicationEvaluationApi { + + @Autowired + private ApplicationEvaluationService applicationEvaluationService; + + @Override + public ResponseEntity> createOrUpdateApplicationEvaluation( + HttpServletRequest request, + Long assignedApplicationsId, + ApplicationEvaluationRequest evaluationRequest) { + + ApplicationEvaluationResponse response = applicationEvaluationService.createOrUpdateApplicationEvaluation( + request, evaluationRequest, assignedApplicationsId); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.EVALUATION_CREATED_SUCCESSFULLY))); + } + + + @Override + public ResponseEntity> getApplicationEvaluationByApplicationId( + HttpServletRequest request, Long applicationId, Long assignedApplicationId) { + + ApplicationEvaluationResponse response = null; + response = applicationEvaluationService.getApplicationEvaluationByApplicationId(request, applicationId,assignedApplicationId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.EVALUATION_FETCHED_SUCCESSFULLY))); + } + + + @Override + public ResponseEntity> deleteApplicationEvaluation(HttpServletRequest request, + Long id) { + applicationEvaluationService.deleteApplicationEvaluation(request,id); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.EVALUATION_DELETED_SUCCESSFULLY))); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CommunicationController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CommunicationController.java new file mode 100644 index 00000000..4805d2ce --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CommunicationController.java @@ -0,0 +1,56 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.model.request.CommunicationRequestBean; +import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse; +import net.gepafin.tendermanagement.model.response.CommunicationResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.CommunicationService; +import net.gepafin.tendermanagement.web.rest.api.CommunicationApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/communication}") +public class CommunicationController implements CommunicationApi { + + @Autowired + CommunicationService communicationService; + + @Override + public ResponseEntity> addCommentToAmendmentRequest(HttpServletRequest request, CommunicationRequestBean communicationRequestBean, + Long amendmentId) { + + CommunicationResponseBean communicationResponseBean = communicationService.addCommentToAmendmentRequest(communicationRequestBean, amendmentId); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(communicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMMUNICATION_ADDED_TO_AMENDMENT_REQUEST_SUCCESS))); + } + @Override + public ResponseEntity> getAmendmentComments(Long amendmentId) { + + ApplicationAmendmentResponse response = communicationService.getAmendmentComments(amendmentId); + return ResponseEntity.ok(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.AMENDMENT_FOUND_SUCCESS))); + } + @Override + public ResponseEntity> updateCommunicationAmendment(HttpServletRequest request, CommunicationRequestBean communicationRequestBean, + Long amendmentId, Long commentId) { + + CommunicationResponseBean communicationResponseBean = communicationService.updateAmendmentComment(communicationRequestBean, amendmentId, commentId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(communicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMMENT_UPDATED_SUCCESS_MSG))); + } + @Override + public ResponseEntity> deleteApplicationAmendmentComment(HttpServletRequest request, Long applicationAmendId, Long commentId) { + + String communicationResponseBean = communicationService.deleteComment(applicationAmendId, commentId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(communicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMMENT_DELETED_SUCCESS_MSG))); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f19adfb0..d2a1e3fb 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.application.name=tendermanagement spring.servlet.multipart.max-file-size=300MB spring.servlet.multipart.max-request-size=300MB -spring.profiles.active=testing +spring.profiles.active=testing # JPA Configuration @@ -60,8 +60,10 @@ mailGun_domainName=paghiamoci.ai mailGun_base_url=https://api.eu.mailgun.net/ # SendinBlue API key apiKey=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 +api.pecUrl=https://ws.pecmassiva.com #senderEmail=mailer@bflows.net +application.amendment.expiration.days=30 default.email.signature=Gepafin S.p.a default.hub.pdf.banner=https://mementoresources.s3.amazonaws.com/gepafin/staging/template/gepafin-logo.jpg diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index ed4e78ec..9aa2ec42 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -1336,20 +1336,20 @@ - - - - - + + + + + - + @@ -1357,24 +1357,24 @@ - - - - + + + + - + @@ -1382,17 +1382,17 @@ - - - + + + @@ -1402,12 +1402,12 @@ - + @@ -1482,18 +1482,216 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UNIQUE_UUID = 'p4lk3bcx1RStqTaIVVbXs' + + + + UNIQUE_UUID = 't7jh5wfg9QXylNaTZkPoE' + + + + + + + - + - + @@ -1504,20 +1702,22 @@ UNIQUE_UUID = 't7jh5wfg9QXylNaTZkPoE' - - - - - - - - UNIQUE_UUID = 'p4lk3bcx1RStqTaIVVbXs' - - - - UNIQUE_UUID = 't7jh5wfg9QXylNaTZkPoE' - + + select + setval('gepafin_schema.system_email_template_id_seq', (select + max(id)+1 + from gepafin_schema.system_email_template), false) + + - + + + + + + diff --git a/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_31_10_2024.sql b/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_31_10_2024.sql new file mode 100644 index 00000000..83cfc6c3 --- /dev/null +++ b/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_31_10_2024.sql @@ -0,0 +1,141 @@ +INSERT INTO gepafin_schema.system_email_template +( + id, template_name, "type", html_content, subject, "json", "system", + is_deleted, created_date, updated_date +) +VALUES +( + 3, + 'Instructional Aid/Request for Documentation Integration Template', + 'DOCUMENTATION_INTEGRATION_REQUEST', + ' + +
+

RICHIESTA INTEGRAZIONE DOCUMENTALE

+

Buongiorno,

+

In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui al Protocollo n. {{protocol_number}} del + {{protocol_date}} e {{protocol_time}}, alla luce dell’attività istruttoria svolta, + segnaliamo quanto segue:

+
    +
  • {{form_dataInput}}
  • +
+

{{note}}

+

Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione sia caricandola all’interno dello sportello + online {{platform_link}} che inviandola a mezzo PEC all’indirizzo + {{legal_mail}} entro e non oltre 10 giorni dal ricevimento della presente comunicazione, + precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.

+

Vi informiamo che per la ricezione della PEC farà fede la ricevuta di avvenuta consegna che attesterà il buon esito + dell’invio. La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ', + 'RICHIESTA INTEGRAZIONE DOCUMENTALE - {{call_name}}', + NULL, + true, + false, + '2024-10-26 20:00:00', + '2024-10-26 20:00:00' +); + +-- Insert for INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE +INSERT INTO gepafin_schema.system_email_template +( + id, template_name, "type", html_content, subject, "json", "system", + is_deleted, created_date, updated_date +) +VALUES +( + 4, + 'Notification of Inadmissibility Due to Failure to Respond Template', + 'INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE', + ' + +
+

Comunicazione di non ammissibilità per mancata risposta a richiesta integrazione documentale

+

Buongiorno,

+

Con posta elettronica certificata del {{date_time_emailSend}}, vi abbiamo comunicato che i documenti richiesti + dal Gestore sarebbero dovuti pervenire entro 10 giorni dal ricevimento di detta comunicazione. + Trascorso il termine senza la ricezione dei documenti richiesti, il Gestore non ha potuto prendere in considerazione la richiesta di finanziamento.

+

È possibile presentare ricorso tramite modello disponibile nello sportello online + {{platform_link}} entro 10 giorni dalla ricezione di questa comunicazione.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ', + 'BANDO {{call_name}} - Domanda di finanziamento non ammessa {{company_name}}', + NULL, + true, + false, + '2024-10-26 20:00:00', + '2024-10-26 20:00:00' +); + +-- Insert for ADMISSIBILITY_NOTIFICATION +INSERT INTO gepafin_schema.system_email_template +( + id, template_name, "type", html_content, subject, "json", "system", + is_deleted, created_date, updated_date +) +VALUES +( + 5, + 'Notification of Admissibility Template', + 'ADMISSIBILITY_NOTIFICATION', + ' + +
+

Buongiorno,

+

In riferimento alla domanda di concessione di Finanziamento agevolato “{{call_name}}” di cui al + Protocollo n. {{protocol_number}} del {{protocol_date}} alle {{protocol_time}}, l’istruttoria di ammissibilità + è stata completata con esito positivo.

+

Seguirà una comunicazione relativa alla valutazione tecnica ed economico-finanziaria ai fini della valutazione finale.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ', + 'BANDO {{call_name}} – Esito positivo istruttoria di ammissibilità {{company_name}}', + NULL, + true, + false, + '2024-10-26 20:00:00', + '2024-10-26 20:00:00' +); + +-- Insert for INADMISSIBILITY_NOTIFICATION +INSERT INTO gepafin_schema.system_email_template +( + id, template_name, "type", html_content, subject, "json", "system", + is_deleted, created_date, updated_date +) +VALUES +( + 6, + 'Notification of Inadmissibility Template', + 'INADMISSIBILITY_NOTIFICATION', + ' + +
+

Buongiorno,

+

In riferimento alla domanda di concessione di Finanziamento agevolato “{{call_name}}” di cui al + Protocollo n. {{protocol_number}} del {{protocol_date}} alle {{protocol_time}}, + l''istruttoria di ammissibilità è stata completata con esito negativo.

+

Motivazioni: {{form_text}}

+

È possibile presentare ricorso tramite modello disponibile nello sportello online + {{platform_link}} entro 10 giorni dalla ricezione di questa comunicazione.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ', + 'BANDO {{call_name}} – Esito negativo istruttoria di ammissibilità {{company_name}}', + NULL, + true, + false, + '2024-10-26 20:00:00', + '2024-10-26 20:00:00' +); \ No newline at end of file diff --git a/src/main/resources/db/dump/insert_system_email_template_for_sollecito_30_10_2024.sql b/src/main/resources/db/dump/insert_system_email_template_for_sollecito_30_10_2024.sql new file mode 100644 index 00000000..435cf965 --- /dev/null +++ b/src/main/resources/db/dump/insert_system_email_template_for_sollecito_30_10_2024.sql @@ -0,0 +1,29 @@ +-- SQL Dump to insert system email template for amendment reminder email with calculated due date +INSERT INTO gepafin_schema.system_email_template +(template_name, "type", html_content, subject, "json", "system", is_deleted, created_date, updated_date) +VALUES +( + 'Amendment Reminder Email', + 'AMENDMENT_REMINDER', + ' + +
+

PROMEMORIA PER LA PRESENTAZIONE DELL''EMENDAMENTO

+

Buongiorno,

+

Questo è un promemoria per completare la presentazione dell''emendamento entro il termine specificato. Di seguito i dettagli:

+
    +
  • Amendment ID: {{amendment_id}}
  • +
  • Data di Scadenza: {{amendment_due_date}}
  • +
+

Si prega di assicurarsi che l''emendamento venga presentato entro la data di scadenza per evitare ritardi. Inviare l''emendamento tramite la piattaforma online {{platform_link}}

+

Distinti saluti,

+

{{email_signature}}

+
+ + ', + 'Reminder: Pending Amendment Submission - ID {{amendment_id}}', + NULL, + true, + false, +CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP); diff --git a/src/main/resources/db/dump/update_hub_data_for_email_service_config_31_10_2024_1.sql b/src/main/resources/db/dump/update_hub_data_for_email_service_config_31_10_2024_1.sql new file mode 100644 index 00000000..e5a8da72 --- /dev/null +++ b/src/main/resources/db/dump/update_hub_data_for_email_service_config_31_10_2024_1.sql @@ -0,0 +1,9 @@ +UPDATE hub +SET email_service_type = 'PEC_SERVICE', + email_service_config = 'JkFbBfuVvq7VWwp5LcWIi+hAa1RJ1ekI0jq3w7gLTXETZiTaN8zC4OBWD53x8FtbfFTh3L/5805CIYTH1BQGa3X9q16q9SDzMy7DKHdmJzOnLKhn74C5akoXKaeXUCGnzp0cSk2c01FV6lwefC29IshijFSumCHtVlgWNeZigBx51GL2Coh8nF1Mu7/KIcny' +WHERE UNIQUE_UUID = 'p4lk3bcx1RStqTaIVVbXs'; + +UPDATE hub +SET email_service_type = 'MAILGUN_SERVICE', + email_service_config = 'mhyP0kKQCrsbhGv3PGx4yob4dPSNBOd2xFnAPkikJE7VHkydklfUSVWAdYjhXwOz8rglH2YYEC/xGZdrEgSnkS9Ed56/qzmaU1667GGf+kc5mciOiECW5/sVmhtbVClEnu1FGZMzlsJSqYKlTmqfCYD0lTAlak1Lu2n030tj6nhMDvUxP9CbeTwkzALMtmgt' +WHERE UNIQUE_UUID = 't7jh5wfg9QXylNaTZkPoE'; \ No newline at end of file diff --git a/src/main/resources/db/dump/update_system_email_template_for_notification_mail_04_11_2024_1.sql b/src/main/resources/db/dump/update_system_email_template_for_notification_mail_04_11_2024_1.sql new file mode 100644 index 00000000..fbb2c1c1 --- /dev/null +++ b/src/main/resources/db/dump/update_system_email_template_for_notification_mail_04_11_2024_1.sql @@ -0,0 +1,78 @@ +UPDATE gepafin_schema.system_email_template +SET html_content = ' + +
+

RICHIESTA INTEGRAZIONE DOCUMENTALE

+

Buongiorno,

+

In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui al Protocollo n. {{protocol_number}} del + {{protocol_date}} e {{protocol_time}}, alla luce dell’attività istruttoria svolta, + segnaliamo quanto segue:

+
    +
  • {{form_dataInput}}
  • +
+

{{note}}

+

Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione sia caricandola all’interno dello sportello + online {{platform_link}} che inviandola a mezzo PEC all’indirizzo + {{legal_mail}} entro e non oltre 10 giorni dal ricevimento della presente comunicazione, + precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.

+

Vi informiamo che per la ricezione della PEC farà fede la ricevuta di avvenuta consegna che attesterà il buon esito + dell’invio. La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ' +WHERE "type" = 'DOCUMENTATION_INTEGRATION_REQUEST' AND "system" = true; + +UPDATE gepafin_schema.system_email_template +SET html_content = ' + +
+

Comunicazione di non ammissibilità per mancata risposta a richiesta integrazione documentale

+

Buongiorno,

+

Con posta elettronica certificata del {{date_time_emailSend}}, vi abbiamo comunicato che i documenti richiesti + dal Gestore sarebbero dovuti pervenire entro 10 giorni dal ricevimento di detta comunicazione. + Trascorso il termine senza la ricezione dei documenti richiesti, il Gestore non ha potuto prendere in considerazione la richiesta di finanziamento.

+

È possibile presentare ricorso tramite modello disponibile nello sportello online + {{platform_link}} entro 10 giorni dalla ricezione di questa comunicazione.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ' +WHERE "type" = 'INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE' AND "system" = true; + +UPDATE gepafin_schema.system_email_template +SET html_content = ' + +
+

Buongiorno,

+

In riferimento alla domanda di concessione di Finanziamento agevolato “{{call_name}}” di cui al + Protocollo n. {{protocol_number}} del {{protocol_date}} alle {{protocol_time}}, l’istruttoria di ammissibilità + è stata completata con esito positivo.

+

Seguirà una comunicazione relativa alla valutazione tecnica ed economico-finanziaria ai fini della valutazione finale.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ' +WHERE "type" = 'ADMISSIBILITY_NOTIFICATION' AND "system" = true; + +UPDATE gepafin_schema.system_email_template +SET html_content = ' + +
+

Buongiorno,

+

In riferimento alla domanda di concessione di Finanziamento agevolato “{{call_name}}” di cui al + Protocollo n. {{protocol_number}} del {{protocol_date}} alle {{protocol_time}}, + l''istruttoria di ammissibilità è stata completata con esito negativo.

+

Motivazioni: {{form_text}}

+

È possibile presentare ricorso tramite modello disponibile nello sportello online + {{platform_link}} entro 10 giorni dalla ricezione di questa comunicazione.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ' +WHERE "type" = 'INADMISSIBILITY_NOTIFICATION' AND "system" = true; diff --git a/src/main/resources/db/dump/update_system_email_template_for_notification_mail_05_11_2024_4.sql b/src/main/resources/db/dump/update_system_email_template_for_notification_mail_05_11_2024_4.sql new file mode 100644 index 00000000..1b43db33 --- /dev/null +++ b/src/main/resources/db/dump/update_system_email_template_for_notification_mail_05_11_2024_4.sql @@ -0,0 +1,16 @@ +UPDATE gepafin_schema.system_email_template +SET + subject = 'BANDO {{call_name}}- Domanda di concessione di finanziamento agevolato {{company_name}}', + html_content = ' + +
+

In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui all’oggetto, la stessa è stata regolarmente acquisita ed è stata + registrata con Protocollo n. {{protocol_number}} del {{protocol_date}} + alle {{protocol_time}}.

+

Distinti Saluti,

+

{{email_signature}}

+
+ + ' +WHERE "type" = 'DOCUMENTATION_INTEGRATION_REQUEST' AND "system" = true; diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index b92a48f9..220d4654 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -101,6 +101,7 @@ success.password.changed=Password changed successfully. logout.successful.msg=Logout successful. You have been logged out successfully. #Update user Active or Deactive status update.user.status.success=User status has been successfully updated. +beneficiary.email.not.found.msg=The email address for the beneficiary could not be found. Please ensure that the beneficiary has a valid email address. #Form-field-related messages @@ -253,8 +254,18 @@ get_login_attempt_se_msg=Login attempts fetched successfully. application.in.submit.status.cannot.delete.company=The company cannot be deleted because there are active applications in the SUBMITTED status. get.users.success.msg = Successfully fetched users. cannot.create.beneficiary.user = Creation of a Beneficiary user is not allowed. Please assign the appropriate role. -evaluationCriteria.invalid=This evaluation criterion does not belong to the current call. +application.evaluation.not.found=Application Evaluation not found with ID: {0} +evaluation.created.successfully = Application evaluation created successfully. +evaluation.updated.successfully = Application evaluation updated successfully. +evaluation.fetched.successfully = Application evaluation fetched successfully. +evaluation.deleted.successfully = Application evaluation deleted successfully. +evaluations.fetched.successfully = All application evaluations fetched successfully. +application.evaluation.status.updated.successfully=Application evaluation status updated successfully. +evaluationCriteria.invalid=This evaluation criterion does not belong to the current call. +assigned.application.not.found.with.id=Assigned application with this application ID not found +either.application.or.assigned.application.id.required=Either applicationId or assignedApplicationId is required. +evaluation.already.exists=An application evaluation already exists for this application ID. # Hub Messages hub_create_success=Hub created successfully @@ -276,3 +287,22 @@ assigned.application.get.success=Assigned Application details fetched successful assigned.application.update.successfully=Assigned Application updated successfully. get.error.s3=Failed to fetch the file from S3. invalid.application.status = Invalid Application status. + +application.data.amendment.success = Successfully retrieved the application data for the amendment process. +delete.application.amendment.success = Application Amendment successfully deleted. +create.application.data.amendment.msg = Application amendment submited succesfully. +application.amendment.not.found = Application Amendment Request not found with the given ID. +application.amendment.get.success = Application Amendment details fetched successfully with given ID. +application.amendment.update.successfully = Application Amendment Updated Successfully. +application.amendment.closed.successfully = Application Amendment Closed Successfully. +response.days.extended.success=Response days extended successfully. +reminder.email.sent.success.msg=Reminder email sent successfully! + +added.comment.to.amendment.request.success = Application Amendment Comment Added Successfully. +comment.not.found = Comment Not Found. +comment.updated.successfully = Comment Updated Successfully. +comment.deleted.successfully = Comment Deleted Successfully. +comment.not.associate.with.amendment = Comment Not Associated with Amendment Request. +amendment.found.success = Amendment Request Found Successfully. +invalid.amendment.for.comment = Invalid Amendment Request for the Given Comment. +DD_MM_YYYY_HH_MM = dd_MM_yyyy HH:mm diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 214a198e..ea702497 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -252,6 +252,16 @@ get.users.success.msg = Utenti recuperati con successo cannot.create.beneficiary.user = La creazione di un utente beneficiario non � consentita. Si prega di assegnare il ruolo appropriato. evaluationCriteria.invalid=Questo criterio di valutazione non appartiene alla chiamata corrente. +application.evaluation.not.found=Valutazione dell'applicazione non trovata con ID: {0} +evaluation.created.successfully = Valutazione dell'applicazione creata con successo. +evaluation.updated.successfully = Valutazione dell'applicazione aggiornata con successo. +evaluation.fetched.successfully = Valutazione dell'applicazione recuperata con successo. +evaluation.deleted.successfully = Valutazione dell'applicazione eliminata con successo. +evaluations.fetched.successfully = Tutte le valutazioni delle applicazioni recuperate con successo. +application.evaluation.status.updated.successfully=Stato della valutazione dell'applicazione aggiornato con successo. +assigned.application.not.found.with.id=Applicazione assegnata con questo ID dell'applicazione non trovata +either.application.or.assigned.application.id.required=� richiesto almeno uno tra applicationId o assignedApplicationId. +evaluation.already.exists=Una valutazione dell'applicazione esiste gi� per questo ID applicazione. application.assigned.success.msg =Domanda assegnata con successo application.already.assigned.msg =La domanda � gi� assegnata @@ -271,3 +281,23 @@ hub_not_found=Hub non trovato application.not.in.draft.status=La domanda non � in stato DRAFT. get.error.s3=Impossibile recuperare il file da S3. + +application.data.amendment.success = Recupero riuscito dei dati dell'applicazione per il processo di modifica +delete.application.amendment.success =Emendamento all'applicazione eliminato con successo. +application.amendment.not.found = Richiesta di modifica dell'applicazione non trovata con l'ID indicato. +application.amendment.get.success = Dettagli della modifica dell'applicazione recuperati correttamente con l'ID fornito. +application.amendment.update.successfully = Emendamento all'applicazione aggiornato con successo. +application.amendment.closed.successfully = Emendamento alla domanda chiuso con successo. +response.days.extended.success=Giorni di risposta estesi con successo. + +added.comment.to.amendment.request.success = Commento aggiunto con successo alla richiesta di emendamento. +comment.not.found = Commento non trovato. +comment.updated.successfully = Commento aggiornato con successo. +comment.deleted.successfully = Commento eliminato con successo. +comment.not.associate.with.amendment = Il commento non � associato alla richiesta di emendamento. +amendment.found.success = Richiesta di emendamento trovata con successo. +invalid.amendment.for.comment = Richiesta di emendamento non valida per il commento fornito. +DD_MM_YYYY_HH_MM = dd_MM_yyyy HH:mm +create.application.data.amendment.msg =Emendamento alla domanda inviato con successo +beneficiary.email.not.found.msg=L'indirizzo email per il beneficiario non stato trovato. Si prega di assicurarsi che il beneficiario abbia un indirizzo email valido. +reminder.email.sent.success.msg=Email di promemoria inviata con successo!