package net.gepafin.tendermanagement.dao; import java.util.*; import java.util.stream.Collectors; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CompanyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.enums.FormActionEnum; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; @Component public class FlowFormDao { @Autowired private FlowEdgesRepository flowEdgesRepository; @Autowired private FlowDataRepository flowDataRepository; @Autowired private ApplicationFormFieldRepository applicationFormFieldRepository; @Autowired private ApplicationFormRepository applicationFormRepository; @Autowired private ApplicationDao applicationDao; @Autowired private FormService formService; @Autowired private FormDao formDao; @Autowired private CompanyService companyService; // Long getNextForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // // vlaidation if next form findout and cuuent from is not fill the give error // List flowEdgesList = flowEdgesRepository.findBySourceIdAndCallId(currentFormEntity.getId(), applicationEntity.getCall().getId()); // ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), currentFormEntity.getId()); // if(applicationFormEntity == null) { // throw new CustomValidationException(Status.VALIDATION_ERROR, // Translator.toLocale("current form is not fill")); // } // if(flowEdgesList.isEmpty()) { // throw new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.NEXT_FORM_NOT_FOUND)); // } else if(flowEdgesList.size() == 1) { // return flowEdgesList.get(0).getTargetId(); // } else { // List nextFormIds = flowEdgesList.stream().map(FlowEdgesEntity::getTargetId).toList(); // FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndCallId(currentFormEntity.getId(), applicationEntity.getCall().getId()); // // ApplicationFormFieldEntity applicationFormFieldEntity = applicationFormFieldRepository // .findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId(flowDataEntity.getChoosenField(), // currentFormEntity.getId(), applicationEntity.getId()).orElseThrow(()-> new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.NEXT_FORM_NOT_FOUND))); // // flowDataEntity = flowDataRepository.findByChoosenValueAndFormIdIn(applicationFormFieldEntity.getFieldValue(), nextFormIds).orElseThrow(()-> new NullPointerException()); // return flowDataEntity.getFormId(); // } // } // // // Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // // // Step 1: Find all edges where the current form is the target (i.e., reverse flow) // List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( // currentFormEntity.getId(), applicationEntity.getCall().getId()); // // if (flowEdgesList.isEmpty()) { // // If no previous edges are found, return null or handle this case based on your needs // throw new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); // } // // // Step 2: If only one edge exists, return the source (previous) form ID directly have to look into it // if (flowEdgesList.size() == 1) { // return flowEdgesList.get(0).getSourceId(); // } // List previousFormIds = flowEdgesList.stream().map(FlowEdgesEntity::getSourceId).toList(); // // // // Step 3: Try to find flow data for the current form. If not found, we know it's the last step (or no field filtering is needed). // List flowDataList = flowDataRepository.findByFormIdInAndCallId( // previousFormIds, applicationEntity.getCall().getId()); // // List fieldValue = flowDataList.stream().map(FlowDataEntity::getChoosenValue).toList(); // //// if (flowDataEntity == null || flowDataEntity.getChoosenField() == null) { //// // If flow data is not found, simply return the first matching previous form //// return flowEdgesList.get(0).getSourceId(); // You can modify this logic if needed //// } // // // Step 4: Fetch the field value from the application form fields // Set formList = applicationFormFieldRepository // .findByFieldValueInAndAndApplicationFormApplicationId( // fieldValue, applicationEntity.getId()).stream().map(applicationFormFieldEntity->applicationFormFieldEntity.getApplicationForm().getForm()).collect(Collectors.toSet()); // // List fieldIds = formList.stream().map(formEntity->getNextForm(formEntity, applicationEntity)).toList(); // for(Long formId:previousFormIds) { // fieldIds.contains(formId); // return formId; // } // return null; //// .orElseThrow(() -> new NullPointerException("Field value not found for the current form and application.")); // // //// // Step 5: Check if there's a matching previous form based on the chosen value //// FlowDataEntity previousFlowDataEntity = flowDataRepository.findByChoosenValueAndFormIdIn( //// applicationFormFieldEntity.getFieldValue(), flowEdgesList.stream().map(FlowEdgesEntity::getSourceId).toList()) //// .orElse(null); // If no matching form is found, return null or the first source form //// //// // Step 6: Return the formId of the matching previous form, or the first one if no specific match is found //// return previousFlowDataEntity != null ? previousFlowDataEntity.getFormId() : flowEdgesList.get(0).getSourceId(); // } public Long getNextForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // Validate if the current form has been filled ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId( applicationEntity.getId(), currentFormEntity.getId()); // Retrieve the flow edges for the next forms List flowEdgesList = flowEdgesRepository.findBySourceIdAndCallId( currentFormEntity.getId(), applicationEntity.getCall().getId()); if (flowEdgesList.isEmpty()) { return null; // throw new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.NEXT_FORM_NOT_FOUND)); } // If only one edge exists, return the target form ID if (flowEdgesList.size() == 1) { return flowEdgesList.get(0).getTargetId(); } if (applicationFormEntity == null) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.CURRENT_FORM_INCOMPLETE)); } // For multiple edges, find the next form based on the chosen value List nextFormIds = flowEdgesList.stream() .map(FlowEdgesEntity::getTargetId) .toList(); // Retrieve the flow data for the current form FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndCallId( currentFormEntity.getId(), applicationEntity.getCall().getId()); // Fetch the application form field related to the chosen field ApplicationFormFieldEntity applicationFormFieldEntity = applicationFormFieldRepository .findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId( flowDataEntity.getChoosenField(), currentFormEntity.getId(), applicationEntity.getId()).orElse(null); // Find the next form based on the chosen value and return its ID return flowDataRepository.findByChoosenValueAndFormIdIn( applicationFormFieldEntity.getFieldValue(), nextFormIds) .map(FlowDataEntity::getFormId) .orElse(null); } public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // Retrieve the flow edges for the previous forms List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( currentFormEntity.getId(), applicationEntity.getCall().getId()); if (flowEdgesList.isEmpty()) { return null; // throw new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); } // If only one edge exists, return the source form ID if (flowEdgesList.size() == 1) { return flowEdgesList.get(0).getSourceId(); } // For multiple edges, find the previous form based on the chosen value List previousFormIds = flowEdgesList.stream() .map(FlowEdgesEntity::getSourceId) .toList(); // Fetch the flow data based on previous form IDs List flowDataList = flowDataRepository.findByFormIdInAndCallId( previousFormIds, applicationEntity.getCall().getId()); List chosenValues = flowDataList.stream() .map(FlowDataEntity::getChoosenValue) .toList(); // Fetch the previous forms based on the chosen field values Set formList = applicationFormFieldRepository .findByFieldValueInAndApplicationFormApplicationId(chosenValues, applicationEntity.getId()).stream() .map(fieldEntity -> fieldEntity.getApplicationForm().getForm()) .collect(Collectors.toSet()); // Find next form IDs recursively for all forms in the formList List fieldIds = formList.stream() .map(formEntity -> getNextForm(formEntity, applicationEntity)) .toList(); // Return the first matching previous form ID that corresponds to a next form return previousFormIds.stream() .filter(fieldIds::contains) .findFirst().orElse(null); } // public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // // List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( // currentFormEntity.getId(), applicationEntity.getCall().getId()); // // if (flowEdgesList.isEmpty()) { // return null; //// throw new ResourceNotFoundException(Status.NOT_FOUND, //// Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); // } // // // // If only one edge exists, return the source form ID // // if (flowEdgesList.size() == 1) { // // return flowEdgesList.get(0).getSourceId(); // // } // // // For multiple edges, find the previous form based on the chosen value // List previousFormIds = flowEdgesList.stream() // .map(FlowEdgesEntity::getSourceId) // .toList(); // if (previousFormIds.size() == 1) { // return previousFormIds.get(0); // } // // List applicationFormEntities=applicationFormRepository.findByFormIdInAndApplicationId(previousFormIds,applicationEntity.getId()); // applicationFormEntities.sort(Comparator.comparing(ApplicationFormEntity::getCreatedDate).reversed()); // // return applicationFormEntities.isEmpty() ? null : applicationFormEntities.get(0).getForm().getId(); // } public NextOrPreviousFormResponse getNextOrPreviousForm(ApplicationEntity applicationEntity,Long companyId, Long formId, FormActionEnum action) { Long calculatedFormId = null; FormEntity formEntity = null; if (formId == null) { calculatedFormId = getDefaultForm(applicationEntity); } else { if(action==null) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.ACTION_REQUIRED)); } // formEntity = Optional // .ofNullable(applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formId)) // .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.APPLICATION_FORM_NOT_FOUND))) // .getForm(); formEntity = formService.validateForm(formId); if (action.equals(FormActionEnum.NEXT)) { calculatedFormId = getNextForm(formEntity, applicationEntity); } else { calculatedFormId = getPreviousForm(formEntity, applicationEntity); } } NextOrPreviousFormResponse nextOrPreviousFormResponse = null; if (calculatedFormId == null && formId == null) { FormEntity form=formService.validateForm(applicationEntity.getCall().getInitialForm()); calculatedFormId=form.getId(); } if (calculatedFormId == null) { calculatedFormId=formId; } nextOrPreviousFormResponse = setNextOrPreviousResponse(calculatedFormId, applicationEntity); return nextOrPreviousFormResponse; } private NextOrPreviousFormResponse setNextOrPreviousResponse(Long calculatedFormId, ApplicationEntity applicationEntity) { NextOrPreviousFormResponse nextOrPreviousFormResponse = new NextOrPreviousFormResponse(); Integer completedSteps=0; CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId()); FormEntity formEntity = formService.validateForm(calculatedFormId); nextOrPreviousFormResponse.setFormId(calculatedFormId); nextOrPreviousFormResponse.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(applicationEntity.getStatus())); nextOrPreviousFormResponse.setApplicationFormResponse( applicationDao.processForm(formEntity, applicationEntity)); nextOrPreviousFormResponse.setCallId(applicationEntity.getCall().getId()); nextOrPreviousFormResponse.setCallTitle(applicationEntity.getCall().getName()); nextOrPreviousFormResponse.setCallEndDate(applicationEntity.getCall().getEndDate()); nextOrPreviousFormResponse.setCallEndTime(applicationEntity.getCall().getEndTime()); nextOrPreviousFormResponse.setCompanyId(applicationEntity.getCompanyId()); nextOrPreviousFormResponse.setCompanyName(company.getCompanyName()); List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = calculateTotalSteps(flowEdgesList); Long currentStep = calculateCurrentStep(flowEdgesList, formEntity); nextOrPreviousFormResponse.setTotalFormSteps(totalFormSteps); completedSteps = getCompletedSteps(applicationEntity, false); nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(completedSteps)); nextOrPreviousFormResponse.setCurrentStep(currentStep); if(applicationEntity.getProtocol() != null) { nextOrPreviousFormResponse.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); } nextOrPreviousFormResponse.setAmountAccepted(applicationEntity.getAmountAccepted()); nextOrPreviousFormResponse.setAmountRequested(applicationEntity.getAmountRequested()); nextOrPreviousFormResponse.setDateAccepted(applicationEntity.getDateAccepted()); nextOrPreviousFormResponse.setDateRejected(applicationEntity.getDateRejected()); return nextOrPreviousFormResponse; } public Integer getCompletedSteps(ApplicationEntity applicationEntity, Boolean isSendValidationError) { Integer completedSteps=0; List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); List applicationFormFieldEntities=new ArrayList<>(); for (ApplicationFormEntity applicationFormEntity:applicationFormList){ applicationFormFieldEntities=applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()); Boolean isCompleted=formDao.validateCompletedSteps(applicationFormFieldEntities, applicationEntity, applicationFormEntity.getForm(), isSendValidationError); if(Boolean.TRUE.equals(isCompleted)){ completedSteps++; } } return completedSteps; } public Long calculateCurrentStep(List flowEdgesList, FormEntity formEntity) { Long currentStep = 2l; if (formEntity.getId().equals(formEntity.getCall().getInitialForm())) { currentStep = 1l; } else if (flowEdgesList.size()>1 && formEntity.getId().equals(formEntity.getCall().getFinalForm())) { currentStep = 3l; } return currentStep; } public Long calculateTotalSteps(List flowEdgesList) { Long totalFormSteps = 3l; if (flowEdgesList.size() == 1) { totalFormSteps = 2l; } return totalFormSteps; } private Long getDefaultForm(ApplicationEntity applicationEntity) { List applicationFormList = applicationFormRepository.findByApplicationIdOrderByCreatedDateAsc(applicationEntity.getId()); if (applicationFormList.isEmpty()) { return applicationEntity.getCall().getInitialForm(); } if (applicationFormList.get(applicationFormList.size() - 1).getForm().getId().equals(applicationEntity.getCall().getFinalForm())) { return applicationEntity.getCall().getInitialForm(); } FormEntity currentFormEntity = applicationFormList.get(applicationFormList.size() - 1).getForm(); for (ApplicationFormEntity applicationFormEntity : applicationFormList) { Boolean isCompleted = formDao.validateCompletedSteps(applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()), applicationEntity, applicationFormEntity.getForm(), false); if (Boolean.FALSE.equals(isCompleted)) { return applicationFormEntity.getForm().getId(); } } return getNextForm(currentFormEntity, applicationEntity); } }