diff --git a/pom.xml b/pom.xml index ad01e409..e8fb4bca 100644 --- a/pom.xml +++ b/pom.xml @@ -167,6 +167,12 @@ + + org.springframework.cloud + spring-cloud-starter-openfeign + 4.1.3 + + diff --git a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java index f9a97be8..7ec98464 100644 --- a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java +++ b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java @@ -2,12 +2,14 @@ package net.gepafin.tendermanagement; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableScheduling +@EnableFeignClients @SpringBootApplication public class TendermanagementApplication { diff --git a/src/main/java/net/gepafin/tendermanagement/config/Translator.java b/src/main/java/net/gepafin/tendermanagement/config/Translator.java index b3c02401..35ad8227 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/Translator.java +++ b/src/main/java/net/gepafin/tendermanagement/config/Translator.java @@ -22,4 +22,9 @@ public class Translator { Locale locale = LocaleContextHolder.getLocale(); return messageSource.getMessage(msgCode, null, locale); } + + public static String toLocale(String key, Object... args) { + return messageSource.getMessage(key, args, LocaleContextHolder.getLocale()); + } + } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 4ed09d15..395d883c 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -132,6 +132,29 @@ public class GepafinConstant { public static final String APPLICATION_ALREADY_SUBMITTED="application.already.submitted"; public static final String INITAL_AND_FINAL_FORM_CANNOT_NULL="initial.and.final.form.cannot.null"; public static final String APPLICATION_FORM_NOT_FOUND="application.form.not.found"; - + public static final String UPDATING_FORM_VALUE_IMPACT_ON_FLOW="updating.form.value.impact.on.flow"; + public static final String APPLICATION_IS_INCOMPLETE_MSG = "application.is.incomplete"; + public static final String AUTHORIZATION = "Authorization"; + public static final String CHECK_VATNUMBER_V2_NEW_URL = "https://imprese.openapi.it/advance"; + public static final String VATNUMBER_V2 = "https://imprese.openapi.it/advance"; + public static final String VALIDATION_FIELD_CUSTOM="validation.field.custom"; + public static final String VALIDATION_CODICE_FISCALE = "validation.codice.fiscale"; + public static final String VALIDATION_CAP = "validation.cap"; + public static final String VALIDATION_IBAN = "validation.iban"; + public static final String VALIDATION_EMAIL = "validation.email"; + public static final String VALIDATION_EMAIL_PEC = "validation.email.pec"; + public static final String VALIDATION_URL = "validation.url"; + public static final String VALIDATION_MARCA_DA_BOLLO = "validation.marca.da.bollo"; + public static final String VALIDATION_PIVA = "validation.piva"; + public static final String VALIDATION_VALID_PIVA="valid.vat.number"; + public static final String IS_MARCA_DA_BOLLO="isMarcaDaBollo"; + public static final String IS_URL="isUrl"; + public static final String IS_EMAIL_PEC="isEmailPEC"; + public static final String IS_EMAIL="isEmail"; + public static final String IS_IBAN="isIBAN"; + public static final String IS_CAP="isCAP"; + public static final String IS_CODICE_FISCALE="isCodiceFiscale"; + public static final String IS_PIVA="isPIVA"; + public static final String FAILED_RETAIN_FIELD="failed.retain.field"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index d6e5e77a..f8e86e7e 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -352,12 +352,26 @@ public class ApplicationDao { } - 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); - } + public void updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { + ApplicationEntity applicationEntity = validateApplication(applicationId); + + if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { + CallEntity callEntity = applicationEntity.getCall(); + Long initialFormId = callEntity.getInitialForm(); + Long finalFormId = callEntity.getFinalForm(); +// if (initialFormId == null || finalFormId == null) { +// throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG)); +// } + ApplicationFormEntity initialApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), initialFormId); + ApplicationFormEntity finalApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), finalFormId); + if (initialApplicationForm == null || finalApplicationForm == null) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG)); + } + applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue()); + applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + } else { + applicationEntity.setStatus(status.getValue()); + } + saveApplicationEntity(applicationEntity); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index 8861ccbc..1b3f60d0 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -3,12 +3,14 @@ package net.gepafin.tendermanagement.dao; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.service.*; +import net.gepafin.tendermanagement.util.Utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @@ -116,7 +118,7 @@ public class CallDao { } callEntity.setStatus(CallStatusEnum.DRAFT.getValue()); callEntity.setAmountMax(createCallRequest.getAmountMax()); - callEntity.setAmount(createCallRequest.getAmountMax()); + callEntity.setAmount(createCallRequest.getAmount()); callEntity.setConfidi(false); if (createCallRequest.getConfidi() != null) { callEntity.setConfidi(createCallRequest.getConfidi()); @@ -424,8 +426,14 @@ public class CallDao { public CallResponse updateCallStep1(Long callId, UpdateCallRequestStep1 updateCallRequest, Long userId) { CallEntity callEntity = validateCall(callId); - validateUpdate(callEntity); - UserEntity userEntity = userService.validateUser(userId); + if(Boolean.TRUE.equals(callEntity.getStatus().equals(CallStatusEnum.PUBLISH.getValue()))) { + try { + Utils.retainOnlySpecificFields(updateCallRequest, Collections.singletonList("faq")); + } catch (IllegalAccessException e) { + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.FAILED_RETAIN_FIELD)); + } + } + UserEntity userEntity = userService.validateUser(userId); isValidDateRange(updateCallRequest, callEntity); setIfUpdated(callEntity::getName, callEntity::setName, updateCallRequest.getName()); setIfUpdated(callEntity::getDescriptionShort, callEntity::setDescriptionShort, diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java index 0ded1ac5..34bf0e59 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java @@ -135,9 +135,13 @@ public class FlowDao { public FlowDataEntity createFlowDataEntity(FlowDataRequestBean flowDataRequestBean,CallEntity call) { FlowDataEntity flowDataEntity = new FlowDataEntity(); flowDataEntity.setFormId(flowDataRequestBean.getFormId()); + if(Boolean.FALSE.equals(flowDataRequestBean.getChosenField().isEmpty()) || flowDataRequestBean.getChosenField()!=null){ flowDataEntity.setChoosenField(flowDataRequestBean.getChosenField()); - flowDataEntity.setChoosenValue(flowDataRequestBean.getChosenValue()); - flowDataEntity.setCallId(call.getId()); + } + if(Boolean.FALSE.equals(flowDataRequestBean.getChosenValue().isEmpty()) || flowDataRequestBean.getChosenValue()!=null) { + flowDataEntity.setChoosenValue(flowDataRequestBean.getChosenValue()); + } + flowDataEntity.setCallId(call.getId()); return flowDataEntity; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 0df71aa8..f46e61f5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -1,10 +1,12 @@ package net.gepafin.tendermanagement.dao; +import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import net.gepafin.tendermanagement.repositories.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -18,10 +20,6 @@ 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.service.FormService; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; @@ -47,7 +45,8 @@ public class FlowFormDao { @Autowired private FormService formService; - + @Autowired + private FormRepository formRepository; // Long getNextForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // // vlaidation if next form findout and cuuent from is not fill the give error @@ -177,52 +176,79 @@ public class FlowFormDao { .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()); +// 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); +// } - if (flowEdgesList.isEmpty()) { - return 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(); - } + // // 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(); + 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 previousForms = formRepository.findByIdIn(previousFormIds); - List chosenValues = flowDataList.stream() - .map(FlowDataEntity::getChoosenValue) - .toList(); + previousForms.sort(Comparator.comparing(FormEntity::getCreatedDate).reversed()); - // 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); + return previousForms.isEmpty() ? null : previousForms.get(0).getId(); } - public NextOrPreviousFormResponse getnextOrPreviousForm(ApplicationEntity applicationEntity, Long formId, FormActionEnum action) { Long calculatedFormId = null; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 0cc4b2eb..11a27915 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -3,14 +3,11 @@ 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.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.request.*; 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.model.response.VatNumberResponseBean; +import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.FieldValidator; @@ -20,7 +17,9 @@ import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundExceptio import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import java.text.MessageFormat; import java.time.LocalDateTime; import java.util.LinkedHashMap; import java.util.List; @@ -42,6 +41,18 @@ public class FormDao { @Autowired private CallDao callDao; + @Autowired + private FlowDataRepository flowDataRepository; + + @Autowired + private FlowEdgesRepository flowEdgesRepository; + + @Autowired + private VatCheckDao vatCheckDao; + + @Autowired + private CallRepository callRepository; + public FormEntity saveFormEntity(FormEntity formEntity){ formEntity=formRepository.save(formEntity); return formEntity; @@ -66,6 +77,16 @@ public class FormDao { } public FormResponseBean createForm(Long callId,FormRequest formRequest){ validateForm(formRequest); + CallEntity callEntity=callService.validateCall(callId); + List flowDataEntities=flowDataRepository.findByCallId(callId); + List flowEdgesEntities=flowEdgesRepository.findByCallId(callId); + if(Boolean.FALSE.equals(flowDataEntities.isEmpty() || flowDataEntities==null ) || Boolean.FALSE.equals(flowEdgesEntities.isEmpty() || flowEdgesEntities==null) ){ + flowDataRepository.deleteAll(flowDataEntities); + flowEdgesRepository.deleteAll(flowEdgesEntities); + callEntity.setInitialForm(null); + callEntity.setFinalForm(null); + callRepository.save(callEntity); + } FormEntity formEntity=convertFormRequestToFormEntity(callId,formRequest); return convertFormEntityToFormResponseBean(formEntity); } @@ -74,14 +95,65 @@ public class FormDao { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.REQUIRED_PARAMETER_NOT_FOUND_FOR_FORM)); } } - public FormResponseBean updateForm(Long formId, FormRequest formRequest){ + public FormResponseBean updateForm(Long formId, FormRequest formRequest,Boolean forceDeleteFlow){ + ContentRequestBean contentRequestBean2=null; + String choosenField=null; FormEntity formEntity = validateForm(formId); - callDao.validateUpdate(formEntity.getCall()); - Utils.setIfUpdated(formEntity::getLabel,formEntity::setLabel,formRequest.getLabel()); - Utils.setIfUpdated(formEntity::getContent,formEntity::setContent,setContentResponseBean(formRequest.getContent())); - formEntity.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); - formEntity=saveFormEntity(formEntity); - return convertFormEntityToFormResponseBean(formEntity); + callDao.validateUpdate(formEntity.getCall()); + List contentRequestBean = Utils.convertJsonStringToList(formEntity.getContent(), ContentRequestBean.class); + for (ContentRequestBean contentRequestBean1 : contentRequestBean) { + FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndChoosenField(formEntity.getId(), contentRequestBean1.getId()); + if (flowDataEntity != null) { + choosenField = flowDataEntity.getChoosenField(); + if (Boolean.TRUE.equals(contentRequestBean1.getId().equals(choosenField))) { + contentRequestBean2 = contentRequestBean1; + break; + } + } + } + if (contentRequestBean2 != null) { + List settingRequestBeansDB = contentRequestBean2.getSettings(); + for (ContentRequestBean contentRequestBeanRequest : formRequest.getContent()) { + if (contentRequestBeanRequest.getId().equals(contentRequestBean2.getId())) { + for (SettingRequestBean settingRequestBeanRequest : contentRequestBeanRequest.getSettings()) { + for (SettingRequestBean settingRequestBeanDB : settingRequestBeansDB) { + if (settingRequestBeanRequest.getName().equals(settingRequestBeanDB.getName())) { + if (!settingRequestBeanRequest.getValue().equals(settingRequestBeanDB.getValue())) { + if (Boolean.TRUE.equals(forceDeleteFlow)) { + Utils.setIfUpdated(formEntity::getLabel, formEntity::setLabel, formRequest.getLabel()); + Utils.setIfUpdated(formEntity::getContent, formEntity::setContent, setContentResponseBean(formRequest.getContent())); + formEntity.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + formEntity = saveFormEntity(formEntity); + List flowDataEntities = flowDataRepository.findByCallId(formEntity.getCall().getId()); + List flowEdgesEntities = flowEdgesRepository.findByCallId(formEntity.getCall().getId()); + flowDataRepository.deleteAll(flowDataEntities); + flowEdgesRepository.deleteAll(flowEdgesEntities); + CallEntity callEntity = formEntity.getCall(); + callEntity.setInitialForm(null); + callEntity.setFinalForm(null); + callRepository.save(callEntity); + return convertFormEntityToFormResponseBean(formEntity); + } else { + throw new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.UPDATING_FORM_VALUE_IMPACT_ON_FLOW, choosenField) + ); + } + } + } + } + } + } + } + } + else { + Utils.setIfUpdated(formEntity::getLabel, formEntity::setLabel, formRequest.getLabel()); + Utils.setIfUpdated(formEntity::getContent, formEntity::setContent, setContentResponseBean(formRequest.getContent())); + formEntity.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + formEntity = saveFormEntity(formEntity); + return convertFormEntityToFormResponseBean(formEntity); + } + return convertFormEntityToFormResponseBean(formEntity); } public FormEntity validateForm(Long formId) { @@ -96,6 +168,14 @@ public class FormDao { } public void deleteFormById(Long formId){ FormEntity formEntity = validateForm(formId); + List flowDataEntities=flowDataRepository.findByCallId(formEntity.getCall().getId()); + List flowEdgesEntities=flowEdgesRepository.findByCallId(formEntity.getCall().getId()); + flowDataRepository.deleteAll(flowDataEntities); + flowEdgesRepository.deleteAll(flowEdgesEntities); + CallEntity callEntity=formEntity.getCall(); + callEntity.setFinalForm(null); + callEntity.setInitialForm(null); + callRepository.save(callEntity); formRepository.delete(formEntity); } public List getFormsByCallId(Long callId){ @@ -115,7 +195,7 @@ public class FormDao { } public void validateFormField(List applicationFormFieldRequestList, ApplicationEntity applicationEntity, FormEntity formEntity) { - Map formFieldMap = new LinkedHashMap(); + Map formFieldMap = new LinkedHashMap(); for(ApplicationFormFieldRequestBean applicationFormFieldRequestBean:applicationFormFieldRequestList) { formFieldMap.put(applicationFormFieldRequestBean.getFieldId(),applicationFormFieldRequestBean.getFieldValue()); } @@ -126,20 +206,25 @@ public class FormDao { FieldValidator validator = FieldValidator.create(); formResponseBean.getContent().forEach(contentResponseBean -> { String fieldId = contentResponseBean.getId(); - String value = formFieldMap.get(fieldId); + String value = String.valueOf(formFieldMap.get(fieldId)); + if(value == null && isApplicationFormExist) { return; } - FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean, FieldValidatorBean.class); + FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean.getValidators(), FieldValidatorBean.class); validator .notNull(value, fieldId) + .isRequired(value,fieldValidatorBean.getIsRequired(),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 + .matchesPattern(value, fieldValidatorBean.getPattern(), fieldId) // Only applies if pattern is present + .validateCustom(value, fieldValidatorBean.getCustom(), fieldId); // Add the custom validation here + if (fieldValidatorBean.getCustom() != null && fieldValidatorBean.getCustom().equals(GepafinConstant.IS_PIVA)) { + String error = validateVatNumber(value, fieldValidatorBean.getCustom(), fieldId); + validator.addError(error); + } }); - validator.validate(); - } private Boolean getApplicationFormExist(ApplicationFormEntity applicationFormEntity) { @@ -148,4 +233,20 @@ public class FormDao { } return false; } + + public String validateVatNumber(String value,String customRule,String fieldId){ + String error=null; + if (value.matches("^\\d{1,11}$")) { + Map customData=null; + try { + Map vatCheckResponse = vatCheckDao.checkVatNumberApi(value); + if (Boolean.FALSE.equals(CollectionUtils.isEmpty(vatCheckResponse))) { + customData = vatCheckResponse; + } + } catch (Exception e) { + error=(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_VALID_PIVA), fieldId)); + } + } + return error; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java new file mode 100644 index 00000000..4d1d0f58 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java @@ -0,0 +1,74 @@ +package net.gepafin.tendermanagement.dao; + +import feign.FeignException; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.service.feignClient.VatCheckService; +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.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import java.net.URI; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +@Component +public class VatCheckDao { + + @Autowired + private VatCheckService vatCheckService; + + @Value("${vatCheckNewToken}") + public String vatCheckNewToken; + + @Value("${isVatCheckGloballyDisabled}") + public String isVatCheckGloballyDisabled; + + public final Logger log = LoggerFactory.getLogger(VatCheckDao.class); + + + + public Map checkVatNumberApi(String vatNumber) { + if (Boolean.TRUE.equals(Boolean.parseBoolean(isVatCheckGloballyDisabled))) { + return new HashMap<>(); + } + Map responseBody = new HashMap<>(); + try { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set(GepafinConstant.AUTHORIZATION, "Bearer " + vatCheckNewToken); + headers.add(org.apache.http.HttpHeaders.USER_AGENT, + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"); + + URI baseUrl = URI.create(GepafinConstant.CHECK_VATNUMBER_V2_NEW_URL); + ResponseEntity> response = vatCheckService.checkVatNumber(baseUrl,vatNumber, headers); + + if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) { + log.info("Successfully checked vat number"); + Map responseMap = response.getBody(); + if (responseMap != null && responseMap.containsKey("data")) { + responseBody = (Map) responseMap.get("data"); + responseBody.remove("timestamp_creation"); + responseBody.remove("timestamp_last_update"); + responseBody.remove("data_iscrizione"); + responseBody.remove("id"); + Map data = new LinkedHashMap<>(); + data.put("data", responseBody); + return data; + } + } + } catch (FeignException ex) { + log.error("Exception occurred while checking vat number: {0}", ex); + throw ex; + } + return responseBody; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java index df120d29..08b436c8 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java @@ -6,8 +6,7 @@ public enum ApplicationStatusTypeEnum { DRAFT("DRAFT"), SUBMIT("SUBMIT"), - EXPIRED("EXPIRED"), - READY_TO_SUBMIT("READY_TO_SUBMIT"); + DISCARD("DISCARD"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/VatNumberResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/VatNumberResponseBean.java new file mode 100644 index 00000000..f98e60c5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/VatNumberResponseBean.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class VatNumberResponseBean { + + private Boolean valid; + + private String validation; + + private String companyName; + + private String errorMessage; +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/FlowDataRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/FlowDataRepository.java index 8f752aa9..dffaee53 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/FlowDataRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/FlowDataRepository.java @@ -17,4 +17,7 @@ public interface FlowDataRepository extends JpaRepository { public Optional findByChoosenValueAndFormIdIn(String fieldValue, List nextFormIds); public List findByFormIdInAndCallId(List previousFormIds, Long callId); + + public FlowDataEntity findByFormIdAndChoosenField(Long formId, String choosenField); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java index 6250b21b..db35477f 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java @@ -10,4 +10,6 @@ import java.util.List; public interface FormRepository extends JpaRepository { List findByCallId(Long callId); + + List findByIdIn(List formId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/FormService.java b/src/main/java/net/gepafin/tendermanagement/service/FormService.java index cf896b73..84447ebb 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/FormService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/FormService.java @@ -14,7 +14,7 @@ public interface FormService { public FormResponseBean createForm(HttpServletRequest request,Long callId,FormRequest formRequest); - public FormResponseBean updateForm(HttpServletRequest request, Long formId, FormRequest formRequest); + public FormResponseBean updateForm(HttpServletRequest request, Long formId, FormRequest formRequest,Boolean forceDeleteFlow); public FormResponseBean getFormById(HttpServletRequest request, Long formId); diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java new file mode 100644 index 00000000..6665690d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.service.feignClient; + +import net.gepafin.tendermanagement.constants.GepafinConstant; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; + +import java.net.URI; +import java.util.Map; + +@FeignClient(value = "vat-check-service", url = GepafinConstant.VATNUMBER_V2) +public interface VatCheckService { + + + @GetMapping("/{vatNumber}") + ResponseEntity> checkVatNumber(URI baseUrl, + @PathVariable("vatNumber") String vatNumber, + @RequestHeader HttpHeaders headers + ); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/FormServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/FormServiceImpl.java index ee56bf88..9d04dbc5 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/FormServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/FormServiceImpl.java @@ -26,8 +26,8 @@ public class FormServiceImpl implements FormService { } @Override - public FormResponseBean updateForm(HttpServletRequest request, Long formId, FormRequest formRequest) { - return formDao.updateForm(formId,formRequest); + public FormResponseBean updateForm(HttpServletRequest request, Long formId, FormRequest formRequest,Boolean forceDeleteFlow) { + return formDao.updateForm(formId,formRequest,forceDeleteFlow); } @Override diff --git a/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java b/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java index 18a1f042..71c76f1a 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java @@ -3,12 +3,17 @@ package net.gepafin.tendermanagement.util; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.dao.FormDao; +import net.gepafin.tendermanagement.dao.VatCheckDao; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import net.gepafin.tendermanagement.web.rest.api.errors.ValidationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; public class FieldValidator { @@ -18,6 +23,10 @@ public class FieldValidator { return new FieldValidator(); } + @Autowired + private VatCheckDao vatCheckDao; + + public FieldValidator notNull(Object object, String fieldName) { if (Objects.isNull(object)) { errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_NOT_NULL), fieldName)); @@ -65,4 +74,77 @@ public class FieldValidator { public static boolean isNullOrZero(Long value) { return value == null || value == 0L; } + + public FieldValidator validateCustom(String value, String customRule, String fieldId) { + if (customRule == null || value == null) { + return this; // No custom rule to validate + } + + switch (customRule) { + + case GepafinConstant.IS_PIVA: + // VAT number: max 11 digits, can start with 0 + if (!value.matches("^\\d{1,11}$")) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_PIVA), fieldId, customRule)); + } + break; + case GepafinConstant.IS_CODICE_FISCALE: + // 16 characters: 6 letters, 2 digits, 1 letter, 2 digits, 1 letter, 3 digits, 1 letter + if (!value.matches("^[A-Z]{6}[0-9]{2}[A-Z]{1}[0-9]{2}[A-Z]{1}[0-9]{3}[A-Z]{1}$")) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_CODICE_FISCALE), fieldId, customRule)); + } + break; + + case GepafinConstant.IS_CAP: + // 5 digits (can start with 0) + if (!value.matches("^[0-9]{5}$")) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_CAP), fieldId, customRule)); + } + break; + + case GepafinConstant.IS_IBAN: + // IBAN must be 27 characters + if (value.length() != 27) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_IBAN), fieldId, customRule)); + } + break; + + case GepafinConstant.IS_EMAIL: + case GepafinConstant.IS_EMAIL_PEC: + // Email validation (using a simple regex for email) + if (!value.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_EMAIL), fieldId, customRule)); + } + break; + + case GepafinConstant.IS_URL: + // URL validation (simple regex for URL) + if (!value.matches("^(https?|ftp)://[^\s/$.?#].[^\s]*$")) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_URL), fieldId, customRule)); + } + break; + + case GepafinConstant.IS_MARCA_DA_BOLLO: + // Length must be 14 digits (can start with 0) + if (!value.matches("^[0-9]{14}$")) { + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_MARCA_DA_BOLLO), fieldId, customRule)); + } + break; + + default: + // If the custom rule is unknown, just log or add an error (optional) + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_CUSTOM), fieldId, customRule)); + break; + } + + return this; + } + public FieldValidator isRequired(String value,Boolean isRequired, String fieldName) { + if (Boolean.TRUE.equals(isRequired)) { // Only check if isRequired is true + if (Objects.isNull(value) || value.isEmpty()) { // Check if value is null or empty + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_NOT_NULL), fieldName)); + } + } + return this; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 5560809f..055fb8e8 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -12,6 +12,7 @@ import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -147,4 +148,17 @@ public class Utils { } return null; } + public static void retainOnlySpecificFields(T requestObject, List retainFields) throws IllegalAccessException { + // Get all declared fields of the request object's class + Field[] fields = requestObject.getClass().getDeclaredFields(); + + for (Field field : fields) { + field.setAccessible(true); // To allow access to private fields + + // Check if the field is in the retainFields list + if (!retainFields.contains(field.getName())) { + field.set(requestObject, null); // Set the field to null if not in the retain list + } + } + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java index 63d813e6..61115f63 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java @@ -14,6 +14,7 @@ import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -33,6 +34,7 @@ public interface FlowApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/call/{callId}", produces = { "application/json" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity> createOrUpdateFlow(HttpServletRequest request, @Parameter(description = " Flow request object", required = true) @Valid @RequestBody FlowRequestBean flowRequestBean, @Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java index 001de040..04417439 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java @@ -13,6 +13,7 @@ import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -31,6 +32,7 @@ public interface FormApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "/call/{callId}", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") public ResponseEntity> createForm(HttpServletRequest request,@Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId, @Parameter(description = "form request object", required = true) @Valid @RequestBody FormRequest formRequest); @@ -49,7 +51,7 @@ public interface FormApi { produces = { "application/json" }) ResponseEntity> updateForm(HttpServletRequest request, @Parameter(description = "The form ID", required = true) @PathVariable("formId") Long formId, - @Parameter(description = "form request object", required = true) @Valid @RequestBody FormRequest formRequest); + @Parameter(description = "form request object", required = true) @Valid @RequestBody FormRequest formRequest,@Parameter(description = "force delete flow ",required = true)@RequestParam(value = "forceDeleteFlow",required = true)Boolean forceDeleteFlow); @Operation(summary = "Api to get form by id", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FormApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FormApiController.java index 72e8bd2b..5b8b54a5 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FormApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FormApiController.java @@ -32,8 +32,8 @@ public class FormApiController implements FormApi { } @Override - public ResponseEntity> updateForm(HttpServletRequest request, Long formId, FormRequest formRequest) { - FormResponseBean formResponseBean = formService.updateForm(request, formId, formRequest); + public ResponseEntity> updateForm(HttpServletRequest request, Long formId, FormRequest formRequest,Boolean forceDeleteFlow) { + FormResponseBean formResponseBean = formService.updateForm(request, formId, formRequest,forceDeleteFlow); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(formResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.FORM_UPDATED_SUCCESSFULLY))); } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index c160287a..930cbd9f 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -6,4 +6,6 @@ spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration spring.h2.console.enabled=true -base-url=https://api-dev-gepafin.memento.credit \ No newline at end of file +base-url=https://api-dev-gepafin.memento.credit + +isVatCheckGloballyDisabled = false diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1b6634c5..1e41a2e9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -40,3 +40,6 @@ base-url=https://api-dev-gepafin.memento.credit spring.main.allow-circular-references=true +isVatCheckGloballyDisabled = true +vatCheckNewToken: 66026bd891a51044e90e08c4 + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index cb423966..981ed852 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -166,3 +166,21 @@ validation.message=Validation messages. action.required=Action field required. call.not.published=Call is not published. application.form.not.found=Application form not found. + +updating.form.value.impact.on.flow=Updating this value of form {0} can make impact on flow. +validation.field.custom=The value for field {0} does not meet the custom validation rule. + +validation.codice.fiscale=The field {0} must be a valid Codice Fiscale with exactly 16 characters: 6 letters, 2 digits, 1 letter, 2 digits, 1 letter, 3 digits, and 1 letter. +validation.cap=The field {0} must be a valid CAP with exactly 5 digits. +validation.iban=The field {0} must be a valid IBAN with exactly 27 characters. +validation.email=The field {0} must be a valid email address. +validation.email.pec=The field {0} must be a valid PEC email address. +validation.url=The field {0} must be a valid URL. +validation.marca.da.bollo=The field {0} must be a valid Marca Da Bollo with exactly 14 digits. +validation.piva=The VAT number for {0} must be up to 11 digits. +valid.vat.number=The VAT number is not valid for field {0}. + + +failed.retain.field=Failed to retain specific fields. + +application.is.incomplete = The application is incomplete. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 0c47f666..5a7899df 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -146,7 +146,7 @@ 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� per questa chiamata. -application.already.submitted=La domanda è già stata inviata. +application.already.submitted=La domanda � gi� stata inviata. #Validation related messages validation.field.required=Il campo {0} � obbligatorio. @@ -159,5 +159,20 @@ current.form.incomplete=il modulo corrente non � compilato flow.not.found=Flow not found. validation.message=Messaggi di convalida. action.required=Campo azione obbligatorio. -call.not.published=La chiamata non è stata pubblicata. -application.form.not.found=Modulo di domanda non trovato. \ No newline at end of file +call.not.published=La chiamata non � stata pubblicata. +application.form.not.found=Modulo di domanda non trovato. + +application.is.incomplete = L'applicazione � incompleta. +updating.form.value.impact.on.flow=L'aggiornamento di questo valore del modulo {0} pu� avere un impatto sul flusso. +validation.field.custom=Il valore per il campo {0} non soddisfa la regola di convalida personalizzata. + +validation.codice.fiscale=Il campo {0} deve essere un Codice Fiscale valido con esattamente 16 caratteri: 6 lettere, 2 cifre, 1 lettera, 2 cifre, 1 lettera, 3 cifre e 1 lettera. +validation.cap=Il campo {0} deve essere un CAP valido con esattamente 5 cifre. +validation.iban=Il campo {0} deve essere un IBAN valido con esattamente 27 caratteri. +validation.email=Il campo {0} deve essere un indirizzo email valido. +validation.email.pec=Il campo {0} deve essere un indirizzo email PEC valido. +validation.url=Il campo {0} deve essere un URL valido. +validation.marca.da.bollo=Il campo {0} deve essere una Marca Da Bollo valida con esattamente 14 cifre. +validation.piva=Il numero di partita IVA per {0} deve essere lungo fino a 11 cifre. +valid.vat.number=Il numero di partita IVA non � valido per il campo {0}. +failed.retain.field=Impossibile conservare campi specifici.