Merge pull request #18 from Kitzanos/feature/GEPAFINBE-21

GEPAFINBE-21(Implemented Application Management Tables and CRUD Operations)
This commit is contained in:
rajeshkhore
2024-09-15 12:20:46 +05:30
committed by GitHub
35 changed files with 1503 additions and 5 deletions

View File

@@ -108,5 +108,25 @@ public class GepafinConstant {
public static final String FLOW_FETCHED_SUCCESSFULLY="flow.fetched.successfully";
public static final String FLOW_ALREADY_EXISTS="flow.already.exists";
public static final String FLOW_REQUEST_NOT_PROPER="flow.request.not.complete";
public static final String APPLICATION_CREATED_SUCCESS_MSG = "application.created.success";
public static final String APPLICATION_UPDATED_SUCCESS_MSG = "application.updated.success";
public static final String DELETE_APPLICATION_SUCCESS_MSG = "application.deleted.success";
public static final String GET_APPLICATION_SUCCESS_MSG = "application.get.success";
public static final String APPLICATION_NOT_FOUND_MSG = "application.not.found";
public static final String APPLICATION_FORM_FIELD_NOT_FOUND="application.form.field.not.found";
public static final String FORM_ID_DOES_NOT_MACTHES="Form.not.matches.to.call.initial.form";
public static final String VALIDATION_FIELD_REQUIRED = "validation.field.required";
public static final String VALIDATION_FIELD_MIN_LENGTH = "validation.field.min_length";
public static final String VALIDATION_FIELD_MAX_LENGTH = "validation.field.max_length";
public static final String VALIDATION_FIELD_PATTERN = "validation.field.pattern";
public static final String VALIDATION_FIELD_NOT_NULL = "validation.field.not_null";
public static final String VALIDATION_FIELD_NOT_EMPTY = "validation.field.not_empty";
public static final String APPLICATION_ALREADY_EXISTS="application.already.exists";
// public static final String NEXT_FORM_NOT_FOUND = "next.form.not.found";
// public static final String PREVIOUS_FORM_NOT_FOUND = "previous.form.not.found";
public static final String CURRENT_FORM_INCOMPLETE = "current.form.incomplete";
public static final String FLOW_NOT_FOUND = "flow.not.found";
}

View File

@@ -0,0 +1,321 @@
package net.gepafin.tendermanagement.dao;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
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.response.*;
import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository;
import net.gepafin.tendermanagement.repositories.ApplicationFormRepository;
import net.gepafin.tendermanagement.repositories.ApplicationRepository;
import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.service.FormService;
import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class ApplicationDao {
private final Logger log = LoggerFactory.getLogger(ApplicationDao.class);
@Autowired
private CallService callService;
@Autowired
private ApplicationRepository applicationRepository;
@Autowired
private ApplicationFormRepository applicationFormRepository;
@Autowired
private ApplicationFormFieldRepository applicationFormFieldRepository;
@Autowired
private FormService formService;
@Autowired
private FormDao formDao;
public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId) {
FormEntity formEntity = formService.validateForm(formId);
CallEntity call = callService.validateCall(formEntity.getCall().getId());
ApplicationEntity applicationEntity = getApplicationOrCreate(userEntity, call, formEntity);
formService.validateFormField(applicationRequestBean.getFormFields(),applicationEntity,formEntity);
ApplicationFormEntity applicationFormEntity = getApplicationFormOrCreate(formEntity, applicationEntity);
createOrUpdateMultipleFormFields(applicationRequestBean.getFormFields(), applicationFormEntity);
return getApplicationById(applicationEntity.getId(),formEntity.getId());
}
public ApplicationFormEntity saveApplicationFormEntity(ApplicationFormEntity applicationFormEntity) {
ApplicationFormEntity applicationFormEntity1 = applicationFormRepository.save(applicationFormEntity);
return applicationFormEntity1;
}
public void validateFormId(FormEntity formEntity, CallEntity callEntity) {
if (Boolean.FALSE.equals(formEntity.getId().equals(callEntity.getInitialForm()))) {
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.FORM_ID_DOES_NOT_MACTHES));
}
}
public ApplicationFormEntity createApplicationFormEntity(ApplicationEntity application, FormEntity formEntity) {
ApplicationFormEntity applicationFormEntity = new ApplicationFormEntity();
applicationFormEntity.setApplication(application);
applicationFormEntity.setForm(formEntity);
applicationFormEntity = saveApplicationFormEntity(applicationFormEntity);
return applicationFormEntity;
}
public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call) {
ApplicationEntity entity = new ApplicationEntity();
entity.setUser(user);
entity.setCall(call);
entity.setIsDeleted(false);
entity.setStatus(ApplicationStatusTypeEnum.DRAFT.getValue());
return entity;
}
public ApplicationResponseBean getApplicationById(Long id,Long formId) {
log.info("Fetching application with ID: {}", id);
ApplicationEntity applicationEntity = validateApplication(id);
List<ApplicationFormEntity> applicationFormEntities = applicationFormRepository.findByApplicationId(applicationEntity.getId());
List<ApplicationFormFieldResponseBean> applicationFormFieldResponseBeans=new ArrayList<>();
ApplicationFormFieldResponseBean applicationFormFieldResponseBeans1=null;
for (ApplicationFormEntity applicationFormEntity:applicationFormEntities){
List<ApplicationFormFieldEntity> applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
for(ApplicationFormFieldEntity applicationFormFieldEntity:applicationFormFieldEntities) {
applicationFormFieldResponseBeans1 = convertApplicationFormFieldEntityToApplicationFormFieldResponseBean(applicationFormFieldEntity, applicationFormEntity.getId());
applicationFormFieldResponseBeans.add(applicationFormFieldResponseBeans1);
}
}
ApplicationResponseBean applicationResponseBean= convertApplicationEntityToApplicationResponseBean(applicationEntity);
applicationResponseBean.setFormFields(applicationFormFieldResponseBeans);
applicationResponseBean.setCurrentFormId(formId);
return applicationResponseBean;
}
public void deleteById(Long id) {
log.info("Deleting application with ID: {}", id);
ApplicationEntity applicationEntity= validateApplication(id);
applicationEntity.setIsDeleted(true);
applicationEntity=saveApplicationEntity(applicationEntity);
log.info("Application deleted with ID: {}", id);
}
public List<ApplicationResponse> getAllApplications(UserEntity userEntity) {
log.info("Fetching all applications");
List<ApplicationResponse> applicationResponses=new ArrayList<>();
List<ApplicationEntity> applicationEntities = applicationRepository.findByUserIdAndIsDeletedFalse(userEntity.getId());
for(ApplicationEntity applicationEntity:applicationEntities){
ApplicationResponse responseBean = getApplicationResponse(applicationEntity);
applicationResponses.add(responseBean);
}
return applicationResponses;
}
private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) {
ApplicationResponse responseBean = new ApplicationResponse();
responseBean.setId(applicationEntity.getId());
responseBean.setCallId(applicationEntity.getCall().getId());
responseBean.setSubmissionDate(applicationEntity.getSubmissionDate());
responseBean.setStatus(applicationEntity.getStatus());
responseBean.setComments(applicationEntity.getComments());
return responseBean;
}
public ApplicationEntity validateApplication(Long id) {
ApplicationEntity applicationEntity= applicationRepository.findById(id).orElseThrow(() ->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());
return response;
}
public ApplicationEntity getApplicationOrCreate(UserEntity userEntity, CallEntity callEntity, FormEntity formEntity) {
ApplicationEntity applicationEntity = applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), callEntity.getId()).orElse(null);
if (applicationEntity == null) {
validateFormId(formEntity, callEntity);
applicationEntity = createApplicationEntity(userEntity, callEntity);
applicationEntity=saveApplicationEntity(applicationEntity);
}
return applicationEntity;
}
private ApplicationFormEntity getApplicationFormOrCreate(FormEntity formEntity, ApplicationEntity applicationEntity) {
ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formEntity.getId());
if(applicationFormEntity == null){
applicationFormEntity = createApplicationFormEntity(applicationEntity, formEntity);
}
return applicationFormEntity;
}
public List<ApplicationFormFieldEntity> createOrUpdateMultipleFormFields(List<ApplicationFormFieldRequestBean> formFieldResponseBeans, ApplicationFormEntity applicationFormEntity) {
List<ApplicationFormFieldEntity> applicationFormFieldEntity = formFieldResponseBeans.stream()
.map(requestBean -> createOrUpdateApplicationFormField(requestBean, applicationFormEntity))
.collect(Collectors.toList());
return applicationFormFieldEntity;
}
public ApplicationFormFieldEntity createOrUpdateApplicationFormField(ApplicationFormFieldRequestBean applicationFormFieldRequestBean, ApplicationFormEntity applicationFormEntity) {
ApplicationFormFieldEntity applicationFormFieldEntity;
if (applicationFormFieldRequestBean.getId() == null || applicationFormFieldRequestBean.getId() == 0) {
applicationFormFieldEntity = new ApplicationFormFieldEntity();
applicationFormFieldEntity.setApplicationForm(applicationFormEntity);
} else {
applicationFormFieldEntity = validateApplicationFormField(applicationFormFieldRequestBean.getId());
}
Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId());
Utils.setIfUpdated(applicationFormFieldEntity::getFieldValue, applicationFormFieldEntity::setFieldValue, applicationFormFieldRequestBean.getFieldValue());
return applicationFormFieldRepository.save(applicationFormFieldEntity);
}
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());
applicationFormFieldResponseBean.setFieldValue(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);
return applicationEntity;
}
public ApplicationGetResponseBean getApplicationByFormId( Long applicationId,Long formId, UserEntity userEntity) {
List<FormApplicationResponse> formApplicationResponses = new ArrayList<>();
List<FormEntity> formEntities = new ArrayList<>();
ApplicationEntity applicationEntity = applicationRepository.findById(applicationId)
.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.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(),
formEntity.getCall().getId());
applicationEntity=application.get();
formEntities.add(formEntity);
processForm(formEntity, applicationEntity, formApplicationResponses);
}
else {
List<ApplicationFormEntity> applicationFormEntities = applicationFormRepository.findByApplicationId(applicationEntity.getId());
for (ApplicationFormEntity applicationFormEntity : applicationFormEntities) {
FormEntity form = formService.validateForm(applicationFormEntity.getForm().getId());
formEntities.add(form);
processForm(form, applicationEntity, formApplicationResponses);
}
}
return createApplicationGetResponseBean(applicationEntity, formEntities, formApplicationResponses);
}
private void processForm(FormEntity formEntity, ApplicationEntity applicationEntity, List<FormApplicationResponse> formApplicationResponses) {
ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formEntity.getId());
if(applicationFormEntity!=null) {
List<ApplicationFormFieldEntity> applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
FormApplicationResponse formApplicationResponse = createFormApplicationResponse(formEntity);
List<ApplicationFormFieldResponseBean> applicationFormFieldResponseBeans = convertApplicationFormFieldEntitiesToApplicationFormFieldResponseBeans(applicationFormFieldEntities, applicationFormEntity.getId());
formApplicationResponse.setFormFields(applicationFormFieldResponseBeans);
formApplicationResponses.add(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());
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));
return formApplicationResponse;
}
public ApplicationResponse createApplicationByCallId(ApplicationRequest applicationRequest,Long callId,UserEntity userEntity){
CallEntity call=callService.validateCall(callId);
checkIfApplicationExists(call,userEntity);
ApplicationEntity applicationEntity=saveApplicationEntity(createApplicationEntity(userEntity,call));
ApplicationResponse applicationResponse=getApplicationResponse(applicationEntity);
return applicationResponse;
}
public void checkIfApplicationExists(CallEntity call,UserEntity userEntity){
Optional<ApplicationEntity> applicationEntity=applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(),call.getId());
if(applicationEntity.isPresent()){
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS));
}
}
public ApplicationEntity getApplicationByCallAndUser(CallEntity call, UserEntity userEntity) {
return applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId())
.orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)));
}
public void updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
applicationEntity.setStatus(status.getValue());
if(status.equals(ApplicationStatusTypeEnum.SUBMIT)) {
applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
}
saveApplicationEntity(applicationEntity);
}
}

View File

@@ -0,0 +1,255 @@
package net.gepafin.tendermanagement.dao;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
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.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.ApplicationFormEntity;
import net.gepafin.tendermanagement.entities.ApplicationFormFieldEntity;
import net.gepafin.tendermanagement.entities.FlowDataEntity;
import net.gepafin.tendermanagement.entities.FlowEdgesEntity;
import net.gepafin.tendermanagement.entities.FormEntity;
import net.gepafin.tendermanagement.enums.FormActionEnum;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository;
import net.gepafin.tendermanagement.repositories.ApplicationFormRepository;
import net.gepafin.tendermanagement.repositories.FlowDataRepository;
import net.gepafin.tendermanagement.repositories.FlowEdgesRepository;
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;
@Component
public class FlowFormDao {
@Autowired
private FlowEdgesRepository flowEdgesRepository;
@Autowired
private FlowDataRepository flowDataRepository;
@Autowired
private ApplicationFormFieldRepository applicationFormFieldRepository;
@Autowired
private ApplicationFormRepository applicationFormRepository;
// Long getNextForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) {
// // vlaidation if next form findout and cuuent from is not fill the give error
// List<FlowEdgesEntity> 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<Long> 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<FlowEdgesEntity> 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<Long> 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<FlowDataEntity> flowDataList = flowDataRepository.findByFormIdInAndCallId(
// previousFormIds, applicationEntity.getCall().getId());
//
// List<String> 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<FormEntity> formList = applicationFormFieldRepository
// .findByFieldValueInAndAndApplicationFormApplicationId(
// fieldValue, applicationEntity.getId()).stream().map(applicationFormFieldEntity->applicationFormFieldEntity.getApplicationForm().getForm()).collect(Collectors.toSet());
//
// List<Long> 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<FlowEdgesEntity> 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<Long> 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<FlowEdgesEntity> 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<Long> previousFormIds = flowEdgesList.stream()
.map(FlowEdgesEntity::getSourceId)
.toList();
// Fetch the flow data based on previous form IDs
List<FlowDataEntity> flowDataList = flowDataRepository.findByFormIdInAndCallId(
previousFormIds, applicationEntity.getCall().getId());
List<String> chosenValues = flowDataList.stream()
.map(FlowDataEntity::getChoosenValue)
.toList();
// Fetch the previous forms based on the chosen field values
Set<FormEntity> 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<Long> 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 NextOrPreviousFormResponse getnextOrPreviousForm(ApplicationEntity applicationEntity, Long formId,
FormActionEnum action) {
FormEntity fromEntity = null;
if(formId == null) {
NextOrPreviousFormResponse nextOrPreviousFormResponse = new NextOrPreviousFormResponse();
nextOrPreviousFormResponse.setNextFormId(getDefaultForm(applicationEntity));
return nextOrPreviousFormResponse;
}else {
fromEntity = Optional
.of(applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formId))
.orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.FORM_NOT_FOUND)))
.getForm();
}
NextOrPreviousFormResponse nextOrPreviousFormResponse = new NextOrPreviousFormResponse();
if (action.equals(FormActionEnum.NEXT)) {
nextOrPreviousFormResponse.setNextFormId(getNextForm(fromEntity, applicationEntity));
} else {
nextOrPreviousFormResponse.setPreviousFormId(getPreviousForm(fromEntity, applicationEntity));
}
return nextOrPreviousFormResponse;
}
private Long getDefaultForm(ApplicationEntity applicationEntity) {
List<ApplicationFormEntity> 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();
}
return getNextForm(applicationFormList.get(applicationFormList.size()-1).getForm(), applicationEntity);
}
}

View File

@@ -2,15 +2,18 @@ package net.gepafin.tendermanagement.dao;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.CallEntity;
import net.gepafin.tendermanagement.entities.FormEntity;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean;
import net.gepafin.tendermanagement.model.request.ContentRequestBean;
import net.gepafin.tendermanagement.model.request.FieldValidatorBean;
import net.gepafin.tendermanagement.model.request.FormRequest;
import net.gepafin.tendermanagement.model.response.ContentResponseBean;
import net.gepafin.tendermanagement.model.response.FormResponseBean;
import net.gepafin.tendermanagement.repositories.ApplicationFormRepository;
import net.gepafin.tendermanagement.repositories.FormRepository;
import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.FieldValidator;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
@@ -20,6 +23,7 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@@ -31,6 +35,9 @@ public class FormDao {
@Autowired
private CallService callService;
@Autowired
private ApplicationFormRepository applicationFormRepository;
public FormEntity saveFormEntity(FormEntity formEntity){
formEntity=formRepository.save(formEntity);
return formEntity;
@@ -101,4 +108,37 @@ public class FormDao {
public String setContentResponseBean(List<ContentRequestBean> contentRequestBeans){
return Utils.convertListToJsonString(contentRequestBeans);
}
public void validateFormField(List<ApplicationFormFieldRequestBean> applicationFormFieldRequestList, ApplicationEntity applicationEntity, FormEntity formEntity) {
Map<String, String> formFieldMap = applicationFormFieldRequestList.stream()
.collect(Collectors.toMap(ApplicationFormFieldRequestBean::getFieldId, ApplicationFormFieldRequestBean::getFieldValue));
FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity);
ApplicationFormEntity applicationFormEntity=applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formEntity.getId());
Boolean isApplicationFormExist= getApplicationFormExist(applicationFormEntity);
FieldValidator validator = FieldValidator.create();
formResponseBean.getContent().forEach(contentResponseBean -> {
String fieldId = contentResponseBean.getId();
String value = formFieldMap.get(fieldId);
if(value == null && isApplicationFormExist) {
return;
}
FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean, FieldValidatorBean.class);
validator
.notNull(value, fieldId)
.minLength(value, fieldValidatorBean.getMinLength(), fieldId) // Only applies if minLength is not null
.maxLength(value, fieldValidatorBean.getMaxLength(), fieldId) // Only applies if maxLength is not null
.matchesPattern(value, fieldValidatorBean.getPattern(), fieldId); // Only applies if pattern is present
});
validator.validate();
}
private Boolean getApplicationFormExist(ApplicationFormEntity applicationFormEntity) {
if(applicationFormEntity !=null) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,36 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "APPLICATION")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ApplicationEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "USER_ID", nullable = false)
private UserEntity user;
@Column(name = "SUBMISSION_DATE")
private LocalDateTime submissionDate;
@Column(name = "STATUS", length = 255)
private String status;
@Column(name = "COMMENTS", columnDefinition = "TEXT")
private String comments;
@ManyToOne
@JoinColumn(name = "CALL_ID", nullable = false)
private CallEntity call;
@Column(name="IS_DELETED")
private Boolean isDeleted;
}

View File

@@ -0,0 +1,20 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Table(name = "APPLICATION_FORM")
@Data
public class ApplicationFormEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "APPLICATION_ID", nullable = false)
private ApplicationEntity application;
@ManyToOne
@JoinColumn(name = "FORM_ID", nullable = false)
private FormEntity form;
}

View File

@@ -0,0 +1,27 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "APPLICATION_FORM_FIELD")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ApplicationFormFieldEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "APPLICATION_FORM_ID", nullable = false)
private ApplicationFormEntity applicationForm;
@Column(name = "FIELD_ID")
private String fieldId;
@Column(name = "FIELD_VALUE", length = 255)
private String fieldValue;
}

View File

@@ -0,0 +1,22 @@
package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum ApplicationStatusTypeEnum {
DRAFT("DRAFT"),
SUBMIT("SUBMIT"),
EXPIRED("EXPIRED"),
READY_TO_SUBMIT("READY_TO_SUBMIT");
private String value;
ApplicationStatusTypeEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
}

View File

@@ -0,0 +1,20 @@
package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum FormActionEnum {
NEXT("NEXT"),
PREVIOUS("PREVIOUS");
private String value;
FormActionEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
}

View File

@@ -0,0 +1,16 @@
package net.gepafin.tendermanagement.model.request;
import jakarta.persistence.Column;
import lombok.Data;
import net.gepafin.tendermanagement.entities.ApplicationFormEntity;
@Data
public class ApplicationFormFieldRequestBean {
private Long id;
private String fieldId;
private String fieldValue;
}

View File

@@ -0,0 +1,16 @@
package net.gepafin.tendermanagement.model.request;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ApplicationRequest {
private LocalDateTime submissionDate;
private String status;
private String comments;
}

View File

@@ -0,0 +1,13 @@
package net.gepafin.tendermanagement.model.request;
import jakarta.persistence.Column;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class ApplicationRequestBean {
private List<ApplicationFormFieldRequestBean> formFields;
}

View File

@@ -0,0 +1,18 @@
package net.gepafin.tendermanagement.model.request;
import lombok.Data;
@Data
public class FieldValidatorBean {
private Boolean isRequired;
private Long minLength;
private Long maxLength;
private String pattern;
private String custom;
}

View File

@@ -0,0 +1,16 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.model.BaseBean;
@Data
public class ApplicationFormFieldResponseBean extends BaseBean {
private Long id;
private Long applicationFormId;
private String fieldId;
private String fieldValue;
}

View File

@@ -0,0 +1,23 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.FormResponseBean;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class ApplicationGetResponseBean {
private Long id;
private LocalDateTime submissionDate;
private String status;
private String comments;
private List<FormApplicationResponse> form;
}

View File

@@ -0,0 +1,22 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.model.response.ApplicationFormFieldResponseBean;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class ApplicationResponse{
private Long id;
private Long callId;
private LocalDateTime submissionDate;
private String status;
private String comments;
}

View File

@@ -0,0 +1,25 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.model.BaseBean;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class ApplicationResponseBean extends BaseBean {
private Long callId;
private LocalDateTime submissionDate;
private String status;
private String comments;
private List<ApplicationFormFieldResponseBean> formFields;
private Long currentFormId;
private Long nextFormId;
}

View File

@@ -0,0 +1,21 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.model.response.ApplicationFormFieldResponseBean;
import net.gepafin.tendermanagement.model.response.ContentResponseBean;
import java.util.List;
@Data
public class FormApplicationResponse {
private Long id;
private String label;
private Long callId;
private List<ContentResponseBean> content;
private List<ApplicationFormFieldResponseBean> formFields;
}

View File

@@ -0,0 +1,12 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
@Data
public class NextOrPreviousFormResponse {
Long nextFormId;
Long previousFormId;
}

View File

@@ -0,0 +1,27 @@
package net.gepafin.tendermanagement.repositories;
import net.gepafin.tendermanagement.entities.ApplicationFormFieldEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface ApplicationFormFieldRepository extends JpaRepository<ApplicationFormFieldEntity,Long> {
public List<ApplicationFormFieldEntity> findByApplicationFormIdIn(List<Long> applicationFormIds);
public List<ApplicationFormFieldEntity> findByApplicationFormId(Long applicationFormId);
public Optional<ApplicationFormFieldEntity> findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId(
String fieldId, Long formId, Long applicationId);
public Optional<ApplicationFormFieldEntity> findByFieldValueInAndApplicationFormFormIdInAndApplicationFormApplicationId(
List<String> fieldValues, List<Long> previousFormIds, Long applicationId);
public List<ApplicationFormFieldEntity> findByFieldValueInAndApplicationFormApplicationId(
List<String> fieldValue, Long applicationId);
}

View File

@@ -0,0 +1,20 @@
package net.gepafin.tendermanagement.repositories;
import net.gepafin.tendermanagement.entities.ApplicationFormEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ApplicationFormRepository extends JpaRepository<ApplicationFormEntity, Long> {
public ApplicationFormEntity findByApplicationIdAndFormId(Long applicationId,Long formId);
List<ApplicationFormEntity> findByApplicationIdIn(List<Long> applicationIds);
public List<ApplicationFormEntity> findByApplicationId(Long applicationId);
public List<ApplicationFormEntity> findByApplicationIdOrderByCreatedDateAsc(Long applicationId);
}

View File

@@ -0,0 +1,22 @@
package net.gepafin.tendermanagement.repositories;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.FaqEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface ApplicationRepository extends JpaRepository<ApplicationEntity,Long> {
public Optional<ApplicationEntity> findByUserIdAndCallIdAndIsDeletedFalse(Long userId,Long callId);
public List<ApplicationEntity> findByUserIdAndIsDeletedFalse(Long userId);
@Query("SELECT a FROM ApplicationEntity a WHERE a.id = :id AND a.isDeleted = false")
Optional<ApplicationEntity> findById(@Param("id") Long id);
}

View File

@@ -5,9 +5,16 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface FlowDataRepository extends JpaRepository<FlowDataEntity,Long> {
public List<FlowDataEntity> findByCallId(Long callId);
public FlowDataEntity findByFormIdAndCallId(Long formId, Long callId);
public Optional<FlowDataEntity> findByChoosenValueAndFormIdIn(String fieldValue, List<Long> nextFormIds);
public List<FlowDataEntity> findByFormIdInAndCallId(List<Long> previousFormIds, Long callId);
}

View File

@@ -10,4 +10,8 @@ import java.util.List;
public interface FlowEdgesRepository extends JpaRepository<net.gepafin.tendermanagement.entities.FlowEdgesEntity,Long> {
public List<FlowEdgesEntity> findByCallId(Long callId);
public List<FlowEdgesEntity> findBySourceIdAndCallId(Long sourceId, Long callId);
public List<FlowEdgesEntity> findByTargetIdAndCallId(Long targetId, Long callId);
}

View File

@@ -0,0 +1,33 @@
package net.gepafin.tendermanagement.service;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.FormActionEnum;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import java.util.List;
public interface ApplicationService {
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId);
ApplicationGetResponseBean getApplicationByFormId(HttpServletRequest request, Long applicationId,Long formId);
List<ApplicationResponse> getAllApplications(HttpServletRequest request);
void deleteApplication(HttpServletRequest request, Long applicationId);
public ApplicationEntity validateApplication(Long userId);
public ApplicationResponse createApplication(HttpServletRequest request, ApplicationRequest applicationRequest, Long callId);
public NextOrPreviousFormResponse getnextOrPreviousForm(HttpServletRequest request, Long applicationId, Long formId, FormActionEnum action);
public void updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status);
}

View File

@@ -1,7 +1,10 @@
package net.gepafin.tendermanagement.service;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.FormEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean;
import net.gepafin.tendermanagement.model.request.FormRequest;
import net.gepafin.tendermanagement.model.response.FormResponseBean;
@@ -20,4 +23,6 @@ public interface FormService {
public FormEntity validateForm(Long id);
public List<FormResponseBean> getFormsByCallId(HttpServletRequest request,Long callId);
void validateFormField(List<ApplicationFormFieldRequestBean> formFields, ApplicationEntity applicationEntity, FormEntity formEntity);
}

View File

@@ -0,0 +1,92 @@
package net.gepafin.tendermanagement.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.dao.ApplicationDao;
import net.gepafin.tendermanagement.dao.FlowFormDao;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.FormEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.FormActionEnum;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.service.FormService;
import net.gepafin.tendermanagement.util.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class ApplicationServiceImpl implements ApplicationService {
@Autowired
private ApplicationDao applicationDao;
@Autowired
private FlowFormDao flowFormDao;
@Autowired
private FormService formService;
@Autowired
private Validator validator;
@Override
@Transactional(rollbackFor = Exception.class)
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId) {
UserEntity userEntity = validator.validateUser(request);
return applicationDao.createApplication(applicationRequestBean,userEntity,formId);
}
@Override
@Transactional(readOnly = true)
public ApplicationGetResponseBean getApplicationByFormId(HttpServletRequest request, Long applicationId,Long formId) {
UserEntity userEntity = validator.validateUser(request);
return applicationDao.getApplicationByFormId(applicationId,formId,userEntity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteApplication(HttpServletRequest request, Long applicationId) {
applicationDao.deleteById(applicationId);
}
@Override
public ApplicationEntity validateApplication(Long id) {
return applicationDao.validateApplication(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public ApplicationResponse createApplication(HttpServletRequest request, ApplicationRequest applicationRequest, Long callId) {
UserEntity userEntity = validator.validateUser(request);
return applicationDao.createApplicationByCallId(applicationRequest,callId,userEntity);
}
@Override
public NextOrPreviousFormResponse getnextOrPreviousForm(HttpServletRequest request, Long applicationId, Long formId,
FormActionEnum action) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
return flowFormDao.getnextOrPreviousForm(applicationEntity, formId, action);
}
@Override
public void updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) {
applicationDao.updateApplicationStatus(applicationId, status);
}
@Override
@Transactional(readOnly = true)
public List<ApplicationResponse> getAllApplications(HttpServletRequest request) {
UserEntity userEntity = validator.validateUser(request);
return applicationDao.getAllApplications(userEntity);
}
}

View File

@@ -2,7 +2,10 @@ package net.gepafin.tendermanagement.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.dao.FormDao;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.FormEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean;
import net.gepafin.tendermanagement.model.request.FormRequest;
import net.gepafin.tendermanagement.model.response.FormResponseBean;
import net.gepafin.tendermanagement.service.FormService;
@@ -47,4 +50,10 @@ public class FormServiceImpl implements FormService {
public List<FormResponseBean> getFormsByCallId(HttpServletRequest request, Long callId) {
return formDao.getFormsByCallId(callId);
}
@Override
public void validateFormField(List<ApplicationFormFieldRequestBean> formFields, ApplicationEntity applicationEntity, FormEntity formEntity) {
formDao.validateFormField(formFields,applicationEntity, formEntity);
}
}

View File

@@ -37,6 +37,26 @@ public class FieldValidator {
throw new ValidationException(Status.VALIDATION_ERROR, errors);
}
}
public FieldValidator minLength(String value, Long minLength, String fieldName) {
if (minLength != null && value != null && value.length() < minLength) {
errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_MIN_LENGTH), fieldName, minLength));
}
return this;
}
public FieldValidator maxLength(String value, Long maxLength, String fieldName) {
if (maxLength != null && value != null && value.length() > maxLength) {
errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_MAX_LENGTH), fieldName, maxLength));
}
return this;
}
public FieldValidator matchesPattern(String value, String pattern, String fieldName) {
if (value != null && pattern != null && !value.matches(pattern)) {
errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_PATTERN), fieldName));
}
return this;
}
public FieldValidator addError( String errorMessage) {
errors.add(errorMessage);

View File

@@ -5,12 +5,14 @@ import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.micrometer.common.util.StringUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
@@ -99,7 +101,13 @@ public class Utils {
}
public static <T> List<T> convertJsonStringToList(String jsonString, Class<T> clazz) {
try {
return mapper.readValue(jsonString, new TypeReference<List<T>>() {});
TypeReference<List<T>> typeRef = new TypeReference<List<T>>() {
@Override
public Type getType() {
return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz);
}
};
return mapper.readValue(jsonString, typeRef);
} catch (Exception e) {
e.printStackTrace();
// Handle the exception appropriately (e.g., throw a custom exception)
@@ -129,5 +137,14 @@ public class Utils {
}
return null;
}
public static <T, U> U convertSourceObjectToDestinationObject(T source, Class<U> destinationClass) {
try {
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.registerModule(new JavaTimeModule());
return mapper.convertValue(source, destinationClass);
} catch (Exception e) {
log.error("Error converting object: " + e.getMessage(), e);
}
return null;
}
}

View File

@@ -0,0 +1,132 @@
package net.gepafin.tendermanagement.web.rest.api;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.FormActionEnum;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
@Validated
public interface ApplicationApi {
@Operation(summary = "Api to create or update application",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PutMapping(value = "/form/{formId}",
produces = { "application/json" })
ResponseEntity<Response<ApplicationResponseBean>> createApplication(HttpServletRequest request,
@Parameter(description = " Flow request object", required = true) @Valid @RequestBody ApplicationRequestBean applicationRequestBean,
@Parameter(description = "The form ID", required = true) @PathVariable("formId") Long formId);
@Operation(summary = "Api to get an application by id",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "/{applicationId}", produces = "application/json")
ResponseEntity<Response<ApplicationGetResponseBean>> getApplicationByFormId(HttpServletRequest request, @Parameter(description = "The application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId,@Parameter(description = "The form id", required = false) @RequestParam(value = "formId",required = false) Long formId);
@Operation(summary = "Api to get all applications",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "", produces = "application/json")
ResponseEntity<Response<List<ApplicationResponse>>> getAllApplications(HttpServletRequest request);
@Operation(summary = "Api to delete application",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@DeleteMapping(value = "/{applicationId}")
ResponseEntity<Response<Void>> deleteApplication(HttpServletRequest request,
@Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId);
@Operation(summary = "Api to create application",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PostMapping(value = "/call/{callId}",
produces = { "application/json" })
ResponseEntity<Response<ApplicationResponse>> createApplicationByCallId(HttpServletRequest request,
@Parameter(description = " Flow request object", required = true) @Valid @RequestBody ApplicationRequest applicationRequest,
@Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId);
@Operation(summary = "Api to get an next or previous form by current form id",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "/{applicationId}/form/next-previous", produces = "application/json")
ResponseEntity<Response<NextOrPreviousFormResponse>> getnextOrPreviousForm(HttpServletRequest request,
@Parameter(description = "The applicaltion id", required = true) @PathVariable("applicationId") Long applicationId,
@Parameter(description = "The form id", required = false) @RequestParam(value = "formId", required = false) Long formId,
@RequestParam("action") FormActionEnum action);
@Operation(summary = "Api to update application status",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PutMapping(value = "/{applicationId}/status", produces = { "application/json" })
ResponseEntity<Response<Void>> updateApplicationStatus(HttpServletRequest request,
@Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId,
@Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) ApplicationStatusTypeEnum status);
}

View File

@@ -0,0 +1,92 @@
package net.gepafin.tendermanagement.web.rest.api.impl;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.FormActionEnum;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.web.rest.api.ApplicationApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.slf4j.Logger;
import java.util.List;
@RestController
@RequestMapping("${openapi.gepafin.base-path:/v1/application}")
public class ApplicationApiController implements ApplicationApi {
private final Logger log = LoggerFactory.getLogger(ApplicationApiController.class);
@Autowired
private ApplicationService applicationService;
@Override
public ResponseEntity<Response<ApplicationResponseBean>> createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId) {
ApplicationResponseBean applicationResponseBean= applicationService.createApplication(request,applicationRequestBean,formId);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG))); }
@Override
public ResponseEntity<Response<ApplicationGetResponseBean>> getApplicationByFormId(HttpServletRequest request
, Long applicationId,Long formId) {
log.info("Get Application by ID - Application ID: {}", applicationId);
ApplicationGetResponseBean application = applicationService.getApplicationByFormId(request,applicationId,formId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(application, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<Void>> deleteApplication(HttpServletRequest request,
Long applicationId) {
log.info("Delete Application - Application ID: {}", applicationId);
applicationService.deleteApplication(request,applicationId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_APPLICATION_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<ApplicationResponse>> createApplicationByCallId(HttpServletRequest request, ApplicationRequest applicationRequest, Long callId) {
ApplicationResponse applicationResponseBean=applicationService.createApplication(request,applicationRequest,callId);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<List<ApplicationResponse>>> getAllApplications(HttpServletRequest request) {
List<ApplicationResponse> applications = applicationService.getAllApplications(request);
log.info("Get All Applications");
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(applications, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<NextOrPreviousFormResponse>> getnextOrPreviousForm(HttpServletRequest request,Long applicationId,
Long formId, FormActionEnum action) {
NextOrPreviousFormResponse data = applicationService.getnextOrPreviousForm(request, applicationId, formId, action);
log.info("Get Next Or Previous Form ");
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<Void>> updateApplicationStatus(HttpServletRequest request, Long applicationId,
ApplicationStatusTypeEnum status) {
applicationService.updateApplicationStatus(request, applicationId, status);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG)));
}
}

View File

@@ -642,6 +642,42 @@
<column name="final_form" type="INTEGER"></column>
</addColumn>
</changeSet>
<changeSet id="11-09-2024_1" author="Rajesh Khore">
<createTable tableName="application">
<column name="id" type="INTEGER" autoIncrement="true">
<constraints nullable="false" primaryKey="true" primaryKeyName="application_pkey"/>
</column>
<column name="user_id" type="INTEGER">
<constraints nullable="false" foreignKeyName="fk_user_application" references="gepafin_user(id)"/>
</column>
<column name="submission_date" type="TIMESTAMP WITHOUT TIME ZONE"></column>
<column name="status" type="VARCHAR(255)"></column>
<column name="comments" type="TEXT"></column>
<column name="call_id" type="INTEGER">
<constraints nullable="false" foreignKeyName="fk_call_application" references="call(id)"/>
</column>
<column name="is_deleted" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="created_date" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="updated_date" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/></column>
</createTable>
<addColumn tableName="application_form">
<column name="application_id" type="INTEGER">
<constraints nullable="false" foreignKeyName="fk_application_application_form" references="application(id)"/>
</column>
</addColumn>
<dropColumn tableName="application_form">
<column name="order_no" type="VARCHAR(255)"></column>
</dropColumn>
</changeSet>
<changeSet id="13-09-2024_1" author="Harish Bagora">
<addColumn tableName="form_field">
<column name="description" type="TEXT">

View File

@@ -139,4 +139,24 @@ flow.created.successfully=Flow created successfully.
flow.fetched.successfully=Flow fetched successfully.
flow.already.exists= Flow already exist for this call.
flow.request.not.complete=Flow request is not complete.
# Application related messages
application.created.success=Application successfully created.
application.updated.success=Application successfully updated.
application.deleted.success=Application successfully deleted.
application.get.success=Application details fetched successfully.
application.not.found=Application not found with the given ID.
application.form.field.not.found=Application form field not found.
Form.not.matches.to.call.initial.form=Form id does not matches to initial form id of call.
application.already.exists=Application already exists for this call.
#Validation related messages
validation.field.required=Field {0} is required.
validation.field.min_length=Field {0} must be at least {1} characters long.
validation.field.max_length=Field {0} must be no more than {1} characters long.
validation.field.pattern=Field {0} does not match the required pattern.
validation.field.not_null=Field {0} must not be null.
validation.field.not_empty=Field {0} must not be empty.
current.form.incomplete=Current form is not filled.
flow.not.found=Flow not found.

View File

@@ -135,4 +135,23 @@ flow.created.successfully=Flusso creato con successo.
flow.fetched.successfully=Flusso recuperato con successo.
flow.already.exists= Il flusso esiste gi<67> per questa chiamata.
flow.request.not.complete=La richiesta di flusso non <20> completa.
# Application related messages
application.created.success=Applicazione creata con successo.
application.updated.success=Applicazione aggiornata con successo.
application.deleted.success=Applicazione eliminata con successo.
application.get.success=Dettagli dell'applicazione recuperati con successo.
application.not.found=Applicazione non trovata con l'ID fornito.
application.form.field.not.found=Campo del modulo di domanda non trovato.
Form.not.matches.to.call.initial.form=L'ID del modulo non corrisponde all'ID del modulo iniziale della chiamata.
application.already.exists=L'applicazione esiste gi<67> per questa chiamata.
#Validation related messages
validation.field.required=Il campo {0} <20> obbligatorio.
validation.field.min_length=Il campo {0} deve essere lungo almeno {1} caratteri.
validation.field.max_length=Il campo {0} deve essere lungo al massimo {1} caratteri.
validation.field.pattern=Il campo {0} non corrisponde al modello richiesto.
validation.field.not_null=Il campo {0} non deve essere nullo.
validation.field.not_empty=Il campo {0} non deve essere vuoto.
current.form.incomplete=il modulo corrente non <20> compilato
flow.not.found=Flow not found.