Files
bflows-bandi-be/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
2026-04-15 17:30:43 +05:30

2975 lines
165 KiB
Java

package net.gepafin.tendermanagement.dao;
import com.amazonaws.services.dynamodbv2.xspec.L;
import com.amazonaws.services.dynamodbv2.xspec.S;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.*;
import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum;
import net.gepafin.tendermanagement.enums.*;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean;
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.request.EmailLogRequest;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.model.util.SortBy;
import net.gepafin.tendermanagement.repositories.*;
import net.gepafin.tendermanagement.service.AmazonS3Service;
import net.gepafin.tendermanagement.service.ApplicationEvaluationService;
import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.service.CompanyService;
import net.gepafin.tendermanagement.service.DocumentService;
import net.gepafin.tendermanagement.service.FormService;
import net.gepafin.tendermanagement.service.HubService;
import net.gepafin.tendermanagement.service.SystemEmailTemplatesService;
import net.gepafin.tendermanagement.service.UserService;
import net.gepafin.tendermanagement.util.*;
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.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.lang3.StringUtils;
import org.h2.util.IOUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static org.apache.commons.lang3.StringUtils.isEmpty;
@Component
public class ApplicationDao {
private final Logger log = LoggerFactory.getLogger(ApplicationDao.class);
@Autowired
private CallService callService;
@Autowired
private ApplicationRepository applicationRepository;
@Autowired
private DocumentRepository documentRepository;
@Autowired
private ApplicationFormRepository applicationFormRepository;
@Autowired
private ApplicationFormFieldRepository applicationFormFieldRepository;
@Autowired
private FormService formService;
@Autowired
private DocumentService documentService;
@Autowired
private CallDao callDao;
@Autowired
private FlowFormDao flowFormDao;
@Autowired
private FlowEdgesRepository flowEdgesRepository;
@Autowired
private FlowDataRepository flowDataRepository;
@Autowired
private UserCompanyDelegationRepository userCompanyDelegationRepository;
@Autowired
private Validator validator;
@Autowired
private CompanyService companyService;
@Autowired
private S3PathConfig s3PathConfig;
@Autowired
private SystemEmailTemplatesService systemEmailTemplatesService;
@Autowired
private AssignedApplicationsRepository assignedApplicationsRepository;
@Autowired
private CommunicationRepository communicationRepository;
// @Value("${default_System_Receiver_Email}")
// private String defaultSystemReceiverEmail;
@Value("${rinaldo_email}")
private String rinaldoEmail;
@Value("${call.id}")
private String callId;
@Value("${sviluppumbriaUuid}")
private String sviluppumbriaUuid;
@Autowired
private AmazonS3Service amazonS3Service;
@Autowired
private ApplicationSignedDocumentRepository applicationSignedDocumentRepository;
// @Value("${aws.s3.url.folder.signed.document}")
// private String signedDocumentS3Folder;
@Value("${default.hub.uuid}")
private String defaultHubUuid;
@Autowired
private UserService userService;
@Autowired
private S3PathConfig s3ConfigBean;
@Autowired
private ProtocolDao protocolDao;
@Autowired
private HubService hubService;
@Autowired
private EmailNotificationDao emailNotificationDao;
@Autowired
private FormDao formDao;
@Autowired
private EmailLogDao emailLogDao;
@Autowired
private UserWithCompanyRepository userWithCompanyRepository;
@Autowired
private LoggingUtil loggingUtil;
@Autowired
private HttpServletRequest request;
@Autowired
private ApplicationEvaluationService applicationEvaluationService;
@Autowired
private NotificationDao notificationDao;
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository;
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
@Autowired
private ApplicationViewRepository applicationViewRepository;
@Autowired
private ApplicationFormViewRepository applicationFormViewRepository;
@Autowired
private ApplicationRankingViewRepository applicationRankingViewRepository;
@Autowired
private FormRepository formRepository;
@Autowired
private ApplicationEvaluationDao applicationEvaluationDao;
@Autowired
private EvaluationCriteriaRepository evaluationCriteriaRepository;
@Autowired
private CallRepository callRepository;
@Autowired
private SystemEmailTemplatesDao systemEmailTemplatesDao;
@Autowired
private ApplicationContractRepository applicationContractRepository;
@Autowired
private CompanyDocumentRepository companyDocumentRepository;
@Autowired
private AppointmentDao appointmentDao;
@Autowired
private DocumentDao documentDao;
public final Random random = new Random();
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) {
log.info("Starting createApplication: formId={}, applicationId={}", formId, applicationId);
FormEntity formEntity = formService.validateForm(formId);
// callService.validatePublishedCall(formEntity.getCall().getId());
validateFormFields(applicationRequestBean,formEntity);
ApplicationEntity applicationEntity = validateApplication(applicationId);
checkCallEndDate(applicationEntity.getCall());
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
log.info("Validated user-company association for company ID: {}", applicationEntity.getCompanyId());
if(Boolean.FALSE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.DRAFT.getValue()))) {
log.warn("Application ID {} is not in DRAFT status", applicationId);
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_NOT_IN_DRAFT_STATUS));
}
formService.validateFormField(applicationRequestBean.getFormFields(),applicationEntity,formEntity);
ApplicationFormEntity applicationFormEntity = getApplicationFormOrCreate(formEntity, applicationEntity);
createOrUpdateMultipleFormFields(applicationRequestBean.getFormFields(), applicationFormEntity, formEntity);
return getApplicationById(applicationEntity.getId(),formEntity.getId());
}
public void validateDelegation(UserEntity user, UserWithCompanyEntity userWithCompany) {
UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository
.findByUserIdAndUserWithCompanyIdAndStatus(user.getId(), userWithCompany.getId(),
UserCompanyDelegationStatusEnum.ACTIVE.getValue());
if (!userWithCompany.getIsLegalRepresentant() && userCompanyDelegationEntity == null) {
throw new CustomValidationException(Status.BAD_REQUEST,
Translator.toLocale(GepafinConstant.USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION));
}
}
public ApplicationFormEntity saveApplicationFormEntity(ApplicationFormEntity applicationFormEntity) {
ApplicationFormEntity applicationFormEntity1 = applicationFormRepository.save(applicationFormEntity);
return applicationFormEntity1;
}
public ApplicationFormEntity createApplicationFormEntity(ApplicationEntity application, FormEntity formEntity) {
log.info("Creating ApplicationFormEntity for applicationId: {}, formId: {}", application.getId(), formEntity.getId());
ApplicationFormEntity applicationFormEntity = new ApplicationFormEntity();
applicationFormEntity.setApplication(application);
applicationFormEntity.setForm(formEntity);
applicationFormEntity = saveApplicationFormEntity(applicationFormEntity);
log.info("Created ApplicationFormEntity with id: {}", applicationFormEntity.getId());
return applicationFormEntity;
}
public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, UserWithCompanyEntity userWithCompany) {
// validateDelegation(user,userWithCompany);
ApplicationEntity entity = new ApplicationEntity();
entity.setUserId(user.getId());
entity.setCompanyId(userWithCompany.getCompanyId());
entity.setCall(call);
entity.setHubId(call.getHub().getId());
entity.setUserWithCompany(userWithCompany);
entity.setIsDeleted(false);
entity.setStatus(ApplicationStatusTypeEnum.DRAFT.getValue());
entity.setEvaluationVersion(call.getEvaluationVersion());
return entity;
}
public ApplicationResponseBean getApplicationById(Long id,Long formId) {
log.info("Fetching application with ID: {}", id);
ApplicationEntity applicationEntity = validateApplication(id);
ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formId);
List<ApplicationFormFieldResponseBean> applicationFormFieldResponseBeans=new ArrayList<>();
List<ApplicationFormFieldEntity> applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
applicationFormFieldResponseBeans=createApplicationFormFieldResponse(applicationFormFieldEntities, applicationFormEntity, applicationFormFieldResponseBeans);
ApplicationResponseBean applicationResponseBean= convertApplicationEntityToApplicationResponseBean(applicationEntity);
applicationResponseBean.setFormFields(applicationFormFieldResponseBeans);
return applicationResponseBean;
}
private List<ApplicationFormFieldResponseBean> createApplicationFormFieldResponse(
List<ApplicationFormFieldEntity> applicationFormFieldEntities,
ApplicationFormEntity applicationFormEntity,
List<ApplicationFormFieldResponseBean> applicationFormFieldResponseBeans) {
// List<ContentResponseBean> contentResponseBeans = Utils.convertJsonStringToList(
// applicationFormEntity.getForm().getContent(), ContentResponseBean.class);
List<ContentResponseBean> contentResponseBeans = formDao.convertFormEntityToFormResponseBean(applicationFormEntity.getForm()).getContent();
for (ApplicationFormFieldEntity applicationFormFieldEntity : applicationFormFieldEntities) {
Optional<ContentResponseBean> fileUploadContent = contentResponseBeans.stream()
.filter(contentResponseBean -> ("fileupload".equals(contentResponseBean.getName()) ||
"fileselect".equals(contentResponseBean.getName())) &&
contentResponseBean.getId().equals(applicationFormFieldEntity.getFieldId()))
.findFirst();
List<DocumentResponseBean> documentResponseBeans = new ArrayList<>();
if (fileUploadContent.isPresent()) {
String documentId = applicationFormFieldEntity.getFieldValue();
log.debug("Field is file upload/select type. Document IDs: {}", documentId);
if (documentId != null && !documentId.isEmpty()) {
documentResponseBeans = Arrays.stream(documentId.split(","))
.map(String::trim)
.map(Long::parseLong)
.map(docId -> {
DocumentEntity documentEntity = documentService.validateDocument(docId);
if (Boolean.FALSE.equals(DocumentSourceTypeEnum.APPLICATION.getValue().equals(documentEntity.getSource()))) {
log.warn("Document {} source type invalid: {}", docId, documentEntity.getSource());
throw new CustomValidationException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND));
}
return documentEntity;
})
.map(callDao::convertToDocumentResponseBean)
.collect(Collectors.toList());
}
}
ApplicationFormFieldResponseBean responseBean = convertApplicationFormFieldEntityToApplicationFormFieldResponseBean(
applicationFormFieldEntity, applicationFormEntity.getId());
if (!documentResponseBeans.isEmpty()) {
responseBean.setFieldValue(documentResponseBeans);
}
applicationFormFieldResponseBeans.add(responseBean);
}
return applicationFormFieldResponseBeans;
}
public void deleteById(HttpServletRequest request, Long id) {
log.info("Deleting application with ID: {}", id);
ApplicationEntity applicationEntity= validateApplication(id);
if (Boolean.FALSE.equals(ApplicationStatusTypeEnum.DRAFT.getValue().equals(applicationEntity.getStatus()))) {
log.warn("Application with ID: {} is not in DRAFT status, cannot delete. Current status: {}", id, applicationEntity.getStatus());
throw new CustomValidationException(
Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.APPLICATION_NOT_IN_DRAFT_STATUS)
);
}
ApplicationEntity oldApplicationDataEntity = Utils.getClonedEntityForData(applicationEntity);
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
applicationEntity.setIsDeleted(true);
applicationEntity = applicationRepository.save(applicationEntity);
log.info("Marked application as deleted and saved for ID: {}", id);
/** This code is responsible for adding a version history log for the "Delete application" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldApplicationDataEntity).newData(applicationEntity).build());
log.info("Application deleted with ID: {}", id);
}
// public List<ApplicationResponse> getAllApplications(UserEntity userEntity, Long callId, CompanyEntity companyEntity) {
// boolean isBeneficiary = validator.checkIsBeneficiary();
//
// log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType());
// List<ApplicationResponse> applicationResponses = new ArrayList<>();
//
// if (callId != null) {
// // Fetch based on callId and user if role is BENEFICIARY, otherwise fetch all for the call
// log.info("Fetching applications for callId: {}", callId);
// CallEntity call = callService.validateCall(callId);
//
// // Use a single method to handle both conditions for consistency
// List<ApplicationEntity> applicationEntities = isBeneficiary
// ? applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId())
// .map(List::of) // Convert Optional<ApplicationEntity> to a List of one element
// .orElse(List.of()) // If not present, return an empty list
// : applicationRepository.findByCallIdAndIsDeletedFalse(call.getId());
//
// applicationResponses = applicationEntities.stream()
// .map(this::getApplicationResponse)
// .collect(Collectors.toList());
//
// } else {
// // Fetch all applications for the user if BENEFICIARY, or fetch all applications in general
// List<ApplicationEntity> applicationEntities = isBeneficiary
// ? applicationRepository.findByUserIdAndIsDeletedFalse(companyEntity.getId())
// : applicationRepository.findByIsDeletedFalse();
//
// applicationResponses = applicationEntities.stream()
// .map(this::getApplicationResponse)
// .collect(Collectors.toList());
// }
//
// return applicationResponses;
// }
public List<ApplicationResponse> getAllApplications(UserEntity userEntity, Long callId, Long companyId,List<ApplicationStatusTypeEnum> statusList) {
log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType());
Specification<ApplicationEntity> spec = search(userEntity, callId, companyId,statusList);
List<ApplicationEntity> applicationEntities = applicationRepository.findAll(spec);
return applicationEntities.stream()
.map(this::getApplicationResponse)
.collect(Collectors.toList());
}
private Specification<ApplicationEntity> search(UserEntity userEntity, Long callId, Long companyId,List<ApplicationStatusTypeEnum> statusList) {
return (root, query, builder) -> {
Boolean isBeneficiary = validator.checkIsBeneficiary();
Predicate predicate = builder.isFalse(root.get("isDeleted"));
if (Boolean.TRUE.equals(validator.checkIsBeneficiary()) || Boolean.TRUE.equals(validator.checkIsConfidi())) {
predicate = builder.and(predicate, builder.equal(root.get("userId"), userEntity.getId()));
}
if (callId != null) {
predicate = builder.and(predicate, builder.equal(root.get("call").get("id"), callId));
}
if (companyId != null) {
predicate = builder.and(predicate, builder.equal(root.get("companyId"), companyId));
}
if (statusList != null && !statusList.isEmpty()) {
List<String> statusNames = statusList.stream()
.map(Enum::name)
.collect(Collectors.toList());
predicate = builder.and(predicate, root.get("status").in(statusNames));
}
query.orderBy(
builder.desc(builder.isNotNull(root.get(GepafinConstant.SUBMISSION_DATE))),
builder.desc(root.get(GepafinConstant.SUBMISSION_DATE))
);
predicate = builder.and(predicate, builder.equal(root.get("hubId"), userEntity.getHub().getId()));
return predicate;
};
}
private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) {
log.info("Generating ApplicationResponse for application ID: {}", applicationEntity.getId());
ApplicationResponse responseBean = new ApplicationResponse();
List<FlowEdgesEntity> flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId());
Long totalFormSteps = flowFormDao.calculateTotalSteps(flowEdgesList);
Long completedSteps= Long.valueOf(flowFormDao.getCompletedSteps(applicationEntity, false));
Integer progress = calculateProgress(totalFormSteps, completedSteps);
responseBean.setId(applicationEntity.getId());
responseBean.setProgress(progress);
responseBean.setCallTitle(applicationEntity.getCall().getName());
responseBean.setCallEndDate(applicationEntity.getCall().getEndDate());
responseBean.setCallEndTime(applicationEntity.getCall().getEndTime());
responseBean.setModifiedDate(applicationEntity.getUpdatedDate());
responseBean.setCallId(applicationEntity.getCall().getId());
responseBean.setSubmissionDate(applicationEntity.getSubmissionDate());
responseBean.setStatus(applicationEntity.getStatus());
responseBean.setEvaluationVersion(EvaluationVersionEnum.valueOf(applicationEntity.getCall().getEvaluationVersion()));
responseBean.setComments(applicationEntity.getComments());
responseBean.setCompanyId(applicationEntity.getCompanyId());
Optional<AssignedApplicationsEntity> assignedApplicationsOptional =
assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationEntity.getId());
if(assignedApplicationsOptional.isPresent()){
responseBean.setAssignedUserId(assignedApplicationsOptional.get().getUserId());
UserEntity user = userService.validateUser(assignedApplicationsOptional.get().getUserId());
String firstName = user.getFirstName() != null ? user.getFirstName() : "";
String lastName = user.getLastName() != null ? user.getLastName() : "";
String userName = String.join(" ", firstName, lastName).trim();
responseBean.setAssignedUserName(userName);
}
CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId());
responseBean.setCompanyName(company.getCompanyName());
if(applicationEntity.getProtocol() != null) {
responseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber());
}
responseBean.setAmountAccepted(applicationEntity.getAmountAccepted());
responseBean.setAmountRequested(applicationEntity.getAmountRequested());
responseBean.setDateAccepted(applicationEntity.getDateAccepted());
responseBean.setDateRejected(applicationEntity.getDateRejected());
responseBean.setNdg(applicationEntity.getNdg());
if (applicationEntity.getRankingActionType() != null && !applicationEntity.getRankingActionType().isBlank()) {
responseBean.setRankingActionType(
ApplicationRankingActionTypeEnum.valueOf(applicationEntity.getRankingActionType().trim()));
}
responseBean.setManualRanking(applicationEntity.getManualRanking());
return responseBean;
}
public ApplicationEntity validateApplication(Long id) {
log.info("Validating existence of Application with ID: {}", id);
ApplicationEntity applicationEntity = applicationRepository.findById(id)
.orElseThrow(() -> {
log.warn("Application not found for ID: {}", id);
return new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG));
});
return applicationEntity;
}
private ApplicationResponseBean convertApplicationEntityToApplicationResponseBean(ApplicationEntity entity) {
ApplicationResponseBean response = new ApplicationResponseBean();
response.setId(entity.getId());
response.setSubmissionDate(entity.getSubmissionDate());
response.setStatus(entity.getStatus());
response.setComments(entity.getComments());
response.setCallId(entity.getCall().getId());
response.setCreatedDate(entity.getCreatedDate());
response.setUpdatedDate(entity.getUpdatedDate());
response.setAmountAccepted(entity.getAmountAccepted());
response.setAmountRequested(entity.getAmountRequested());
response.setDateAccepted(entity.getDateAccepted());
response.setDateRejected(entity.getDateRejected());
if(entity.getProtocol() != null) {
response.setProtocolNumber(entity.getProtocol().getProtocolNumber());
}
return response;
}
private ApplicationFormEntity getApplicationFormOrCreate(FormEntity formEntity, ApplicationEntity applicationEntity) {
log.info("Fetching ApplicationForm for Application ID: {} and Form ID: {}", applicationEntity.getId(), formEntity.getId());
ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formEntity.getId());
ApplicationFormEntity oldApplicationFormEntity = Utils.getClonedEntityForData(applicationFormEntity);
if (applicationFormEntity == null) {
log.info("No existing ApplicationForm found. Creating new ApplicationForm for Application ID: {}, Form ID: {}", applicationEntity.getId(), formEntity.getId());
applicationFormEntity = createApplicationFormEntity(applicationEntity, formEntity);
/** This code is responsible for adding a version history log for the "Create application form" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(oldApplicationFormEntity).newData(applicationFormEntity)
.build());
}
return applicationFormEntity;
}
public List<ApplicationFormFieldEntity> createOrUpdateMultipleFormFields(List<ApplicationFormFieldRequestBean> formFieldResponseBeans,
ApplicationFormEntity applicationFormEntity, FormEntity formEntity) {
FieldValidator fieldValidator = FieldValidator.create();
List<ApplicationFormFieldEntity> existingFields = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
List<ApplicationFormFieldEntity> applicationFormFieldEntities=formFieldResponseBeans.stream().map(requestBean -> createOrUpdateApplicationFormField(requestBean, applicationFormEntity, existingFields, formEntity,fieldValidator))
.collect(Collectors.toList());
fieldValidator.validate();
return applicationFormFieldEntities;
}
public ApplicationFormFieldEntity createOrUpdateApplicationFormField(ApplicationFormFieldRequestBean applicationFormFieldRequestBean,
ApplicationFormEntity applicationFormEntity, List<ApplicationFormFieldEntity> applicationFormFieldEntities, FormEntity formEntity,FieldValidator fieldValidator) {
log.info("Starting createOrUpdateApplicationFormField for ApplicationForm ID: {}", applicationFormEntity.getId());
ApplicationFormFieldEntity applicationFormFieldEntity = new ApplicationFormFieldEntity();
List<Long> newDocumentIds = validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity);
validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity);
VersionActionTypeEnum actionType = VersionActionTypeEnum.INSERT;
List<ContentResponseBean> contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
// contentResponseBeans.stream()
// .filter(content -> "numberinput".equals(content.getName()) && content.getId().toString().equals(applicationFormFieldRequestBean.getFieldId()))
// .map(ContentResponseBean::getSettings)
// .flatMap(List::stream)
// .filter(setting -> "isRequestedAmount".equals(setting.getName()) && Boolean.TRUE.equals(setting.getValue()))
// .findFirst()
// .ifPresent(setting -> {
// Object fieldValue = applicationFormFieldRequestBean.getFieldValue();
// if(fieldValue!=null) {
// try {
// BigDecimal amountRequested = new BigDecimal(fieldValue.toString());
// applicationFormEntity.getApplication().setAmountRequested(amountRequested);
// log.info("Set amountRequested to {} for Application ID: {}", amountRequested, applicationFormEntity.getApplication().getId());
// } catch (NumberFormatException e) {
// log.error("Invalid number format for requested amount: {}", fieldValue, e);
// throw new IllegalArgumentException("Field value is not a valid number: " + fieldValue, e);
// }
// }
// });
contentResponseBeans.stream()
.filter(content -> content.getId().toString().equals(applicationFormFieldRequestBean.getFieldId()))
.findFirst()
.ifPresent(content -> {
Object fieldValue = applicationFormFieldRequestBean.getFieldValue();
if (fieldValue == null) {
return;
}
// Convert settings list to a map
Map<String, Object> settingMap = content.getSettings().stream()
.collect(Collectors.toMap(SettingResponseBean::getName, SettingResponseBean::getValue, (v1, v2) -> v1));
String fieldType = content.getName();
// Define handlers for different (fieldType + settingName) combinations
// Add handler for isRequestedAmount
if ("numberinput".equals(fieldType) && Boolean.TRUE.equals(settingMap.get("isRequestedAmount"))) {
try {
BigDecimal amountRequested = new BigDecimal(fieldValue.toString());
applicationFormEntity.getApplication().setAmountRequested(amountRequested);
log.info("Set amountRequested to {} for Application ID: {}", amountRequested, applicationFormEntity.getApplication().getId());
} catch (NumberFormatException e) {
log.error("Invalid number format for requested amount: {}", fieldValue, e);
throw new IllegalArgumentException("Field value is not a valid number: " + fieldValue, e);
}
}
if ("textinput".equals(fieldType) && Boolean.TRUE.equals(settingMap.get("isPIVA"))) {
applicationFormEntity.getApplication().setVatNumber(fieldValue.toString());
log.info("Set PEC to {} for Application ID: {}", fieldValue, applicationFormEntity.getApplication().getId());
}
// Run all applicable handlers
});
ApplicationFormFieldEntity oldApplicationFormFieldData = null;
if (applicationFormFieldEntities == null || applicationFormFieldEntities.isEmpty()) {
applicationFormFieldEntity.setApplicationForm(applicationFormEntity);
} else {
for (ApplicationFormFieldEntity applicationFormFieldEntity1 : applicationFormFieldEntities) {
if (applicationFormFieldEntity1.getFieldId().equals(applicationFormFieldRequestBean.getFieldId())) {
applicationFormFieldEntity = applicationFormFieldEntity1;
oldApplicationFormFieldData = Utils.getClonedEntityForData(applicationFormFieldEntity);
if (applicationFormEntity.getForm().getId().equals(applicationFormEntity.getApplication().getCall().getInitialForm()) && checkIfRequestFieldIsDifferent(applicationFormFieldEntity1, applicationFormFieldRequestBean)) {
validateRequiredFields(applicationFormEntity.getForm(), applicationFormEntity.getApplication(), applicationFormFieldRequestBean.getFieldId());
}
actionType = VersionActionTypeEnum.UPDATE;
break;
} else {
applicationFormFieldEntity.setApplicationForm(applicationFormEntity);
}
}
}
Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId());
if (applicationFormFieldRequestBean.getFieldValue() != null) {
updateDocumentDeletionStatus(applicationFormFieldEntity, applicationFormFieldRequestBean, formEntity, newDocumentIds, null, false);
applicationFormFieldEntity.setFieldValue(Utils.convertObjectToJsonString(applicationFormFieldRequestBean.getFieldValue()));
}
if (applicationFormFieldRequestBean.getFieldValue() == null) {
updateDocumentDeletionStatus(applicationFormFieldEntity, applicationFormFieldRequestBean, formEntity, newDocumentIds, null, false);
}
if (applicationFormFieldRequestBean.getFieldValue() != null) {
applicationFormFieldEntity.setFieldValue(Utils.convertObjectToJsonString(applicationFormFieldRequestBean.getFieldValue()));
} else {
applicationFormFieldEntity.setFieldValue(null);
}
ApplicationFormFieldEntity applicationFormField = applicationFormFieldRepository.save(applicationFormFieldEntity);
/** This code is responsible for adding a version history log for the "Create update application form" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(actionType).oldData(oldApplicationFormFieldData).newData(applicationFormField).build());
log.info("Version history logged for action: {}, Field ID: {}", actionType, applicationFormFieldEntity.getFieldId());
return applicationFormField;
}
private Boolean checkIfRequestFieldIsDifferent(ApplicationFormFieldEntity applicationFormFieldEntity,
ApplicationFormFieldRequestBean applicationFormFieldRequestBean) {
// Retrieve the field values from both objects
String entityFieldValue = applicationFormFieldEntity.getFieldValue();
Object requestFieldValue = applicationFormFieldRequestBean.getFieldValue();
// Check if both are null
if (entityFieldValue == null && requestFieldValue == null) {
return false; // No difference if both are null
}
// Compare values
Boolean check = !Objects.equals(entityFieldValue, requestFieldValue);
// Additional comparison if both are non-null
if (Boolean.TRUE.equals(check) && entityFieldValue != null && requestFieldValue != null) {
check = !entityFieldValue.equals(requestFieldValue.toString());
}
return check;
}
void updateDocumentDeletionStatus(ApplicationFormFieldEntity applicationFormFieldEntity, ApplicationFormFieldRequestBean applicationFormFieldRequestBean, FormEntity formEntity, List<Long> newDocumentIds,
List<String> preInstructorDocumentId,boolean isPreInstructor) {
if (newDocumentIds == null) {
newDocumentIds = Collections.emptyList();
}
if (preInstructorDocumentId == null) {
preInstructorDocumentId = Collections.emptyList();
}
List<ContentResponseBean> contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
for (ContentResponseBean contentResponseBean : contentResponseBeans) {
if (Boolean.FALSE.equals(contentResponseBean.getName().equals("fileupload") || contentResponseBean.getName().equals("fileselect"))) {
return;
}
}
if(!isPreInstructor){
List<Long> currentDocumentIds = parseDocumentIds(applicationFormFieldEntity.getFieldValue());
if (Boolean.TRUE.equals(newDocumentIds.isEmpty())) {
currentDocumentIds.forEach(docId -> documentService.deleteFile(docId));
} else {
List<Long> finalNewDocumentIds = newDocumentIds;
List<Long> documentsToDelete = currentDocumentIds.stream()
.filter(docId -> !finalNewDocumentIds.contains(docId))
.toList();
documentsToDelete.forEach(docId -> documentService.deleteFile(docId));
}}
else{
List<Long> currentDocumentIds = parseDocumentIds(applicationFormFieldEntity.getFieldValue());
if (Boolean.TRUE.equals(preInstructorDocumentId.isEmpty())) {
currentDocumentIds.forEach(docId -> documentService.deleteFile(docId));
} else {
List<Long> preInstructorDocIds = preInstructorDocumentId.stream()
.map(Long::valueOf)
.collect(Collectors.toList());
List<Long> documentsToDelete = currentDocumentIds.stream()
.filter(docId -> !preInstructorDocIds.contains(docId))
.toList();
documentsToDelete.forEach(docId -> documentService.deleteFile(docId));
}}
}
private List<Long> parseDocumentIds(String fieldValue) {
if (fieldValue == null || fieldValue.isEmpty()) {
return Collections.emptyList();
}
if (fieldValue.contains(",")) {
return Arrays.stream(fieldValue.split(","))
.map(String::trim)
.map(Long::parseLong)
.collect(Collectors.toList());
} else {
try {
return Collections.singletonList(Long.parseLong(fieldValue.trim()));
} catch (NumberFormatException e) {
e.printStackTrace();
return Collections.emptyList();
}
}
}
private List<Long> validateFileUploadDocuments(ApplicationFormFieldRequestBean applicationFormFieldRequestBean, FormEntity formEntity) {
List<Long> documentIds=null;
// List<ContentResponseBean> contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class);
List<ContentResponseBean> contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
log.debug("Validating file upload documents for field ID: {} in form ID: {}", applicationFormFieldRequestBean.getFieldId(), formEntity.getId());
for (ContentResponseBean contentResponseBean:contentResponseBeans){
if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload")) || Boolean.TRUE.equals(contentResponseBean.getName().equals("fileselect"))) {
if (contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) {
Object fieldValueObject = applicationFormFieldRequestBean.getFieldValue();
if (fieldValueObject instanceof String) {
// Safely cast the object to a string
String documentId = (String) fieldValueObject;
// Now you can use documentId as needed
documentIds = validateDocumentIds(documentId);
log.info("Validated document IDs: {}", documentIds);
}
}
}
}
return documentIds;
}
public List<Long> validateDocumentIds(String documentId) {
if (documentId != null && !documentId.isEmpty()) {
log.info("Validating document IDs: {}", documentId);
return Arrays.stream(documentId.split(","))
.map(Long::parseLong)
.peek(docId -> documentService.validateDocument(docId))
.collect(Collectors.toList());
}
return Collections.emptyList();
}
public ApplicationFormFieldEntity validateApplicationFormField(Long applicationFormFieldId) {
Optional<ApplicationFormFieldEntity> applicationFormFieldEntity = applicationFormFieldRepository.findById(applicationFormFieldId);
if (applicationFormFieldEntity.isEmpty()) {
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_FORM_FIELD_NOT_FOUND));
}
return applicationFormFieldEntity.get();
}
public List<ApplicationFormFieldEntity> saveApplicationFormFieldEntities(List<ApplicationFormFieldEntity> applicationFormFieldEntities) {
List<ApplicationFormFieldEntity> applicationFormFieldEntities1 = applicationFormFieldRepository.saveAll(applicationFormFieldEntities);
return applicationFormFieldEntities1;
}
public List<ApplicationFormFieldResponseBean> convertApplicationFormFieldEntitiesToApplicationFormFieldResponseBeans(List<ApplicationFormFieldEntity> applicationFormFieldEntities, Long applicationFormId) {
return applicationFormFieldEntities.stream()
.map(requestBean -> convertApplicationFormFieldEntityToApplicationFormFieldResponseBean(requestBean, applicationFormId))
.collect(Collectors.toList());
}
public ApplicationFormFieldResponseBean convertApplicationFormFieldEntityToApplicationFormFieldResponseBean(ApplicationFormFieldEntity applicationFormFieldEntity, Long applicationFormId) {
ApplicationFormFieldResponseBean applicationFormFieldResponseBean = new ApplicationFormFieldResponseBean();
applicationFormFieldResponseBean.setApplicationFormId(applicationFormId);
applicationFormFieldResponseBean.setFieldId(applicationFormFieldEntity.getFieldId());
if(applicationFormFieldEntity.getFieldValue() != null) {
applicationFormFieldResponseBean.setFieldValue(Utils.getFieldValueAsObject(applicationFormFieldEntity.getFieldValue()));
}
applicationFormFieldResponseBean.setId(applicationFormFieldEntity.getId());
applicationFormFieldResponseBean.setCreatedDate(applicationFormFieldEntity.getCreatedDate());
applicationFormFieldResponseBean.setUpdatedDate(applicationFormFieldEntity.getUpdatedDate());
return applicationFormFieldResponseBean;
}
public ApplicationEntity saveApplicationEntity(ApplicationEntity application) {
ApplicationEntity applicationEntity = applicationRepository.save(application);
/** This code is responsible for adding a version history log for "Create application" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(applicationEntity).build());
return applicationEntity;
}
public ApplicationGetResponseBean getApplicationByFormId(HttpServletRequest request, Long applicationId, Long formId) {
log.info("Received request to get application by formId. ApplicationId: {}, FormId: {}", applicationId, formId);
List<FormApplicationResponse> formApplicationResponses = new ArrayList<>();
List<FormEntity> formEntities = new ArrayList<>();
UserEntity userEntity = validator.validateUser(request);
boolean isBeneficiary = Boolean.TRUE.equals(validator.checkIsBeneficiary()) || Boolean.TRUE.equals(validator.checkIsConfidi());
ApplicationEntity applicationEntity = isBeneficiary
? applicationRepository.findByIdAndUserIdAndIsDeletedFalse(applicationId, userEntity.getId())
.orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)))
: applicationRepository.findById(applicationId)
.stream().findFirst()
.orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)));
if (formId != null) {
FormEntity formEntity = formService.validateForm(formId);
Optional<ApplicationEntity> application = applicationRepository.findByIdAndUserIdAndCallIdAndIsDeletedFalse(applicationId, userEntity.getId(),
formEntity.getCall().getId());
applicationEntity=application.get();
formEntities.add(formEntity);
addFormApplication(formEntity, applicationEntity, formApplicationResponses);
}
else {
List<ApplicationFormEntity> applicationFormEntities = applicationFormRepository.findByApplicationId(applicationEntity.getId());
List<ApplicationFormEntity> sequencedApplicationFormEntity = new ArrayList<>();
Long formIdMiddle = null;
List<FlowEdgesEntity> flowEdgesList = flowEdgesRepository.findBySourceIdAndCallId(
applicationEntity.getCall().getInitialForm(), applicationEntity.getCall().getId());
if (!flowEdgesList.isEmpty()) {
if (flowEdgesList.size() == 1) {
formIdMiddle = flowEdgesList.get(0).getTargetId();
} else {
List<Long> 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<Long> 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);
}
}
return createApplicationGetResponseBean(applicationEntity, formEntities, formApplicationResponses);
}
private boolean isBeneficiary(UserEntity userEntity) {
RoleStatusEnum roleStatus = RoleStatusEnum.valueOf(userEntity.getRoleEntity().getRoleType());
boolean isBeneficiary = RoleStatusEnum.ROLE_BENEFICIARY.equals(roleStatus);
return isBeneficiary;
}
private void addFormApplication(FormEntity formEntity, ApplicationEntity applicationEntity,
List<FormApplicationResponse> formApplicationResponses) {
FormApplicationResponse formApplicationResponse = processForm(formEntity, applicationEntity);
if(formApplicationResponse.getContent() != null && formApplicationResponse.getFormFields() != null) {
formApplicationResponses.add(formApplicationResponse);
}
}
public FormApplicationResponse processForm(FormEntity formEntity, ApplicationEntity applicationEntity) {
FormApplicationResponse formApplicationResponse = createFormApplicationResponse(formEntity);
List<ApplicationFormFieldResponseBean> applicationFormFieldResponseBeans =new ArrayList<>();
ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formEntity.getId());
if(applicationFormEntity!=null) {
List<ApplicationFormFieldEntity> applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
// formApplicationResponse = createFormApplicationResponse(formEntity);
applicationFormFieldResponseBeans = createApplicationFormFieldResponse(applicationFormFieldEntities, applicationFormEntity,applicationFormFieldResponseBeans);
formApplicationResponse.setFormFields(applicationFormFieldResponseBeans);
}
return formApplicationResponse;
}
private ApplicationGetResponseBean createApplicationGetResponseBean(ApplicationEntity applicationEntity, List<FormEntity> formEntities, List<FormApplicationResponse> formApplicationResponses) {
ApplicationGetResponseBean applicationGetResponseBean = createApplicationGetResponseBean(applicationEntity);
applicationGetResponseBean.setForm(formApplicationResponses);
return applicationGetResponseBean;
}
private ApplicationGetResponseBean createApplicationGetResponseBean(ApplicationEntity applicationEntity) {
ApplicationGetResponseBean applicationGetResponseBean = new ApplicationGetResponseBean();
applicationGetResponseBean.setId(applicationEntity.getId());
applicationGetResponseBean.setStatus(applicationEntity.getStatus());
applicationGetResponseBean.setComments(applicationEntity.getComments());
applicationGetResponseBean.setSubmissionDate(applicationEntity.getSubmissionDate());
applicationGetResponseBean.setCallId(applicationEntity.getCall().getId());
applicationGetResponseBean.setCallTitle(applicationEntity.getCall().getName());
applicationGetResponseBean.setCompanyId(applicationEntity.getCompanyId());
applicationGetResponseBean.setAmountAccepted(applicationEntity.getAmountAccepted());
applicationGetResponseBean.setAmountRequested(applicationEntity.getAmountRequested());
applicationGetResponseBean.setDateAccepted(applicationEntity.getDateAccepted());
applicationGetResponseBean.setDateRejected(applicationEntity.getDateRejected());
if(applicationEntity.getProtocol() != null) {
applicationGetResponseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber());
}
CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId());
applicationGetResponseBean.setCompanyName(company.getCompanyName());
return applicationGetResponseBean;
}
private FormApplicationResponse createFormApplicationResponse(FormEntity formEntity) {
FormApplicationResponse formApplicationResponse=new FormApplicationResponse();
formApplicationResponse.setId(formEntity.getId());
formApplicationResponse.setLabel(formEntity.getLabel());
formApplicationResponse.setCallId(formEntity.getCall().getId());
// formApplicationResponse.setContent(Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class)
formApplicationResponse.setContent(formDao.convertFormEntityToFormResponseBean(formEntity).getContent());
return formApplicationResponse;
}
public ApplicationResponse createApplicationByCallId(CompanyEntity companyEntity,
ApplicationRequest applicationRequest, Long callId, UserEntity userEntity) {
log.info("Start creating application for CallId: {}, UserId: {}, CompanyId: {}", callId, userEntity.getId(), companyEntity.getId());
CallEntity call = callService.validateCall(callId);
UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),companyEntity.getId());
checkCallEndDate(call);
// call = callService.validatePublishedCall(call.getId());
// checkIfApplicationExists(call, userWithCompanyEntity, userEntity);
HubEntity hubEntity = hubService.valdateHub(call.getHub().getId());
if(call.getAllowMultipleApplications() == null || Boolean.FALSE.equals(call.getAllowMultipleApplications())){
if(hubEntity.getUniqueUuid().equals(defaultHubUuid)){
checkIfApplicationExists(call, userWithCompanyEntity, userEntity);
}
}
ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, userWithCompanyEntity);
applicationEntity.setComments(applicationRequest.getComments());
applicationEntity = saveApplicationEntity(applicationEntity);
return getApplicationResponse(applicationEntity);
}
// public void checkIfApplicationExists(CallEntity call, UserWithCompanyEntity userWithCompanyEntity, UserEntity userEntity){
// Optional<ApplicationEntity> applicationEntity=applicationRepository.findByUserIdAndUserWithCompanyIdAndCallIdAndIsDeletedFalse(userEntity.getId(), userWithCompanyEntity.getId(),call.getId());
// if(applicationEntity.isPresent()){
// throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS));
// }
// }
public void checkIfApplicationExists(CallEntity call, UserWithCompanyEntity userWithCompanyEntity, UserEntity userEntity){
log.info("Checking existing applications for UserId: {}, UserWithCompanyId: {}, CallId: {}",
userEntity.getId(), userWithCompanyEntity.getId(), call.getId());
List<ApplicationEntity> applications = applicationRepository.findByUserIdAndUserWithCompany_IdAndCall_IdAndIsDeletedFalseAndStatusNot(
userEntity.getId(), userWithCompanyEntity.getId(), call.getId(), ApplicationStatusTypeEnum.REJECTED.name()
);
if (!applications.isEmpty()) {
log.warn("Application already exists for UserId: {}, UserWithCompanyId: {}, CallId: {}. Applications found: {}",
userEntity.getId(), userWithCompanyEntity.getId(), call.getId(), applications.size());
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS));
}
}
public String generateRandomFiveDigitNumber() {
int number = 10000 + random.nextInt(90000); // Generates a number from 10000 to 99999
return String.valueOf(number);
}
public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) {
log.info("Updating status for Application id : " + applicationId);
ApplicationEntity applicationEntity = validateApplication(applicationId);
if (ApplicationStatusTypeEnum.DELETED.equals(status) || ApplicationStatusTypeEnum.DELETED_CONFIRMED.equals(status)) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_TRANSITION_RESTRICTED));
}
log.info("Call end date verified successfully | callId: {}", applicationEntity.getCall().getId());
//cloned entity for old application data
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
HubEntity hub=hubService.valdateHub(applicationEntity.getHubId());
UserEntity userEntity = userService.validateUser(applicationEntity.getUserId());
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
if (ApplicationStatusTypeEnum.SUBMIT.getValue().equals(applicationEntity.getStatus())) {
log.warn("Attempt to change status after submission denied | applicationId: {}", applicationId);
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_SUBMITTED_CANNOT_CHANGE));
}
if (Boolean.TRUE.equals(applicationEntity.getStatus().equals(status.getValue()))) {
log.warn("Requested status is the same as current status | applicationId: {}, status: {}", applicationId, status);
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_IN_PREVIOUS_STATUS));
}
if (status.equals(ApplicationStatusTypeEnum.APPOINTMENT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.NDG.getValue()))){
String appointmentId = generateRandomFiveDigitNumber();
applicationEntity.setAppointmentId(appointmentId);
applicationEntity.setStatus(ApplicationStatusTypeEnum.APPOINTMENT.getValue());
}
if (status.equals(ApplicationStatusTypeEnum.SUBMIT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.READY.getValue()))) {
CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId());
// callService.validatePublishedCall(applicationEntity.getCall().getId(), userEntity.getHub().getId());
checkCallEndDate(applicationEntity.getCall());
Long protocolNumber = protocolDao.getProtocolNumber(userEntity.getHub());
ProtocolEntity protocolEntity = protocolDao.createProtocolEntity(applicationEntity, protocolNumber, userEntity.getHub().getId(),true);
protocolDao.saveProtocolEntity(protocolEntity);
applicationEntity.setProtocol(protocolEntity);
// if(Boolean.TRUE.equals(hub.getUniqueUuid().equals(sviluppumbriaUuid))) {
// protocolEntity = protocolDao.createExternalProtocol(applicationEntity, company, protocolEntity);
// }
applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue());
applicationEntity.setSubmissionDate(protocolEntity.getCreatedDate());
applicationEntity = applicationRepository.save(applicationEntity);
Map<String ,String> placeHolders=notificationDao.sendNotificationToBeneficiary(applicationEntity,NotificationTypeEnum.APPLICATION_SUBMISSION);
notificationDao.sendNotificationToSuperUser(applicationEntity,placeHolders,NotificationTypeEnum.APPLICATION_SUBMISSION);
/** This code is responsible for adding a version history log for "Update application status" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntity).newData(applicationEntity).build());
sendMailToUserAndCompany(userEntity, applicationEntity,company);
sendMailTodefaultSystemAndGepafin(userEntity, applicationEntity);
applicationEntity.setStatus(status.getValue());
log.info("Status updated to SUBMIT for applicationId: " + applicationId);
}
if (status.equals(ApplicationStatusTypeEnum.DRAFT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.AWAITING.getValue()))) {
checkCallEndDate(applicationEntity.getCall());
applicationEntity.setStatus(status.getValue());
log.info("Status updated to DRAFT for applicationId: " + applicationId);
}
if (status.equals(ApplicationStatusTypeEnum.AWAITING) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.READY.getValue()))) {
checkCallEndDate(applicationEntity.getCall());
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository.findByApplicationIdAndStatus(applicationId,
ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
deleteSignedDocumentFromS3(applicationSignedDocument);
applicationEntity.setStatus(status.getValue());
log.info("Status updated to AWAITING for applicationId: " + applicationId);
}
applicationEntity = applicationRepository.save(applicationEntity);
log.info("Application status updated successfully | applicationId: {}, newStatus: {}", applicationId, applicationEntity.getStatus());
if (!status.equals(ApplicationStatusTypeEnum.SUBMIT)) {
/** This code is responsible for adding a version history log for "Update application status" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntity).newData(applicationEntity).build());
}
return getApplicationResponse(applicationEntity);
}
/**
* Opaque registry segment update (restricted operators only). {@code segment} 1 → {@link ApplicationStatusTypeEnum#DELETED},
* 2 → {@link ApplicationStatusTypeEnum#DELETED_CONFIRMED}.
*/
public ApplicationResponse recordApplicationRegistrySegment(HttpServletRequest request, Long applicationId,ApplicationStatusTypeEnum status) {
validator.validateSuperAdminOrDirector();
validator.validateUser(request);
if (Boolean.FALSE.equals(status.equals(ApplicationStatusTypeEnum.DELETED)) && Boolean.FALSE.equals(status.equals(ApplicationStatusTypeEnum.DELETED_CONFIRMED))) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_REGISTRY_SEGMENT_INVALID));
}
ApplicationEntity applicationEntity = validateApplication(applicationId);
if (Boolean.FALSE.equals(validator.checkIsSuperAdmin())) {
validator.validateHubId(request, applicationEntity.getHubId());
}
if (status.getValue().equals(applicationEntity.getStatus())) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_IN_PREVIOUS_STATUS));
}
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
applicationEntity.setStatus(status.getValue());
applicationEntity = applicationRepository.save(applicationEntity);
closeAmendmentsEvaluationAndAssignedApplicationForRegistry(request, applicationId);
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntity).newData(applicationEntity).build());
log.info("Registry segment persisted | applicationId={}, status={}", applicationId, status);
return getApplicationResponse(applicationEntity);
}
public ApplicationResponse updateApplicationRankingAction(HttpServletRequest request, Long applicationId,
ApplicationRankingActionTypeEnum rankingActionType, Long manualRanking) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
validator.validateRequest(request, RoleStatusEnum.ROLE_SUPER_ADMIN);
validateCallClosedForRankingAction(applicationEntity.getCall());
if (!ApplicationStatusTypeEnum.APPROVED.getValue().equals(applicationEntity.getStatus())) {
throw new CustomValidationException(Status.BAD_REQUEST,
Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_INVALID));
}
validateRankingActionRequest(rankingActionType, manualRanking);
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
if (rankingActionType == null) {
compactManualRanksAfterLeavingReposition(applicationEntity);
applicationEntity.setRankingActionType(null);
applicationEntity.setManualRanking(null);
} else {
if (rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION) {
shiftOtherManualRanksForReposition(applicationEntity, manualRanking);
} else if (rankingActionType == ApplicationRankingActionTypeEnum.REMOVE) {
compactManualRanksAfterLeavingReposition(applicationEntity);
}
applicationEntity.setRankingActionType(rankingActionType.getValue());
applicationEntity.setManualRanking(
rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION ? manualRanking : null);
}
applicationEntity = applicationRepository.save(applicationEntity);
normalizeDenseManualRanksForCall(applicationEntity.getCall().getId());
applicationEntity = applicationRepository.findById(applicationEntity.getId()).orElse(applicationEntity);
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE)
.oldData(oldApplicationEntity).newData(applicationEntity).build());
return getApplicationResponse(applicationEntity);
}
/**
* Keeps stored manual ranks in {@code 1..N} for the call (same count as repositioned rows with a manual value),
* preserving relative order. Prevents gaps or values above the pool size (e.g. 2,3,4,5 with four apps → 1,2,3,4).
*/
private void normalizeDenseManualRanksForCall(Long callId) {
String reposition = ApplicationRankingActionTypeEnum.REPOSITION.getValue();
List<ApplicationEntity> repositioned = applicationRepository.findByCallIdAndIsDeletedFalse(callId).stream()
.filter(a -> ApplicationStatusTypeEnum.APPROVED.getValue().equals(a.getStatus()))
.filter(a -> reposition.equalsIgnoreCase(StringUtils.trimToEmpty(a.getRankingActionType())))
.filter(a -> a.getManualRanking() != null)
.sorted(Comparator.comparing(ApplicationEntity::getManualRanking).thenComparing(ApplicationEntity::getId))
.collect(Collectors.toList());
if (repositioned.isEmpty()) {
return;
}
boolean changed = false;
long slot = 1L;
for (ApplicationEntity a : repositioned) {
if (!Objects.equals(a.getManualRanking(), slot)) {
a.setManualRanking(slot);
changed = true;
}
slot++;
}
if (changed) {
applicationRepository.saveAll(repositioned);
}
}
public CallRankingSummaryResponse getApplicationRanking(Long callId,
List<ApplicationRankingActionTypeEnum> rankingActionTypes) {
CallEntity call = callRepository.findById(callId)
.orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.CALL_NOT_FOUND)));
Specification<ApplicationRankingView> spec = (root, query, criteriaBuilder) -> {
List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("callId"), callId));
if (rankingActionTypes != null && !rankingActionTypes.isEmpty()) {
List<String> types = rankingActionTypes.stream()
.filter(Objects::nonNull)
.map(ApplicationRankingActionTypeEnum::getValue)
.distinct()
.collect(Collectors.toList());
if (!types.isEmpty()) {
predicates.add(root.get("rankingActionType").in(types));
}
}
query.orderBy(criteriaBuilder.asc(root.get("rank")));
return criteriaBuilder.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
};
List<ApplicationRankingView> rows = applicationRankingViewRepository.findAll(spec);
CallRankingSummaryResponse summary = new CallRankingSummaryResponse();
summary.setCallId(call.getId());
summary.setCallName(call.getName());
summary.setAmount(call.getAmount());
if (call.getRankingType() != null && !call.getRankingType().isBlank()) {
summary.setRankingType(CallRankingTypeEnum.valueOf(call.getRankingType().trim()));
}
summary.setApplications(rows.stream()
.map(this::convertToApplicationRankingResponse)
.collect(Collectors.toList()));
return summary;
}
private ApplicationRankingResponse convertToApplicationRankingResponse(ApplicationRankingView entity) {
ApplicationRankingResponse response = new ApplicationRankingResponse();
response.setApplicationId(entity.getApplicationId());
response.setCallId(entity.getCallId());
response.setUserId(entity.getUserId());
response.setStatus(entity.getStatus());
response.setSubmissionDate(entity.getSubmissionDate());
response.setProtocolDatetime(entity.getProtocolDatetime());
response.setProtocolNumber(entity.getProtocolNumber());
response.setNdg(entity.getNdg());
response.setAmountAccepted(entity.getAmountAccepted());
response.setPecEmail(entity.getPecEmail());
response.setManualRanking(entity.getManualRanking());
response.setRank(entity.getRank());
response.setTotalScore(entity.getTotalScore());
if (entity.getRankingActionType() != null && !entity.getRankingActionType().isBlank()) {
response.setRankingActionType(ApplicationRankingActionTypeEnum.valueOf(entity.getRankingActionType().trim()));
}
if (entity.getRankingType() != null && !entity.getRankingType().isBlank()) {
response.setRankingType(CallRankingTypeEnum.valueOf(entity.getRankingType().trim()));
}
return response;
}
private void validateCallClosedForRankingAction(CallEntity callEntity) {
if (!CallStatusEnum.EXPIRED.getValue().equals(callEntity.getStatus())) {
throw new CustomValidationException(Status.BAD_REQUEST,
Translator.toLocale(GepafinConstant.CALL_MUST_BE_CLOSED_FOR_RANKING_ACTION));
}
}
private void validateRankingActionRequest(ApplicationRankingActionTypeEnum rankingActionType, Long manualRanking) {
if (rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION
&& (manualRanking == null || manualRanking <= 0)) {
throw new CustomValidationException(Status.BAD_REQUEST,
Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_INVALID));
}
}
/**
* When an application stops using manual REPOSITION (cleared or REMOVE), every other manual rank above its
* old slot shifts down by one so ranks stay dense (e.g. after removing rank 1, 2 and 3 become 1 and 2).
*/
private void compactManualRanksAfterLeavingReposition(ApplicationEntity applicationEntity) {
String repositionType = ApplicationRankingActionTypeEnum.REPOSITION.getValue();
if (!repositionType.equalsIgnoreCase(StringUtils.trimToEmpty(applicationEntity.getRankingActionType()))) {
return;
}
Long releasedRank = applicationEntity.getManualRanking();
if (releasedRank == null) {
return;
}
applicationRepository.compactRepositionedManualRankingAfterSlotFreed(
applicationEntity.getCall().getId(),
applicationEntity.getId(),
releasedRank,
repositionType);
}
private void shiftOtherManualRanksForReposition(ApplicationEntity applicationEntity, Long newRank) {
Long callId = applicationEntity.getCall().getId();
Long applicationId = applicationEntity.getId();
String repositionType = ApplicationRankingActionTypeEnum.REPOSITION.getValue();
Long oldRank = applicationEntity.getManualRanking();
if (Objects.equals(oldRank, newRank)) {
return;
}
if (oldRank == null) {
applicationRepository.bumpRepositionedManualRankingFromRankInclusive(callId, applicationId, newRank,
repositionType);
return;
}
if (newRank < oldRank) {
applicationRepository.bumpRepositionedManualRankingUpInHalfOpenInterval(callId, applicationId, newRank,
oldRank, repositionType);
} else {
applicationRepository.bumpRepositionedManualRankingDownInHalfOpenInterval(callId, applicationId, oldRank,
newRank, repositionType);
}
}
/**
* Sets all non-terminal amendments, the application evaluation (if any), and the assigned application row to CLOSE.
*/
private void closeAmendmentsEvaluationAndAssignedApplicationForRegistry(HttpServletRequest httpRequest, Long applicationId) {
LocalDateTime nowUtc = DateTimeUtil.DateServerToUTC(LocalDateTime.now());
List<ApplicationAmendmentRequestEntity> amendments = applicationAmendmentRequestRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
for (ApplicationAmendmentRequestEntity amendment : amendments) {
if (ApplicationAmendmentRequestEnum.CLOSE.getValue().equals(amendment.getStatus())
|| ApplicationAmendmentRequestEnum.EXPIRED.getValue().equals(amendment.getStatus())
|| ApplicationAmendmentRequestEnum.REJECTED.getValue().equals(amendment.getStatus())) {
continue;
}
ApplicationAmendmentRequestEntity oldAmendment = Utils.getClonedEntityForData(amendment);
amendment.setStatus(ApplicationAmendmentRequestEnum.CLOSE.getValue());
amendment.setClosingDate(nowUtc);
applicationAmendmentRequestRepository.save(amendment);
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(httpRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAmendment).newData(amendment).build());
}
applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationId).ifPresent(evaluation -> {
if (ApplicationEvaluationStatusTypeEnum.CLOSE.getValue().equals(evaluation.getStatus())) {
return;
}
ApplicationEvaluationEntity oldEvaluation = Utils.getClonedEntityForData(evaluation);
evaluation.setStatus(ApplicationEvaluationStatusTypeEnum.CLOSE.getValue());
evaluation.setClosingDate(nowUtc);
if (evaluation.getStartDate() != null && evaluation.getClosingDate() != null) {
long activeDays = ChronoUnit.DAYS.between(evaluation.getStartDate(), evaluation.getClosingDate());
activeDays -= evaluation.getSuspendedDays() != null ? evaluation.getSuspendedDays() : 0;
evaluation.setActiveDays(activeDays);
}
applicationEvaluationRepository.save(evaluation);
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(httpRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldEvaluation).newData(evaluation).build());
});
assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).ifPresent(assigned -> {
if (AssignedApplicationEnum.CLOSE.getValue().equals(assigned.getStatus())) {
return;
}
AssignedApplicationsEntity oldAssigned = Utils.getClonedEntityForData(assigned);
assigned.setStatus(AssignedApplicationEnum.CLOSE.getValue());
assignedApplicationsRepository.save(assigned);
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(httpRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssigned).newData(assigned).build());
});
}
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));
}
if (completedSteps < 0 || completedSteps > totalSteps) {
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.COMPLETED_STEPS_NOT_VALID));
}
double progress = ((double) completedSteps / totalSteps) * 100;
return (int) Math.round(progress);
}
public void validateFormFields(ApplicationRequestBean request, FormEntity formEntity) {
// List<ContentResponseBean> contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class);
List<ContentResponseBean> contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
List<ApplicationFormFieldRequestBean> requestFields = request.getFormFields();
Map<String, String> contentMap = contentResponseBeans.stream()
.collect(Collectors.toMap(ContentResponseBean::getId, ContentResponseBean::getLabel)); // Change getLabel() if needed
FieldValidator validator = FieldValidator.create();
for (ApplicationFormFieldRequestBean requestField : requestFields) {
String fieldId = requestField.getFieldId();
if (!contentMap.containsKey(fieldId)) {
validator.addError(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_ID_NOT_FOUND), fieldId));
}
}
validator.validate();
}
public void validateRequiredFields(FormEntity formEntity, ApplicationEntity applicationEntity, String fieldId) {
FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndCallId(
formEntity.getId(), applicationEntity.getCall().getId());
if (flowDataEntity == null) {
return;
}
ApplicationFormFieldEntity applicationFormFieldEntity = applicationFormFieldRepository
.findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId(
flowDataEntity.getChoosenField(), formEntity.getId(), applicationEntity.getId())
.orElse(null);
if (applicationFormFieldEntity == null || !fieldId.equals(applicationFormFieldEntity.getFieldId())) {
return;
}
List<Long> nextFormIds = flowEdgesRepository.findBySourceIdAndCallId(
formEntity.getId(), applicationEntity.getCall().getId())
.stream()
.map(FlowEdgesEntity::getTargetId)
.collect(Collectors.toList());
Optional<Long> nextFormIdOptional = flowDataRepository.findByChoosenValueAndFormIdIn(
applicationFormFieldEntity.getFieldValue(), nextFormIds)
.map(FlowDataEntity::getFormId);
if (nextFormIdOptional.isPresent()) {
Long nextFormId = nextFormIdOptional.get();
FormEntity nextForm = formService.validateForm(nextFormId);
ApplicationFormEntity nextApplicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(
applicationEntity.getId(), nextForm.getId());
if (nextApplicationFormEntity != null) {
List<ApplicationFormFieldEntity> nextApplicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(nextApplicationFormEntity.getId());
nextApplicationFormFieldEntities.forEach(applicationFormFieldEntityToDelete ->
/** This code is responsible for adding a version history log for "Deleting application form field" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.DELETE).oldData(applicationFormFieldEntityToDelete).build()));
applicationFormFieldRepository.deleteAll(nextApplicationFormFieldEntities);
/** This code is responsible for adding a version history log for the "Deleting next application form" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.DELETE).oldData(nextApplicationFormEntity).build());
applicationFormRepository.delete(nextApplicationFormEntity);
}
}
}
private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity,CompanyEntity company) {
log.info("Preparing to send submission email | applicationId: {}, userId: {}", applicationEntity.getId(), userEntity.getId());
CallEntity call =applicationEntity.getCall();
UserWithCompanyEntity userWithCompany=companyService.getUserWithCompany(userEntity.getId(),company.getId());
ProtocolEntity protocol= applicationEntity.getProtocol();
HubEntity hub = hubService.valdateHub(applicationEntity.getHubId());
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
.retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_USER_AND_COMPANY,
hub, null);
if (Boolean.TRUE.equals(validator.isProductionProfileActivated()) && applicationEntity.getCall().getId().equals(23l)) {
systemEmailTemplateResponse.setHtmlContent(GepafinConstant.APPLICATION_SUBMISSION_MAIL_BODY);
systemEmailTemplateResponse.setHtmlContent(systemEmailTemplatesDao.replaceEmailSignature(hub,GepafinConstant.APPLICATION_SUBMISSION_MAIL_BODY,null));
systemEmailTemplateResponse.setSubject(GepafinConstant.APPLICATION_SUBMISSION_MAIL_SUBJECT);
}
// Create the map for subject placeholders
Map<String, String> subjectPlaceholders = new HashMap<>();
subjectPlaceholders.put("{{call_name}}", call.getName());
subjectPlaceholders.put("{{company_name}}", company.getCompanyName());
// Create the map for body placeholders
Map<String, String> bodyPlaceholders = new HashMap<>();
bodyPlaceholders.put("{{call_name}}", call.getName());
String protocolNumber=applicationEntity.getProtocol().getExternalProtocolNumber();
if(protocolNumber==null){
protocolNumber= String.valueOf(applicationEntity.getProtocol().getProtocolNumber());
}
bodyPlaceholders.put("{{protocol_number}}",protocolNumber);
String protocolDate= DateTimeUtil.formatLocalDateTime(protocol.getCreatedDate(), GepafinConstant.DD_MM_YYYY);
if(protocol.getExternalProtocolDate()!=null){
protocolDate= DateTimeUtil.formatLocalDateTime(protocol.getExternalProtocolDate(), GepafinConstant.DD_MM_YYYY);
}
bodyPlaceholders.put("{{date}}", protocolDate);
bodyPlaceholders.put("{{time}}", DateTimeUtil.parseLocalTimeToString(protocol.getTime(), GepafinConstant.HH_MM_SS));
// Replace placeholders in the subject and body
String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders);
String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders);
EmailLogRequest emailLogRequest=emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(),RecipientTypeEnum.USER,userEntity.getId(),userEntity.getEmail(),userEntity.getId(),applicationEntity.getId(),null,applicationEntity.getCall().getId(),subject,body);
String email = userEntity.getEmail();
if (userEntity.getBeneficiary() != null) {
emailLogRequest.setRecipientType(RecipientTypeEnum.BENEFICIARY);
if(Boolean.TRUE.equals(hub.getUniqueUuid().equals(defaultHubUuid))){
emailLogRequest.setRecipientType(RecipientTypeEnum.APPLICATION_PEC);
email=applicationEntity.getPecEmail();
}else {
email = userEntity.getBeneficiary().getEmail();
}
emailLogRequest.setRecipientId(userEntity.getBeneficiary().getId());
}
EmailLogEntity emailLogEntity=emailLogDao.createEmailLog(emailLogRequest,null);
emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email),emailLogEntity);
if (Boolean.TRUE.equals(hub.getUniqueUuid().equals(defaultHubUuid)) && userEntity.getBeneficiary() != null) {
emailLogRequest.setRecipientType(RecipientTypeEnum.BENEFICIARY);
email = userEntity.getBeneficiary().getEmail();
emailLogRequest.setRecipientId(userEntity.getBeneficiary().getId());
EmailLogEntity emailLog=emailLogDao.createEmailLog(emailLogRequest,null);
emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email),emailLog);
}
List<String> recipientEmails = new ArrayList<>();
// recipientEmails.add(email);
String companyEmail = userWithCompany.getEmail();
String contactEmail = userWithCompany.getContactEmail();
if(Boolean.TRUE.equals(hub.getUniqueUuid().equals(defaultHubUuid))){
if (company.getPec()!=null) {
recipientEmails.add(company.getPec());
}else {
recipientEmails.add(userWithCompany.getPec());
}
}
else {
if (companyEmail != null && !companyEmail.isEmpty()) {
recipientEmails.add(companyEmail);
}
if (contactEmail != null && !contactEmail.isEmpty() && !contactEmail.equals(companyEmail)) {
recipientEmails.add(contactEmail);
}
}
if(Boolean.FALSE.equals(recipientEmails.isEmpty())){
emailLogRequest.setRecipientId(applicationEntity.getCompanyId());
emailLogRequest.setRecipientType(RecipientTypeEnum.COMPANY);
emailLogRequest.setRecipientEmails(String.valueOf(recipientEmails));
}
EmailLogEntity emailLog=emailLogDao.createEmailLog(emailLogRequest,null);
emailNotificationDao.sendMail(hub.getId(), subject, body, recipientEmails,emailLog);
}
private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) {
CallEntity call = applicationEntity.getCall();
CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId());
ProtocolEntity protocol = applicationEntity.getProtocol();
HubEntity hub = hubService.valdateHub(applicationEntity.getHubId());
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
.retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_GEPAFIN,
hub, null);
if (Boolean.TRUE.equals(validator.isProductionProfileActivated()) && applicationEntity.getCall().getId().equals(23l)) {
systemEmailTemplateResponse.setHtmlContent(GepafinConstant.APPLICATION_SUBMISSION_MAIL_BODY);
systemEmailTemplateResponse.setHtmlContent(systemEmailTemplatesDao.replaceEmailSignature(hub,GepafinConstant.APPLICATION_SUBMISSION_MAIL_BODY,null));
systemEmailTemplateResponse.setSubject(GepafinConstant.APPLICATION_SUBMISSION_MAIL_SUBJECT);
}
// Create the map for subject placeholders
Map<String, String> subjectPlaceholders = new HashMap<>();
subjectPlaceholders.put("{{call_name}}", call.getName());
subjectPlaceholders.put("{{company_name}}", company.getCompanyName());
// Create the map for body placeholders
Map<String, String> bodyPlaceholders = new HashMap<>();
bodyPlaceholders.put("{{call_name}}", call.getName());
String protocolNumber=applicationEntity.getProtocol().getExternalProtocolNumber();
if(protocolNumber==null){
protocolNumber= String.valueOf(applicationEntity.getProtocol().getProtocolNumber());
}
String protocolDate= DateTimeUtil.formatLocalDateTime(protocol.getCreatedDate(), GepafinConstant.DD_MM_YYYY);
if(protocol.getExternalProtocolDate()!=null){
protocolDate= DateTimeUtil.formatLocalDateTime(protocol.getExternalProtocolDate(), GepafinConstant.DD_MM_YYYY);
}
bodyPlaceholders.put("{{protocol_number}}", protocolNumber);
bodyPlaceholders.put("{{date}}",protocolDate);
bodyPlaceholders.put("{{time}}", DateTimeUtil.parseLocalTimeToString(protocol.getTime(), GepafinConstant.HH_MM_SS));
// Replace placeholders in the subject and body
String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders);
String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders);
EmailLogRequest emailLogRequest=emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(),RecipientTypeEnum.PROPERTIES,null,userEntity.getEmail(),userEntity.getId(),applicationEntity.getId(),null,applicationEntity.getCall().getId(),subject,body);
List<String> hubEmails = Arrays.stream(hub.getEmail().split(","))
.map(String::trim)
.filter(email -> !email.isEmpty())
.toList();
emailLogRequest.setRecipientEmails(hub.getEmail());
EmailLogEntity emailLogEntity=emailLogDao.createEmailLog(emailLogRequest,null);
emailNotificationDao.sendMail(hub.getId(), subject, body,hubEmails,emailLogEntity);
emailLogRequest.setRecipientEmails(rinaldoEmail);
EmailLogEntity emailLog=emailLogDao.createEmailLog(emailLogRequest,null);
emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(rinaldoEmail),emailLog);
}
public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId,
MultipartFile file) {
log.info("Received request to upload signed document | applicationId: {}, fileName: {}", applicationId, file.getOriginalFilename());
ApplicationEntity applicationEntity = validateApplication(applicationId);
checkCallEndDate(applicationEntity.getCall());
//cloned entity for old data
ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(applicationEntity);
validateFileTypeForCall(file, applicationEntity);
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository.findByApplicationIdAndStatus(applicationId,
ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
//cloned entity for old data
ApplicationSignedDocumentEntity oldApplicationSingedDocumentData = Utils.getClonedEntityForData(applicationSignedDocument);
if (applicationSignedDocument != null) {
log.info("Existing active signed document found and will be deleted | applicationId: {}, fileName: {}", applicationId, applicationSignedDocument.getFileName());
deleteSignedDocumentFromS3(applicationSignedDocument);
}
String hash ="";
try {
hash = FileHashUtil.calculateSHA256(file.getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
UploadFileOnAmazonS3Response uploadFileOnAmazonS3 = uploadFileOnAmazonS3ForUserSignedDocument(file, applicationEntity.getCall().getId(), applicationId);
log.info("File uploaded to S3 successfully | applicationId: {}", applicationId);
applicationSignedDocument = new ApplicationSignedDocumentEntity();
applicationSignedDocument.setApplication(applicationEntity);
applicationSignedDocument.setFileName(uploadFileOnAmazonS3.getFileName());
applicationSignedDocument.setFilePath(uploadFileOnAmazonS3.getFilePath());
applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
applicationSignedDocument.setFileHash(hash);
applicationSignedDocument = applicationSignedDocumentRepository.save(applicationSignedDocument);
/** This code is responsible for adding a version history log for the "assign application document" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(oldApplicationSingedDocumentData)
.newData(applicationSignedDocument).build());
applicationEntity.setStatus(ApplicationStatusTypeEnum.READY.getValue());
applicationEntity = applicationRepository.save(applicationEntity);
log.info("Application status updated to READY | applicationId: {}", applicationEntity.getId());
/** This code is responsible for adding a version history log for the "Create Call" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(applicationEntity).build());
return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
}
public void deleteSignedDocumentFromS3(ApplicationSignedDocumentEntity applicationSignedDocumentEntity){
log.info("Starting soft delete of signed document | applicationSignedDocumentId: {}, fileName: {}",
applicationSignedDocumentEntity.getId(), applicationSignedDocumentEntity.getFileName());
ApplicationSignedDocumentEntity oldApplicationSignedDocument = Utils.getClonedEntityForData(applicationSignedDocumentEntity);
String oldS3Path = applicationSignedDocumentEntity.getFilePath();
log.debug("Old S3 path: {} ", oldS3Path);
String newS3Path = s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.DELETED_USER_SIGNED_DOCUMENT,applicationSignedDocumentEntity.getApplication().getCall().getId(),applicationSignedDocumentEntity.getApplication().getId(),0L,0L,0l);
log.debug("Generated new S3 path for deleted document: {}", newS3Path);
UploadFileOnAmazonS3Response response = amazonS3Service.moveFile(applicationSignedDocumentEntity.getFileName(), oldS3Path, newS3Path);
log.info("Moved file in S3 from {} to {} | fileName: {}", oldS3Path, newS3Path, response.getFileName());
applicationSignedDocumentEntity.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue());
applicationSignedDocumentEntity.setFileName(response.getFileName());
applicationSignedDocumentEntity.setFilePath(response.getFilePath());
applicationSignedDocumentRepository.save(applicationSignedDocumentEntity);
log.info("Updated signed document entity status to INACTIVE and saved | applicationSignedDocumentId: {}", applicationSignedDocumentEntity.getId());
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldApplicationSignedDocument).newData(applicationSignedDocumentEntity).build());
}
private void validateFileTypeForCall(MultipartFile file, ApplicationEntity applicationEntity) {
List<String> validCallIds = Arrays.asList(callId.split(","));
if (applicationEntity != null && validCallIds.contains(applicationEntity.getCall().getId().toString())) {
return;
}
validateFileType(file);
}
private UploadFileOnAmazonS3Response uploadFileOnAmazonS3ForUserSignedDocument(MultipartFile file, Long callId, Long applicationId) {
try {
String s3Path = generateS3PathForDelegation(callId, applicationId);
log.info("S3 Path {}", s3Path);
return amazonS3Service.uploadFileOnAmazonS3(s3Path, file);
} catch (Exception e) {
log.error("Failed to upload user signed document | callId: {}, applicationId: {}, error: {}", callId, applicationId, e.getMessage(), e);
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3));
}
}
private String generateS3PathForDelegation(Long callId, Long applicationId) {
try {
return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId,0L,0L,0L);
} catch (IllegalArgumentException e) {
log.error("Failed to generate S3 path for delegation | callId: {}, applicationId: {}, error: {}", callId, applicationId, e.getMessage(), e);
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG));
}
}
public ApplicationSignedDocumentResponse convertApplicationSignedDocumentToApplicationSignedDocumentResponse(
ApplicationSignedDocumentEntity applicationSignedDocument) {
ApplicationSignedDocumentResponse applicationSignedDocumentResponse = new ApplicationSignedDocumentResponse();
applicationSignedDocumentResponse.setId(applicationSignedDocument.getId());
applicationSignedDocumentResponse.setApplicationId(applicationSignedDocument.getApplication().getId());
applicationSignedDocumentResponse.setFileName(applicationSignedDocument.getFileName());
applicationSignedDocumentResponse.setFilePath(applicationSignedDocument.getFilePath());
applicationSignedDocumentResponse
.setStatus(ApplicationSignedDocumentStatusEnum.valueOf(applicationSignedDocument.getStatus()));
applicationSignedDocumentResponse.setCreatedDate(applicationSignedDocument.getCreatedDate());
applicationSignedDocumentResponse.setUpdatedDate(applicationSignedDocument.getUpdatedDate());
applicationSignedDocumentResponse.setFileHash(applicationSignedDocument.getFileHash());
applicationSignedDocumentResponse.setDocumentAttachmentId(applicationSignedDocument.getDocumentAttachmentId());
return applicationSignedDocumentResponse;
}
private void validateFileType(MultipartFile file) {
if (file.isEmpty()) {
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.VALIDATION_ERROR_FILE_EMPTY));
}
String filename = file.getOriginalFilename();
if (filename == null || !filename.endsWith(".p7m")) {
log.warn("Invalid file type detected | filename: {}", filename);
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.VALIDATION_ERROR_FILE_INVALIDTYPE));
}
}
public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) {
log.info("Fetching signed document for applicationId: {}", applicationId);
ApplicationEntity applicationEntity = validateApplication(applicationId);
// validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
if (validator.checkIsPreInstructor()) {
ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluationByApplicationId(applicationId);
validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId());
} else {
validator.validateUserId(request, applicationEntity.getUserId());
}
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
if(applicationSignedDocument == null) {
log.warn("No active signed document found for applicationId: {}", applicationId);
throw new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND));
}
return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
}
public void deleteSignedDocument(HttpServletRequest request, Long applicationId) {
log.info("Initiating deletion of signed document for applicationId: {}", applicationId);
ApplicationEntity applicationEntity = validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
//cloned entity for old data
ApplicationSignedDocumentEntity oldApplicationSignedDocument = Utils.getClonedEntityForData(applicationSignedDocument);
if(applicationSignedDocument == null) {
log.warn("No active signed document found to delete for applicationId: {}", applicationId);
throw new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND));
}
applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue());
applicationSignedDocument = applicationSignedDocumentRepository.save(applicationSignedDocument);
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationSignedDocument).newData(applicationSignedDocument)
.build());
}
public ApplicationResponse validateApplication(HttpServletRequest request, Long applicationId) {
log.info("Starting application validation process | applicationId: {}", applicationId);
ApplicationEntity applicationEntity = validateApplication(applicationId);
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
checkCallEndDate(applicationEntity.getCall());
UserEntity userEntity = userService.validateUser(applicationEntity.getUserId());
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
if (Boolean.FALSE.equals(ApplicationStatusTypeEnum.DRAFT.getValue().equals(applicationEntity.getStatus()))) {
log.warn("Application not in draft status | applicationId: {}, status: {}", applicationId, applicationEntity.getStatus());
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_IN_DRAFT_STATUS));
}
if (applicationEntity.getAmountRequested() == null || applicationEntity.getAmountRequested().compareTo(BigDecimal.ZERO) <= 0 ) {
log.warn("Invalid amount requested | amount: {}", applicationEntity.getAmountRequested());
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.AMOUNT_REQUEST_SHOULD_GREATED_THEN_ZERO));
}
List<FlowEdgesEntity> flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId());
Long totalSteps = flowFormDao.calculateTotalSteps(flowEdgesList);
Integer completedSteps = flowFormDao.getCompletedSteps(applicationEntity, true);
if (totalSteps.intValue() != completedSteps) {
log.warn("Application incomplete | applicationId: {}", applicationId);
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG));
}
applicationEntity.setStatus(ApplicationStatusTypeEnum.AWAITING.getValue());
applicationEntity = applicationRepository.save(applicationEntity);
/** This code is responsible for adding a version history log for "Update application status or other details" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntity).newData(applicationEntity).build());
return getApplicationResponse(applicationEntity);
}
public byte[] downloadApplicationDocumentsAsZip(HttpServletRequest request, Long applicationId) {
log.info("Starting ZIP download process for applicationId: {}", applicationId);
ApplicationEntity applicationEntity = validateApplication(applicationId);
validateAssignedUser(request, applicationId);
Set<Long> documentIds = extractDocumentIdsFromApplicationForms(applicationId);
List<DocumentEntity> documents = documentRepository.findAllByIdInAndIsDeletedFalse(documentIds);
ApplicationSignedDocumentEntity signedDocument = applicationSignedDocumentRepository.findByApplicationIdAndStatus(applicationId,
ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
List<DocumentEntity> amendmentDocuments = fetchAmendmentDocuments(applicationId);
List<DocumentEntity> evaluationDocuments = fetchEvaluationDocuments(applicationId);
List<DocumentEntity> communicationnDocuments = fetchCommunicationDocuments(applicationId);
List<DocumentEntity> contractDocuments=fetchContractDocuments(applicationId);
if (documents.isEmpty() && signedDocument == null && amendmentDocuments.isEmpty() && evaluationDocuments.isEmpty()) {
log.warn("No documents found for applicationId: {}", applicationId);
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND));
}
return createZipWithDocuments(applicationEntity, documents, signedDocument, amendmentDocuments, evaluationDocuments, applicationId,communicationnDocuments,contractDocuments);
}
private void validateAssignedUser(HttpServletRequest request, Long applicationId) {
log.info("Validating assigned user for applicationId: {}", applicationId);
AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null);
if (assignedApplications != null) {
validator.validatePreInstructor(request, assignedApplications.getUserId());
}
}
private Set<Long> extractDocumentIdsFromApplicationForms(Long applicationId) {
log.info("Extracting document IDs from application forms | applicationId: {}", applicationId);
Set<Long> documentIds = new HashSet<>();
List<ApplicationFormEntity> applicationForms = applicationFormRepository.findByApplicationId(applicationId);
applicationForms.forEach(applicationForm -> {
FormEntity formEntity = applicationForm.getForm();
if (formEntity != null) {
List<ContentResponseBean> contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
contentResponseBeans.stream().filter(content -> "fileupload".equals(content.getName()) || "fileselect".equals(content.getName())).forEach(content -> {
Optional<ApplicationFormFieldEntity> formField = applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId(
content.getId(), applicationForm.getId(), applicationId);
formField.ifPresent(field -> {
if (field.getFieldValue() != null) {
Arrays.stream(field.getFieldValue().split(",")).map(String::trim).map(Long::valueOf).forEach(documentIds::add);
}
});
});
}
});
return documentIds;
}
private List<DocumentEntity> fetchAmendmentDocuments(Long applicationId) {
log.info("Fetching amendment documents for applicationId: {}", applicationId);
List<ApplicationAmendmentRequestEntity> amendmentRequests = applicationAmendmentRequestRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
Set<Long> amendmentIds = amendmentRequests.stream().map(ApplicationAmendmentRequestEntity::getId).collect(Collectors.toSet());
return documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(amendmentIds, DocumentSourceTypeEnum.AMENDMENT.getValue());
}
private List<DocumentEntity> fetchEvaluationDocuments(Long applicationId) {
log.info("Fetching evaluation documents for applicationId: {}", applicationId);
Optional<ApplicationEvaluationEntity> evaluationEntity = applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
if (evaluationEntity.isPresent()) {
Long evaluationId = evaluationEntity.get().getId();
log.debug("Found evaluation entity with id: {}", evaluationId);
return documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(Collections.singleton(evaluationId), DocumentSourceTypeEnum.EVALUATION.getValue());
}
return Collections.emptyList();
}
private List<DocumentEntity> fetchCommunicationDocuments(Long applicationId) {
log.info("Fetching communication documents for applicationId: {}", applicationId);
List<ApplicationAmendmentRequestEntity> amendmentRequests = applicationAmendmentRequestRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
List<Long> amendmentRequestIds = amendmentRequests.stream()
.map(ApplicationAmendmentRequestEntity::getId)
.collect(Collectors.toList());
List<CommunicationEntity> communicationEntities=communicationRepository.findByApplicationAmendmentRequestIdInAndIsDeletedFalse(amendmentRequestIds);
List<DocumentEntity> documentEntities=new ArrayList<>();
if (Boolean.FALSE.equals(communicationEntities.isEmpty())) {
for (CommunicationEntity communicationEntity : communicationEntities) {
{
Long communicationId = communicationEntity.getId();
log.debug("Found communication entity with id: {}", communicationId);
List<DocumentEntity> communicationDocuments= documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(Collections.singleton(communicationId), DocumentSourceTypeEnum.COMMUNICATION.getValue());
documentEntities.addAll(communicationDocuments);
}
}
return documentEntities;
}
return Collections.emptyList();
}
private String fetchProtocolNumberForAmendment(Long amendmentRequestId) {
ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(amendmentRequestId).orElse(null);
if (amendmentRequest != null && amendmentRequest.getProtocol() != null) {
return amendmentRequest.getProtocol().getProtocolNumber().toString();
}
return "unknown";
}
private void addDocumentToZip(ZipOutputStream zos, String s3Folder, String filePath, String fullPath) {
log.info("Attempting to add file to ZIP. S3 folder: {}, file path: {}", s3Folder, filePath);
try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, filePath)) {
zos.putNextEntry(new ZipEntry(fullPath));
IOUtils.copy(fileInputStream, zos);
zos.closeEntry();
} catch (IOException e) {
log.error("Failed to add file to ZIP. S3 folder: {}, file path: {}, error: {}",
s3Folder, filePath, e.getMessage(), e);
throw new RuntimeException("Error downloading or adding document to ZIP: " + fullPath, e);
}
}
private byte[] createZipWithDocuments(ApplicationEntity applicationEntity, List<DocumentEntity> documents, ApplicationSignedDocumentEntity signedDocument,
List<DocumentEntity> amendmentDocuments, List<DocumentEntity> evaluationDocuments, Long applicationId,List<DocumentEntity> communicationDocuments,List<DocumentEntity> contractDocuments) {
try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) {
Long callId = applicationEntity.getCall().getId();
// Add Application Documents
String appS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.APPLICATION, callId, applicationId, 0L,0L,0L);
for (DocumentEntity document : documents) {
String fileName = Utils.extractFileName(document.getFilePath());
addDocumentToZip(zos, appS3Folder, document.getFilePath(), fileName);
}
// Add Signed Document
if (signedDocument != null) {
String signedFolder = "SIGNED_DOCUMENT/";
String signedDocS3Folder = s3PathConfig.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId, 0L,0L,0L);
String fileName = signedDocument.getFileName();
addDocumentToZip(zos, signedDocS3Folder, signedDocument.getFilePath(), signedFolder + fileName);
}
// Add Amendment (Soccorso) Documents
for (DocumentEntity amendmentDocument : amendmentDocuments) {
String protocolNumber = fetchProtocolNumberForAmendment(amendmentDocument.getSourceId());
String amendmentFolder = "SOCCORSO_" + protocolNumber + "/";
String amendmentS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.AMENDMENT, callId, applicationId, amendmentDocument.getSourceId(),0L,0L);
String fileName = Utils.extractFileName(amendmentDocument.getFilePath());
addDocumentToZip(zos, amendmentS3Folder, amendmentDocument.getFilePath(), amendmentFolder + fileName);
}
// Add Evaluation Documents
for (DocumentEntity evaluationDocument : evaluationDocuments) {
String evaluationFolder = "EVALUATION/";
String evaluationS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.EVALUATION, callId, applicationId, evaluationDocument.getSourceId(),0L,0L);
String fileName = Utils.extractFileName(evaluationDocument.getFilePath());
addDocumentToZip(zos, evaluationS3Folder, evaluationDocument.getFilePath(), evaluationFolder + fileName);
}
for (DocumentEntity communicationDocument : communicationDocuments) {
Optional<CommunicationEntity> communicationEntity=communicationRepository.findByIdAndIsDeletedFalse(communicationDocument.getSourceId());
String communicationFolder = "COMMUNICATION/";
String communicationS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.COMMUNICATION, callId, applicationId, communicationEntity.get().getApplicationAmendmentRequest().getId(),communicationDocument.getSourceId(),0L);
String fileName = Utils.extractFileName(communicationDocument.getFilePath());
addDocumentToZip(zos, communicationS3Folder, communicationDocument.getFilePath(), communicationFolder + fileName);
}
for (DocumentEntity contractDocument : contractDocuments) {
ApplicationContractEntity applicationContractEntity=applicationContractRepository.findByIdAndIsDeletedFalse(contractDocument.getSourceId());
String contractFolder = "CONTRACT/";
String contractS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.CONTRACT, callId, applicationId, 0L,0L,applicationContractEntity.getId());
String fileName = Utils.extractFileName(contractDocument.getFilePath());
addDocumentToZip(zos, contractS3Folder, contractDocument.getFilePath(), contractFolder + fileName);
}
zos.finish();
return zipOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error while creating ZIP file", e);
}
}
// private Path<?> getFieldPath(Root<?> root, String fieldName) {
// try {
// return switch (fieldName) {
//// case GepafinConstant.CALL_ID -> root.get(GepafinConstant.CALL).get(GepafinConstant.ID);
//// case GepafinConstant.CALL_TITLE -> root.get(GepafinConstant.CALL).get(GepafinConstant.NAME);
//// case GepafinConstant.CALL_END_DATE -> root.get(GepafinConstant.CALL).get(GepafinConstant.END_DATE);
//// case GepafinConstant.CALL_END_TIME -> root.get(GepafinConstant.CALL).get(GepafinConstant.END_TIME);
//// case GepafinConstant.MODIFIED_DATE -> root.get(GepafinConstant.CALL).get(GepafinConstant.UPDATED_DATE);
//// case GepafinConstant.PROTOCOL_NUMBER-> root.get(GepafinConstant.PROTOCOL).get(GepafinConstant.PROTOCOL_NUMBER);
// default -> root.get(fieldName);
// };
// } catch (IllegalArgumentException e) {
// return null;
// }
// }
public void checkCallEndDate(CallEntity call) {
callService.validatePublishedCall(call.getId(), call.getHub().getId());
// LocalDateTime now = DateTimeUtil.DateServerToUTC(LocalDateTime.now());
//
// LocalDateTime callEndDateTime = LocalDateTime.of(
// call.getEndDate().toLocalDate(),
// call.getEndTime()
// );
//
// if (now.isAfter(callEndDateTime)) {
// throw new CustomValidationException(
// Status.BAD_REQUEST,
// Translator.toLocale(GepafinConstant.CALL_EXPIRED)
// );
// }
}
public void calculationProcessForFormula(ApplicationFormEntity applicationFormEntity, List<ContentResponseBean> contentResponseBeans,String fromFieldId,String formFieldValue,FieldValidator fieldValidator) {
List<String> formulaValue = new ArrayList<>();
String formulaValueOpt=null;
String label=null;
for (ContentResponseBean contentResponseBean:contentResponseBeans){
if(contentResponseBean.getId().equals(fromFieldId)){
for (SettingResponseBean settingResponseBean:contentResponseBean.getSettings()){
if (settingResponseBean.getName().equals("label")){
label= String.valueOf(settingResponseBean.getValue());
}
if(settingResponseBean.getName().equals("formula")){
String value= (String) settingResponseBean.getValue();
formulaValueOpt=value;
formulaValue=Utils.extractValues(value);
}
}
}
}
Map<String, String> mappedFormulaValue = new HashMap<>();
Object fieldValue = formFieldValue;
if (formulaValueOpt != null && fieldValue==null) {
fieldValue=0;
}
for (ContentResponseBean contentResponseBean : contentResponseBeans) {
String contentId = contentResponseBean.getId();
// Extract variable values once per contentResponseBean to avoid repeated stream operations
Set<String> variableValues = contentResponseBean.getSettings().stream()
.filter(setting -> "variable".equals(setting.getName()))
.flatMap(setting -> {
Object value = setting.getValue(); // Get the raw value
if (value instanceof String) {
return Stream.of((String) value); // Handle single String case
} else if (value instanceof List) {
return ((List<?>) value).stream()
.filter(item -> item instanceof String) // Ensure it's a String
.map(item -> (String) item); // Convert to String
} else {
return Stream.empty(); // Ignore unexpected types
}
})
.collect(Collectors.toSet()); // Collect into a Set for uniqueness
for (String formula : formulaValue) {
if (variableValues.contains(formula)) { // O(1) lookup instead of O(n)
mappedFormulaValue.put(formula, contentId);
}
}
}
Map<String, String> updatedMappedFormulaValue = new HashMap<>();
for (Map.Entry<String, String> entry : mappedFormulaValue.entrySet()) {
String variable = entry.getKey();
String contentId = entry.getValue();
// Repository call using contentId
Optional<ApplicationFormFieldEntity> optionalEntity = applicationFormFieldRepository.findByApplicationFormIdAndFieldId(applicationFormEntity.getId(),contentId);
// If entity is found, extract fieldValue and fieldId
optionalEntity.ifPresent(entity -> {
String entityFieldValue = entity.getFieldValue(); // Assuming getter method exists
String fieldId = entity.getFieldId(); // Assuming getter method exists
String tableType = contentResponseBeans.stream()
.filter(content -> content.getId().equals(fieldId)) // Match Content ID with fieldId
.flatMap(content -> content.getSettings().stream()) // Extract settings
.filter(setting -> "criteria_table_columns".equals(setting.getName())) // Match name
.map(setting -> setting.getName()) // Return the name of the setting
.findFirst() // Get the first match
.orElse(null); // Default to null if no match
if(tableType!=null){
JSONObject jsonObject = new JSONObject(entityFieldValue);
// Extract the value of total
entityFieldValue = jsonObject.getString("total");
}
updatedMappedFormulaValue.put(fieldId, entityFieldValue);
});
}
if(formulaValueOpt==null || formulaValueOpt.isEmpty()){
return;
}
double finalValue = evaluateFormula(formulaValueOpt, mappedFormulaValue, updatedMappedFormulaValue);
fieldValidator.formulaValidation(fieldValue, finalValue, label);
}
public static double evaluateFormula(String formula, Map<String, String> mappedFormulaValue, Map<String, String> updatedMappedFormulaValue) {
// Step 1: Extract all placeholders (variables) like {rest}, {another_var}, etc.
Pattern pattern = Pattern.compile("\\{(.*?)\\}");
Matcher matcher = pattern.matcher(formula);
List<String> variables = new ArrayList<>();
while (matcher.find()) {
variables.add(matcher.group(1)); // Extract variable names inside the curly braces
}
// Step 2: Replace placeholders with corresponding fieldValue
Map<String, Double> variableValues = new HashMap<>();
for (String variable : variables) {
String fieldId = mappedFormulaValue.get(variable);
if (fieldId != null && updatedMappedFormulaValue.containsKey(fieldId)) {
String fieldValueStr = updatedMappedFormulaValue.get(fieldId);
try {
double fieldValue = Double.parseDouble(fieldValueStr); // Assuming fieldValue is numeric
variableValues.put(variable, fieldValue);
} catch (NumberFormatException e) {
// Handle invalid number format gracefully (e.g., log an error or default to 0)
variableValues.put(variable, 0.0);
}
}
}
// Step 3: Replace variables in the formula with their corresponding values
String expression = formula;
for (String variable : variables) {
Double value = variableValues.get(variable);
String placeholder = "{" + variable + "}";
// If value is null, use 0 instead
String replacement = String.valueOf(value != null ? value : 0);
expression = expression.replace(placeholder, replacement);
}
if (expression.matches(".*\\{.*\\}.*")) {
return 0;
}
// Step 4: Evaluate the mathematical expression
return Utils.evaluateExpression(expression);
}
public ApplicationEntity validateApplicationWithCompany(Long id,Long companyId) {
ApplicationEntity application=applicationRepository.findByIdAndCompanyIdAndIsDeletedFalse(id,companyId);
if (application==null){
throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
}
return application;
}
public PageableResponseBean<List<ApplicationResponse>> getAllApplicationByPaginationByView(UserEntity userEntity, Long callId, Long companyId, ApplicationPageableRequestBean applicationPageableRequestBean) {
Integer pageNo = null;
Integer pageLimit = null;
UserWithCompanyEntity userWithCompany= userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userEntity.getId(), companyId).orElse(null);
Long userWithCompanyId = userWithCompany!=null?userWithCompany.getId():null;
if (applicationPageableRequestBean.getGlobalFilters() != null) {
pageNo = applicationPageableRequestBean.getGlobalFilters().getPage();
pageLimit = applicationPageableRequestBean.getGlobalFilters().getLimit();
}
if (pageLimit == null || pageLimit <= 0) {
pageLimit = GepafinConstant.DEFAULT_PAGE_LIMIT;
}
if (pageNo == null || pageNo <= 0) {
pageNo = GepafinConstant.DEFAULT_PAGE;
}
Specification<ApplicationView> spec = searchByView(callId,companyId, userWithCompanyId, applicationPageableRequestBean, userEntity);
Page<ApplicationView> entityPage = applicationViewRepository.findAll(spec, PageRequest.of(pageNo - 1, pageLimit));
// Prepare the response
List<ApplicationResponse> applicationResponses = entityPage.getContent().stream()
.map(application -> {
ApplicationResponse response = getApplicationResponseByView(application);
return response;
})
.collect(Collectors.toList());
PageableResponseBean<List<ApplicationResponse>> pageableResponseBean = new PageableResponseBean<>();
pageableResponseBean.setBody(applicationResponses);
pageableResponseBean.setCurrentPage(entityPage.getNumber() + 1); // Page numbers typically start from 0, so add 1 for user-friendly indexing
pageableResponseBean.setTotalPages(entityPage.getTotalPages());
pageableResponseBean.setTotalRecords(entityPage.getTotalElements());
pageableResponseBean.setPageSize(entityPage.getSize());
return pageableResponseBean;
}
public Specification<ApplicationView> searchByView(Long callId, Long companyId, Long userWithCompanyId, ApplicationPageableRequestBean applicationPageableRequestBean, UserEntity userEntity) {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = getPredicatesByView(applicationPageableRequestBean, criteriaBuilder, root, callId,companyId, userWithCompanyId, userEntity);
SortBy sortBy = new SortBy(GepafinConstant.CREATED_DATE, true);
if (applicationPageableRequestBean.getGlobalFilters() != null
&& applicationPageableRequestBean.getGlobalFilters().getSortBy() != null &&
applicationPageableRequestBean.getGlobalFilters().getSortBy().getColumnName() != null && Boolean.FALSE.equals(
isEmpty(applicationPageableRequestBean.getGlobalFilters().getSortBy().getColumnName()))) {
sortBy.setColumnName(applicationPageableRequestBean.getGlobalFilters().getSortBy().getColumnName());
sortBy.setSortDesc(true);
if (applicationPageableRequestBean.getGlobalFilters().getSortBy().getSortDesc() != null) {
sortBy.setSortDesc(applicationPageableRequestBean.getGlobalFilters().getSortBy().getSortDesc());
}
}
query.orderBy(criteriaBuilder.desc(root.get(sortBy.getColumnName())));
if (Boolean.FALSE.equals(sortBy.getSortDesc())) {
query.orderBy(criteriaBuilder.asc(root.get(sortBy.getColumnName())));
}
return query.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))).getRestriction();
};
}
private List<Predicate> getPredicatesByView(ApplicationPageableRequestBean applicationPageableRequestBean,
CriteriaBuilder criteriaBuilder, Root<ApplicationView> root, Long callId,Long companyId, Long userWithCompanyId, UserEntity userEntity) {
Integer year = null;
String search = null;
Integer daysRange = null;
Map<String, FilterCriteria> filters = new HashMap<>();
if (applicationPageableRequestBean.getGlobalFilters() != null) {
year = applicationPageableRequestBean.getGlobalFilters().getYear();
search = applicationPageableRequestBean.getGlobalFilters().getSearch();
daysRange = applicationPageableRequestBean.getDaysRange();
}
if (applicationPageableRequestBean.getFilters() != null) {
filters = applicationPageableRequestBean.getFilters();
}
List<Predicate> predicates = new ArrayList<>();
// Boolean isBeneficiary = validator.checkIsBeneficiary();
if (Boolean.TRUE.equals(validator.checkIsBeneficiary()) || Boolean.TRUE.equals(validator.checkIsConfidi())) {
predicates.add(criteriaBuilder.equal(root.get(GepafinConstant.USER_ID), userEntity.getId()));
}
if (year != null && year > 0) {
int filterYear = applicationPageableRequestBean.getGlobalFilters().getYear();
// Create LocalDateTime boundaries for the start and end of the year
LocalDateTime startOfYear = LocalDateTime.of(filterYear, 1, 1, 0, 0);
LocalDateTime endOfYear = LocalDateTime.of(filterYear, 12, 31, 23, 59, 59);
// Add the range comparison to filter records within the year
predicates.add(criteriaBuilder.between(root.get(GepafinConstant.CREATED_DATE), startOfYear, endOfYear));
}
// Search in `title` and `message` (if search term is provided)
if (search != null && !search.isEmpty()) {
String searchPattern = "%" + search.toUpperCase() + "%";
Predicate titlePredicate = criteriaBuilder.like(
criteriaBuilder.upper(root.get(GepafinConstant.COMMENTS)),
searchPattern
);
Predicate callTitlePredicate = criteriaBuilder.like(
criteriaBuilder.upper(root.get(GepafinConstant.CALL_TITLE)),
searchPattern
);
Predicate callNamePredicate = criteriaBuilder.like(
criteriaBuilder.upper(root.get(GepafinConstant.CALL_NAME)),
searchPattern
);
Predicate companyName = criteriaBuilder.like(
criteriaBuilder.upper(root.get(GepafinConstant.COMPANY_NAME)),
searchPattern
);
Predicate ndgPredicate = criteriaBuilder.like(
criteriaBuilder.upper(root.get(GepafinConstant.NDG_STRING)),
searchPattern
);
// Combine them using a single `or()`
Predicate finalPredicate = criteriaBuilder.or(titlePredicate, callTitlePredicate,callNamePredicate,companyName, ndgPredicate);
predicates.add(finalPredicate);
}
// Filter by `status` (if status list is provided)
if (applicationPageableRequestBean.getStatus() != null && !applicationPageableRequestBean.getStatus().isEmpty()) {
List<String> statusValues = applicationPageableRequestBean.getStatus().stream()
.map(ApplicationStatusTypeEnum::name) // Convert enum to string
.toList();
predicates.add(root.get(GepafinConstant.STATUS).in(statusValues));
}
if (callId != null) {
CallEntity call = callService.validateCall(callId);
predicates.add(criteriaBuilder.equal(root.get(GepafinConstant.CALL_ID), callId));
}
// Optional companyId filter
if (userWithCompanyId != null) {
predicates.add(criteriaBuilder.equal(root.get(GepafinConstant.USER_WITH_COMPANY_ID), userWithCompanyId));
}
if (companyId != null) {
predicates.add(criteriaBuilder.equal(root.get(GepafinConstant.COMPANY_ID), companyId));
}
if (daysRange != null && daysRange >= 0) {
LocalDateTime today = LocalDateTime.now();
LocalDateTime pastDate = today.minusDays(daysRange);
predicates.add(criteriaBuilder.between(root.get(GepafinConstant.CREATED_DATE), pastDate, today));
}
Utils.applyFiltersByPagination(root, criteriaBuilder, predicates, filters);
predicates.add(criteriaBuilder.isFalse(root.get(GepafinConstant.IS_DELETED)));
predicates.add(criteriaBuilder.equal(root.get(GepafinConstant.HUB_ID), userEntity.getHub().getId()));
return predicates;
}
private ApplicationResponse getApplicationResponseByView(ApplicationView applicationView) {
ApplicationResponse responseBean = new ApplicationResponse();
List<FlowEdgesEntity> flowEdgesList = flowEdgesRepository.findByCallId(applicationView.getCallId());
Long totalFormSteps = flowFormDao.calculateTotalSteps(flowEdgesList);
Long completedSteps = Long.valueOf(flowFormDao.getCompletedStepsByView(applicationView.getId(), false));
Integer progress = calculateProgress(totalFormSteps, completedSteps);
responseBean.setId(applicationView.getId());
responseBean.setProgress(progress);
responseBean.setCallTitle(applicationView.getCallTitle());
responseBean.setCallEndDate(applicationView.getCallEndDate());
responseBean.setCallEndTime(applicationView.getCallEndTime());
responseBean.setModifiedDate(applicationView.getModifiedDate());
responseBean.setCallId(applicationView.getCallId());
responseBean.setSubmissionDate(applicationView.getSubmissionDate());
responseBean.setStatus(applicationView.getStatus());
responseBean.setEvaluationVersion(EvaluationVersionEnum.valueOf(applicationView.getEvaluationVersion()));
responseBean.setComments(applicationView.getComments());
responseBean.setCompanyId(applicationView.getCompanyId());
responseBean.setAssignedUserId(applicationView.getAssignedUserId());
responseBean.setAssignedUserName(applicationView.getAssignedUserName());
responseBean.setCompanyName(applicationView.getCompanyName());
responseBean.setProtocolNumber(applicationView.getProtocolNumber());
responseBean.setAmountAccepted(applicationView.getAmountAccepted());
responseBean.setAmountRequested(applicationView.getAmountRequested());
responseBean.setDateAccepted(applicationView.getDateAccepted());
responseBean.setDateRejected(applicationView.getDateRejected());
responseBean.setNdg(applicationView.getNdg());
return responseBean;
}
public List<ApplicationFormView> getApplicationFormData(Long callId) {
List<ApplicationFormView> applicationFormViews=new ArrayList<>();
applicationFormViews= applicationFormViewRepository.findByCallId(callId);
return applicationFormViews;
}
private List<Method> getStaticGetterMethods() {
List<String> excluded = Arrays.asList(
GepafinConstant.GET_FIELD_TYPE,GepafinConstant.GET_APPLICATION_FORM_ID,GepafinConstant.GET_ID,GepafinConstant.GET_CLASS,GepafinConstant.GET_FORM_ID,GepafinConstant.GET_FIELD_ID,GepafinConstant.GET_FIELD_LABEL,GepafinConstant.GET_FIELD_VALUE,GepafinConstant.GET_REPORT_HEADER,GepafinConstant.GET_REPORT_ENABLE
);
Method applicationIdMethod = null;
List<Method> methods = new ArrayList<>();
for (Method m : ApplicationFormView.class.getMethods()) {
if (m.getName().equals(GepafinConstant.GET_APPLICATION_ID)) {
applicationIdMethod = m;
} else if (m.getName().startsWith(GepafinConstant.GET) && m.getParameterCount() == 0 && !excluded.contains(m.getName())) {
methods.add(m);
}
}
methods.sort(Comparator.comparing(Method::getName)); // Sort remaining
if (applicationIdMethod != null) {
methods.add(0, applicationIdMethod); // Add it to the beginning
}
return methods;
}
private String methodToHeader(Method method) {
String name = method.getName().substring(3); // strip "get"
return Arrays.stream(name.split("(?=[A-Z])"))
.map(String::toLowerCase)
.map(word -> Character.toUpperCase(word.charAt(0)) + word.substring(1))
.collect(Collectors.joining(" "));
}
private String invokeGetter(ApplicationFormView view, Method method) {
try {
Object value = method.invoke(view);
if (value == null) return "";
String stringValue;
if (value instanceof LocalDate) {
stringValue = ((LocalDate) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} else if (value instanceof LocalDateTime) {
stringValue = ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} else if (value instanceof Date) {
stringValue = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) value);
} else {
stringValue = value.toString();
}
// Wrap it in ="..." to make Excel treat it as a literal string
return stringValue;
} catch (Exception e) {
return "";
}
}
public byte[] exportCsv(Long callId) {
List<ApplicationFormView> results = getApplicationFormData(callId);
Map<Long, ApplicationFormView> appInfo = new HashMap<>();
Map<Long, Map<String, String>> appFieldValues = new LinkedHashMap<>();
Set<String> tableFieldIds = new HashSet<>();
Map<String, String> fieldIdToLabel = new LinkedHashMap<>();
for (ApplicationFormView row : results) {
appInfo.putIfAbsent(row.getApplicationId(), row);
String label=row.getReportHeader();
if(Boolean.TRUE.equals(StringUtils.isEmpty(label))){
label=row.getFieldLabel();
}
fieldIdToLabel.putIfAbsent(row.getFieldId(), label);
if (GepafinConstant.TABLE.equalsIgnoreCase(row.getFieldType())) {
tableFieldIds.add(row.getFieldId());
continue;
}
String value = Optional.ofNullable(row.getFieldValue())
.map(v -> v.startsWith("\"") && v.endsWith("\"") ? v.substring(1, v.length() - 1) : v)
.orElse("");
appFieldValues
.computeIfAbsent(row.getApplicationId(), k -> new LinkedHashMap<>())
.merge(row.getFieldId(), value, (v1, v2) -> v1.equals(v2) ? v1 : String.join(", ", v1, v2));
}
Map<String, List<String>> tableHeadersByFieldId = new LinkedHashMap<>();
Map<Long, Map<String, String>> tableDataByApp = new HashMap<>();
prepareTableFieldData(results, tableFieldIds, tableHeadersByFieldId, tableDataByApp);
// Final header construction
List<Method> staticMethods = getStaticGetterMethods();
List<String> staticHeaders = staticMethods.stream().map(this::methodToHeader).toList();
List<String> dynamicHeaders = new ArrayList<>();
for (String fieldId : fieldIdToLabel.keySet()) {
if (tableHeadersByFieldId.containsKey(fieldId)) {
dynamicHeaders.addAll(tableHeadersByFieldId.get(fieldId));
} else {
dynamicHeaders.add(fieldIdToLabel.get(fieldId));
}
}
List<String> allHeaders = new ArrayList<>(staticHeaders);
allHeaders.addAll(dynamicHeaders);
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (CSVPrinter printer = new CSVPrinter(new OutputStreamWriter(out), CSVFormat.DEFAULT.withHeader(allHeaders.toArray(new String[0])))) {
for (Long appId : appFieldValues.keySet()) {
ApplicationFormView appRow = appInfo.get(appId);
Map<String, String> flatFieldVals = appFieldValues.get(appId);
Map<String, String> tableVals = tableDataByApp.getOrDefault(appId, Collections.emptyMap());
List<String> row = new ArrayList<>();
for (Method method : staticMethods) {
row.add(invokeGetter(appRow, method));
}
for (String fieldId : fieldIdToLabel.keySet()) {
if (tableHeadersByFieldId.containsKey(fieldId)) {
for (String header : tableHeadersByFieldId.get(fieldId)) {
row.add(tableVals.getOrDefault(header, ""));
}
} else {
row.add(flatFieldVals.getOrDefault(fieldId, ""));
}
}
printer.printRecord(row);
}
} catch (IOException e) {
throw new RuntimeException("CSV generation failed", e);
}
return out.toByteArray();
}
private Map<String, String> extractTableData(String fieldType,
ContentResponseBean content, String fieldValue) {
if (content == null) return Map.of();
Map<String, String> result = new LinkedHashMap<>();
List<Map<String, Object>> rows = null;
try {
rows = GepafinConstant.CRITERIA_TABLE_COLUMNS.equals(fieldType)
? Utils.convertJsonToListMap(String.valueOf(PdfUtils.extractRows(fieldValue)))
: Utils.convertJsonToListMap(fieldValue);
} catch (Exception e) {
throw new RuntimeException(e);
}
Map<String, String> fieldLabelMap = new LinkedHashMap<>();
Set<String> predefinedIds = new LinkedHashSet<>();
Set<String> dynamicIds = new LinkedHashSet<>();
Set<String> numericFormulaIds = new LinkedHashSet<>();
for (SettingResponseBean setting : content.getSettings()) {
String settingName = setting.getName();
if(settingName.equals(GepafinConstant.REPORT_ENABLE)){
Boolean enable= (Boolean) setting.getValue();
if(Boolean.FALSE.equals(enable)){
return null;
}
}
if (Boolean.TRUE.equals(GepafinConstant.TABLE_COLUMNS.equals(settingName)) || Boolean.TRUE.equals(GepafinConstant.CRITERIA_TABLE_COLUMNS.equals(settingName))) {
Map<String, Object> valueMap = (Map<String, Object>) setting.getValue();
if (valueMap == null) continue;
List<Map<String, Object>> columns = (List<Map<String, Object>>) valueMap.get(GepafinConstant.STATE_FIELD_DATA);
if (columns != null) {
for (Map<String, Object> col : columns) {
String id = String.valueOf(col.get(GepafinConstant.NAME));
if (Boolean.FALSE.equals(col.get(GepafinConstant.PREDEFINED))) {
if (GepafinConstant.NUMERIC.equals(col.get(GepafinConstant.FIELD_TYPE)) && Boolean.TRUE.equals(col.get(GepafinConstant.ENABLE_FORMULA))) {
numericFormulaIds.add(id);
}
}
}
}
}
if (Boolean.TRUE.equals(GepafinConstant.REPORT_COLUMNS.equals(settingName))) {
List<Map<String, Object>> reportColumns = (List<Map<String, Object>>) setting.getValue();
if (reportColumns != null) {
for (Map<String, Object> col : reportColumns) {
Boolean enableCsv = (Boolean) col.get(GepafinConstant.EBABLE_CSV);
if (Boolean.TRUE.equals(enableCsv)) {
String id = String.valueOf(col.get(GepafinConstant.NAME));
String fieldCsvLabel = col.get(GepafinConstant.LABEL_CSV) != null
? String.valueOf(col.get(GepafinConstant.LABEL_CSV))
: String.valueOf(col.get(GepafinConstant.LABEL));
fieldLabelMap.put(id, fieldCsvLabel);
if (Boolean.TRUE.equals(col.get(GepafinConstant.PREDEFINED))) {
predefinedIds.add(id);
} else {
dynamicIds.add(id);
}
}
}
}
}
}
if (predefinedIds.isEmpty()) {
return null;
}
for (Map<String, Object> row : rows) {
String prefix = predefinedIds.stream()
.map(id -> String.valueOf(row.getOrDefault(id, "")))
.filter(s -> !s.isBlank())
.findFirst().orElse("");
for (String dynId : dynamicIds) {
String dynLabel = fieldLabelMap.get(dynId);
for (String preId : predefinedIds.isEmpty() ? List.of("") : predefinedIds) {
String preLabel = fieldLabelMap.get(preId);
String key = dynLabel + " " + (preLabel != null ? preLabel + " " : "") + prefix;
result.put(key, String.valueOf(row.getOrDefault(dynId, "")));
}
}
}
// Add totals for numeric formula-enabled columns
for (String dynId : numericFormulaIds) {
double sum = rows.stream()
.mapToDouble(r -> {
try {
return Double.parseDouble(String.valueOf(r.getOrDefault(dynId, "0")));
} catch (NumberFormatException e) {
return 0.0;
}
}).sum();
String dynLabel = fieldLabelMap.get(dynId);
result.put("TOTAL " + dynLabel, String.valueOf(sum));
}
return result;
}
private void prepareTableFieldData(
List<ApplicationFormView> results,
Set<String> tableFieldIds,
Map<String, List<String>> tableHeadersByFieldId,
Map<Long, Map<String, String>> tableDataByApp) {
if (tableFieldIds.isEmpty()) return;
Map<Long, List<ApplicationFormView>> groupedByApp = results.stream()
.filter(r -> tableFieldIds.contains(r.getFieldId()))
.collect(Collectors.groupingBy(ApplicationFormView::getApplicationId));
for (Map.Entry<Long, List<ApplicationFormView>> entry : groupedByApp.entrySet()) {
Long appId = entry.getKey();
Map<String, String> flattenedAll = new LinkedHashMap<>();
for (ApplicationFormView row : entry.getValue()) {
formRepository.findById(row.getFormId()).ifPresent(form -> {
List<ContentResponseBean> contentList = Utils.convertJsonStringToList(form.getContent(), ContentResponseBean.class);
ContentResponseBean content = contentList.stream()
.filter(c -> c.getId().equals(row.getFieldId()))
.findFirst()
.orElse(null);
if (content == null) return;
content.getSettings().stream()
.filter(setting -> GepafinConstant.TABLE_COLUMNS.equals(setting.getName())
|| GepafinConstant.CRITERIA_TABLE_COLUMNS.equals(setting.getName()))
.findFirst()
.ifPresent(setting -> {
Map<String, String> flattened = extractTableData(
row.getFieldType(),
content,
row.getFieldValue()
);
if (flattened != null) {
tableHeadersByFieldId.putIfAbsent(row.getFieldId(), new ArrayList<>(flattened.keySet()));
flattenedAll.putAll(flattened);
}
});
});
}
tableDataByApp.put(appId, flattenedAll);
}
}
public ApplicationResponse readmitApplication(HttpServletRequest request, Long applicationId) {
log.info("Re-admiting the Application with id : {}", applicationId);
ApplicationEntity applicationEntity = fetchRejectedApplication(applicationId);
if(applicationEntity == null){
throw new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG));
}
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationEntity.getId())
.ifPresent(assignedApp -> processAssignedAppAndEvaluation(request, applicationEntity, assignedApp));
return getApplicationResponse(applicationEntity);
}
private ApplicationEntity fetchRejectedApplication(Long applicationId) {
return applicationRepository.findByIdAndStatusAndIsDeletedFalse(applicationId, ApplicationStatusTypeEnum.REJECTED.getValue());
}
private void processAssignedAppAndEvaluation(HttpServletRequest request, ApplicationEntity applicationEntity, AssignedApplicationsEntity assignedApp) {
applicationEvaluationRepository.findByAssignedApplicationsEntity_IdAndIsDeletedFalse(assignedApp.getId())
.ifPresent(eval -> reopenApplication(request, applicationEntity, assignedApp, eval));
}
private void reopenApplication(HttpServletRequest request, ApplicationEntity applicationEntity,
AssignedApplicationsEntity assignedApp, ApplicationEvaluationEntity evaluationEntity) {
ApplicationEntity oldApplication = Utils.getClonedEntityForData(applicationEntity);
AssignedApplicationsEntity oldAssignedApp = Utils.getClonedEntityForData(assignedApp);
ApplicationEvaluationEntity oldEvaluation = Utils.getClonedEntityForData(evaluationEntity);
updateApplicationStatus(applicationEntity);
updateAssignedApplicationStatus(assignedApp);
updateEvaluationEntity(applicationEntity.getHubId(), evaluationEntity);
saveEntities(applicationEntity, assignedApp, evaluationEntity);
/** This code is responsible for adding a version history log for the "Update Application" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplication).newData(applicationEntity).build());
/** This code is responsible for adding a version history log for the "Update Application Evaluation" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldEvaluation).newData(evaluationEntity).build());
/** This code is responsible for adding a version history log for the "Update Assigned Application" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApp).newData(assignedApp).build());
}
private void updateApplicationStatus(ApplicationEntity applicationEntity) {
applicationEntity.setStatus(ApplicationStatusTypeEnum.EVALUATION.getValue());
applicationEntity.setDateRejected(null);
}
private void updateAssignedApplicationStatus(AssignedApplicationsEntity assignedApp) {
assignedApp.setStatus(AssignedApplicationEnum.OPEN.getValue());
}
private void updateEvaluationEntity(Long hubId, ApplicationEvaluationEntity evaluationEntity) {
HubEntity hub = hubService.valdateHub(hubId);
Long evaluationDays = (hub != null) ? hub.getEvaluationExpirationDays() : 30L;
LocalDateTime now = DateTimeUtil.DateServerToUTC(LocalDateTime.now());
evaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.OPEN.getValue());
evaluationEntity.setClosingDate(null);
evaluationEntity.setActiveDays(null);
evaluationEntity.setEndDate(now.plusDays(evaluationDays));
evaluationEntity.setStartDate(now);
evaluationEntity.setRemainingDays(evaluationDays);
evaluationEntity.setSuspendedDays(0L);
evaluationEntity.setStopDateTime(null);
}
private void saveEntities(ApplicationEntity app, AssignedApplicationsEntity assignedApp, ApplicationEvaluationEntity eval) {
applicationRepository.save(app);
assignedApplicationsRepository.save(assignedApp);
applicationEvaluationRepository.save(eval);
}
public void sendApplicationSubmissionFailureEmail(EmailLogEntity emailLogEntity){
Long callId = emailLogEntity.getCallId();
CallEntity call = callService.validateCall(callId);
HubEntity hub = call.getHub();
Long userId = emailLogEntity.getUserId();
UserEntity user = userService.validateUser(userId);
Long applicationId = emailLogEntity.getApplicationId();
ApplicationEntity applicationEntity = validateApplication(applicationId);
CompanyEntity company = companyService.validateCompany(applicationEntity.getCompanyId());
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
.retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_FAILURE_NOTIFICATION,
hub, null);
Map<String, String> subjectPlaceholders = new HashMap<>();
subjectPlaceholders.put("{{call_name}}", call.getName());
Map<String, String> bodyPlaceholders = new HashMap<>();
bodyPlaceholders.put("{{scenario}}",emailLogEntity.getEmailType());
bodyPlaceholders.put("{{call_name}}", call.getName());
bodyPlaceholders.put("{{application_id}}", applicationEntity.getId().toString());
bodyPlaceholders.put("{{company_name}}", company.getCompanyName());
String protocolNumber=applicationEntity.getProtocol().getExternalProtocolNumber();
if(protocolNumber==null){
protocolNumber= String.valueOf(applicationEntity.getProtocol().getProtocolNumber());
}
bodyPlaceholders.put("{{protocol_number}}", protocolNumber);
bodyPlaceholders.put("{{user_action_id}}",emailLogEntity.getUserAction().getId().toString());
String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders);
String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders);
EmailLogRequest emailLogRequest=emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(),RecipientTypeEnum.PROPERTIES,null,user.getEmail(),user.getId(),applicationEntity.getId(),null,callId,subject,body);
emailLogRequest.setRecipientEmails(GepafinConstant.RINALDO_EMAIL);
EmailLogEntity newEmailLogEntity=emailLogDao.createEmailLog(emailLogRequest,null);
emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(GepafinConstant.RINALDO_EMAIL),newEmailLogEntity);
}
public byte[] downloadRankingCsv(Long callId,UserEntity userEntity) {
CallEntity callEntity = validator.validateUserWithCall(userEntity,callId);
List<ApplicationEntity> applications =
applicationRepository.findByCallIdAndIsDeletedFalseAndStatusIn(
callId,
List.of(
ApplicationStatusForEvaluation.APPROVED.getValue(),
ApplicationStatusForEvaluation.ADMISSIBLE.getValue(),
ApplicationStatusForEvaluation.TECHNICAL_EVALUATION.getValue()
));
List<String> dynamicLabels = new ArrayList<>(); // Maintain insertion order, allow duplicates only once
Map<Long, Map<String, String>> appLabelScoresMap = new HashMap<>();
Map<Long, ApplicationEntity> applicationMap = new HashMap<>();
Map<Long, String> appTotalScoreMap = new HashMap<>();
Map<Long, String> appInstructorMap = new HashMap<>(); // New map to store instructor name per app
for (ApplicationEntity app : applications) {
Long appId = app.getId();
applicationMap.put(appId, app);
ApplicationEvaluationEntity evaluation =
applicationEvaluationRepository.findByApplicationId(appId);
if (evaluation != null && evaluation.getAssignedApplicationsEntity() != null) {
Long userId = evaluation.getAssignedApplicationsEntity().getUserId();
if (userId != null) {
userRepository.findById(userId).ifPresent(user -> {
String firstName = user.getFirstName() != null ? user.getFirstName() : "";
String lastName = user.getLastName() != null ? user.getLastName() : "";
appInstructorMap.put(appId, firstName + " " + lastName);
});
}
}
BigDecimal totalScore = applicationEvaluationDao.calculateTotalScore(evaluation.getCriteria());
appTotalScoreMap.put(appId, Utils.convertToItalianFormatWithOnlyDecimalValue(String.valueOf(totalScore)));
List<CriteriaResponse> criteriaList =
evaluation.getCriteria() != null ?
Utils.convertJsonToList(evaluation.getCriteria(), new TypeReference<List<CriteriaResponse>>() {}) :
List.of();
List<CriteriaResponse> dbCriteriaList = applicationEvaluationDao.getCriteriaResponse(appId);
Map<String, String> scoreByLabel = new HashMap<>();
for (CriteriaResponse criteria : criteriaList) {
Optional<CriteriaResponse> matchedDb = dbCriteriaList.stream()
.filter(db -> Objects.equals(db.getId(), criteria.getId()))
.findFirst();
String label = matchedDb.map(CriteriaResponse::getLabel).orElse("");
if (!dynamicLabels.contains(label)) {
dynamicLabels.add(label);
}
String criteriaScore= String.valueOf(criteria.getScore() != null ? criteria.getScore() : BigDecimal.ZERO);
scoreByLabel.put(label, Utils.convertToItalianFormatWithOnlyDecimalValue(criteriaScore));
}
appLabelScoresMap.put(appId, scoreByLabel);
}
// Build headers dynamically
List<String> headers = new ArrayList<>(List.of(
"ApplicationID","Application VatNumber", "VatNumber", "Company Name", "Protocol", "Requested Amount", "Status","Instructor Name","Application PEC","Company PEC","Total Score"
));
headers.addAll(dynamicLabels);
// Prepare data rows
List<List<Object>> rows = new ArrayList<>();
for (ApplicationEntity app : applications) {
Long appId = app.getId();
CompanyEntity company = companyService.validateCompany(app.getCompanyId());
ProtocolEntity protocolEntity = app.getProtocol();
List<Object> row = new ArrayList<>();
row.add(appId);
row.add(app.getVatNumber());
row.add(company.getVatNumber());
row.add(company.getCompanyName());
row.add(protocolEntity != null ? protocolEntity.getProtocolNumber() : 0L);
String formattedAmount=Utils.convertToItalianFormatWithOnlyDecimalValue(String.valueOf(app.getAmountRequested()));
row.add(formattedAmount);
row.add(app.getStatus());
row.add(appInstructorMap.getOrDefault(appId, ""));
row.add(app.getPecEmail());
row.add(company.getPec());
row.add(appTotalScoreMap.get(appId));
Map<String, String> scores = appLabelScoresMap.getOrDefault(appId, Collections.emptyMap());
for (String label : dynamicLabels) {
row.add(scores.getOrDefault(label, ""));
}
rows.add(row);
}
// Generate CSV
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
CSVPrinter csvPrinter = new CSVPrinter(writer,
CSVFormat.DEFAULT
.withDelimiter(';')
.withHeader(headers.toArray(new String[0])))) {
for (List<Object> row : rows) {
csvPrinter.printRecord(row);
}
csvPrinter.flush();
} catch (IOException e) {
throw new RuntimeException("Error while generating CSV", e);
}
return out.toByteArray();
}
private List<DocumentEntity> fetchContractDocuments(Long applicationId) {
log.info("Fetching contract documents for applicationId: {}", applicationId);
ApplicationContractEntity applicationContractEntity=applicationContractRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
List<DocumentEntity> documentEntities=new ArrayList<>();
if(applicationContractEntity!=null){
Long contractId = applicationContractEntity.getId();
log.debug("Found contract entity with id: {}", contractId);
List<DocumentEntity> communicationDocuments= documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(Collections.singleton(contractId), DocumentSourceTypeEnum.CONTRACT.getValue());
documentEntities.addAll(communicationDocuments);
return documentEntities;
}
return Collections.emptyList();
}
public void uploadCompanyDocumentsToApplication( Long applicationId,List<Long> companyDocumentIds,UserEntity user) {
ApplicationEntity applicationEntity=validateApplication(applicationId);
ApplicationEntity oldApplication = Utils.getClonedEntityForData(applicationEntity);
List<CompanyDocumentEntity> companyDocumentEntities=validateCompanyDocuments(companyDocumentIds);
List<MultipartFile> multipartFiles=new ArrayList<>();
for(CompanyDocumentEntity companyDocumentEntity:companyDocumentEntities) {
try {
File localFile = appointmentDao.downloadFileFromS3(companyDocumentEntity.getFilePath());
MultipartFile multipartFile = appointmentDao.convertFileToMultipartFile(localFile);
multipartFiles.add(multipartFile);
} catch (Exception e) {
throw new RuntimeException(e);
}
List<DocumentResponseBean> documentResponseBeans=documentDao.uploadFiles(user.getId(),multipartFiles,applicationId,DocumentSourceTypeEnum.APPLICATION,DocumentTypeEnum.DOCUMENT);
List<Long> initialDocumentIds = documentResponseBeans.stream()
.map(DocumentResponseBean::getId)
.collect(Collectors.toList());
String initialDocumentId = initialDocumentIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
applicationEntity.setCompanyDocument(initialDocumentId);
applicationRepository.save(applicationEntity);
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplication).newData(applicationEntity).build());
}
}
public List<CompanyDocumentEntity> validateCompanyDocuments(List<Long> ids) {
List<CompanyDocumentEntity> documents =
companyDocumentRepository.findByIdInAndIsDeletedFalseAndStatusNot(ids,CompanyDocumentStatusEnum.EXPIRED.getValue());
Set<Long> foundIds = documents.stream()
.map(CompanyDocumentEntity::getId)
.collect(Collectors.toSet());
List<Long> missingIds = ids.stream()
.filter(id -> !foundIds.contains(id))
.toList();
if (!missingIds.isEmpty()) {
log.warn("Company Document(s) not found with IDs {}", missingIds);
throw new ResourceNotFoundException(
Status.NOT_FOUND,
MessageFormat.format(
Translator.toLocale(GepafinConstant.COMPANY_DOCUMENT_NOT_FOUND_WITH_IDS),
missingIds
));
}
return documents;
}
}