diff --git a/dossierfacile-api-owner/pom.xml b/dossierfacile-api-owner/pom.xml index d117859c9..9ab80e6e5 100644 --- a/dossierfacile-api-owner/pom.xml +++ b/dossierfacile-api-owner/pom.xml @@ -14,7 +14,7 @@ dossierfacile-api-owner Owner api for DossierFacile - 19 + 21 1.5.5.Final 1.18.30 21.1.2 diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/log/OwnerLogServiceImpl.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/log/OwnerLogServiceImpl.java index 24100fe6b..c3866b564 100644 --- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/log/OwnerLogServiceImpl.java +++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/log/OwnerLogServiceImpl.java @@ -6,6 +6,7 @@ import fr.dossierfacile.common.entity.Owner; import fr.dossierfacile.common.entity.OwnerLog; import fr.dossierfacile.common.enums.OwnerLogType; +import fr.dossierfacile.common.utils.MapperUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -19,10 +20,8 @@ public class OwnerLogServiceImpl implements OwnerLogService { private final OwnerLogRepository repository; private final DeletedOwnerMapper deletedOwnerMapper; - private ObjectMapper objectMapper = new ObjectMapper(); - { - objectMapper.registerModule(new JavaTimeModule()); - } + private final ObjectMapper objectMapper = MapperUtil.newObjectMapper(); + private void saveLog(OwnerLog log) { repository.save(log); } diff --git a/dossierfacile-api-tenant/.java-version b/dossierfacile-api-tenant/.java-version index 6ea9a3bd4..5f39e9144 100644 --- a/dossierfacile-api-tenant/.java-version +++ b/dossierfacile-api-tenant/.java-version @@ -1 +1 @@ -19.0 +21.0 diff --git a/dossierfacile-api-tenant/pom.xml b/dossierfacile-api-tenant/pom.xml index 5f6025dc9..1fbfa9ba3 100644 --- a/dossierfacile-api-tenant/pom.xml +++ b/dossierfacile-api-tenant/pom.xml @@ -15,7 +15,7 @@ Front api for dossier facile - 19 + 21 ${java.version} ${java.version} 1.5.5.Final diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/featureflipping/PartnerAccessRevocationToggle.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/featureflipping/PartnerAccessRevocationToggle.java new file mode 100644 index 000000000..b6a09bbd1 --- /dev/null +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/featureflipping/PartnerAccessRevocationToggle.java @@ -0,0 +1,15 @@ +package fr.dossierfacile.api.front.config.featureflipping; + +import fr.dossierfacile.common.utils.DateBasedFeatureToggle; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +// TODO delete after activation +public class PartnerAccessRevocationToggle extends DateBasedFeatureToggle { + + public PartnerAccessRevocationToggle(@Value("${toggle.partners.revocation.activation.date:}") String activationDate) { + super(activationDate); + } + +} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/featureflipping/VersionedCategoriesMapper.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/featureflipping/VersionedCategoriesMapper.java new file mode 100644 index 000000000..97b7821d9 --- /dev/null +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/featureflipping/VersionedCategoriesMapper.java @@ -0,0 +1,56 @@ +package fr.dossierfacile.api.front.config.featureflipping; + +import fr.dossierfacile.api.front.security.interfaces.ClientAuthenticationFacade; +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.common.enums.DocumentSubCategory; +import fr.dossierfacile.common.mapper.CategoriesMapper; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +import static fr.dossierfacile.common.enums.DocumentSubCategory.CERTIFICATE_VISA; +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_IDENTIFICATION; + +@Primary +@Component +@AllArgsConstructor +public class VersionedCategoriesMapper implements CategoriesMapper { + + private final ClientAuthenticationFacade clientAuthenticationFacade; + + @Override + public DocumentCategory mapCategory(DocumentCategory category) { + Optional version = clientAuthenticationFacade.getApiVersion(); + if (version.isPresent() && version.get() < 3) { + return hideCategoriesIntroducedInV3(category); + } + return category; + } + + @Override + public DocumentSubCategory mapSubCategory(DocumentSubCategory subCategory) { + Optional version = clientAuthenticationFacade.getApiVersion(); + if (version.isPresent() && version.get() < 3) { + return hideSubCategoriesIntroducedInV3(subCategory); + } + return subCategory; + } + + private DocumentCategory hideCategoriesIntroducedInV3(DocumentCategory category) { + if (category == DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE) { + return DocumentCategory.IDENTIFICATION; + } + return category; + } + + private DocumentSubCategory hideSubCategoriesIntroducedInV3(DocumentSubCategory subCategory) { + return switch (subCategory) { + case FRANCE_IDENTITE -> OTHER_IDENTIFICATION; + case VISALE, OTHER_GUARANTEE -> CERTIFICATE_VISA; + default -> subCategory; + }; + } + +} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/PartnerAccessController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/PartnerAccessController.java index 60fd9be9d..37c7ff194 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/PartnerAccessController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/PartnerAccessController.java @@ -1,16 +1,14 @@ package fr.dossierfacile.api.front.controller; +import fr.dossierfacile.api.front.config.featureflipping.PartnerAccessRevocationToggle; import fr.dossierfacile.api.front.model.tenant.PartnerAccessModel; import fr.dossierfacile.api.front.security.interfaces.AuthenticationFacade; import fr.dossierfacile.api.front.service.interfaces.PartnerAccessService; import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.utils.DateBasedFeatureToggle; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -52,14 +50,4 @@ public ResponseEntity revokePartnerAccess(@PathVariable("id") Long userApi return ok().build(); } - @Component - // TODO delete after activation - static class PartnerAccessRevocationToggle extends DateBasedFeatureToggle { - - public PartnerAccessRevocationToggle(@Value("${toggle.partners.revocation.activation.date:}") String activationDate) { - super(activationDate); - } - - } - } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java index 28bd38960..b4a794628 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java @@ -4,7 +4,6 @@ import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.register.enums.StepRegister; import fr.dossierfacile.api.front.register.form.tenant.AccountForm; -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; import fr.dossierfacile.api.front.register.form.tenant.ApplicationFormV2; import fr.dossierfacile.api.front.register.form.tenant.DocumentFinancialForm; import fr.dossierfacile.api.front.register.form.tenant.DocumentIdentificationForm; @@ -63,23 +62,13 @@ public ResponseEntity confirmAccount(@PathVariable String token) { @PreAuthorize("hasPermissionOnTenant(#namesForm.tenantId)") @PostMapping(value = "/names", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity names(@Validated(Dossier.class) @RequestBody NamesForm namesForm) { - var tenant = authenticationFacade.getTenant(namesForm.getTenantId() ); + var tenant = authenticationFacade.getTenant(namesForm.getTenantId()); TenantModel tenantModel = tenantService.saveStepRegister(tenant, namesForm, StepRegister.NAMES); logService.saveStepLog(tenantModel.getId(), StepRegister.NAMES.getClazz().getSimpleName()); Tenant loggedTenant = (namesForm.getTenantId() == null) ? tenant : authenticationFacade.getLoggedTenant(); return ok(tenantMapper.toTenantModel(loggedTenant)); } - @Deprecated - @PostMapping(value = "/application", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity application(@Validated(Dossier.class) @RequestBody ApplicationForm applicationForm) { - Tenant tenant = authenticationFacade.getTenant(applicationForm.getTenantId()); - TenantModel tenantModel = tenantService.saveStepRegister(tenant, applicationForm, StepRegister.APPLICATION_V1); - logService.saveLog(LogType.ACCOUNT_EDITED, tenantModel.getId()); - Tenant loggedTenant = (applicationForm.getTenantId() == null) ? tenant : authenticationFacade.getLoggedTenant(); - return ok(tenantMapper.toTenantModel(loggedTenant)); - } - @PostMapping(value = "/application/v2", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity application(@Validated(Dossier.class) @RequestBody ApplicationFormV2 applicationForm) { Tenant tenant = authenticationFacade.getTenant(applicationForm.getTenantId()); diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterGuarantorOrganismController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterGuarantorOrganismController.java index c57c1371f..219f46b3c 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterGuarantorOrganismController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterGuarantorOrganismController.java @@ -3,6 +3,7 @@ import fr.dossierfacile.api.front.mapper.TenantMapper; import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.register.enums.StepRegister; +import fr.dossierfacile.api.front.register.form.guarantor.organism.DocumentGuaranteeProviderCertificateForm; import fr.dossierfacile.api.front.register.form.guarantor.organism.DocumentIdentificationGuarantorOrganismForm; import fr.dossierfacile.api.front.security.interfaces.AuthenticationFacade; import fr.dossierfacile.api.front.service.interfaces.TenantService; @@ -23,16 +24,28 @@ @RequiredArgsConstructor @RequestMapping(value = "/api/register/guarantorOrganism", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public class RegisterGuarantorOrganismController { + private final TenantService tenantService; private final TenantMapper tenantMapper; private final AuthenticationFacade authenticationFacade; @PreAuthorize("hasPermissionOnTenant(#documentIdentificationGuarantorOrganismForm.tenantId)") @PostMapping("/documentIdentification") + @Deprecated public ResponseEntity documentIdentification(@Validated(Dossier.class) DocumentIdentificationGuarantorOrganismForm documentIdentificationGuarantorOrganismForm) { var tenant = authenticationFacade.getTenant(documentIdentificationGuarantorOrganismForm.getTenantId()); tenantService.saveStepRegister(tenant, documentIdentificationGuarantorOrganismForm, StepRegister.DOCUMENT_IDENTIFICATION_GUARANTOR_ORGANISM); Tenant loggedTenant = (documentIdentificationGuarantorOrganismForm.getTenantId() == null) ? tenant : authenticationFacade.getLoggedTenant(); return ok(tenantMapper.toTenantModel(loggedTenant)); } + + @PreAuthorize("hasPermissionOnTenant(#form.tenantId)") + @PostMapping("/documentCertificate") + public ResponseEntity documentCertificate(@Validated(Dossier.class) DocumentGuaranteeProviderCertificateForm form) { + var tenant = authenticationFacade.getTenant(form.getTenantId()); + tenantService.saveStepRegister(tenant, form, StepRegister.DOCUMENT_GUARANTEE_PROVIDER_CERTIFICATE); + Tenant loggedTenant = (form.getTenantId() == null) ? tenant : authenticationFacade.getLoggedTenant(); + return ok(tenantMapper.toTenantModel(loggedTenant)); + } + } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/mapper/TenantMapper.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/mapper/TenantMapper.java index aa5b260bd..a105b7a43 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/mapper/TenantMapper.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/mapper/TenantMapper.java @@ -11,10 +11,13 @@ import fr.dossierfacile.common.entity.File; import fr.dossierfacile.common.entity.Tenant; import fr.dossierfacile.common.enums.TenantFileStatus; +import fr.dossierfacile.common.mapper.CategoriesMapper; +import fr.dossierfacile.common.mapper.MapDocumentCategories; import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -34,15 +37,23 @@ public abstract class TenantMapper { @Value("${application.domain}") protected String domain; + protected CategoriesMapper categoriesMapper; + + @Autowired + public void setCategoriesMapper(CategoriesMapper categoriesMapper) { + this.categoriesMapper = categoriesMapper; + } + @Mapping(target = "passwordEnabled", expression = "java(tenant.getPassword() != null)") public abstract TenantModel toTenantModel(Tenant tenant); @Mapping(target = "name", expression = "java((document.getWatermarkFile() != null )? domain + \"/" + PATH + "/\" + document.getName() : null)") - @Mapping(target = "subCategory", source = "documentSubCategory") - @Mapping(target = "documentSubCategory", expression = "java(document.getDocumentSubCategory().getOnlyOldCategories())") + @MapDocumentCategories public abstract DocumentModel toDocumentModel(Document document); @Mapping(target = "name", expression = "java((document.getWatermarkFile() != null )? domain + \"/" + PATH + "/\" + document.getName() : null)") + @Mapping(target = "documentCategory", expression = "java(categoriesMapper.mapCategory(document.getDocumentCategory()))") + @Mapping(target = "documentSubCategory", expression = "java(categoriesMapper.mapSubCategory(document.getDocumentSubCategory()))") public abstract fr.dossierfacile.api.front.model.dfc.apartment_sharing.DocumentModel documentToDocumentModel(Document document); @Mapping(target = "connectedTenantId", source = "id") diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/DocumentModel.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/DocumentModel.java index 7b8bbbd06..6d0ee6a30 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/DocumentModel.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/DocumentModel.java @@ -19,7 +19,6 @@ public class DocumentModel { private Long id; private DocumentCategory documentCategory; - private DocumentSubCategory documentSubCategory; // TODO delete this field 6 months from now private DocumentSubCategory subCategory; private Boolean noDocument; private String customText; diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/EmailExistsModel.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/EmailExistsModel.java deleted file mode 100644 index eb29001e7..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/model/tenant/EmailExistsModel.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.dossierfacile.api.front.model.tenant; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class EmailExistsModel { - private String email; - private boolean exists; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterController.java index 0275d335e..0a1745e62 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterController.java @@ -4,7 +4,6 @@ import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.register.enums.StepRegister; import fr.dossierfacile.api.front.register.form.partner.AccountPartnerForm; -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; import fr.dossierfacile.api.front.register.form.tenant.ApplicationFormV2; import fr.dossierfacile.api.front.register.form.tenant.DocumentFinancialForm; import fr.dossierfacile.api.front.register.form.tenant.DocumentIdentificationForm; @@ -58,16 +57,6 @@ public ResponseEntity names(@Validated(ApiPartner.class) @RequestBo return ok(tenantModel); } - @ApiOperation("Deprecated since 2022.09.15 - use /application/v2") - @PreAuthorize("hasPermissionOnTenant(#applicationForm.tenantId)") - @Deprecated - @PostMapping(value = "/application", consumes = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity application(@Validated(ApiPartner.class) @RequestBody ApplicationForm applicationForm) { - var tenant = tenantService.findById(applicationForm.getTenantId()); - var tenantModel = tenantService.saveStepRegister(tenant, applicationForm, StepRegister.APPLICATION_V1); - logService.saveLog(LogType.ACCOUNT_EDITED, tenantModel.getId()); - return ok(tenantModel); - } @ApiOperation("En cas de couple(COUPLE), le nom et le prénom sont requis mais pas l'email.
En cas de colocation(GROUP): nom, prénom et email sont requis") @PreAuthorize("hasPermissionOnTenant(#applicationForm.tenantId)") @PostMapping(value = "/application/v2", consumes = MediaType.APPLICATION_JSON_VALUE) diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterGuarantorOrganismController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterGuarantorOrganismController.java index 067ee35b5..6c1d39f50 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterGuarantorOrganismController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerRegisterGuarantorOrganismController.java @@ -2,6 +2,7 @@ import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.register.enums.StepRegister; +import fr.dossierfacile.api.front.register.form.guarantor.organism.DocumentGuaranteeProviderCertificateForm; import fr.dossierfacile.api.front.register.form.guarantor.organism.DocumentIdentificationGuarantorOrganismForm; import fr.dossierfacile.api.front.service.interfaces.TenantService; import fr.dossierfacile.api.front.validator.group.ApiPartner; @@ -21,13 +22,24 @@ @RequiredArgsConstructor @RequestMapping(value = "/api-partner/register/guarantorOrganism", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public class ApiPartnerRegisterGuarantorOrganismController { + private final TenantService tenantService; @PreAuthorize("hasPermissionOnTenant(#documentIdentificationGuarantorOrganismForm.tenantId)") @PostMapping("/documentIdentification") + @Deprecated public ResponseEntity documentIdentification(@Validated({ApiPartner.class, DocumentIdentificationGuarantor.class}) DocumentIdentificationGuarantorOrganismForm documentIdentificationGuarantorOrganismForm) { var tenant = tenantService.findById(documentIdentificationGuarantorOrganismForm.getTenantId()); var tenantModel = tenantService.saveStepRegister(tenant, documentIdentificationGuarantorOrganismForm, StepRegister.DOCUMENT_IDENTIFICATION_GUARANTOR_ORGANISM); return ok(tenantModel); } + + @PreAuthorize("hasPermissionOnTenant(#form.tenantId)") + @PostMapping("/documentCertificate") + public ResponseEntity documentCertificate(@Validated({ApiPartner.class, DocumentGuaranteeProviderCertificateForm.class}) DocumentGuaranteeProviderCertificateForm form) { + var tenant = tenantService.findById(form.getTenantId()); + var tenantModel = tenantService.saveStepRegister(tenant, form, StepRegister.DOCUMENT_GUARANTEE_PROVIDER_CERTIFICATE); + return ok(tenantModel); + } + } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerTenantController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerTenantController.java index f376acd92..664589962 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerTenantController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerTenantController.java @@ -50,7 +50,6 @@ public ResponseEntity, ListMetadata>> list(@R @RequestParam(value = "includeDeleted", defaultValue = "false") boolean includeDeleted, @RequestParam(value = "includeRevoked", defaultValue = "false") boolean includeRevoked ) { - System.out.println("after = " + after); UserApi userApi = clientAuthenticationFacade.getClient(); List result; LocalDateTime nextTimeToken; diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerUserController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerUserController.java index 24b96062f..f17ce980c 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerUserController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/partner/controller/ApiPartnerUserController.java @@ -2,9 +2,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import fr.dossierfacile.api.front.mapper.TenantMapper; -import fr.dossierfacile.api.front.model.tenant.EmailExistsModel; import fr.dossierfacile.api.front.model.tenant.TenantModel; -import fr.dossierfacile.api.front.register.form.partner.EmailExistsForm; import fr.dossierfacile.api.front.security.interfaces.ClientAuthenticationFacade; import fr.dossierfacile.api.front.service.interfaces.TenantService; import fr.dossierfacile.api.front.service.interfaces.UserApiService; @@ -59,15 +57,6 @@ public ResponseEntity getTenantByEmail(@JsonDeserialize(using = Ema return ok(tenantMapperForPartner.toTenantModel(tenant.get())); } - /** - * @deprecated use /email/{email}/tenant endpoint - */ - @Deprecated - @PostMapping(value = "/emailexists", consumes = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity emailExists(@Validated @RequestBody EmailExistsForm emailExistsForm) { - return ok(tenantService.emailExists(emailExistsForm)); - } - @PreAuthorize("hasPermissionOnTenant(#tenantId)") @DeleteMapping("/tenant/{tenantId}/user/deleteAccount") public ResponseEntity deleteAccount(@PathVariable Long tenantId) { diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/enums/StepRegister.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/enums/StepRegister.java index abd5f7797..089d62ef3 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/enums/StepRegister.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/enums/StepRegister.java @@ -11,8 +11,19 @@ import fr.dossierfacile.api.front.register.guarantor.natural_person.DocumentResidencyGuarantorNaturalPerson; import fr.dossierfacile.api.front.register.guarantor.natural_person.DocumentTaxGuarantorNaturalPerson; import fr.dossierfacile.api.front.register.guarantor.natural_person.NameGuarantorNaturalPerson; +import fr.dossierfacile.api.front.register.guarantor.organism.DocumentGuaranteeProviderCertificate; import fr.dossierfacile.api.front.register.guarantor.organism.DocumentIdentificationGuarantorOrganism; -import fr.dossierfacile.api.front.register.tenant.*; +import fr.dossierfacile.api.front.register.tenant.Account; +import fr.dossierfacile.api.front.register.tenant.AccountApiPartner; +import fr.dossierfacile.api.front.register.tenant.Application; +import fr.dossierfacile.api.front.register.tenant.DocumentFinancial; +import fr.dossierfacile.api.front.register.tenant.DocumentIdentification; +import fr.dossierfacile.api.front.register.tenant.DocumentProfessional; +import fr.dossierfacile.api.front.register.tenant.DocumentResidency; +import fr.dossierfacile.api.front.register.tenant.DocumentTax; +import fr.dossierfacile.api.front.register.tenant.GuarantorType; +import fr.dossierfacile.api.front.register.tenant.HonorDeclaration; +import fr.dossierfacile.api.front.register.tenant.Names; import lombok.Getter; @Getter @@ -20,7 +31,6 @@ public enum StepRegister { ACCOUNT_PARTNER_API(AccountApiPartner.class), ACCOUNT(Account.class), NAMES(Names.class), - APPLICATION_V1(ApplicationV1.class), APPLICATION(Application.class), HONOR_DECLARATION(HonorDeclaration.class), DOCUMENT_IDENTIFICATION(DocumentIdentification.class), @@ -36,6 +46,7 @@ public enum StepRegister { DOCUMENT_FINANCIAL_GUARANTOR_NATURAL_PERSON(DocumentFinancialGuarantorNaturalPerson.class), DOCUMENT_TAX_GUARANTOR_NATURAL_PERSON(DocumentTaxGuarantorNaturalPerson.class), DOCUMENT_IDENTIFICATION_GUARANTOR_ORGANISM(DocumentIdentificationGuarantorOrganism.class), + DOCUMENT_GUARANTEE_PROVIDER_CERTIFICATE(DocumentGuaranteeProviderCertificate.class), DOCUMENT_IDENTIFICATION_GUARANTOR_LEGAL_PERSON(DocumentIdentificationGuarantorLegalPerson.class), DOCUMENT_IDENTIFICATION_REPRESENTANT_GUARANTOR_LEGAL_PERSON(DocumentIdentificationRepresentanGuarantorLegalPerson.class), GUARANTOR_TYPE(GuarantorType.class), diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/legal_person/DocumentIdentificationRepresentanGuarantorLegalPersonForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/legal_person/DocumentIdentificationRepresentanGuarantorLegalPersonForm.java index 5fe7902d3..6e99e020e 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/legal_person/DocumentIdentificationRepresentanGuarantorLegalPersonForm.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/legal_person/DocumentIdentificationRepresentanGuarantorLegalPersonForm.java @@ -15,6 +15,7 @@ import javax.validation.constraints.NotNull; import static fr.dossierfacile.common.enums.DocumentSubCategory.DRIVERS_LICENSE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.FRANCE_IDENTITE; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_IDENTITY_CARD; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_PASSPORT; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_RESIDENCE_PERMIT; @@ -31,8 +32,10 @@ public class DocumentIdentificationRepresentanGuarantorLegalPersonForm extends D private String firstName; @NotNull - @DocumentSubcategorySubset(anyOf = - {FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, OTHER_IDENTIFICATION}) + @DocumentSubcategorySubset(anyOf = { + FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, + FRANCE_IDENTITE, OTHER_IDENTIFICATION + }) private DocumentSubCategory typeDocumentIdentification; private TypeGuarantor typeGuarantor = TypeGuarantor.LEGAL_PERSON; diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonFileForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonFileForm.java index 144afbe34..cc711c129 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonFileForm.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonFileForm.java @@ -3,7 +3,6 @@ import fr.dossierfacile.api.front.register.form.guarantor.DocumentGuarantorFormAbstract; import fr.dossierfacile.api.front.validator.anotation.DocumentSubcategorySubset; import fr.dossierfacile.api.front.validator.anotation.NumberOfPages; -import fr.dossierfacile.api.front.validator.anotation.guarantor.natural_person.identification.NumberOfDocumentIdentificationGuarantorNaturalPerson; import fr.dossierfacile.api.front.validator.anotation.guarantor.natural_person.identification.NumberOfDocumentIdentificationGuarantorNaturalPersonFile; import fr.dossierfacile.common.enums.DocumentCategory; import fr.dossierfacile.common.enums.DocumentSubCategory; @@ -16,6 +15,7 @@ import javax.validation.constraints.NotNull; import static fr.dossierfacile.common.enums.DocumentSubCategory.DRIVERS_LICENSE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.FRANCE_IDENTITE; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_IDENTITY_CARD; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_PASSPORT; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_RESIDENCE_PERMIT; @@ -30,8 +30,10 @@ public class DocumentIdentificationGuarantorNaturalPersonFileForm extends DocumentGuarantorFormAbstract { @NotNull - @DocumentSubcategorySubset(anyOf = - {FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, OTHER_IDENTIFICATION}) + @DocumentSubcategorySubset(anyOf = { + FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, + FRANCE_IDENTITE, OTHER_IDENTIFICATION + }) private DocumentSubCategory typeDocumentIdentification; private TypeGuarantor typeGuarantor = TypeGuarantor.NATURAL_PERSON; diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonForm.java index 4048be639..5ec4e662d 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonForm.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/natural_person/DocumentIdentificationGuarantorNaturalPersonForm.java @@ -16,6 +16,7 @@ import javax.validation.constraints.NotNull; import static fr.dossierfacile.common.enums.DocumentSubCategory.DRIVERS_LICENSE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.FRANCE_IDENTITE; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_IDENTITY_CARD; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_PASSPORT; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_RESIDENCE_PERMIT; @@ -36,8 +37,10 @@ public class DocumentIdentificationGuarantorNaturalPersonForm extends DocumentGu private String lastName; @NotNull - @DocumentSubcategorySubset(anyOf = - {FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, OTHER_IDENTIFICATION}) + @DocumentSubcategorySubset(anyOf = { + FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, + FRANCE_IDENTITE, OTHER_IDENTIFICATION + }) private DocumentSubCategory typeDocumentIdentification; private TypeGuarantor typeGuarantor = TypeGuarantor.NATURAL_PERSON; diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentGuaranteeProviderCertificateForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentGuaranteeProviderCertificateForm.java new file mode 100644 index 000000000..caea1d3e1 --- /dev/null +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentGuaranteeProviderCertificateForm.java @@ -0,0 +1,36 @@ +package fr.dossierfacile.api.front.register.form.guarantor.organism; + +import fr.dossierfacile.api.front.register.form.guarantor.DocumentGuarantorFormAbstract; +import fr.dossierfacile.api.front.validator.anotation.DocumentSubcategorySubset; +import fr.dossierfacile.api.front.validator.anotation.NumberOfPages; +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.common.enums.DocumentSubCategory; +import fr.dossierfacile.common.enums.TypeGuarantor; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_GUARANTEE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.VISALE; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@NumberOfPages(category = DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE, max = 10) +public class DocumentGuaranteeProviderCertificateForm extends DocumentGuarantorFormAbstract { + + private TypeGuarantor typeGuarantor = TypeGuarantor.ORGANISM; + + private DocumentCategory documentCategory = DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE; + + @NotNull + @DocumentSubcategorySubset(anyOf = { + VISALE, OTHER_GUARANTEE + }) + private DocumentSubCategory typeDocumentCertificate; + +} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentIdentificationGuarantorOrganismForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentIdentificationGuarantorOrganismForm.java index 878241abc..19918cd1b 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentIdentificationGuarantorOrganismForm.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/guarantor/organism/DocumentIdentificationGuarantorOrganismForm.java @@ -13,10 +13,11 @@ @Data @AllArgsConstructor @NoArgsConstructor -@NumberOfPages(category = DocumentCategory.IDENTIFICATION, max = 10) +@NumberOfPages(category = DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE, max = 10) +@Deprecated public class DocumentIdentificationGuarantorOrganismForm extends DocumentGuarantorFormAbstract { private TypeGuarantor typeGuarantor = TypeGuarantor.ORGANISM; - private DocumentCategory documentCategory = DocumentCategory.IDENTIFICATION; + private DocumentCategory documentCategory = DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE; } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/partner/EmailExistsForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/partner/EmailExistsForm.java deleted file mode 100644 index bd3ea1ad0..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/partner/EmailExistsForm.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.dossierfacile.api.front.register.form.partner; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import fr.dossierfacile.common.deserializer.EmailDeserializer; -import javax.validation.constraints.Email; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class EmailExistsForm { - - @Email - @JsonDeserialize(using = EmailDeserializer.class) - private String email; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/ApplicationForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/ApplicationForm.java deleted file mode 100644 index d14eebd94..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/ApplicationForm.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.dossierfacile.api.front.register.form.tenant; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import fr.dossierfacile.api.front.form.interfaces.FormWithTenantId; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.CheckTenantTypeAcceptAccess; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.CheckTenantTypeCountListCoTenant; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.DeniedJoinTenant; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.DistinctEmailList; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.DistinctTenantPrincipalEmailListCoTenant; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.UniqueEmailListCoTenant; -import fr.dossierfacile.api.front.validator.group.ApiPartner; -import fr.dossierfacile.api.front.validator.group.Dossier; -import fr.dossierfacile.common.deserializer.EmailDeserializer; -import fr.dossierfacile.common.enums.ApplicationType; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Email; -import javax.validation.constraints.NotNull; -import java.util.ArrayList; -import java.util.List; - -@Data -@AllArgsConstructor -@NoArgsConstructor -@CheckTenantTypeCountListCoTenant -@CheckTenantTypeAcceptAccess -@DeniedJoinTenant -@UniqueEmailListCoTenant -@DistinctTenantPrincipalEmailListCoTenant -public class ApplicationForm implements FormWithTenantId { - - @NotNull(groups = ApiPartner.class) - private Long tenantId; - - @NotNull - private ApplicationType applicationType; - - @DistinctEmailList - @JsonDeserialize(contentUsing = EmailDeserializer.class) - private List<@Email String> coTenantEmail = new ArrayList<>(); - - private Boolean acceptAccess; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/DocumentIdentificationForm.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/DocumentIdentificationForm.java index 2e270576d..638c0b94f 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/DocumentIdentificationForm.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/form/tenant/DocumentIdentificationForm.java @@ -14,6 +14,7 @@ import javax.validation.constraints.NotNull; import static fr.dossierfacile.common.enums.DocumentSubCategory.DRIVERS_LICENSE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.FRANCE_IDENTITE; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_IDENTITY_CARD; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_PASSPORT; import static fr.dossierfacile.common.enums.DocumentSubCategory.FRENCH_RESIDENCE_PERMIT; @@ -28,7 +29,9 @@ public class DocumentIdentificationForm extends DocumentForm { @NotNull - @DocumentSubcategorySubset(anyOf = - {FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, OTHER_IDENTIFICATION}) + @DocumentSubcategorySubset(anyOf = { + FRENCH_IDENTITY_CARD, FRENCH_PASSPORT, FRENCH_RESIDENCE_PERMIT, DRIVERS_LICENSE, + FRANCE_IDENTITE, OTHER_IDENTIFICATION + }) private DocumentSubCategory typeDocumentIdentification; } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentGuaranteeProviderCertificate.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentGuaranteeProviderCertificate.java new file mode 100644 index 000000000..761477f0e --- /dev/null +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentGuaranteeProviderCertificate.java @@ -0,0 +1,59 @@ +package fr.dossierfacile.api.front.register.guarantor.organism; + +import fr.dossierfacile.api.front.exception.GuarantorNotFoundException; +import fr.dossierfacile.api.front.register.AbstractDocumentSaveStep; +import fr.dossierfacile.api.front.register.SaveStep; +import fr.dossierfacile.api.front.register.form.guarantor.organism.DocumentGuaranteeProviderCertificateForm; +import fr.dossierfacile.api.front.repository.DocumentRepository; +import fr.dossierfacile.api.front.repository.GuarantorRepository; +import fr.dossierfacile.api.front.service.interfaces.ApartmentSharingService; +import fr.dossierfacile.api.front.service.interfaces.TenantStatusService; +import fr.dossierfacile.common.entity.Document; +import fr.dossierfacile.common.entity.Guarantor; +import fr.dossierfacile.common.entity.Tenant; +import fr.dossierfacile.common.enums.DocumentStatus; +import fr.dossierfacile.common.enums.TypeGuarantor; +import fr.dossierfacile.common.repository.TenantCommonRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +import static fr.dossierfacile.common.enums.DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE; + +@Service +@RequiredArgsConstructor +public class DocumentGuaranteeProviderCertificate + extends AbstractDocumentSaveStep + implements SaveStep { + + private final TenantCommonRepository tenantRepository; + private final DocumentRepository documentRepository; + private final GuarantorRepository guarantorRepository; + private final TenantStatusService tenantStatusService; + private final ApartmentSharingService apartmentSharingService; + + @Override + protected Document saveDocument(Tenant tenant, DocumentGuaranteeProviderCertificateForm form) { + Guarantor guarantor = guarantorRepository.findByTenantAndTypeGuarantorAndId(tenant, TypeGuarantor.ORGANISM, form.getGuarantorId()) + .orElseThrow(() -> new GuarantorNotFoundException(form.getGuarantorId())); + + Document document = documentRepository.findFirstByDocumentCategoryAndGuarantor(GUARANTEE_PROVIDER_CERTIFICATE, guarantor) + .orElse(Document.builder() + .documentCategory(GUARANTEE_PROVIDER_CERTIFICATE) + .guarantor(guarantor) + .build()); + document.setDocumentStatus(DocumentStatus.TO_PROCESS); + document.setDocumentDeniedReasons(null); + document.setDocumentSubCategory(form.getTypeDocumentCertificate()); + documentRepository.save(document); + + saveFiles(form, document); + + tenant.lastUpdateDateProfile(LocalDateTime.now(), GUARANTEE_PROVIDER_CERTIFICATE); + tenantStatusService.updateTenantStatus(tenant); + apartmentSharingService.resetDossierPdfGenerated(tenant.getApartmentSharing()); + tenantRepository.save(tenant); + return document; + } +} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentIdentificationGuarantorOrganism.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentIdentificationGuarantorOrganism.java index 31c54d981..ca96cc6fa 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentIdentificationGuarantorOrganism.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/guarantor/organism/DocumentIdentificationGuarantorOrganism.java @@ -7,14 +7,12 @@ import fr.dossierfacile.api.front.repository.DocumentRepository; import fr.dossierfacile.api.front.repository.GuarantorRepository; import fr.dossierfacile.api.front.service.interfaces.ApartmentSharingService; -import fr.dossierfacile.api.front.service.interfaces.DocumentService; import fr.dossierfacile.api.front.service.interfaces.TenantStatusService; import fr.dossierfacile.common.entity.Document; import fr.dossierfacile.common.entity.Guarantor; import fr.dossierfacile.common.entity.Tenant; import fr.dossierfacile.common.enums.DocumentCategory; import fr.dossierfacile.common.enums.DocumentStatus; -import fr.dossierfacile.common.enums.DocumentSubCategory; import fr.dossierfacile.common.enums.TypeGuarantor; import fr.dossierfacile.common.repository.TenantCommonRepository; import lombok.RequiredArgsConstructor; @@ -22,7 +20,11 @@ import java.time.LocalDateTime; +import static fr.dossierfacile.common.enums.DocumentCategory.*; +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_GUARANTEE; + @Service +@Deprecated @RequiredArgsConstructor public class DocumentIdentificationGuarantorOrganism extends AbstractDocumentSaveStep @@ -31,7 +33,6 @@ public class DocumentIdentificationGuarantorOrganism private final TenantCommonRepository tenantRepository; private final DocumentRepository documentRepository; private final GuarantorRepository guarantorRepository; - private final DocumentService documentService; private final TenantStatusService tenantStatusService; private final ApartmentSharingService apartmentSharingService; @@ -40,19 +41,19 @@ protected Document saveDocument(Tenant tenant, DocumentIdentificationGuarantorOr Guarantor guarantor = guarantorRepository.findByTenantAndTypeGuarantorAndId(tenant, TypeGuarantor.ORGANISM, documentIdentificationGuarantorOrganismForm.getGuarantorId()) .orElseThrow(() -> new GuarantorNotFoundException(documentIdentificationGuarantorOrganismForm.getGuarantorId())); - Document document = documentRepository.findFirstByDocumentCategoryAndGuarantor(DocumentCategory.IDENTIFICATION, guarantor) + Document document = documentRepository.findFirstByDocumentCategoryAndGuarantor(GUARANTEE_PROVIDER_CERTIFICATE, guarantor) .orElse(Document.builder() - .documentCategory(DocumentCategory.IDENTIFICATION) + .documentCategory(GUARANTEE_PROVIDER_CERTIFICATE) .guarantor(guarantor) .build()); document.setDocumentStatus(DocumentStatus.TO_PROCESS); document.setDocumentDeniedReasons(null); - document.setDocumentSubCategory(DocumentSubCategory.CERTIFICATE_VISA); + document.setDocumentSubCategory(OTHER_GUARANTEE); documentRepository.save(document); saveFiles(documentIdentificationGuarantorOrganismForm, document); - tenant.lastUpdateDateProfile(LocalDateTime.now(), DocumentCategory.IDENTIFICATION); + tenant.lastUpdateDateProfile(LocalDateTime.now(), GUARANTEE_PROVIDER_CERTIFICATE); tenantStatusService.updateTenantStatus(tenant); apartmentSharingService.resetDossierPdfGenerated(tenant.getApartmentSharing()); tenantRepository.save(tenant); diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/tenant/ApplicationV1.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/tenant/ApplicationV1.java deleted file mode 100644 index a45a47694..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/register/tenant/ApplicationV1.java +++ /dev/null @@ -1,59 +0,0 @@ -package fr.dossierfacile.api.front.register.tenant; - -import fr.dossierfacile.api.front.model.tenant.TenantModel; -import fr.dossierfacile.api.front.register.SaveStep; -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.register.form.tenant.CoTenantForm; -import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.entity.User; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.validation.constraints.Email; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -@Service -@AllArgsConstructor -public class ApplicationV1 implements SaveStep { - - private Application application; - - @Override - @Transactional - public TenantModel saveStep(Tenant tenant, ApplicationForm applicationForm) { - List existingCoTenants = tenant.getApartmentSharing().getTenants() - .stream() - .filter(t -> !t.getId().equals(tenant.getId())) - .collect(Collectors.toList()); - - List<@Email String> invitedCoTenants = applicationForm.getCoTenantEmail(); - - List tenantToCreate = getTenantsToCreate(existingCoTenants, invitedCoTenants); - List tenantToDelete = getTenantsToDelete(existingCoTenants, invitedCoTenants); - - return application.saveStep(tenant, applicationForm.getApplicationType(), tenantToDelete, tenantToCreate); - } - - private static List getTenantsToCreate(List existingCoTenants, List<@Email String> invitedCoTenants) { - List existingCoTenantsEmails = existingCoTenants.stream() - .map(User::getEmail) - .collect(Collectors.toList()); - Predicate alreadyInvited = email -> !existingCoTenantsEmails.contains(email); - - return invitedCoTenants.stream() - .filter(alreadyInvited) - .map(email -> new CoTenantForm("", "", "", email)) - .collect(Collectors.toList()); - } - - private static List getTenantsToDelete(List existingCoTenants, List<@Email String> invitedCoTenants) { - Predicate notInvited = tenant -> invitedCoTenants.stream().noneMatch(email -> email.equals(tenant.getEmail())); - return existingCoTenants.stream() - .filter(notInvited) - .collect(Collectors.toList()); - } - -} \ No newline at end of file diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/ClientAuthenticationFacadeImpl.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/ClientAuthenticationFacadeImpl.java index 057e027c4..9a2440df4 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/ClientAuthenticationFacadeImpl.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/ClientAuthenticationFacadeImpl.java @@ -10,6 +10,8 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.stereotype.Component; +import java.util.Optional; + @Component @RequiredArgsConstructor @Slf4j @@ -30,4 +32,10 @@ public String getKeycloakClientId() { public UserApi getClient() { return userApiService.findByName(getKeycloakClientId()).orElseThrow(ClientNotFoundException::new); } + + @Override + public Optional getApiVersion() { + return userApiService.findByName(getKeycloakClientId()).map(UserApi::getVersion); + } + } \ No newline at end of file diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/interfaces/ClientAuthenticationFacade.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/interfaces/ClientAuthenticationFacade.java index 23acdf8e8..46674f472 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/interfaces/ClientAuthenticationFacade.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/security/interfaces/ClientAuthenticationFacade.java @@ -2,8 +2,13 @@ import fr.dossierfacile.common.entity.UserApi; +import java.util.Optional; + public interface ClientAuthenticationFacade { String getKeycloakClientId(); UserApi getClient(); + + Optional getApiVersion(); + } \ No newline at end of file diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java index b904759b6..d31b46838 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java @@ -4,11 +4,9 @@ import fr.dossierfacile.api.front.exception.TenantNotFoundException; import fr.dossierfacile.common.converter.AcquisitionData; import fr.dossierfacile.api.front.model.KeycloakUser; -import fr.dossierfacile.api.front.model.tenant.EmailExistsModel; import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.register.RegisterFactory; import fr.dossierfacile.api.front.register.enums.StepRegister; -import fr.dossierfacile.api.front.register.form.partner.EmailExistsForm; import fr.dossierfacile.api.front.service.interfaces.KeycloakService; import fr.dossierfacile.api.front.service.interfaces.MailService; import fr.dossierfacile.api.front.service.interfaces.TenantService; @@ -88,14 +86,6 @@ public Tenant create(Tenant tenant) { return tenantRepository.save(tenant); } - @Override - public EmailExistsModel emailExists(EmailExistsForm emailExistsForm) { - return EmailExistsModel.builder() - .email(emailExistsForm.getEmail()) - .exists(tenantRepository.existsByEmail(emailExistsForm.getEmail())) - .build(); - } - @Override public Tenant findById(Long id) { return tenantRepository.findById(id).orElse(null); diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java index 829fd70a1..da6a64f3f 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java @@ -2,10 +2,8 @@ import fr.dossierfacile.common.converter.AcquisitionData; import fr.dossierfacile.api.front.model.KeycloakUser; -import fr.dossierfacile.api.front.model.tenant.EmailExistsModel; import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.register.enums.StepRegister; -import fr.dossierfacile.api.front.register.form.partner.EmailExistsForm; import fr.dossierfacile.common.entity.Tenant; import fr.dossierfacile.common.entity.UserApi; import fr.dossierfacile.common.model.TenantUpdate; @@ -21,8 +19,6 @@ public interface TenantService { Tenant create(Tenant tenant); - EmailExistsModel emailExists(EmailExistsForm emailExistsForm); - Tenant findById(Long coTenantId); Tenant findByKeycloakId(String keycloakId); diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/OtherResidencyToggle.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/OtherResidencyToggle.java deleted file mode 100644 index 6372d69ea..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/OtherResidencyToggle.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.dossierfacile.api.front.validator; - -import fr.dossierfacile.common.utils.DateBasedFeatureToggle; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Component -// TODO delete after activation -public class OtherResidencyToggle extends DateBasedFeatureToggle { - - public OtherResidencyToggle(@Value("${categories.otherresidency.activation.date:}") String otherResidencyActivationDate) { - super(otherResidencyActivationDate); - } - -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/CheckTenantTypeAcceptAccess.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/CheckTenantTypeAcceptAccess.java deleted file mode 100644 index f5ccbd061..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/CheckTenantTypeAcceptAccess.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.dossierfacile.api.front.validator.anotation.tenant.application; - -import fr.dossierfacile.api.front.validator.tenant.application.CheckTenantTypeAcceptAccessValidator; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Deprecated -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Constraint( - validatedBy = {CheckTenantTypeAcceptAccessValidator.class} -) -public @interface CheckTenantTypeAcceptAccess { - String message() default "accept access must not null"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/CheckTenantTypeCountListCoTenant.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/CheckTenantTypeCountListCoTenant.java deleted file mode 100644 index c94bc522e..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/CheckTenantTypeCountListCoTenant.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.dossierfacile.api.front.validator.anotation.tenant.application; - -import fr.dossierfacile.api.front.validator.tenant.application.CheckTenantTypeCountListCoTenantValidator; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Deprecated -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Constraint( - validatedBy = {CheckTenantTypeCountListCoTenantValidator.class} -) -public @interface CheckTenantTypeCountListCoTenant { - String message() default "there is no correspondence between the type of application and the number of co-tenants"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DeniedJoinTenant.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DeniedJoinTenant.java deleted file mode 100644 index c661a6812..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DeniedJoinTenant.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.dossierfacile.api.front.validator.anotation.tenant.application; - -import fr.dossierfacile.api.front.validator.tenant.application.DeniedJoinTenantValidator; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Deprecated -@Target({ElementType.TYPE, ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -@Constraint( - validatedBy = {DeniedJoinTenantValidator.class} -) -public @interface DeniedJoinTenant { - String message() default "join tenant cannot access to this step"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DistinctEmailList.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DistinctEmailList.java deleted file mode 100644 index d85760538..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DistinctEmailList.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.dossierfacile.api.front.validator.anotation.tenant.application; - -import fr.dossierfacile.api.front.validator.tenant.application.DistinctEmailListValidator; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) - -@Constraint( - validatedBy = {DistinctEmailListValidator.class} -) - -public @interface DistinctEmailList { - String message() default "the emails must be different"; - - Class[] groups() default {}; - - Class[] payload() default {}; - -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DistinctTenantPrincipalEmailListCoTenant.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DistinctTenantPrincipalEmailListCoTenant.java deleted file mode 100644 index 47709ca5d..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/DistinctTenantPrincipalEmailListCoTenant.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.dossierfacile.api.front.validator.anotation.tenant.application; - -import fr.dossierfacile.api.front.validator.tenant.application.DistinctTenantPrincipalEmailListCoTenantValidator; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Deprecated -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) - -@Constraint( - validatedBy = {DistinctTenantPrincipalEmailListCoTenantValidator.class} -) -public @interface DistinctTenantPrincipalEmailListCoTenant { - - String message() default "the co-tenants' email must be different from the email of the main tenant"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/UniqueEmailListCoTenant.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/UniqueEmailListCoTenant.java deleted file mode 100644 index f2270bfba..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/anotation/tenant/application/UniqueEmailListCoTenant.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.dossierfacile.api.front.validator.anotation.tenant.application; - -import fr.dossierfacile.api.front.validator.tenant.application.UniqueEmailListCoTenantValidator; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** deprecated since 202209 */ -@Deprecated -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Constraint( - validatedBy = {UniqueEmailListCoTenantValidator.class} -) -public @interface UniqueEmailListCoTenant { - - String message() default "the emails %s are already being used"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/guarantor/natural_person/residency/CustomTextResidencyGuarantorNaturalPersonValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/guarantor/natural_person/residency/CustomTextResidencyGuarantorNaturalPersonValidator.java index 2e50292cb..449364054 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/guarantor/natural_person/residency/CustomTextResidencyGuarantorNaturalPersonValidator.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/guarantor/natural_person/residency/CustomTextResidencyGuarantorNaturalPersonValidator.java @@ -1,7 +1,6 @@ package fr.dossierfacile.api.front.validator.guarantor.natural_person.residency; import fr.dossierfacile.api.front.register.form.guarantor.natural_person.DocumentResidencyGuarantorNaturalPersonForm; -import fr.dossierfacile.api.front.validator.OtherResidencyToggle; import fr.dossierfacile.api.front.validator.anotation.guarantor.natural_person.residency.CustomTextResidencyGuarantorNaturalPerson; import fr.dossierfacile.common.enums.DocumentSubCategory; import lombok.AllArgsConstructor; @@ -12,26 +11,18 @@ import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; -import static fr.dossierfacile.api.front.validator.tenant.residency.CustomTextResidencyValidator.rejectOtherResidencyCategory; import static fr.dossierfacile.api.front.validator.tenant.residency.CustomTextResidencyValidator.validateCustomText; -import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_RESIDENCY; @Slf4j @Component @AllArgsConstructor public class CustomTextResidencyGuarantorNaturalPersonValidator implements ConstraintValidator { - private final OtherResidencyToggle otherResidencyToggle; - @Override public boolean isValid(DocumentResidencyGuarantorNaturalPersonForm documentForm, ConstraintValidatorContext constraintValidatorContext) { boolean isCustomTextPresent = StringUtils.isNotBlank(documentForm.getCustomText()); DocumentSubCategory subCategory = documentForm.getTypeDocumentResidency(); - if (subCategory == OTHER_RESIDENCY && otherResidencyToggle.isNotActive()) { - return rejectOtherResidencyCategory(constraintValidatorContext, otherResidencyToggle); - } - return validateCustomText(constraintValidatorContext, subCategory, isCustomTextPresent); } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/CheckTenantTypeAcceptAccessValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/CheckTenantTypeAcceptAccessValidator.java deleted file mode 100644 index b256bbebb..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/CheckTenantTypeAcceptAccessValidator.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.dossierfacile.api.front.validator.tenant.application; - -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.CheckTenantTypeAcceptAccess; -import fr.dossierfacile.common.enums.ApplicationType; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -/** deprecated since 202209 */ -@Deprecated -public class CheckTenantTypeAcceptAccessValidator implements ConstraintValidator { - @Override - public void initialize(CheckTenantTypeAcceptAccess constraintAnnotation) { - //this method is empty - } - - @Override - public boolean isValid(ApplicationForm applicationForm, ConstraintValidatorContext constraintValidatorContext) { - boolean isValid = (applicationForm.getApplicationType() == ApplicationType.ALONE) - || ((applicationForm.getApplicationType() == ApplicationType.GROUP - || applicationForm.getApplicationType() == ApplicationType.COUPLE) - && applicationForm.getAcceptAccess() != null - && applicationForm.getAcceptAccess()); - - if (!isValid) { - constraintValidatorContext.disableDefaultConstraintViolation(); - constraintValidatorContext - .buildConstraintViolationWithTemplate("{javax.validation.constraints.AssertTrue.message}") - .addPropertyNode("acceptAccess").addConstraintViolation(); - } - - return isValid; - } -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/CheckTenantTypeCountListCoTenantValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/CheckTenantTypeCountListCoTenantValidator.java deleted file mode 100644 index 478aba351..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/CheckTenantTypeCountListCoTenantValidator.java +++ /dev/null @@ -1,29 +0,0 @@ -package fr.dossierfacile.api.front.validator.tenant.application; - -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.CheckTenantTypeCountListCoTenant; -import fr.dossierfacile.common.enums.ApplicationType; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -/** deprecated since 202209 */ -@Deprecated -public class CheckTenantTypeCountListCoTenantValidator implements ConstraintValidator { - - @Override - public void initialize(CheckTenantTypeCountListCoTenant constraintAnnotation) { - //this method is empty - } - - @Override - public boolean isValid(ApplicationForm applicationForm, ConstraintValidatorContext constraintValidatorContext) { - if (applicationForm.getApplicationType() == ApplicationType.COUPLE) { - return applicationForm.getCoTenantEmail().size() == 1; - } - if (applicationForm.getApplicationType() == ApplicationType.GROUP) { - return !applicationForm.getCoTenantEmail().isEmpty(); - } - return applicationForm.getCoTenantEmail().isEmpty(); - } -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DeniedJoinTenantValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DeniedJoinTenantValidator.java deleted file mode 100644 index 4e7f3695e..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DeniedJoinTenantValidator.java +++ /dev/null @@ -1,29 +0,0 @@ -package fr.dossierfacile.api.front.validator.tenant.application; - -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.security.interfaces.AuthenticationFacade; -import fr.dossierfacile.api.front.service.interfaces.TenantService; -import fr.dossierfacile.api.front.validator.TenantConstraintValidator; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.DeniedJoinTenant; -import fr.dossierfacile.common.enums.TenantType; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -/** deprecated since 202209 */ -@Deprecated -@Component -@RequiredArgsConstructor -public class DeniedJoinTenantValidator extends TenantConstraintValidator { - - @Override - public boolean isValid(ApplicationForm applicationForm, ConstraintValidatorContext constraintValidatorContext) { - var tenant = getTenant(applicationForm); - if (tenant == null) { - return true; - } - return tenant.getTenantType() != TenantType.JOIN; - } -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DistinctEmailListValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DistinctEmailListValidator.java deleted file mode 100644 index 135d3acde..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DistinctEmailListValidator.java +++ /dev/null @@ -1,21 +0,0 @@ -package fr.dossierfacile.api.front.validator.tenant.application; - -import fr.dossierfacile.api.front.validator.anotation.tenant.application.DistinctEmailList; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import java.util.List; - -public class DistinctEmailListValidator implements ConstraintValidator> { - - @Override - public void initialize(DistinctEmailList distinctEmailList) { - //this method is empty - } - - @Override - public boolean isValid(List coTenantForms, ConstraintValidatorContext constraintValidatorContext) { - return coTenantForms.stream().map(String::toLowerCase).distinct().count() == coTenantForms.size(); - } - -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DistinctTenantPrincipalEmailListCoTenantValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DistinctTenantPrincipalEmailListCoTenantValidator.java deleted file mode 100644 index cce00051a..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/DistinctTenantPrincipalEmailListCoTenantValidator.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.dossierfacile.api.front.validator.tenant.application; - -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.service.interfaces.TenantService; -import fr.dossierfacile.api.front.validator.TenantConstraintValidator; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.DistinctTenantPrincipalEmailListCoTenant; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -/** - * deprecated since 202209 - */ -@Deprecated -@Component -@AllArgsConstructor -public class DistinctTenantPrincipalEmailListCoTenantValidator extends TenantConstraintValidator { - - @Override - public boolean isValid(ApplicationForm applicationForm, ConstraintValidatorContext constraintValidatorContext) { - var tenant = getTenant(applicationForm); - if (tenant == null) { - return true; - } - var isValid = !applicationForm.getCoTenantEmail().contains(tenant.getEmail()); - if (!isValid) { - constraintValidatorContext.disableDefaultConstraintViolation(); - constraintValidatorContext - .buildConstraintViolationWithTemplate(constraintValidatorContext.getDefaultConstraintMessageTemplate()) - .addPropertyNode("coTenantEmail").addConstraintViolation(); - } - return isValid; - } -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/UniqueEmailListCoTenantValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/UniqueEmailListCoTenantValidator.java deleted file mode 100644 index 0c7c6f0e1..000000000 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/application/UniqueEmailListCoTenantValidator.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.dossierfacile.api.front.validator.tenant.application; - -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.security.interfaces.AuthenticationFacade; -import fr.dossierfacile.api.front.service.interfaces.TenantService; -import fr.dossierfacile.api.front.validator.TenantConstraintValidator; -import fr.dossierfacile.api.front.validator.anotation.tenant.application.UniqueEmailListCoTenant; -import fr.dossierfacile.common.repository.TenantCommonRepository; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import java.util.stream.Collectors; - -@Deprecated -@Component -@AllArgsConstructor -public class UniqueEmailListCoTenantValidator extends TenantConstraintValidator { - - private final TenantCommonRepository tenantRepository; - - @Override - public boolean isValid(ApplicationForm applicationForm, ConstraintValidatorContext constraintValidatorContext) { - var tenant = getTenant(applicationForm); - if (tenant == null) { - return true; - } - var existingEmails = tenantRepository.findByEmailInAndApartmentSharingNot(applicationForm.getCoTenantEmail(), tenant.getApartmentSharing()) - .stream() - .map( t -> t.getEmail()) - .collect(Collectors.toList()); - - if (!existingEmails.isEmpty()) { - constraintValidatorContext.disableDefaultConstraintViolation(); - String msgTemplate = String.format(constraintValidatorContext.getDefaultConstraintMessageTemplate(), - String.join(",", existingEmails)); - constraintValidatorContext - .buildConstraintViolationWithTemplate(msgTemplate) - .addPropertyNode("coTenantEmail").addConstraintViolation(); - return false; - } - return true; - } -} diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/residency/CustomTextResidencyValidator.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/residency/CustomTextResidencyValidator.java index e6fe16a77..6f4afcc6c 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/residency/CustomTextResidencyValidator.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/validator/tenant/residency/CustomTextResidencyValidator.java @@ -1,7 +1,6 @@ package fr.dossierfacile.api.front.validator.tenant.residency; import fr.dossierfacile.api.front.register.form.tenant.DocumentResidencyForm; -import fr.dossierfacile.api.front.validator.OtherResidencyToggle; import fr.dossierfacile.api.front.validator.anotation.tenant.residency.CustomTextResidency; import fr.dossierfacile.common.enums.DocumentSubCategory; import lombok.AllArgsConstructor; @@ -19,29 +18,14 @@ @AllArgsConstructor public class CustomTextResidencyValidator implements ConstraintValidator { - private final OtherResidencyToggle otherResidencyToggle; - @Override public boolean isValid(DocumentResidencyForm documentForm, ConstraintValidatorContext constraintValidatorContext) { boolean isCustomTextPresent = StringUtils.isNotBlank(documentForm.getCustomText()); DocumentSubCategory subCategory = documentForm.getTypeDocumentResidency(); - if (subCategory == OTHER_RESIDENCY && otherResidencyToggle.isNotActive()) { - return rejectOtherResidencyCategory(constraintValidatorContext, otherResidencyToggle); - } - return validateCustomText(constraintValidatorContext, subCategory, isCustomTextPresent); } - public static boolean rejectOtherResidencyCategory(ConstraintValidatorContext constraintValidatorContext, OtherResidencyToggle otherResidencyToggle) { - constraintValidatorContext.disableDefaultConstraintViolation(); - constraintValidatorContext - .buildConstraintViolationWithTemplate("OTHER_RESIDENCY will not be accepted until " + otherResidencyToggle.getActivationDate()) - .addConstraintViolation(); - log.info("Rejecting OTHER_RESIDENCY update because this category is not active yet"); - return false; - } - public static boolean validateCustomText(ConstraintValidatorContext constraintValidatorContext, DocumentSubCategory subCategory, boolean isCustomTextPresent) { if (subCategory == OTHER_RESIDENCY && !isCustomTextPresent) { constraintValidatorContext.disableDefaultConstraintViolation(); diff --git a/dossierfacile-api-tenant/src/main/resources/messages.properties b/dossierfacile-api-tenant/src/main/resources/messages.properties index 2361eaa51..9eec84878 100644 --- a/dossierfacile-api-tenant/src/main/resources/messages.properties +++ b/dossierfacile-api-tenant/src/main/resources/messages.properties @@ -35,6 +35,7 @@ tenant.profile.link5.v2=Justificatif de ressources tenant.profile.link6.v2=Attestation de garantie tenant.profile.link7.v2=Identification de la personne morale tenant.profile.link8.v2=Pièce d'identité du représentant de la personne morale +tenant.profile.link9.v2=Certificat de caution tenant.profile.link1.short.v2=Pièce d'identité tenant.profile.link2.short.v2=Domicile tenant.profile.link3.short.v2=Contrat de travail diff --git a/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/mapper/TenantMapperTest.java b/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/mapper/TenantMapperTest.java deleted file mode 100644 index ebe7e461d..000000000 --- a/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/mapper/TenantMapperTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package fr.dossierfacile.api.front.mapper; - -import fr.dossierfacile.api.front.model.tenant.DocumentModel; -import fr.dossierfacile.common.entity.Document; -import fr.dossierfacile.common.enums.DocumentSubCategory; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.EnumSource; - -import static fr.dossierfacile.common.enums.DocumentSubCategory.DRIVERS_LICENSE; -import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER; -import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_IDENTIFICATION; -import static org.assertj.core.api.Assertions.assertThat; - -class TenantMapperTest { - - private final TenantMapper mapper = new TenantMapperImpl(); - - @ParameterizedTest - @EnumSource(value = DocumentSubCategory.class, - names = {"INTERMITTENT", "STAY_AT_HOME_PARENT", "NO_ACTIVITY", "ARTIST"}) - @DisplayName("New professional categories are replaced by 'OTHER' in field 'documentSubCategory'") - void should_replace_new_professional_categories_by_other(DocumentSubCategory subCategory) { - DocumentModel documentModel = mapDocumentWithSubCategory(subCategory); - - assertThat(documentModel.getDocumentSubCategory()).isEqualTo(OTHER); - } - - @ParameterizedTest - @CsvSource({ - "GUEST_ORGANISM, GUEST", - "SHORT_TERM_RENTAL, TENANT" - }) - @DisplayName("New residency categories are replaced by existing ones in field 'documentSubCategory'") - void should_replace_new_residency_categories(DocumentSubCategory newSubCategory, DocumentSubCategory existingSubCategory) { - DocumentModel documentModel = mapDocumentWithSubCategory(newSubCategory); - - assertThat(documentModel.getDocumentSubCategory()).isEqualTo(existingSubCategory); - } - - @Test - @DisplayName("Driver's license is replaced by 'OTHER_IDENTIFICATION' in field 'documentSubCategory'") - void should_replace_drivers_license_by_other() { - DocumentModel documentModel = mapDocumentWithSubCategory(DRIVERS_LICENSE); - - assertThat(documentModel.getDocumentSubCategory()).isEqualTo(OTHER_IDENTIFICATION); - } - - @ParameterizedTest - @EnumSource(value = DocumentSubCategory.class) - @DisplayName("All categories are mapped as is in field 'subCategory'") - void should_expose_all_categories(DocumentSubCategory subCategory) { - DocumentModel documentModel = mapDocumentWithSubCategory(subCategory); - - assertThat(documentModel.getSubCategory()).isEqualTo(subCategory); - } - - private DocumentModel mapDocumentWithSubCategory(DocumentSubCategory subCategory) { - Document document = Document.builder() - .documentSubCategory(subCategory) - .build(); - - return mapper.toDocumentModel(document); - } - -} \ No newline at end of file diff --git a/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/register/tenant/ApplicationV1Test.java b/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/register/tenant/ApplicationV1Test.java deleted file mode 100644 index e79c07c13..000000000 --- a/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/register/tenant/ApplicationV1Test.java +++ /dev/null @@ -1,103 +0,0 @@ -package fr.dossierfacile.api.front.register.tenant; - -import fr.dossierfacile.api.front.register.form.tenant.ApplicationForm; -import fr.dossierfacile.api.front.register.form.tenant.CoTenantForm; -import fr.dossierfacile.common.entity.ApartmentSharing; -import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.enums.ApplicationType; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.stream.Collectors; - -import static java.util.Collections.emptyList; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -class ApplicationV1Test { - - private final Tenant CO_TENANT_1 = Tenant.builder().id(1L).email("111@test.fr").build(); - private final Tenant CO_TENANT_2 = Tenant.builder().id(2L).email("222@test.fr").build(); - - private final Application application = mock(Application.class); - private final ApplicationV1 applicationV1 = new ApplicationV1(application); - - @Test - void should_add_new_cotenant() { - Tenant tenant = buildTenantWith(CO_TENANT_1); - - whenCoTenantsAreInvited(tenant, "111@test.fr", "222@test.fr"); - - expectCreatedCoTenants(tenant, List.of("222@test.fr")); - expectDeletedCoTenants(tenant, emptyList()); - } - - @Test - void should_keep_existing_cotenant() { - Tenant tenant = buildTenantWith(CO_TENANT_1); - - whenCoTenantsAreInvited(tenant, "111@test.fr"); - - expectCreatedCoTenants(tenant, emptyList()); - expectDeletedCoTenants(tenant, emptyList()); - } - - @Test - void should_remove_existing_cotenant() { - Tenant tenant = buildTenantWith(CO_TENANT_1, CO_TENANT_2); - - whenCoTenantsAreInvited(tenant, "111@test.fr"); - - expectCreatedCoTenants(tenant, emptyList()); - expectDeletedCoTenants(tenant, List.of(CO_TENANT_2)); - } - - @Test - void should_remove_all_cotenant() { - Tenant tenant = buildTenantWith(CO_TENANT_1, CO_TENANT_2); - - whenCoTenantsAreInvited(tenant); - - expectCreatedCoTenants(tenant, emptyList()); - expectDeletedCoTenants(tenant, List.of(CO_TENANT_1, CO_TENANT_2)); - } - - @Test - void should_add_and_remove_cotenants() { - Tenant tenant = buildTenantWith(CO_TENANT_1); - - whenCoTenantsAreInvited(tenant, "222@test.fr"); - - expectDeletedCoTenants(tenant, List.of(CO_TENANT_1)); - expectCreatedCoTenants(tenant, List.of("222@test.fr")); - } - - private static Tenant buildTenantWith(Tenant... existingCoTenants) { - Tenant tenant = Tenant.builder().build(); - ApartmentSharing apartmentSharing = new ApartmentSharing(); - tenant.setApartmentSharing(apartmentSharing); - apartmentSharing.setTenants(List.of(existingCoTenants)); - return tenant; - } - - private void whenCoTenantsAreInvited(Tenant tenant, String... invitedCoTenants) { - ApplicationForm applicationForm = new ApplicationForm(); - applicationForm.setApplicationType(ApplicationType.GROUP); - applicationForm.setCoTenantEmail(List.of(invitedCoTenants)); - applicationV1.saveStep(tenant, applicationForm); - } - - private void expectCreatedCoTenants(Tenant tenant, List createdCoTenantsEmails) { - List coTenantForms = createdCoTenantsEmails.stream() - .map(email -> new CoTenantForm("", "", "", email)) - .collect(Collectors.toList()); - verify(application).saveStep(eq(tenant), eq(ApplicationType.GROUP), any(), eq(coTenantForms)); - } - - private void expectDeletedCoTenants(Tenant tenant, List deletedCoTenants) { - verify(application).saveStep(eq(tenant), eq(ApplicationType.GROUP), eq(deletedCoTenants), any()); - } - -} \ No newline at end of file diff --git a/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/validator/OtherResidencyToggleTest.java b/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/validator/OtherResidencyToggleTest.java deleted file mode 100644 index 3994c9c58..000000000 --- a/dossierfacile-api-tenant/src/test/java/fr/dossierfacile/api/front/validator/OtherResidencyToggleTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.dossierfacile.api.front.validator; - -import org.junit.jupiter.api.Test; - -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; - -import static org.assertj.core.api.Assertions.assertThat; - -class OtherResidencyToggleTest { - - @Test - void should_be_active_if_no_date() { - OtherResidencyToggle toggle = new OtherResidencyToggle(""); - - assertThat(toggle.isNotActive()).isFalse(); - } - - @Test - void should_be_active() { - String activationDate = LocalDate.now().format(DateTimeFormatter.ISO_DATE); - OtherResidencyToggle toggle = new OtherResidencyToggle(activationDate); - - assertThat(toggle.isNotActive()).isFalse(); - } - - @Test - void should_not_be_active() { - String activationDate = LocalDate.now().plusDays(1).format(DateTimeFormatter.ISO_DATE); - OtherResidencyToggle toggle = new OtherResidencyToggle(activationDate); - - assertThat(toggle.isNotActive()).isTrue(); - } - -} \ No newline at end of file diff --git a/dossierfacile-api-watermark/.java-version b/dossierfacile-api-watermark/.java-version index 6ea9a3bd4..5f39e9144 100644 --- a/dossierfacile-api-watermark/.java-version +++ b/dossierfacile-api-watermark/.java-version @@ -1 +1 @@ -19.0 +21.0 diff --git a/dossierfacile-api-watermark/pom.xml b/dossierfacile-api-watermark/pom.xml index 6ac95ce8e..5bf0c54ad 100644 --- a/dossierfacile-api-watermark/pom.xml +++ b/dossierfacile-api-watermark/pom.xml @@ -17,7 +17,7 @@ - 19 + 21 ${java.version} ${java.version} 1.4.2.Final diff --git a/dossierfacile-bo/.java-version b/dossierfacile-bo/.java-version index 6ea9a3bd4..5f39e9144 100644 --- a/dossierfacile-bo/.java-version +++ b/dossierfacile-bo/.java-version @@ -1 +1 @@ -19.0 +21.0 diff --git a/dossierfacile-bo/pom.xml b/dossierfacile-bo/pom.xml index b45e0da58..8d7c8e8af 100644 --- a/dossierfacile-bo/pom.xml +++ b/dossierfacile-bo/pom.xml @@ -21,7 +21,7 @@ 6.0.20.Final UTF-8 UTF-8 - 19 + 21 ${java.version} ${java.version} 2.11.0 diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOController.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOController.java index 5ab7a1666..86af58da3 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOController.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOController.java @@ -38,7 +38,6 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import java.security.Principal; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -49,7 +48,6 @@ @Controller @RequiredArgsConstructor public class BOController { - private static final int BUTTONS_TO_SHOW = 5; private static final String EMAIL = "email"; private static final String PAGER = "pager"; @@ -101,18 +99,6 @@ public String loginPage(Model model) { return "login"; } - @GetMapping("/callback/manually/{userApiId}") - public String callBackManuallyToUserApi(@PathVariable("userApiId") Long userApiId, @RequestParam("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime since) { - tenantService.sendCallBacksManuallyToUserApi(userApiId, since); - return REDIRECT_BO; - } - - @GetMapping("/computeStatusOfAllTenants") - public String computeStatusOfAllTenants() { - tenantService.computeStatusOfAllTenants(); - return REDIRECT_BO; - } - @GetMapping("/bo/documentFailedList") public String documentFailedList(Model model, @RequestParam("pageSize") Optional pageSize, @RequestParam("page") Optional page) { EmailDTO emailDTO = new EmailDTO(); @@ -276,26 +262,6 @@ public String regeneratePdfDocument(RedirectAttributes redirectAttributes, @Mode return REDIRECT_BO; } - @PostMapping(value = "/bo/regenerateStatusOfTenants") - public String regenerateStatusOfTenants(@RequestParam("email") String email) { - tenantService.updateStatusOfSomeTenants(email); - return REDIRECT_BO; - } - - @GetMapping("/bo/computeTenantsStatus") - public String computeTenantStatus(Model model) { - EmailDTO emailDTO = new EmailDTO(); - model.addAttribute("tenantList", emailDTO); - model.addAttribute(EMAIL, emailDTO); - return "bo/compute-status"; - } - - @GetMapping("/update/documents/creationDate") - public String updateDocumentsWithNullCreationDate() { - tenantService.updateDocumentsWithNullCreationDateTime(); - return REDIRECT_BO; - } - @AllArgsConstructor @Getter static class ClientRegistrationLight { diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BORestController.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BORestController.java deleted file mode 100644 index 2f9182b13..000000000 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BORestController.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.gouv.bo.controller; - -import fr.gouv.bo.dto.ApartmentSharingDTO01; -import fr.gouv.bo.model.DataTable; -import fr.gouv.bo.service.ApartmentSharingService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RequiredArgsConstructor -@RestController -@Slf4j -public class BORestController { - - private final ApartmentSharingService apartmentSharingService; - - @GetMapping("/bo/colocation/table") - public ResponseEntity> listAllTable(@RequestParam("draw") int draw, - @RequestParam("start") int start, - @RequestParam("length") int length) { - int page = start / length; //Calculate page number - - Pageable pageable = PageRequest.of( - page, - length, - Sort.by(Sort.Direction.DESC, "id") - ); - Page responseData = apartmentSharingService.findAll(pageable); - DataTable dataTable = new DataTable<>(); - dataTable.setData(responseData.getContent()); - dataTable.setRecordsTotal(responseData.getTotalElements()); - dataTable.setRecordsFiltered(responseData.getTotalElements()); - - dataTable.setDraw(draw); - dataTable.setStart(start); - return ResponseEntity.ok(dataTable); - - } -} diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOToolsController.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOToolsController.java index d81eb827b..248da9215 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOToolsController.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/controller/BOToolsController.java @@ -1,67 +1,42 @@ package fr.gouv.bo.controller; -import fr.dossierfacile.common.entity.StorageFile; -import fr.dossierfacile.common.repository.StorageFileRepository; -import fr.dossierfacile.common.service.interfaces.FileStorageService; import fr.gouv.bo.dto.EmailDTO; -import fr.gouv.bo.service.ToolsService; +import fr.gouv.bo.service.TenantService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.IOUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - - @Slf4j @Controller @RequiredArgsConstructor @PreAuthorize("hasRole('ROLE_ADMIN')") public class BOToolsController { - - private final FileStorageService fileStorageService; - private final StorageFileRepository storageFileRepository; - - private final ToolsService toolsService; + private final TenantService tenantService; @GetMapping("/bo/tools") public String outils(Model model) { model.addAttribute("email", new EmailDTO()); - model.addAttribute("files", toolsService.getFiles()); return "bo/tools"; } - @PostMapping("/bo/tools/lamanufacture") - public String lamanufacture(Model model, @RequestParam("count") int count) { + /** + * Emails list split by "," + */ + @PostMapping(value = "/bo/tools/regenerateStatusOfTenants") + public String regenerateStatusOfTenants(@RequestParam("tenantList") String tenantList, Model model) { try { - toolsService.generateLastTreatedDossiers(count); + tenantService.updateStatusOfSomeTenants(tenantList); } catch (Exception e) { - log.error("not working"); - } - - return "redirect:/bo/tools"; - } - - @GetMapping(value = "/bo/tools/lamanufacture/files/{fileId}") - public void getLaManufactureFiles(HttpServletResponse response, @PathVariable("fileId") Long fileId) { - // Get zip from storage Id - StorageFile file = storageFileRepository.findById(fileId).get(); - - try (InputStream in = fileStorageService.download(file)) { - response.setContentType(file.getContentType()); - IOUtils.copy(in, response.getOutputStream()); - } catch (final IOException e) { - log.error("Error", e); - response.setStatus(404); + log.error("Error regenerating status for tenants", e); + model.addAttribute("errorMessage", "Quelque chose c'est mal passé: " + e.getMessage()); } + model.addAttribute("email", new EmailDTO()); + return "bo/tools"; } } \ No newline at end of file diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/mapper/TenantMapperForOperator.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/mapper/TenantMapperForOperator.java deleted file mode 100644 index 2fa877921..000000000 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/mapper/TenantMapperForOperator.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.gouv.bo.mapper; - -import fr.dossierfacile.common.entity.ApartmentSharing; -import fr.dossierfacile.common.entity.Document; -import fr.dossierfacile.common.entity.File; -import fr.dossierfacile.common.entity.Tenant; -import fr.gouv.bo.model.tenant.ApartmentSharingModel; - -import fr.gouv.bo.model.tenant.DocumentModel; -import fr.gouv.bo.model.tenant.FileModel; -import fr.gouv.bo.model.tenant.TenantModel; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.springframework.stereotype.Component; - -@Component -@Mapper(componentModel = "spring") -public abstract class TenantMapperForOperator { - - public abstract TenantModel toTenantModel(Tenant tenant); - - @Mapping(target = "name", ignore = true) - public abstract DocumentModel toDocumentModel(Document document); - - @Mapping(target = "originalName", ignore = true) - @Mapping(target = "path", expression = "java((file.getStorageFile() != null )? file.getStorageFile().getPath() : null)") - @Mapping(target = "contentType", expression = "java((file.getStorageFile() != null )? file.getStorageFile().getContentType() : null)") - public abstract FileModel toFileModel(File file); - - - @Mapping(target = "token", ignore = true) - @Mapping(target = "tokenPublic", ignore = true) - @Mapping(target = "dossierPdfUrl", ignore = true) - public abstract ApartmentSharingModel toApartmentSharingModel(ApartmentSharing apartmentSharing); - -} diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/repository/DocumentRepository.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/repository/DocumentRepository.java index 0169dcba3..3529df3aa 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/repository/DocumentRepository.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/repository/DocumentRepository.java @@ -15,9 +15,6 @@ public interface DocumentRepository extends JpaRepository { - @Query(value = "SELECT d.* FROM document d WHERE d.creation_date is null ORDER BY d.id DESC", nativeQuery = true) - Page findDocumentsByCreationDateTimeIsNull(Pageable pageable); - @Query(value = """ SELECT d.id FROM Document d diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/KeycloakService.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/KeycloakService.java index ce9b73525..4848ff35e 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/KeycloakService.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/KeycloakService.java @@ -1,6 +1,7 @@ package fr.gouv.bo.service; import fr.dossierfacile.common.entity.User; +import fr.dossierfacile.common.entity.UserApi; import org.keycloak.representations.idm.UserRepresentation; import java.util.List; @@ -11,4 +12,6 @@ public interface KeycloakService { void deleteKeycloakSingleUser(User tenant); void deleteKeycloakUsers(List tenants); + + void createKeycloakClient(UserApi userApi); } diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/TenantService.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/TenantService.java index 323e2c920..530066994 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/TenantService.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/TenantService.java @@ -10,7 +10,6 @@ import fr.dossierfacile.common.entity.OperatorLog; import fr.dossierfacile.common.entity.Tenant; import fr.dossierfacile.common.entity.User; -import fr.dossierfacile.common.entity.UserApi; import fr.dossierfacile.common.enums.ActionOperatorType; import fr.dossierfacile.common.enums.ApplicationType; import fr.dossierfacile.common.enums.DocumentCategory; @@ -20,8 +19,6 @@ import fr.dossierfacile.common.enums.PartnerCallBackType; import fr.dossierfacile.common.enums.TenantFileStatus; import fr.dossierfacile.common.enums.TenantType; -import fr.dossierfacile.common.exceptions.NotFoundException; -import fr.dossierfacile.common.model.WebhookDTO; import fr.dossierfacile.common.repository.TenantCommonRepository; import fr.dossierfacile.common.service.interfaces.PartnerCallBackService; import fr.gouv.bo.dto.CustomMessage; @@ -38,11 +35,9 @@ import fr.gouv.bo.repository.DocumentDeniedReasonsRepository; import fr.gouv.bo.repository.DocumentRepository; import fr.gouv.bo.repository.OperatorLogRepository; -import fr.gouv.bo.repository.UserApiRepository; import fr.gouv.bo.security.UserPrincipal; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.keycloak.representations.idm.UserRepresentation; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.MessageSource; @@ -51,7 +46,6 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -66,6 +60,10 @@ import java.util.Optional; import java.util.stream.Collectors; +import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.apache.commons.lang3.StringUtils.isNotEmpty; +import static org.apache.commons.lang3.StringUtils.isNumeric; + @Service @RequiredArgsConstructor @Slf4j @@ -83,7 +81,6 @@ public class TenantService { private final MessageSource messageSource; private final DocumentRepository documentRepository; private final DocumentDeniedReasonsRepository documentDeniedReasonsRepository; - private final UserApiRepository userApiRepository; private final MessageService messageService; private final BOApartmentSharingRepository apartmentSharingRepository; private final OperatorLogRepository operatorLogRepository; @@ -108,7 +105,7 @@ public class TenantService { public List getTenantByIdOrEmail(EmailDTO emailDTO) { List tenantList = new ArrayList<>(); - if (StringUtils.isNumeric(emailDTO.getEmail())) { + if (isNumeric(emailDTO.getEmail())) { tenantList.add(tenantRepository.findOneById(Long.parseLong(emailDTO.getEmail()))); return tenantList; } @@ -410,63 +407,6 @@ public void declineTenant(Principal principal, Long tenantId) { changeTenantStatusToDeclined(tenant, operator, null, ProcessedDocuments.NONE); } - public void sendCallBacksManuallyToUserApi(Long userApiId, LocalDateTime since) { - synchronized (this) { - UserApi userApi = userApiRepository.findOneById(userApiId).orElseThrow(NotFoundException::new); - - //Finding the IDs of tenants pending to send info for partner with ID 2. - List ids = tenantRepository.listIdTenantsAccountCompletedPendingToSendCallBack(userApiId, since); - int numberOfTotalCalls = ids.size(); - log.info(numberOfTotalCalls + " tenants pending to send the validation information to the partner."); - int indexCall = 1; - for (Long id : ids) { - Tenant tenant = tenantRepository.findOneById(id); - WebhookDTO webhookDTO = partnerCallBackService.getWebhookDTO(tenant, userApi, PartnerCallBackType.VERIFIED_ACCOUNT); - partnerCallBackService.sendCallBack(tenant, webhookDTO); - - if (indexCall < numberOfTotalCalls) { - try { - indexCall++; - log.info("Waiting 50ms for the next call..."); - this.wait(50); //It will wait 3 minutes to send the next callback - } catch (InterruptedException e) { - log.error("InterruptedException sendCallBacksManually ", e); - Thread.currentThread().interrupt(); - } - } - } - } - } - - @Transactional - public void computeStatusOfAllTenants() { - int numberOfUpdate = 1; - int lengthOfPage = 1000; - Pageable page = PageRequest.of(0, lengthOfPage, Sort.Direction.DESC, "id"); - Page allTenants = tenantRepository.findAllTenants(page); - - while (!allTenants.isEmpty()) { - page = page.next(); - - updatePage(numberOfUpdate++, allTenants); - - allTenants = tenantRepository.findAllTenants(page); - } - log.info("Update for [" + allTenants.getTotalElements() + "] tenants finished"); - } - - - private void updatePage(int numberOfUpdate, Page allTenants) { - List tenantsToChange = new ArrayList<>(); - allTenants.forEach(tenant -> { - tenant.setStatus(tenant.computeStatus()); - tenantsToChange.add(tenant); - }); - - tenantRepository.saveAll(tenantsToChange); - log.info("Update number [" + numberOfUpdate + "] for " + allTenants.getNumberOfElements() + " tenants finished"); - } - private int checkValueOfCustomMessage(CustomMessage customMessage) { List messageItems = customMessage.getMessageItems(); @@ -474,12 +414,11 @@ private int checkValueOfCustomMessage(CustomMessage customMessage) { if (!messageItems.isEmpty()) { for (MessageItem messageItem : messageItems) { - ItemDetail messageItemCheck = messageItem.getItemDetailList().stream().filter(itemDetail -> - !messageItem.getCommentDoc().isEmpty() || itemDetail.isCheck()).findAny().orElse(null); - if (messageItemCheck != null) { + boolean messageItemCheck = messageItem.getItemDetailList().stream() + .anyMatch(ItemDetail::isCheck); + if (messageItemCheck || isNotEmpty(messageItem.getCommentDoc())) { forTenant = 2; allMessageResult = forTenant; - } } } @@ -489,9 +428,9 @@ private int checkValueOfCustomMessage(CustomMessage customMessage) { for (GuarantorItem guarantorItem : guarantorItems) { messageItems = guarantorItem.getMessageItems(); for (MessageItem messageItem : messageItems) { - ItemDetail messageItemCheckGuarantor = messageItem.getItemDetailList().stream().filter(itemDetail -> - !messageItem.getCommentDoc().isEmpty() || itemDetail.isCheck()).findAny().orElse(null); - if (messageItemCheckGuarantor != null) { + boolean messageItemCheckGuarantor = messageItem.getItemDetailList().stream() + .anyMatch(ItemDetail::isCheck); + if (messageItemCheckGuarantor || isNotEmpty(messageItem.getCommentDoc())) { allMessageResult = forTenant + 5; } } @@ -605,7 +544,7 @@ private void changeTenantStatusToValidated(Tenant tenant, User operator, Process if (tenant.getApartmentSharing().getTenants().stream() .allMatch(t -> t.getStatus() == TenantFileStatus.VALIDATED)) { tenant.getApartmentSharing().getTenants().stream() - .filter(t -> StringUtils.isNotBlank(t.getEmail())) + .filter(t -> isNotBlank(t.getEmail())) .forEach(t -> mailService.sendEmailToTenantAfterValidateAllDocuments(t)); } } @@ -624,7 +563,7 @@ private void changeTenantStatusToDeclined(Tenant tenant, User operator, Message )); if (tenant.getApartmentSharing().getApplicationType() == ApplicationType.COUPLE) { tenant.getApartmentSharing().getTenants().stream() - .filter(t -> StringUtils.isNotBlank(t.getEmail())) + .filter(t -> isNotBlank(t.getEmail())) .forEach(t -> mailService.sendEmailToTenantAfterTenantDenied(t, tenant)); } else { mailService.sendMailNotificationAfterDeny(tenant); @@ -731,38 +670,6 @@ public List getMissingDocuments(Guarantor guarantor, List documents = documentRepository.findDocumentsByCreationDateTimeIsNull(page); - long totalElements = documents.getTotalElements(); - log.info("[" + totalElements + "] documents to update with [creation_date=null]"); - while (!documents.isEmpty()) { - page = page.next(); - - updatePageOfDocumentsWithNullCreationDateTime(documents); - log.info("Update number [" + numberOfUpdate++ + "] for " + documents.getNumberOfElements() + " documents finished"); - - documents = documentRepository.findDocumentsByCreationDateTimeIsNull(page); - } - log.info("[" + totalElements + "] documents updated with [creation_date=null] finished"); - } - - private void updatePageOfDocumentsWithNullCreationDateTime(Page documents) { - documents.forEach(document -> { - if (document.getCreationDateTime() == null) { - if (document.getTenant() != null) { - document.setCreationDateTime(document.getTenant().getLastUpdateDate()); - } else if (document.getGuarantor() != null) { - document.setCreationDateTime(document.getGuarantor().getTenant().getLastUpdateDate()); - } - documentRepository.save(document); - } - }); - } - public long getCountOfTenantsWithFailedGeneratedPdfDocument() { return tenantRepository.countAllTenantsWithoutPdfDocument(); } diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/ToolsService.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/ToolsService.java deleted file mode 100644 index a6779e3f2..000000000 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/ToolsService.java +++ /dev/null @@ -1,159 +0,0 @@ -package fr.gouv.bo.service; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import fr.dossierfacile.common.entity.Document; -import fr.dossierfacile.common.entity.Guarantor; -import fr.dossierfacile.common.entity.StorageFile; -import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.repository.StorageFileRepository; -import fr.dossierfacile.common.repository.TenantCommonRepository; -import fr.dossierfacile.common.service.interfaces.FileStorageService; -import fr.gouv.bo.mapper.TenantMapperForOperator; -import fr.gouv.bo.model.tenant.TenantModel; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.UUID; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * Temporary code for extract data for Manufacture POC - */ -@RequiredArgsConstructor -@Service -@Slf4j -public class ToolsService { - - private final TenantMapperForOperator tenantMapper; - private final TenantCommonRepository tenantCommonRepository; - private final StorageFileRepository storageFileRepository; - private final FileStorageService fileStorageService; - - public void generateLastTreatedDossiers(int count) throws Exception { - // First generate the "count" dossier - for ( int i = 0 ; i < (count/10) ; i++) { - Pageable pageable = PageRequest.of( - i, - 10, - Sort.by(Sort.Direction.DESC, "lastUpdateDate") - ); - List tenants = tenantCommonRepository.findTenantsToExtract(pageable); - - // then create the zip - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String zipName = "zip-" + UUID.randomUUID() +".zip"; - // Création d'un flux de sortie vers le fichier ZIP - FileOutputStream fos = new FileOutputStream(zipName); - ZipOutputStream zos = new ZipOutputStream(fos); - - for (Tenant tenant : tenants) { - - TenantModel t = tenantMapper.toTenantModel(tenant); - JsonElement je = JsonParser.parseString(objectMapper.writeValueAsString(t)); - - // on traite les fichiers - for (Document d : tenant.getDocuments()) { - for(fr.dossierfacile.common.entity.File f : d.getFiles()) { - try (InputStream fileInputStream = fileStorageService.download(f.getStorageFile())) { - - zos.putNextEntry(new ZipEntry("tid-" + t.getId() + "/doc-" + d.getId() + "/" + f.getStorageFile().getPath())); - - byte[] buffer = new byte[4096]; - int length; - while ((length = fileInputStream.read(buffer)) > 0) { - zos.write(buffer, 0, length); - } - zos.closeEntry(); - } catch (Exception e) { - log.error("Error manufacture", e); - zos.closeEntry(); - } - log.info("Fichier File traitré id:" + f.getId()); - } - } - // guarantor - for (Guarantor g : tenant.getGuarantors()) { - for (Document d : g.getDocuments()) { - for(fr.dossierfacile.common.entity.File f : d.getFiles()) { - try (InputStream fileInputStream = fileStorageService.download(f.getStorageFile())) { - - zos.putNextEntry(new ZipEntry("tid-" + t.getId() + "/doc-" + d.getId() + "/" + f.getStorageFile().getPath())); - - byte[] buffer = new byte[4096]; - int length; - while ((length = fileInputStream.read(buffer)) > 0) { - zos.write(buffer, 0, length); - } - zos.closeEntry(); - } catch (Exception e) { - log.error("Error manufacture", e); - zos.closeEntry(); - } - log.info("Fichier File traitré id:" + f.getId()); - } - } - } - // on traite le tenant en json - String tenantString = gson.toJson(je); - byte[] bytes = tenantString.getBytes(); - InputStream inputStream = new ByteArrayInputStream(bytes); - - try { - zos.putNextEntry(new ZipEntry("tid-" + t.getId() + ".json")); - byte[] buffer = new byte[4096]; - int length; - while ((length = inputStream.read(buffer)) > 0) { - zos.write(buffer, 0, length); - } - zos.closeEntry(); - } catch (Exception e) { - e.printStackTrace(); - log.error("Error manufacture", e); - zos.closeEntry(); - } - } - - zos.close(); - - log.info("ZIP NAME = " + zipName); - //then push the zip - try { - File file = new File(zipName); - - try (InputStream zipInputStream = new FileInputStream(file)) { - StorageFile sfile = StorageFile.builder() - .name("zip-manufacture.zip") - .contentType("application/zip") - .build(); - fileStorageService.upload(zipInputStream, sfile); - } - } catch (IOException e) { - log.error("zip probleme"); - } - } - - } - - public List getFiles() { - return storageFileRepository.findAllByName("zip-manufacture.zip"); - } -} diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/UserApiService.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/UserApiService.java index 03f79c863..490e028e2 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/UserApiService.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/UserApiService.java @@ -17,7 +17,7 @@ @Service @Slf4j public class UserApiService { - + private final KeycloakService keycloakService; private final UserApiRepository userApiRepository; private final ObjectMapper mapper; @@ -36,11 +36,12 @@ public List findPartnersLinkedToTenant(Long id) { } public List findAll() { - return userApiRepository.findAll(Sort.by("disabled","name")); + return userApiRepository.findAll(Sort.by("disabled", "name")); } public UserApi create(UserApiDTO userApiDTO) { UserApi userApi = mapper.convertValue(userApiDTO, UserApi.class); + keycloakService.createKeycloakClient(userApi); return userApiRepository.save(userApi); } diff --git a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/impl/KeycloakServiceImpl.java b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/impl/KeycloakServiceImpl.java index c1336791a..11d0df0fe 100644 --- a/dossierfacile-bo/src/main/java/fr/gouv/bo/service/impl/KeycloakServiceImpl.java +++ b/dossierfacile-bo/src/main/java/fr/gouv/bo/service/impl/KeycloakServiceImpl.java @@ -1,15 +1,19 @@ package fr.gouv.bo.service.impl; import fr.dossierfacile.common.entity.User; +import fr.dossierfacile.common.entity.UserApi; import fr.gouv.bo.service.KeycloakService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.springframework.stereotype.Service; import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.Response; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -48,4 +52,30 @@ public void deleteKeycloakSingleUser(User tenant) { public void deleteKeycloakUsers(List tenants) { tenants.forEach(t -> deleteKeycloakSingleUser(t)); } + + @Override + public void createKeycloakClient(UserApi userApi) { + + String clientTemplateName = (userApi.getName().startsWith("dfconnect-")) ? "dfconnect-template" : + ((userApi.getName().startsWith("hybrid-")) ? "hybrid-template" : null); + + ClientRepresentation clientTemplate = realmResource.clients() + .findByClientId(clientTemplateName).get(0); + + clientTemplate.setId(null); + clientTemplate.setClientId(userApi.getName()); + clientTemplate.setDescription("Client DFC pour " + userApi.getName2() + " créé le " + LocalDateTime.now().toString()); + clientTemplate.setName(userApi.getName2()); + clientTemplate.setSecret(null); + clientTemplate.getProtocolMappers().stream().forEach((pm) -> pm.setId(null)); + clientTemplate.setAttributes(null); + clientTemplate.setEnabled(true); + + Response response = realmResource.clients().create(clientTemplate); + log.info(" status = " + response.getStatus()); + if (response.getStatus() != Response.Status.CREATED.getStatusCode()) { + throw new IllegalStateException("Status de retour création de client " + +response.getStatus()); + } + } + } diff --git a/dossierfacile-bo/src/main/resources/messages.properties b/dossierfacile-bo/src/main/resources/messages.properties index 59e982c59..6fb55b459 100644 --- a/dossierfacile-bo/src/main/resources/messages.properties +++ b/dossierfacile-bo/src/main/resources/messages.properties @@ -20,6 +20,7 @@ tenant.profile.link2.v2=Justificatif de situation d'hébergement tenant.profile.link3.v2=Justificatif d'activité professionnelle tenant.profile.link4.v2=Avis d'imposition conforme tenant.profile.link5.v2=Justificatif de ressources +tenant.profile.link9.v2=Certificat de caution tenant.profile.help=(de 1 à 3 documents) tenant.profile.add.input=Ajouter un document supplémentaire locatio.header.link.login=Me connecter @@ -60,6 +61,7 @@ document_sub_category.FRENCH_IDENTITY_CARD=Carte d'identité document_sub_category.FRENCH_PASSPORT=Passeport document_sub_category.FRENCH_RESIDENCE_PERMIT=Titre de séjour français document_sub_category.DRIVERS_LICENSE=Permis de conduire +document_sub_category.FRANCE_IDENTITE=France Identité document_sub_category.OTHER_IDENTIFICATION=Autre document_sub_category.CERTIFICATE_VISA=Visa @@ -99,6 +101,8 @@ document_sub_category.MY_PARENTS=Au nom des parents document_sub_category.LESS_THAN_YEAR=En France depuis moins d'un an document_sub_category.OTHER_TAX=Autre +document_sub_category.VISALE=VISALE +document_sub_category.OTHER_GUARANTEE=Autre document_sub_category.LEGAL_PERSON=Personne morale document_sub_category.UNDEFINED=Non défini document_sub_category.OTHER_PROFESSION_GUARANTOR=Autre profession du garant diff --git a/dossierfacile-bo/src/main/resources/static/js/main.js b/dossierfacile-bo/src/main/resources/static/js/main.js index df6136447..25c366af9 100644 --- a/dossierfacile-bo/src/main/resources/static/js/main.js +++ b/dossierfacile-bo/src/main/resources/static/js/main.js @@ -226,24 +226,25 @@ $(document).ready(function () { $('#form-change-document-status' + documentId).submit(); }) - $('.chat').click(function (e) { - var id = $(this).attr('data-id'); - var nameAdmin = $(this).attr('data-nameAdmin'); - + function updateMessageForm() { + var id = $('.chat').attr('data-id'); + var nameAdmin = $('.chat').attr('data-nameAdmin'); $('#tenant-message' + id).load("/bo/message/tenant/" + id, function () { - $("#messageForm" + id).submit(function (e) { - var id1 = $(this).attr('data-id'); - sendNewMessage(e, "/bo/message/new/" + id, $(this), nameAdmin, id, function () { location.reload(); }) } ); - }); + } + $('.chat').click(function (e) { + updateMessageForm(); }); + if ($('.chat') !== undefined && $('.chat').attr('aria-expanded') === 'true') { + updateMessageForm(); + } $(document).keydown(function (event) { var flag = true; diff --git a/dossierfacile-bo/src/main/resources/templates/bo/apartment-sharing-view.html b/dossierfacile-bo/src/main/resources/templates/bo/apartment-sharing-view.html index 0bd280569..f3340c6bf 100644 --- a/dossierfacile-bo/src/main/resources/templates/bo/apartment-sharing-view.html +++ b/dossierfacile-bo/src/main/resources/templates/bo/apartment-sharing-view.html @@ -941,6 +941,15 @@

ABSENT

+
+
Admin| Statuts de la vérification automatique: + +
    +
  • + +
  • +
+
- Attention, un avis de situation a été détecté !
diff --git a/dossierfacile-bo/src/main/resources/templates/bo/compute-status.html b/dossierfacile-bo/src/main/resources/templates/bo/compute-status.html deleted file mode 100644 index 92d18fcef..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/compute-status.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - DossierFacile - - - -
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
- -
- -
- -
-
-
- -
-
-
- -
- - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/dsfStatistic.html b/dossierfacile-bo/src/main/resources/templates/bo/dsfStatistic.html deleted file mode 100644 index 942123c8d..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/dsfStatistic.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - DossierFacile - - -
-
...
-
-
-
-

Stats from DossierSuperFacile

- - - - - - - - - - - - - - - - - - - - - - -
Week/FileNumber of tenantLandings (% vs number of tenant)Choosing SuperFacile (% vs landing)Giving the name of their company (% vs choosing SuperFacile)Email sent (% vs giving name)
-
-
- -
-
-

Potential partner companies

- - - - - - - - - - - - - - - -
Name of the companyOccurrenceSent mails (% vs Occurrence)
-
-
- -
-
- - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/feedback.html b/dossierfacile-bo/src/main/resources/templates/bo/feedback.html deleted file mode 100644 index 2291d22ee..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/feedback.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - DossierFacile - - - -
- -
...
-
- -
- - - - - - - - - -
FeedbackMessage
-
-
-
- - - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/statistic-admin.html b/dossierfacile-bo/src/main/resources/templates/bo/statistic-admin.html deleted file mode 100644 index c7a1cd605..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/statistic-admin.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - DossierFacile - - -
-
...
-
- - - - - - Send -
-
-

- - - - - - - - - - - - - - - - - -
Operator nameTO_PROCESS -> DECLINETO_PROCESS -> VALIDATEDTOTAL
- -
-
-
-
-
- - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/statistic-operator.html b/dossierfacile-bo/src/main/resources/templates/bo/statistic-operator.html deleted file mode 100644 index 50e3a69fc..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/statistic-operator.html +++ /dev/null @@ -1,465 +0,0 @@ - - - - DossierFacile - - -
-
...
-
-
-
-

General

- - - - - - - - - - - - - - - - - - - - - -
WeekTotalAverage actions by tenantAvg timeApplication validated actions (ratio)Application denied by checking a box only (ratio)
- - - - - -
-
-
-
-
-

CNI

- - - - - - - - - - - - - - - - - - - - - -
WeekTotalAverage actions by tenantAvg timeApplication validated actions (ratio)Application denied by checking a box only (ratio)
- - - - - -
-
-
-
-
-

Quittances

- - - - - - - - - - - - - - - - - - - - - -
WeekTotalAverage actions by tenantAvg timeApplication validated actions (ratio)Application denied by checking a box only (ratio)
- - - - - -
-
-
-
-
-

Contrat de travail

- - - - - - - - - - - - - - - - - - - - - -
WeekTotalAverage actions by tenantAvg timeApplication validated actions (ratio)Application denied by checking a box only (ratio)
- - - - - -
-
-
-
-
-

Impots

- - - - - - - - - - - - - - - - - - - - - -
WeekTotalAverage actions by tenantAvg timeApplication validated actions (ratio)Application denied by checking a box only (ratio)
- - - - - -
-
-
-
-
-

Fiches de paie

- - - - - - - - - - - - - - - - - - - - - -
WeekTotalAverage actions by tenantAvg timeApplication validated actions (ratio)Application denied by checking a box only (ratio)
- - - - - -
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
chômage contrat travail (file3)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
chômage bulletins de paie (file5)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
visale (file 4)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ctt contrat travail (file3)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ctt bulletins de paie (file 5)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
quittances loctaire (file Guarantor 5)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
taxe foncière garant (file Guarantor 2)
nb teststaux erreurstx erreurs critiques
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bulletins de paie loctaire (file5)
nb teststaux erreurstx erreurs critiques
-
-
- -
-
- - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/statistic-tenant.html b/dossierfacile-bo/src/main/resources/templates/bo/statistic-tenant.html deleted file mode 100644 index 00579ca6b..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/statistic-tenant.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - DossierFacile - - -
-
...
-
-
-
-

Tenants statistics

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
NumberWeek/FileTotal tenantNo files
-
-
- -
-
- - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/statistic.html b/dossierfacile-bo/src/main/resources/templates/bo/statistic.html deleted file mode 100644 index 2ad324864..000000000 --- a/dossierfacile-bo/src/main/resources/templates/bo/statistic.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - DossierFacile - - -
-
...
-
-
-

- Total number of Documents : -

-

- Total number of tenant : -

-

- Total number of owner : -

-
-
-
-

Tenants statistics

- - - - - - - - - - - - - - - - - - - - - - - - - -
Week/FileTotal tenantNo files
-
-
- -
-
-

Guarantor statistics

- - - - - - - - - - - - - - - - - - - - - - - -
Week/FileNot files
-
-
- -
-
-

Actions statistics

- - - - - - - - - - - - - - - - - - - - - - -
Week/ActionINCOMPLETE -> TO_PROCESSTO_PROCESS -> DECLINETO_PROCESS -> VALIDATEDDECLINE -> TO_PROCESSRATIO
- - - 0 -
-
-
- -
-
-

Honor declaration not validated

- - - - - - - - - - - - - -
WeekCGUNotChecked
-
-
-
-
-

Links counters

- - - - - - - - - - - - - - - - - - - - -
WeekLIGHT_APPLICATIONFULL_APPLICATIONTOTALDOCUMENT
- -
-
-
- -
-
-

AVG Time Serve Tenant by Operators

- - - - - - - - - - - - - - - -
WeekAVG (sec)AVG below 3 min (sec)
-
-
- -
-
-

Tenant Satisfaction Rate

- - - - - - - - - - - - - - - - - - - - - -
WeekTenants contactedrepliesReply rateYESRATIO ( yes / replies )
- - - -
-
-
- -
-
-

Properties

- - - - - - - - - - - - - - - - - - - - - -
WeekCreatedDeletedVisitedSubscribed
-
-
- -
-
- - diff --git a/dossierfacile-bo/src/main/resources/templates/bo/tools.html b/dossierfacile-bo/src/main/resources/templates/bo/tools.html index 55cf0e1db..b3e7da8c3 100644 --- a/dossierfacile-bo/src/main/resources/templates/bo/tools.html +++ b/dossierfacile-bo/src/main/resources/templates/bo/tools.html @@ -10,22 +10,29 @@
-
- - - -
-
-

Fichiers :

-
    -
  • - - - -
  • -
+ +
+ +
+
+ +
+
+
+
+
+ +
+ +
+ +
+
diff --git a/dossierfacile-common-library/pom.xml b/dossierfacile-common-library/pom.xml index 7d516f40e..c71216fd1 100644 --- a/dossierfacile-common-library/pom.xml +++ b/dossierfacile-common-library/pom.xml @@ -41,7 +41,7 @@ 1.4.2.Final - 19 + 21 ${java.version} ${java.version} 1.18.30 diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/converter/ParsedFileConverter.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/converter/ParsedFileConverter.java index 3776f1e30..ccdb7eac4 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/converter/ParsedFileConverter.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/converter/ParsedFileConverter.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import fr.dossierfacile.common.entity.ocr.ParsedFile; import fr.dossierfacile.common.enums.ParsedFileClassification; +import fr.dossierfacile.common.utils.MapperUtil; import javax.persistence.AttributeConverter; import javax.persistence.Converter; @@ -11,7 +12,7 @@ @Converter public class ParsedFileConverter implements AttributeConverter { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectMapper objectMapper = MapperUtil.newObjectMapper(); @Override public String convertToDatabaseColumn(ParsedFile object) { diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/DocumentRule.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/DocumentRule.java index b66605145..ec609bd27 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/DocumentRule.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/DocumentRule.java @@ -7,18 +7,23 @@ @AllArgsConstructor public enum DocumentRule { - R_TAX_PARSE(Level.WARN,"La lecture des informations de l'avis a échoué"), - R_TAX_FAKE(Level.CRITICAL,"Les informations sont floues ou corrompues"), - R_TAX_N1( Level.CRITICAL, "L'avis d'imposition sur les revenus N-1 doit etre fournis"), - R_TAX_LEAF( Level.CRITICAL, "Veuillez fournir les feuillets des avis"), - R_TAX_ALL_LEAF( Level.WARN, "Veuillez fournir tous les feuillets des avis"),// feuillet 1 founi - R_TAX_N3( Level.CRITICAL, "Les avis d'imposition antérieur à N-3 ne sont pas autorisé"), - R_TAX_NAMES( Level.CRITICAL, "Les noms et prénoms ne correspondent pas"), - - R_GUARANTEE_NAMES( Level.CRITICAL, "Les noms et prénoms ne correspondent pas"), - R_GUARANTEE_EXIRED( Level.CRITICAL, "La garantie a expiré"); - - public enum Level{ + R_TAX_PARSE(Level.WARN, "La lecture des informations de l'avis a échoué"), + R_TAX_FAKE(Level.CRITICAL, "Les informations sont floues ou corrompues"), + R_TAX_N1(Level.CRITICAL, "L'avis d'imposition sur les revenus N-1 doit etre fournis"), + R_TAX_LEAF(Level.CRITICAL, "Veuillez fournir les feuillets des avis"), + R_TAX_ALL_LEAF(Level.WARN, "Veuillez fournir tous les feuillets des avis"),// feuillet 1 founi + R_TAX_N3(Level.CRITICAL, "Les avis d'imposition antérieur à N-3 ne sont pas autorisé"), + R_TAX_NAMES(Level.CRITICAL, "Les noms et prénoms ne correspondent pas"), + + R_GUARANTEE_NAMES(Level.CRITICAL, "Les noms et prénoms ne correspondent pas"), + R_GUARANTEE_EXPIRED(Level.CRITICAL, "La garantie a expiré"), + + R_PAYSLIP_QRCHECK(Level.CRITICAL, "La lecture des informations et du QR Code ne correspondent pas"), + R_PAYSLIP_NAME(Level.CRITICAL, "Nom/prénoms ne correspondent pas"), + R_PAYSLIP_MONTHS(Level.CRITICAL, "Les 3 derniers bulletins de salaire doivent être transmis"), + R_PAYSLIP_AMOUNT_MISMATCHES(Level.CRITICAL, "Le montant specifié ne correspond pas au montant des bulletins"); + + public enum Level { CRITICAL, WARN } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/Tenant.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/Tenant.java index 1da4cdc46..6dff73656 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/Tenant.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/Tenant.java @@ -183,8 +183,8 @@ public boolean isAllCategories() { if (guarantor.getDocuments() == null || guarantor.getDocuments().isEmpty()) { return false; } else if (guarantor.getTypeGuarantor() == TypeGuarantor.ORGANISM) { - // Must have exactly one Document of type IDENTIFICATION - if (guarantor.getDocuments().size() != 1 || !guarantor.getDocuments().get(0).getDocumentCategory().equals(DocumentCategory.IDENTIFICATION)) { + // Must have exactly one Document of type GUARANTEE_PROVIDER_CERTIFICATE + if (guarantor.getDocuments().size() != 1 || !guarantor.getDocuments().get(0).getDocumentCategory().equals(DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE)) { return false; } } else if (guarantor.getTypeGuarantor() == TypeGuarantor.NATURAL_PERSON) { diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/ParsedFile.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/ParsedFile.java index 4308fd04d..e700a9e79 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/ParsedFile.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/ParsedFile.java @@ -2,6 +2,8 @@ import fr.dossierfacile.common.enums.ParsedFileClassification; -public interface ParsedFile { +import java.io.Serializable; + +public interface ParsedFile extends Serializable { ParsedFileClassification getClassification(); } \ No newline at end of file diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/PublicPayslipFile.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/PublicPayslipFile.java new file mode 100644 index 000000000..119264a9c --- /dev/null +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/PublicPayslipFile.java @@ -0,0 +1,24 @@ +package fr.dossierfacile.common.entity.ocr; + +import com.fasterxml.jackson.annotation.JsonFormat; +import fr.dossierfacile.common.enums.ParsedFileClassification; +import fr.dossierfacile.common.enums.ParsedStatus; +import lombok.*; + +import java.time.YearMonth; + +@Data +@Builder +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class PublicPayslipFile implements ParsedFile { + @Builder.Default + ParsedFileClassification classification = ParsedFileClassification.PUBLIC_PAYSLIP; + ParsedStatus status; + String fullname; + @JsonFormat(pattern = "yyyy-MM") + YearMonth month; + double netTaxableIncome; + double cumulativeNetTaxableIncome; +} \ No newline at end of file diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeLeaf.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeLeaf.java index 4f96789b1..a0d6968b0 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeLeaf.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeLeaf.java @@ -14,7 +14,7 @@ @ToString @NoArgsConstructor @AllArgsConstructor -public class TaxIncomeLeaf implements ParsedFile, Serializable { +public class TaxIncomeLeaf implements ParsedFile { @Builder.Default ParsedFileClassification classification = ParsedFileClassification.TAX_INCOME_LEAF; String numeroFiscal; // declarant1 diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeMainFile.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeMainFile.java index 8c751131b..22c68fbd3 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeMainFile.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/ocr/TaxIncomeMainFile.java @@ -16,7 +16,7 @@ @ToString @NoArgsConstructor @AllArgsConstructor -public class TaxIncomeMainFile implements ParsedFile, Serializable { +public class TaxIncomeMainFile implements ParsedFile { @Builder.Default ParsedFileClassification classification = ParsedFileClassification.TAX_INCOME; String declarant1NumFiscal; diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentCategory.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentCategory.java index 4648820ba..67ded1312 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentCategory.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentCategory.java @@ -4,12 +4,16 @@ @Getter public enum DocumentCategory { + IDENTIFICATION("tenant.profile.link1.v2"), RESIDENCY("tenant.profile.link2.v2"), PROFESSIONAL("tenant.profile.link3.v2"), FINANCIAL("tenant.profile.link5.v2"), TAX("tenant.profile.link4.v2"), + IDENTIFICATION_LEGAL_PERSON("tenant.profile.link1.v2"), + GUARANTEE_PROVIDER_CERTIFICATE("tenant.profile.link9.v2"), + NULL(""); String label; diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentSubCategory.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentSubCategory.java index 0c4f61a6c..0ef65efbd 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentSubCategory.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/DocumentSubCategory.java @@ -14,8 +14,8 @@ public enum DocumentSubCategory { FRENCH_PASSPORT("document_sub_category.FRENCH_PASSPORT"), FRENCH_RESIDENCE_PERMIT("document_sub_category.FRENCH_RESIDENCE_PERMIT"), DRIVERS_LICENSE("document_sub_category.DRIVERS_LICENSE"), + FRANCE_IDENTITE("document_sub_category.FRANCE_IDENTITE"), OTHER_IDENTIFICATION("document_sub_category.OTHER_IDENTIFICATION"), - CERTIFICATE_VISA("document_sub_category.CERTIFICATE_VISA"), // Residency TENANT("document_sub_category.TENANT"), @@ -58,9 +58,14 @@ public enum DocumentSubCategory { LESS_THAN_YEAR("document_sub_category.LESS_THAN_YEAR"), OTHER_TAX("document_sub_category.OTHER_TAX"), + // Guarantor + CERTIFICATE_VISA("document_sub_category.CERTIFICATE_VISA"), + VISALE("document_sub_category.VISALE"), + OTHER_GUARANTEE("document_sub_category.OTHER_GUARANTEE"), LEGAL_PERSON("document_sub_category.LEGAL_PERSON"), - UNDEFINED("document_sub_category.UNDEFINED"), - OTHER_PROFESSION_GUARANTOR("document_sub_category.OTHER_PROFESSION_GUARANTOR"); + OTHER_PROFESSION_GUARANTOR("document_sub_category.OTHER_PROFESSION_GUARANTOR"), + + UNDEFINED("document_sub_category.UNDEFINED"); final String label; @@ -74,14 +79,4 @@ public static List alphabeticallySortedValues() { return values; } - public DocumentSubCategory getOnlyOldCategories() { - return switch (this) { - case INTERMITTENT, STAY_AT_HOME_PARENT, NO_ACTIVITY, ARTIST -> OTHER; - case DRIVERS_LICENSE -> OTHER_IDENTIFICATION; - case SHORT_TERM_RENTAL -> TENANT; - case GUEST_ORGANISM -> GUEST; - default -> this; - }; - } - } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/ParsedFileClassification.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/ParsedFileClassification.java index fa390578a..e37eaec01 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/ParsedFileClassification.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/ParsedFileClassification.java @@ -1,9 +1,6 @@ package fr.dossierfacile.common.enums; -import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; -import fr.dossierfacile.common.entity.ocr.ParsedFile; -import fr.dossierfacile.common.entity.ocr.TaxIncomeLeaf; -import fr.dossierfacile.common.entity.ocr.TaxIncomeMainFile; +import fr.dossierfacile.common.entity.ocr.*; import lombok.AllArgsConstructor; import lombok.Getter; @@ -12,7 +9,8 @@ public enum ParsedFileClassification { TAX_INCOME(TaxIncomeMainFile.class), TAX_INCOME_LEAF(TaxIncomeLeaf.class), - GUARANTEE_PROVIDER(GuaranteeProviderFile.class); + GUARANTEE_PROVIDER(GuaranteeProviderFile.class), + PUBLIC_PAYSLIP(PublicPayslipFile.class),; Class classificationClass; } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/exceptions/OldKeyException.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/exceptions/UnsupportedKeyException.java similarity index 65% rename from dossierfacile-common-library/src/main/java/fr/dossierfacile/common/exceptions/OldKeyException.java rename to dossierfacile-common-library/src/main/java/fr/dossierfacile/common/exceptions/UnsupportedKeyException.java index 31d63b9f7..3aef6787d 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/exceptions/OldKeyException.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/exceptions/UnsupportedKeyException.java @@ -4,9 +4,9 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.BAD_REQUEST) -public class OldKeyException extends RuntimeException { +public class UnsupportedKeyException extends RuntimeException { - public OldKeyException(String message) { + public UnsupportedKeyException(String message) { super(message); } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationFullMapper.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationFullMapper.java index aa228d677..fd298d045 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationFullMapper.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationFullMapper.java @@ -13,6 +13,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -24,13 +25,19 @@ public abstract class ApplicationFullMapper implements ApartmentSharingMapper { @Value("${application.domain:default}") protected String domain; + protected CategoriesMapper categoriesMapper; + + @Autowired + public void setCategoriesMapper(CategoriesMapper categoriesMapper) { + this.categoriesMapper = categoriesMapper; + } + public abstract ApplicationModel toApplicationModel(ApartmentSharing apartmentSharing); public abstract ApplicationModel toApplicationModel(ApartmentSharing apartmentSharing, @Context UserApi userApi); @Mapping(target = "name", expression = "java((document.getWatermarkFile() != null )? domain + \"/\" + PATH + \"/\" + document.getName() : null)") - @Mapping(target = "subCategory", source = "documentSubCategory") - @HideNewSubCategories + @MapDocumentCategories @Mapping(target = "authenticityStatus", expression = "java(fr.dossierfacile.common.entity.AuthenticityStatus.isAuthentic(document))") public abstract DocumentModel toDocumentModel(Document document); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationLightMapper.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationLightMapper.java index c3a607fb9..7ad071b7e 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationLightMapper.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/ApplicationLightMapper.java @@ -6,17 +6,24 @@ import fr.dossierfacile.common.model.apartment_sharing.DocumentModel; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @Mapper(componentModel = "spring") public abstract class ApplicationLightMapper implements ApartmentSharingMapper { + protected CategoriesMapper categoriesMapper; + + @Autowired + public void setCategoriesMapper(CategoriesMapper categoriesMapper) { + this.categoriesMapper = categoriesMapper; + } + public abstract ApplicationModel toApplicationModel(ApartmentSharing apartmentSharing); @Mapping(target = "name", ignore = true) - @Mapping(target = "subCategory", source = "documentSubCategory") - @HideNewSubCategories + @MapDocumentCategories @Mapping(target = "authenticityStatus", expression = "java(fr.dossierfacile.common.entity.AuthenticityStatus.isAuthentic(document))") public abstract DocumentModel documentToDocumentModel(Document document); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/CategoriesMapper.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/CategoriesMapper.java new file mode 100644 index 000000000..ae7d1cdbf --- /dev/null +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/CategoriesMapper.java @@ -0,0 +1,12 @@ +package fr.dossierfacile.common.mapper; + +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.common.enums.DocumentSubCategory; + +public interface CategoriesMapper { + + DocumentCategory mapCategory(DocumentCategory category); + + DocumentSubCategory mapSubCategory(DocumentSubCategory subCategory); + +} diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DeletedTenantCommonMapper.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DeletedTenantCommonMapper.java index a19b91833..3c9034d55 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DeletedTenantCommonMapper.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DeletedTenantCommonMapper.java @@ -20,9 +20,9 @@ public interface DeletedTenantCommonMapper { @Mapping(target = "hashedFirstname", source = "firstName", qualifiedByName = "firstnameToHashedFirstname") @Mapping(target = "hashedPreferredName", source = "preferredName", qualifiedByName = "preferredNameToHashedPreferredName") public abstract DeletedTenantModel toDeletedTenantModel(Tenant tenant); + @Mapping(target = "name", expression = "java((document.getWatermarkFile() != null )? document.getWatermarkFile().getName() : null)") @Mapping(target = "subCategory", source = "documentSubCategory") - @HideNewSubCategories public abstract DocumentModel toDocumentModel(Document document); @Named("emailToHashedEmail") diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DummyCategoriesMapper.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DummyCategoriesMapper.java new file mode 100644 index 000000000..24877881d --- /dev/null +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/DummyCategoriesMapper.java @@ -0,0 +1,20 @@ +package fr.dossierfacile.common.mapper; + +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.common.enums.DocumentSubCategory; +import org.springframework.stereotype.Component; + +@Component +public class DummyCategoriesMapper implements CategoriesMapper { + + @Override + public DocumentCategory mapCategory(DocumentCategory category) { + return category; + } + + @Override + public DocumentSubCategory mapSubCategory(DocumentSubCategory subCategory) { + return subCategory; + } + +} diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/HideNewSubCategories.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/MapDocumentCategories.java similarity index 51% rename from dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/HideNewSubCategories.java rename to dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/MapDocumentCategories.java index fdb3d1a0f..65f26d277 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/HideNewSubCategories.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/MapDocumentCategories.java @@ -7,11 +7,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** - * TODO remove this behavior 6 months from now - */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) -@Mapping(target = "documentSubCategory", expression = "java(document.getDocumentSubCategory().getOnlyOldCategories())") -public @interface HideNewSubCategories { +@Mapping(target = "documentCategory", expression = "java(categoriesMapper.mapCategory(document.getDocumentCategory()))") +@Mapping(target = "subCategory", expression = "java(categoriesMapper.mapSubCategory(document.getDocumentSubCategory()))") +public @interface MapDocumentCategories { } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/TenantCommonMapper.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/TenantCommonMapper.java deleted file mode 100644 index af5a6ee5c..000000000 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/mapper/TenantCommonMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package fr.dossierfacile.common.mapper; - -import fr.dossierfacile.common.entity.Document; -import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.model.apartment_sharing.DocumentModel; -import fr.dossierfacile.common.model.apartment_sharing.TenantModel; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.springframework.stereotype.Component; - -@Component -@Mapper(componentModel = "spring") -public abstract class TenantCommonMapper { - public abstract TenantModel toTenantModel(Tenant tenant); - @Mapping(target = "name", expression = "java((document.getWatermarkFile() != null )? document.getWatermarkFile().getName() : null)") - @Mapping(target = "subCategory", source = "documentSubCategory") - @HideNewSubCategories - public abstract DocumentModel toDocumentModel(Document document); -} diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/model/apartment_sharing/DocumentModel.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/model/apartment_sharing/DocumentModel.java index 919c505fe..63ab171b3 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/model/apartment_sharing/DocumentModel.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/model/apartment_sharing/DocumentModel.java @@ -18,7 +18,6 @@ public class DocumentModel { private Long id; private DocumentCategory documentCategory; - private DocumentSubCategory documentSubCategory; // TODO delete this field 6 months from now private DocumentSubCategory subCategory; private String customText; private Integer monthlySum; diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java index 37da0b878..53a6900d4 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java @@ -98,9 +98,6 @@ default Tenant findNextApplicationByProfessional(LocalDateTime localDateTime, Li ) List listIdTenantsAccountCompletedPendingToSendCallBack(@Param("id") Long userApiId, @Param("since") LocalDateTime lastUpdateSince); - @Query("SELECT t FROM Tenant t ORDER BY t.id DESC") - Page findAllTenants(Pageable page); - @Query(value = """ SELECT COUNT(DISTINCT t.id) FROM tenant t @@ -275,12 +272,4 @@ List findTenantUpdateByLastUpdateAndPartner(@Param("lastUpdateFrom ) List findTenantUpdateByCreationDateAndPartner(@Param("creationDateFrom") LocalDateTime from, @Param("partnerId") Long id, @Param("limit") Long limit); - @Query(""" - SELECT DISTINCT t - FROM Tenant t - JOIN Log l ON t.id = l.tenantId - WHERE l.logType = 'ACCOUNT_VALIDATED' OR l.logType = 'ACCOUNT_DENIED' - """ - ) - List findTenantsToExtract(Pageable pageable); } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/CallbackLogServiceImpl.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/CallbackLogServiceImpl.java index eecab15c2..9b81bbed3 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/CallbackLogServiceImpl.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/CallbackLogServiceImpl.java @@ -1,13 +1,13 @@ package fr.dossierfacile.common.service; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import fr.dossierfacile.common.entity.CallbackLog; import fr.dossierfacile.common.entity.Tenant; import fr.dossierfacile.common.enums.TenantFileStatus; import fr.dossierfacile.common.model.apartment_sharing.ApplicationModel; import fr.dossierfacile.common.repository.CallbackLogRepository; import fr.dossierfacile.common.service.interfaces.CallbackLogService; +import fr.dossierfacile.common.utils.MapperUtil; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -18,13 +18,12 @@ @Slf4j public class CallbackLogServiceImpl implements CallbackLogService { private final CallbackLogRepository callbackLogRepository; + private static final ObjectMapper objectMapper = MapperUtil.newObjectMapper(); @SneakyThrows @Override public void createCallbackLogForPartnerModel(Tenant tenant, Long partnerId, TenantFileStatus tenantFileStatus, ApplicationModel applicationModel) { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); String jsonContent = objectMapper.writeValueAsString(applicationModel); - callbackLogRepository.save(new CallbackLog(tenant.getId(),partnerId,tenantFileStatus, jsonContent)); + callbackLogRepository.save(new CallbackLog(tenant.getId(), partnerId, tenantFileStatus, jsonContent)); } } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/LogServiceImpl.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/LogServiceImpl.java index 0ccd227bc..113dd688c 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/LogServiceImpl.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/LogServiceImpl.java @@ -16,6 +16,7 @@ import fr.dossierfacile.common.model.log.EditionType; import fr.dossierfacile.common.repository.LogRepository; import fr.dossierfacile.common.service.interfaces.LogService; +import fr.dossierfacile.common.utils.MapperUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -30,11 +31,7 @@ public class LogServiceImpl implements LogService { private final LogRepository repository; private final DeletedTenantCommonMapper deletedTenantCommonMapper; - private ObjectMapper objectMapper = new ObjectMapper(); - - { - objectMapper.registerModule(new JavaTimeModule()); - } + private final ObjectMapper objectMapper = MapperUtil.newObjectMapper(); private void saveLog(Log log) { repository.save(log); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/MockStorage.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/MockStorage.java index 65f4de2e1..e0602738b 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/MockStorage.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/MockStorage.java @@ -1,8 +1,10 @@ package fr.dossierfacile.common.service; +import fr.dossierfacile.common.entity.EncryptionKey; import fr.dossierfacile.common.entity.ObjectStorageProvider; import fr.dossierfacile.common.entity.StorageFile; import fr.dossierfacile.common.exceptions.RetryableOperationException; +import fr.dossierfacile.common.exceptions.UnsupportedKeyException; import fr.dossierfacile.common.repository.StorageFileRepository; import fr.dossierfacile.common.service.interfaces.FileStorageService; import lombok.extern.slf4j.Slf4j; @@ -62,9 +64,12 @@ public void delete(StorageFile storageFile) { } } - private InputStream download(String filename, Key key) throws IOException { + private InputStream download(String filename, EncryptionKey key) throws IOException { InputStream in = Files.newInputStream(Path.of(filePath + filename)); if (key != null) { + if (key.getVersion() != 1){ + throw new UnsupportedKeyException("Unsupported key version " + key.getVersion()); + } try { byte[] iv = DigestUtils.md5(filename); GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OutscaleFileStorageServiceImpl.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OutscaleFileStorageServiceImpl.java index 94ae4f7d2..d6ae0b525 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OutscaleFileStorageServiceImpl.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OutscaleFileStorageServiceImpl.java @@ -2,19 +2,13 @@ import com.amazonaws.AmazonServiceException; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.GetObjectRequest; -import com.amazonaws.services.s3.model.ListObjectsRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectSummary; +import com.amazonaws.services.s3.model.*; import fr.dossierfacile.common.config.ThreeDSOutscaleConfig; import fr.dossierfacile.common.entity.EncryptionKey; import fr.dossierfacile.common.entity.ObjectStorageProvider; -import fr.dossierfacile.common.exceptions.OldKeyException; import fr.dossierfacile.common.exceptions.RetryableOperationException; +import fr.dossierfacile.common.exceptions.UnsupportedKeyException; import fr.dossierfacile.common.service.interfaces.FileStorageProviderService; -import io.sentry.Sentry; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; @@ -47,17 +41,16 @@ public class OutscaleFileStorageServiceImpl implements FileStorageProviderServic @Value("${threeds.s3.bucket:dossierfacile-preprod}") private String bucket; - private static InputStream cipherInputStream(String path, Key key, InputStream in) throws IOException { + private static InputStream cipherInputStream(String path, EncryptionKey key, InputStream in) throws IOException { try { Cipher aes; - if (key instanceof EncryptionKey && ((EncryptionKey) key).getVersion() == 0) { - Sentry.captureMessage("Wrong key version used"); - throw new OldKeyException("Wrong key version used"); - } else { + if (key.getVersion() == 1) { byte[] iv = DigestUtils.sha256(path); // arbitrary set the filename to build IV GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv); aes = Cipher.getInstance("AES/GCM/NoPadding"); aes.init(Cipher.DECRYPT_MODE, key, gcmParamSpec); + } else { + throw new UnsupportedKeyException("Unsupported Key version " + key.getVersion()); } in = new CipherInputStream(in, aes); } catch (Exception e) { @@ -79,7 +72,7 @@ public void delete(String name) { } @Override - public InputStream download(String path, Key key) throws IOException { + public InputStream download(String path, EncryptionKey key) throws IOException { AmazonS3 s3client = threeDSOutscaleConfig.getAmazonS3Client(); S3Object fullObject; try { @@ -95,8 +88,11 @@ public InputStream download(String path, Key key) throws IOException { } @Override - public void upload(String name, InputStream inputStream, Key key, String contentType) throws RetryableOperationException, IOException { + public void upload(String name, InputStream inputStream, EncryptionKey key, String contentType) throws RetryableOperationException, IOException { if (key != null) { + if (key.getVersion() != 1){ + throw new UnsupportedKeyException("Unsupported key version " + key.getVersion()); + } try { byte[] iv = DigestUtils.sha256(name); GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OvhFileStorageServiceImpl.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OvhFileStorageServiceImpl.java index 7801bd39a..c056a3bf1 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OvhFileStorageServiceImpl.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/OvhFileStorageServiceImpl.java @@ -4,6 +4,7 @@ import fr.dossierfacile.common.entity.ObjectStorageProvider; import fr.dossierfacile.common.exceptions.OvhConnectionFailedException; import fr.dossierfacile.common.exceptions.RetryableOperationException; +import fr.dossierfacile.common.exceptions.UnsupportedKeyException; import fr.dossierfacile.common.service.interfaces.FileStorageProviderService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; @@ -101,7 +102,7 @@ public void delete(String path) { } @Override - public InputStream download(String path, Key key) throws IOException { + public InputStream download(String path, EncryptionKey key) throws IOException { SwiftObject object; try { object = getClient().objectStorage().objects().get(ovhContainerName, path); @@ -116,14 +117,13 @@ public InputStream download(String path, Key key) throws IOException { if (key != null) { try { Cipher aes; - if (key instanceof EncryptionKey && ((EncryptionKey) key).getVersion() == 0) { - aes = Cipher.getInstance("AES/ECB/PKCS5Padding"); - aes.init(Cipher.DECRYPT_MODE, key); - } else { + if (key.getVersion() == 1) { byte[] iv = DigestUtils.md5(path); // arbitrary set the filename to build IV GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv); aes = Cipher.getInstance("AES/GCM/NoPadding"); aes.init(Cipher.DECRYPT_MODE, key, gcmParamSpec); + } else { + throw new UnsupportedKeyException("Unsupported key version " + key.getVersion()); } in = new CipherInputStream(in, aes); } catch (Exception e) { @@ -134,8 +134,11 @@ public InputStream download(String path, Key key) throws IOException { } @Override - public void upload(String ovhPath, InputStream inputStream, Key key, String contentType) throws RetryableOperationException, IOException { + public void upload(String ovhPath, InputStream inputStream, EncryptionKey key, String contentType) throws RetryableOperationException, IOException { if (key != null) { + if (key.getVersion() != 1){ + throw new UnsupportedKeyException("Unsupported key version " + key.getVersion()); + } try { byte[] iv = DigestUtils.md5(ovhPath); GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/PartnerCallBackServiceImpl.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/PartnerCallBackServiceImpl.java index b8d0de29f..de3d6afa4 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/PartnerCallBackServiceImpl.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/PartnerCallBackServiceImpl.java @@ -98,7 +98,7 @@ public void sendCallBack(Tenant tenant, WebhookDTO webhookDTO) { log.warn("UserApi call has not effect for " + userApi.getName()); return; } - if (userApi.getVersion() != 2) { + if (userApi.getVersion() < 2) { log.error("Unable to send callback to tenant " + tenant.getId() + " due to userApi version" + userApi.getVersion()); return; } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/FileStorageProviderService.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/FileStorageProviderService.java index 1a83bcd85..7d5eacbda 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/FileStorageProviderService.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/FileStorageProviderService.java @@ -1,5 +1,6 @@ package fr.dossierfacile.common.service.interfaces; +import fr.dossierfacile.common.entity.EncryptionKey; import fr.dossierfacile.common.entity.ObjectStorageProvider; import fr.dossierfacile.common.exceptions.RetryableOperationException; @@ -15,9 +16,9 @@ public interface FileStorageProviderService { void delete(String name); - InputStream download(String path, Key key) throws IOException; + InputStream download(String path, EncryptionKey key) throws IOException; - void upload(String ovhPath, InputStream inputStream, Key key, String contentType) throws RetryableOperationException, IOException; + void upload(String ovhPath, InputStream inputStream, EncryptionKey key, String contentType) throws RetryableOperationException, IOException; List listObjectNames(@Nullable String marker, int maxObjects); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/utils/MapperUtil.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/utils/MapperUtil.java new file mode 100644 index 000000000..226f0d3f5 --- /dev/null +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/utils/MapperUtil.java @@ -0,0 +1,14 @@ +package fr.dossierfacile.common.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class MapperUtil { + public static ObjectMapper newObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + return objectMapper; + } +} diff --git a/dossierfacile-common-library/src/main/resources/db/changelog/databaseChangeLog.xml b/dossierfacile-common-library/src/main/resources/db/changelog/databaseChangeLog.xml index de97525c3..a3028066d 100644 --- a/dossierfacile-common-library/src/main/resources/db/changelog/databaseChangeLog.xml +++ b/dossierfacile-common-library/src/main/resources/db/changelog/databaseChangeLog.xml @@ -137,5 +137,8 @@ + + + diff --git a/dossierfacile-common-library/src/main/resources/db/migration/202401260000-rename-sub-category-for-guarantor-organism.xml b/dossierfacile-common-library/src/main/resources/db/migration/202401260000-rename-sub-category-for-guarantor-organism.xml new file mode 100644 index 000000000..ac8e0e14c --- /dev/null +++ b/dossierfacile-common-library/src/main/resources/db/migration/202401260000-rename-sub-category-for-guarantor-organism.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/dossierfacile-common-library/src/main/resources/db/migration/202401260001-rename-category-for-guarantor-organism.xml b/dossierfacile-common-library/src/main/resources/db/migration/202401260001-rename-category-for-guarantor-organism.xml new file mode 100644 index 000000000..766046f30 --- /dev/null +++ b/dossierfacile-common-library/src/main/resources/db/migration/202401260001-rename-category-for-guarantor-organism.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/dossierfacile-common-library/src/main/resources/db/migration/202401300000-change-denied-options-sub-category.xml b/dossierfacile-common-library/src/main/resources/db/migration/202401300000-change-denied-options-sub-category.xml new file mode 100644 index 000000000..7584a7096 --- /dev/null +++ b/dossierfacile-common-library/src/main/resources/db/migration/202401300000-change-denied-options-sub-category.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationFullMapperTest.java b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationFullMapperTest.java index 2a9cba91d..c806bc887 100644 --- a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationFullMapperTest.java +++ b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationFullMapperTest.java @@ -3,11 +3,13 @@ import fr.dossierfacile.common.entity.Document; import fr.dossierfacile.common.model.apartment_sharing.DocumentModel; -class ApplicationFullMapperTest implements DocumentMappingTest, AuthenticityStatusMappingTest { +class ApplicationFullMapperTest implements AuthenticityStatusMappingTest { @Override public DocumentModel mapDocument(Document document) { - return new ApplicationFullMapperImpl().toDocumentModel(document); + ApplicationFullMapperImpl mapper = new ApplicationFullMapperImpl(); + mapper.setCategoriesMapper(new DummyCategoriesMapper()); + return mapper.toDocumentModel(document); } } \ No newline at end of file diff --git a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationLightMapperTest.java b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationLightMapperTest.java index 30d26ca1e..d14d25c15 100644 --- a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationLightMapperTest.java +++ b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/ApplicationLightMapperTest.java @@ -3,11 +3,13 @@ import fr.dossierfacile.common.entity.Document; import fr.dossierfacile.common.model.apartment_sharing.DocumentModel; -class ApplicationLightMapperTest implements DocumentMappingTest, AuthenticityStatusMappingTest { +class ApplicationLightMapperTest implements AuthenticityStatusMappingTest { @Override public DocumentModel mapDocument(Document document) { - return new ApplicationLightMapperImpl().documentToDocumentModel(document); + ApplicationLightMapperImpl mapper = new ApplicationLightMapperImpl(); + mapper.setCategoriesMapper(new DummyCategoriesMapper()); + return mapper.documentToDocumentModel(document); } } \ No newline at end of file diff --git a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/DocumentMappingTest.java b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/DocumentMappingTest.java deleted file mode 100644 index 3d21ff44a..000000000 --- a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/DocumentMappingTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package fr.dossierfacile.common.mapper; - -import fr.dossierfacile.common.entity.Document; -import fr.dossierfacile.common.enums.DocumentSubCategory; -import fr.dossierfacile.common.model.apartment_sharing.DocumentModel; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.EnumSource; - -import static fr.dossierfacile.common.enums.DocumentSubCategory.DRIVERS_LICENSE; -import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER; -import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_IDENTIFICATION; -import static org.assertj.core.api.Assertions.assertThat; - -interface DocumentMappingTest { - - DocumentModel mapDocument(Document document); - - @ParameterizedTest - @EnumSource(value = DocumentSubCategory.class, - names = {"INTERMITTENT", "STAY_AT_HOME_PARENT", "NO_ACTIVITY", "ARTIST"}) - @DisplayName("New professional categories are replaced by 'OTHER' in field 'documentSubCategory'") - default void should_replace_new_professional_categories_by_other(DocumentSubCategory subCategory) { - DocumentModel documentModel = mapDocumentWithSubCategory(subCategory); - - assertThat(documentModel.getDocumentSubCategory()).isEqualTo(OTHER); - } - - @ParameterizedTest - @CsvSource({ - "GUEST_ORGANISM, GUEST", - "SHORT_TERM_RENTAL, TENANT" - }) - @DisplayName("New residency categories are replaced by existing ones in field 'documentSubCategory'") - default void should_replace_new_residency_categories(DocumentSubCategory newSubCategory, DocumentSubCategory existingSubCategory) { - DocumentModel documentModel = mapDocumentWithSubCategory(newSubCategory); - - assertThat(documentModel.getDocumentSubCategory()).isEqualTo(existingSubCategory); - } - - @Test - @DisplayName("Driver's license is replaced by 'OTHER_IDENTIFICATION' in field 'documentSubCategory'") - default void should_replace_drivers_license_by_other() { - DocumentModel documentModel = mapDocumentWithSubCategory(DRIVERS_LICENSE); - - assertThat(documentModel.getDocumentSubCategory()).isEqualTo(OTHER_IDENTIFICATION); - } - - @ParameterizedTest - @EnumSource(value = DocumentSubCategory.class) - @DisplayName("All categories are mapped as is in field 'subCategory'") - default void should_expose_all_categories(DocumentSubCategory subCategory) { - DocumentModel documentModel = mapDocumentWithSubCategory(subCategory); - - assertThat(documentModel.getSubCategory()).isEqualTo(subCategory); - } - - private DocumentModel mapDocumentWithSubCategory(DocumentSubCategory subCategory) { - Document document = Document.builder() - .documentSubCategory(subCategory) - .build(); - - return mapDocument(document); - } - -} \ No newline at end of file diff --git a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/TenantCommonMapperTest.java b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/TenantCommonMapperTest.java deleted file mode 100644 index ab67f2749..000000000 --- a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/mapper/TenantCommonMapperTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package fr.dossierfacile.common.mapper; - -import fr.dossierfacile.common.entity.Document; -import fr.dossierfacile.common.model.apartment_sharing.DocumentModel; - -class TenantCommonMapperTest implements DocumentMappingTest { - - @Override - public DocumentModel mapDocument(Document document) { - return new TenantCommonMapperImpl().toDocumentModel(document); - } - -} \ No newline at end of file diff --git a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/LogServiceImplTest.java b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/LogServiceImplTest.java index c023c8fc5..2a50a8b8f 100644 --- a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/LogServiceImplTest.java +++ b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/LogServiceImplTest.java @@ -27,7 +27,7 @@ class LogServiceImplTest { private final LogRepository logRepository = mock(LogRepository.class); - private final LogService logService = new LogServiceImpl(logRepository, null, new ObjectMapper()); + private final LogService logService = new LogServiceImpl(logRepository, null); @Test void should_save_edition_log_for_tenant_document() { diff --git a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/ThreeDSOutscaleFileStorageServiceImplTest.java b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/ThreeDSOutscaleFileStorageServiceImplTest.java index 77fd92ed7..eb897598c 100644 --- a/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/ThreeDSOutscaleFileStorageServiceImplTest.java +++ b/dossierfacile-common-library/src/test/java/fr/dossierfacile/common/service/ThreeDSOutscaleFileStorageServiceImplTest.java @@ -28,7 +28,7 @@ void connect3DS() throws IOException, NoSuchAlgorithmException, RetryableOperati InputStream fileInputStream = ThreeDSOutscaleFileStorageServiceImplTest.class.getClassLoader().getResourceAsStream("hello.txt"); KeyGenerator keygen = KeyGenerator.getInstance("AES"); SecretKey key = keygen.generateKey(); - Key encryptionKey = EncryptionKey.builder() + EncryptionKey encryptionKey = EncryptionKey.builder() .algorithm(key.getAlgorithm()) .format(key.getFormat()) .encodedSecret(key.getEncoded()) diff --git a/dossierfacile-pdf-generator/pom.xml b/dossierfacile-pdf-generator/pom.xml index 50f283d3e..d35e3a394 100644 --- a/dossierfacile-pdf-generator/pom.xml +++ b/dossierfacile-pdf-generator/pom.xml @@ -15,7 +15,7 @@ Generate tenant's PDF documents - 19 + 21 ${java.version} ${java.version} 1.18.30 diff --git a/dossierfacile-pdf-generator/src/main/resources/messages.properties b/dossierfacile-pdf-generator/src/main/resources/messages.properties index 1d3e6b22d..daa0e2fef 100644 --- a/dossierfacile-pdf-generator/src/main/resources/messages.properties +++ b/dossierfacile-pdf-generator/src/main/resources/messages.properties @@ -23,6 +23,7 @@ tenant.profile.link5.v2=Justificatif de ressources tenant.profile.link6.v2=Attestation de garantie tenant.profile.link7.v2=Identification de la personne morale tenant.profile.link8.v2=Pièce d'identité du représentant de la personne morale +tenant.profile.link9.v2=Certificat de caution tenant.profile.certified=Revenu fiscal certifié tenant.profile.help=(de 1 à 3 documents) diff --git a/dossierfacile-process-file/pom.xml b/dossierfacile-process-file/pom.xml index 96e5b5cfe..ed34300c0 100644 --- a/dossierfacile-process-file/pom.xml +++ b/dossierfacile-process-file/pom.xml @@ -17,7 +17,7 @@ ProcessFile for DossierFacile - 19 + 21 1.18.30 3.0.0 3.0.3 diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/AnalyzeFile.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/AnalyzeFile.java index 2ad7c162e..bcd3916a3 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/AnalyzeFile.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/AnalyzeFile.java @@ -2,7 +2,7 @@ import fr.dossierfacile.process.file.repository.FileRepository; import fr.dossierfacile.process.file.service.processors.BarCodeFileProcessor; -import fr.dossierfacile.process.file.service.processors.OcrParserFileProcessor; +import fr.dossierfacile.process.file.service.processors.FileParserProcessor; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -15,13 +15,13 @@ @AllArgsConstructor public class AnalyzeFile { private final BarCodeFileProcessor barCodeFileProcessor; - private final OcrParserFileProcessor ocrParserFileProcessor; + private final FileParserProcessor fileParserProcessor; private final FileRepository fileRepository; public void processFile(Long fileId) { Optional.ofNullable(fileRepository.findById(fileId).orElse(null)) .filter(Objects::nonNull) .map(barCodeFileProcessor::process) - .map(ocrParserFileProcessor::process); + .map(fileParserProcessor::process); } } diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java index b184f5741..053de9f58 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java @@ -13,6 +13,10 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.util.List; + +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_GUARANTEE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.VISALE; @Service @RequiredArgsConstructor @@ -20,8 +24,8 @@ public class GuaranteeProviderRulesValidationService implements RulesValidationService { @Override public boolean shouldBeApplied(Document document) { - return document.getDocumentCategory() == DocumentCategory.IDENTIFICATION - && document.getDocumentSubCategory() == DocumentSubCategory.CERTIFICATE_VISA + return document.getDocumentCategory() == DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE + && List.of(OTHER_GUARANTEE, VISALE).contains(document.getDocumentSubCategory()) && !CollectionUtils.isEmpty(document.getFiles()) && document.getFiles().stream().anyMatch((f) -> f.getParsedFileAnalysis() != null && f.getParsedFileAnalysis().getParsedFile() != null); @@ -29,7 +33,7 @@ public boolean shouldBeApplied(Document document) { private boolean checkNamesRule(Document document, GuaranteeProviderFile parsedFile) { - Tenant tenant = document.getTenant(); + Tenant tenant = document.getGuarantor().getTenant(); return parsedFile.getNames().stream().anyMatch( (fullname) -> PersonNameComparator.bearlyEqualsTo(fullname.firstName(), tenant.getFirstName()) && PersonNameComparator.bearlyEqualsTo(fullname.lastName(), tenant.getLastName())); @@ -53,20 +57,20 @@ public DocumentAnalysisReport process(Document document, DocumentAnalysisReport GuaranteeProviderFile parsedFile = (GuaranteeProviderFile) document.getFiles().get(0).getParsedFileAnalysis().getParsedFile(); if (parsedFile.getStatus() == ParsedStatus.INCOMPLETE) { - log.error("Document was not correctly parsed :" + document.getTenant().getId()); + log.error("Document was not correctly parsed :" + document.getGuarantor().getTenant().getId()); report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED); } else if (!checkNamesRule(document, parsedFile)) { - log.error("Document names mismatches :" + document.getTenant().getId()); + log.error("Document names mismatches :" + document.getGuarantor().getTenant().getId()); report.getBrokenRules().add(DocumentBrokenRule.builder() .rule(DocumentRule.R_GUARANTEE_NAMES) .message(DocumentRule.R_GUARANTEE_NAMES.getDefaultMessage()) .build()); report.setAnalysisStatus(DocumentAnalysisStatus.DENIED); } else if (!checkValidityRule(parsedFile)) { - log.error("Document is expired :" + document.getTenant().getId()); + log.error("Document is expired :" + document.getGuarantor().getTenant().getId()); report.getBrokenRules().add(DocumentBrokenRule.builder() - .rule(DocumentRule.R_GUARANTEE_EXIRED) - .message(DocumentRule.R_GUARANTEE_EXIRED.getDefaultMessage()) + .rule(DocumentRule.R_GUARANTEE_EXPIRED) + .message(DocumentRule.R_GUARANTEE_EXPIRED.getDefaultMessage()) .build()); report.setAnalysisStatus(DocumentAnalysisStatus.DENIED); } else { @@ -74,7 +78,7 @@ public DocumentAnalysisReport process(Document document, DocumentAnalysisReport } } catch (Exception e) { - log.error("Error during the rules validation execution pocess"); + log.error("Error during the rules validation execution pocess",e); report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED); } return report; diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/PublicPayslipRulesValidationService.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/PublicPayslipRulesValidationService.java new file mode 100644 index 000000000..a77914106 --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/PublicPayslipRulesValidationService.java @@ -0,0 +1,179 @@ +package fr.dossierfacile.process.file.service.documentrules; + +import fr.dossierfacile.common.entity.*; +import fr.dossierfacile.common.entity.ocr.PublicPayslipFile; +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.common.enums.DocumentSubCategory; +import fr.dossierfacile.common.enums.ParsedFileAnalysisStatus; +import fr.dossierfacile.common.enums.ParsedFileClassification; +import fr.dossierfacile.process.file.barcode.twoddoc.parsing.TwoDDocDataType; +import fr.dossierfacile.process.file.util.PersonNameComparator; +import fr.dossierfacile.process.file.util.TwoDDocUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Slf4j +public class PublicPayslipRulesValidationService implements RulesValidationService { + @Override + public boolean shouldBeApplied(Document document) { + return document.getDocumentCategory() == DocumentCategory.FINANCIAL + && document.getDocumentSubCategory() == DocumentSubCategory.SALARY + && !CollectionUtils.isEmpty(document.getFiles()) + && document.getFiles().stream().anyMatch((f) -> f.getParsedFileAnalysis() != null + && f.getParsedFileAnalysis().getParsedFile() != null + && f.getParsedFileAnalysis().getParsedFile().getClassification() == ParsedFileClassification.PUBLIC_PAYSLIP); + } + + private PublicPayslipFile fromQR(BarCodeFileAnalysis barCodeFileAnalysis) { + Map dataWithLabel = (Map) barCodeFileAnalysis.getVerifiedData(); + return PublicPayslipFile.builder() + .fullname(dataWithLabel.get(TwoDDocDataType.ID_10.getLabel())) + .month(YearMonth.from(TwoDDocUtil.getLocalDateFrom2DDocHexDate(dataWithLabel.get(TwoDDocDataType.ID_54.getLabel())))) + .netTaxableIncome(Double.parseDouble(dataWithLabel.get(TwoDDocDataType.ID_58.getLabel()).replace(" ", "").replace(',', '.'))) + .cumulativeNetTaxableIncome(Double.parseDouble(dataWithLabel.get(TwoDDocDataType.ID_59.getLabel()).replace(" ", "").replace(',', '.'))) + .build(); + } + + private boolean checkQRCode(Document document) { + for (File dfFile : document.getFiles()) { + ParsedFileAnalysis analysis = dfFile.getParsedFileAnalysis(); + if (analysis == null || dfFile.getFileAnalysis() == null || analysis.getAnalysisStatus() == ParsedFileAnalysisStatus.FAILED) { + continue; + } + if (analysis.getClassification() == ParsedFileClassification.PUBLIC_PAYSLIP) { + PublicPayslipFile qrDocument = fromQR(dfFile.getFileAnalysis()); + PublicPayslipFile parsedDocument = (PublicPayslipFile) analysis.getParsedFile(); + + if (qrDocument == null + || qrDocument.getFullname() == null + || qrDocument.getMonth() == null + || qrDocument.getCumulativeNetTaxableIncome() == 0 + || !PersonNameComparator.equalsWithNormalization(qrDocument.getFullname(), parsedDocument.getFullname()) + || !qrDocument.getMonth().equals(parsedDocument.getMonth()) + || qrDocument.getNetTaxableIncome() != parsedDocument.getNetTaxableIncome() + || qrDocument.getCumulativeNetTaxableIncome() != parsedDocument.getCumulativeNetTaxableIncome()) { + return false; + } + } + } + return true; + } + + private boolean checkNamesRule(Document document) { + Person documentOwner = Optional.ofNullable((Person) document.getTenant()).orElseGet(() -> document.getGuarantor()); + for (File dfFile : document.getFiles()) { + ParsedFileAnalysis analysis = dfFile.getParsedFileAnalysis(); + PublicPayslipFile parsedFile = (PublicPayslipFile) analysis.getParsedFile(); + + String fullname = parsedFile.getFullname().toUpperCase().replaceFirst("^(MR |MME |MLLE )", ""); + + if (!PersonNameComparator.bearlyEqualsTo(fullname, documentOwner.getLastName(), documentOwner.getFirstName()) + && !PersonNameComparator.bearlyEqualsTo(fullname, documentOwner.getPreferredName(), documentOwner.getFirstName())) { + return false; + } + } + return true; + } + + private List> getExpectedMonthsLists() { + LocalDate localDate = LocalDate.now(); + YearMonth yearMonth = YearMonth.now(); + return (localDate.getDayOfMonth() <= 15) ? + List.of( + List.of(yearMonth.minusMonths(1), yearMonth.minusMonths(2), yearMonth.minusMonths(3)), + List.of(yearMonth.minusMonths(2), yearMonth.minusMonths(3), yearMonth.minusMonths(4))) : + List.of( + List.of(yearMonth, yearMonth.minusMonths(1), yearMonth.minusMonths(2)), + List.of(yearMonth.minusMonths(1), yearMonth.minusMonths(2), yearMonth.minusMonths(3))); + } + + private boolean checkMonthsValidityRule(Document document) { + List> expectedMonthsList = getExpectedMonthsLists(); + + List presentMonths = document.getFiles().stream() + .map(file -> ((PublicPayslipFile) file.getParsedFileAnalysis().getParsedFile()).getMonth()) + .toList(); + + return expectedMonthsList.stream().anyMatch( + expectedMonths -> expectedMonths.stream().allMatch(month -> presentMonths.contains(month)) + ); + } + + private boolean checkAmountValidityRule(Document document) { + List recentFiles = document.getFiles().stream() + .map(file -> (PublicPayslipFile) file.getParsedFileAnalysis().getParsedFile()) + .sorted(Comparator.comparing(PublicPayslipFile::getMonth).reversed()) + .limit(3) + .collect(Collectors.toList()); + + double monthlyAverage = recentFiles.stream() + .mapToDouble(PublicPayslipFile::getNetTaxableIncome) + .sum() / recentFiles.size(); + + // Check percentage difference + double diffPercentage = Math.abs((monthlyAverage - document.getMonthlySum()) / document.getMonthlySum()); + return (diffPercentage <= 0.2); + } + + @Override + public DocumentAnalysisReport process(Document document, DocumentAnalysisReport report) { + + try { + if (CollectionUtils.isEmpty(document.getFiles()) || document.getFiles().stream() + .anyMatch(f -> f.getParsedFileAnalysis() == null || f.getParsedFileAnalysis().getParsedFile() == null) + ) { + report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED); + return report; + } + + if (!checkQRCode(document)) { + log.error("Document mismatch to QR CODE :" + document.getId()); + report.getBrokenRules().add(DocumentBrokenRule.builder() + .rule(DocumentRule.R_PAYSLIP_QRCHECK) + .message(DocumentRule.R_PAYSLIP_QRCHECK.getDefaultMessage()) + .build()); + report.setAnalysisStatus(DocumentAnalysisStatus.DENIED); + } else if (!checkNamesRule(document)) { + log.error("Document names mismatches :" + document.getId()); + report.getBrokenRules().add(DocumentBrokenRule.builder() + .rule(DocumentRule.R_PAYSLIP_NAME) + .message(DocumentRule.R_PAYSLIP_NAME.getDefaultMessage()) + .build()); + report.setAnalysisStatus(DocumentAnalysisStatus.DENIED); + } else if (!checkMonthsValidityRule(document)) { + log.error("Document is expired :" + document.getId()); + report.getBrokenRules().add(DocumentBrokenRule.builder() + .rule(DocumentRule.R_PAYSLIP_MONTHS) + .message(DocumentRule.R_PAYSLIP_MONTHS.getDefaultMessage()) + .build()); + report.setAnalysisStatus(DocumentAnalysisStatus.DENIED); + } else if (!checkAmountValidityRule(document)) { + log.error("Amount specified on document mismatch :" + document.getId()); + report.getBrokenRules().add(DocumentBrokenRule.builder() + .rule(DocumentRule.R_PAYSLIP_AMOUNT_MISMATCHES) + .message(DocumentRule.R_PAYSLIP_AMOUNT_MISMATCHES.getDefaultMessage()) + .build()); + report.setAnalysisStatus(DocumentAnalysisStatus.DENIED); + } else { + report.setAnalysisStatus(DocumentAnalysisStatus.CHECKED); + } + + } catch (Exception e) { + log.error("Error during the rules validation execution pocess", e); + report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED); + } + return report; + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/OcrParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/OcrParser.java deleted file mode 100644 index 92c0b625e..000000000 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/OcrParser.java +++ /dev/null @@ -1,10 +0,0 @@ -package fr.dossierfacile.process.file.service.ocr; - - -import fr.dossierfacile.common.entity.ocr.ParsedFile; - -import java.io.File; - -public interface OcrParser { - T parse(File file); -} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFParser.java new file mode 100644 index 000000000..c53af6509 --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFParser.java @@ -0,0 +1,50 @@ +package fr.dossierfacile.process.file.service.parsers; + + +import fr.dossierfacile.common.entity.ocr.ParsedFile; +import fr.dossierfacile.process.file.service.parsers.tools.PageExtractorModel; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.text.PDFTextStripperByArea; + +import java.io.File; +import java.io.IOException; + +@Slf4j +@RequiredArgsConstructor +public abstract class AbstractPDFParser implements FileParser { + + protected abstract String getJsonModelFile(); + + protected abstract T getResultFromExtraction(PDFTextStripperByArea stripper); + + + @Override + public T parse(File file) { + try (PDDocument document = Loader.loadPDF(file)) { + PDPage page = document.getPage(0); + + PageExtractorModel model = new PageExtractorModel(getJsonModelFile()); + double scale = page.getMediaBox().getWidth() / model.getDefaultWidth(); + + if (modelMatches(page, model)) { + PDFTextStripperByArea stripper = new PDFTextStripperByArea(); + model.getNamedZones(scale).forEach((name, rect) -> stripper.addRegion(name, rect)); + stripper.extractRegions(page); + + return getResultFromExtraction(stripper); + } + } catch (Exception e) { + log.error("Unable to parse"); + throw new RuntimeException(e); + } + return null; + } + + protected boolean modelMatches(PDPage page, PageExtractorModel model) throws IOException { + return true; + } +} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/AbstractSinglePageImageOcrParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractSinglePageImageOcrParser.java similarity index 93% rename from dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/AbstractSinglePageImageOcrParser.java rename to dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractSinglePageImageOcrParser.java index a6527beee..5ddbaf2f9 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/AbstractSinglePageImageOcrParser.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractSinglePageImageOcrParser.java @@ -1,4 +1,4 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; import fr.dossierfacile.common.entity.ocr.ParsedFile; import fr.dossierfacile.common.utils.FileUtility; @@ -11,7 +11,7 @@ import java.io.IOException; @Slf4j -public abstract class AbstractSinglePageImageOcrParser implements OcrParser { +public abstract class AbstractSinglePageImageOcrParser implements FileParser { private BufferedImage getImage(File file) throws IOException { BufferedImage image; diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/FileParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/FileParser.java new file mode 100644 index 000000000..00fe1ac04 --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/FileParser.java @@ -0,0 +1,11 @@ +package fr.dossierfacile.process.file.service.parsers; + +import fr.dossierfacile.common.entity.ocr.ParsedFile; + +import java.io.File; + +public interface FileParser { + T parse(File file); + + boolean shouldTryToApply(fr.dossierfacile.common.entity.File file); +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttParser.java new file mode 100644 index 000000000..3cb74843a --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttParser.java @@ -0,0 +1,75 @@ +package fr.dossierfacile.process.file.service.parsers; + + +import fr.dossierfacile.common.entity.File; +import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.process.file.service.parsers.tools.PageExtractorModel; +import fr.dossierfacile.process.file.util.ImageUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDResources; +import org.apache.pdfbox.pdmodel.graphics.PDXObject; +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.text.PDFTextStripperByArea; +import org.springframework.core.annotation.Order; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; + +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_GUARANTEE; + +/** + * A Parsing POC + */ +@Service +@Slf4j +@RequiredArgsConstructor +@Order(1) +public class GuaranteeFasttParser extends AbstractPDFParser implements FileParser { + + @Override + protected String getJsonModelFile() { + return "/parsers/fasttN1ZT.json"; + } + + @Override + protected GuaranteeProviderFile getResultFromExtraction(PDFTextStripperByArea stripper) { + return GuaranteeProviderFile.builder() + .names(List.of(new GuaranteeProviderFile.FullName( + stripper.getTextForRegion("firstName").trim(), + stripper.getTextForRegion("lastName").trim() + ))) + .visaNumber(stripper.getTextForRegion("visaNumber").trim()) + .validityDate(stripper.getTextForRegion("validityDate").trim()) + .build(); + } + @Override + protected boolean modelMatches(PDPage page, PageExtractorModel model) throws IOException { + PDResources resources = page.getResources(); + for (COSName xObjectName : resources.getXObjectNames()) { + PDXObject xObject = resources.getXObject(xObjectName); + if (xObject instanceof PDImageXObject xImage) { + BufferedImage image = xImage.getImage(); + String md5 = ImageUtils.md5(image); + boolean result = model.getBackgroundImageMD5().equals(md5); + if (!result) { + log.debug("MD5 mismatches " + md5); + } + return result; + } + } + return false; + } + @Override + public boolean shouldTryToApply(File file) { + return (file.getDocument().getDocumentCategory() == DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE + && file.getDocument().getDocumentSubCategory() == OTHER_GUARANTEE + && MediaType.APPLICATION_PDF_VALUE.equalsIgnoreCase(file.getStorageFile().getContentType())); + } +} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttV2Parser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttV2Parser.java new file mode 100644 index 000000000..39ec113cb --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttV2Parser.java @@ -0,0 +1,84 @@ +package fr.dossierfacile.process.file.service.parsers; + + +import fr.dossierfacile.common.entity.File; +import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; +import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile.FullName; +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.process.file.service.parsers.tools.PageExtractorModel; +import fr.dossierfacile.process.file.util.ImageUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDResources; +import org.apache.pdfbox.pdmodel.graphics.PDXObject; +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.text.PDFTextStripperByArea; +import org.springframework.core.annotation.Order; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; + +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_GUARANTEE; + +/** + * A Parsing POC + */ +@Service +@Slf4j +@RequiredArgsConstructor +@Order(2) +public class GuaranteeFasttV2Parser extends AbstractPDFParser implements FileParser { + + @Override + protected String getJsonModelFile() { + return "/parsers/fasttN2ZT.json"; + } + + @Override + protected GuaranteeProviderFile getResultFromExtraction(PDFTextStripperByArea stripper) { + + return GuaranteeProviderFile.builder() + .names(List.of(new FullName( + stripper.getTextForRegion("firstName").trim(), + stripper.getTextForRegion("lastName").trim()), + new FullName( + stripper.getTextForRegion("firstName2").trim(), + stripper.getTextForRegion("lastName2").trim()) + ) + ) + .visaNumber(stripper.getTextForRegion("visaNumber").trim()) + .validityDate(stripper.getTextForRegion("validityDate").trim()) + .build(); + } + + // Currenlty FASTT PDF can be identified thanks to their background image + @Override + protected boolean modelMatches(PDPage page, PageExtractorModel model) throws IOException { + PDResources resources = page.getResources(); + for (COSName xObjectName : resources.getXObjectNames()) { + PDXObject xObject = resources.getXObject(xObjectName); + if (xObject instanceof PDImageXObject xImage) { + BufferedImage image = xImage.getImage(); + String md5 = ImageUtils.md5(image); + boolean result = model.getBackgroundImageMD5().equals(md5); + if (!result) { + log.debug("MD5 mismatches " + md5); + } + return result; + } + } + return false; + } + + @Override + public boolean shouldTryToApply(File file) { + return (file.getDocument().getDocumentCategory() == DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE + && file.getDocument().getDocumentSubCategory() == OTHER_GUARANTEE + && MediaType.APPLICATION_PDF_VALUE.equalsIgnoreCase(file.getStorageFile().getContentType())); + } +} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/GuaranteeVisaleParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeVisaleParser.java similarity index 81% rename from dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/GuaranteeVisaleParser.java rename to dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeVisaleParser.java index 35db6db0f..30c160dbe 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/GuaranteeVisaleParser.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/GuaranteeVisaleParser.java @@ -1,13 +1,15 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; -import com.google.common.annotations.VisibleForTesting; +import fr.dossierfacile.common.entity.File; import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; +import fr.dossierfacile.common.enums.DocumentCategory; import fr.dossierfacile.common.enums.ParsedStatus; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.sourceforge.tess4j.ITessAPI; import net.sourceforge.tess4j.Tesseract; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import java.awt.*; @@ -17,13 +19,17 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static fr.dossierfacile.common.enums.DocumentSubCategory.OTHER_GUARANTEE; +import static fr.dossierfacile.common.enums.DocumentSubCategory.VISALE; + /** * A Parsing POC */ @Service @Slf4j @RequiredArgsConstructor -public class GuaranteeVisaleParser extends AbstractSinglePageImageOcrParser implements OcrParser { +@Order(3) +public class GuaranteeVisaleParser extends AbstractSinglePageImageOcrParser implements FileParser { static final Zones ZONES = new Zones( new Rectangle(120, 150, 370, 30), new Rectangle(35, 205, 530, 40), @@ -71,8 +77,8 @@ public GuaranteeProviderFile parse(BufferedImage image) { String[] firstNames = zonesId[0].split("Pr[éeè]nom[:\\s\\d]+"); String[] lastNames = zonesId[1].split("Nom[:\\s\\d]+"); List fullNames = new LinkedList<>(); - for ( int i = 1 ; i < firstNames.length && i < lastNames.length ; i++){ - fullNames.add(new GuaranteeProviderFile.FullName(firstNames[i], lastNames[i])); + for (int i = 1; i < firstNames.length && i < lastNames.length; i++) { + fullNames.add(new GuaranteeProviderFile.FullName(firstNames[i].trim(), lastNames[i].trim())); } if (fullNames.isEmpty()) { log.error("Firstname/Lastname not found"); @@ -96,6 +102,13 @@ public GuaranteeProviderFile parse(BufferedImage image) { return result; } + @Override + public boolean shouldTryToApply(File file) { + return (file.getDocument().getDocumentCategory() == DocumentCategory.GUARANTEE_PROVIDER_CERTIFICATE + && (file.getDocument().getDocumentSubCategory() == VISALE + || file.getDocument().getDocumentSubCategory() == OTHER_GUARANTEE));// TODO currently there is not way to selection VISALE subcategory on UI + } + public record Zones(Rectangle zoneTitle, Rectangle zoneIdentification, Rectangle zoneValidityDate) { public static Rectangle scale(Rectangle rectangle, double scale) { return new Rectangle((int) (rectangle.x * scale), (int) (rectangle.y * scale), (int) (rectangle.width * scale), (int) (rectangle.height * scale)); diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/PublicPayslipParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/PublicPayslipParser.java new file mode 100644 index 000000000..cc4e183fc --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/PublicPayslipParser.java @@ -0,0 +1,91 @@ +package fr.dossierfacile.process.file.service.parsers; + +import fr.dossierfacile.common.entity.ocr.PublicPayslipFile; +import fr.dossierfacile.common.enums.DocumentCategory; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDDocumentInformation; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.text.PDFTextStripperByArea; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; + +import java.awt.*; +import java.io.File; +import java.time.YearMonth; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.util.Locale; + +import static fr.dossierfacile.common.enums.DocumentSubCategory.SALARY; + +@Service +@Slf4j +@RequiredArgsConstructor +public class PublicPayslipParser implements FileParser { + + private static final DateTimeFormatter YEAR_MONTH_FORMATTER = new DateTimeFormatterBuilder() + .parseCaseInsensitive().appendPattern("MMMM yyyy").toFormatter(Locale.FRENCH); + + @Override + public PublicPayslipFile parse(File file) { + PublicPayslipFile result = PublicPayslipFile.builder().build(); + // file is a pdf + try (PDDocument document = Loader.loadPDF(file)) { + PDDocumentInformation info = document.getDocumentInformation(); + + if (info == null || info.getTitle() == null || !info.getTitle().equalsIgnoreCase("PAY18E")) { + log.info("This document is not in PAY18E format"); + return null; + } + + PDPage page = document.getPage(0); + double scale = page.getMediaBox().getWidth() / 595; + + Rectangle titleRect = new Rectangle((int) (273 * scale), (int) (10 * scale), (int) (134 * scale), (int) (8 * scale)); + Rectangle monthRect = new Rectangle((int) (315 * scale), (int) (22 * scale), (int) (100 * scale), (int) (11 * scale)); + Rectangle netTaxableIncomeRect = new Rectangle((int) (125 * scale), (int) (711 * scale), (int) (80 * scale), (int) (13 * scale)); + Rectangle cumulativeNetIncomeRect = new Rectangle((int) (25 * scale), (int) (711 * scale), (int) (84 * scale), (int) (13 * scale)); + Rectangle fullnameRect = new Rectangle((int) (215 * scale), (int) (680 * scale), (int) (266 * scale), (int) (35 * scale)); + + PDFTextStripperByArea stripper = new PDFTextStripperByArea(); + stripper.addRegion("title", titleRect); + stripper.addRegion("month", monthRect); + stripper.addRegion("netTaxableIncome", netTaxableIncomeRect); + stripper.addRegion("cumulativeNetIncome", cumulativeNetIncomeRect); + stripper.addRegion("fullname", fullnameRect); + + stripper.extractRegions(page); + + String title = stripper.getTextForRegion("title"); + if ("BULLETIN DE PAYE".equalsIgnoreCase(title)) { + log.info("This document is not a public payslip"); + return null; + } + String month = stripper.getTextForRegion("month").trim(); + String netTaxableIncome = stripper.getTextForRegion("netTaxableIncome").trim(); + String cumulativeNetIncome = stripper.getTextForRegion("cumulativeNetIncome").trim(); + String fullname = stripper.getTextForRegion("fullname").replaceAll("\n.*", "").trim(); + + result.setNetTaxableIncome(Double.parseDouble(netTaxableIncome.replace(" ", "").replace(',', '.'))); + result.setCumulativeNetTaxableIncome(Double.parseDouble(cumulativeNetIncome.replace(" ", "").replace(',', '.'))); + result.setFullname(fullname); + + result.setMonth(YearMonth.parse(month, YEAR_MONTH_FORMATTER)); + + return result; + } catch (Exception e) { + log.error("Unable to parse"); + throw new RuntimeException(e); + } + } + + @Override + public boolean shouldTryToApply(fr.dossierfacile.common.entity.File file) { + return (file.getDocument().getDocumentCategory() == DocumentCategory.FINANCIAL + && file.getDocument().getDocumentSubCategory() == SALARY + && MediaType.APPLICATION_PDF_VALUE.equalsIgnoreCase(file.getStorageFile().getContentType())); + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeLeafParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeLeafParser.java similarity index 90% rename from dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeLeafParser.java rename to dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeLeafParser.java index 1b2970f45..d97c4cf59 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeLeafParser.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeLeafParser.java @@ -1,12 +1,15 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; import com.google.common.annotations.VisibleForTesting; +import fr.dossierfacile.common.entity.File; import fr.dossierfacile.common.entity.ocr.TaxIncomeLeaf; +import fr.dossierfacile.common.enums.DocumentCategory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.sourceforge.tess4j.ITessAPI; import net.sourceforge.tess4j.Tesseract; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import java.awt.*; @@ -21,7 +24,8 @@ @Service @Slf4j @RequiredArgsConstructor -public class TaxIncomeLeafParser extends AbstractSinglePageImageOcrParser implements OcrParser { +@Order(2) +public class TaxIncomeLeafParser extends AbstractSinglePageImageOcrParser implements FileParser { static final TaxIncomeLeafParser.TaxIncomeLeafZones TEMPLATE_2023 = new TaxIncomeLeafParser.TaxIncomeLeafZones( @@ -96,6 +100,11 @@ public TaxIncomeLeaf parse(BufferedImage image) { return result; } + @Override + public boolean shouldTryToApply(File file) { + return (file.getDocument().getDocumentCategory() == DocumentCategory.TAX); + } + public record TaxIncomeLeafZones(Rectangle headerLeft, Rectangle headerRight) { public static Rectangle scale(Rectangle rectangle, double scale) { return new Rectangle((int) (rectangle.x * scale), (int) (rectangle.y * scale), (int) (rectangle.width * scale), (int) (rectangle.height * scale)); diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeParser.java similarity index 94% rename from dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeParser.java rename to dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeParser.java index 56cb0b43d..8f5d49df2 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeParser.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeParser.java @@ -1,13 +1,15 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; import fr.dossierfacile.common.entity.ocr.TaxIncomeMainFile; +import fr.dossierfacile.common.enums.DocumentCategory; import fr.dossierfacile.common.utils.FileUtility; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.sourceforge.tess4j.ITessAPI; import net.sourceforge.tess4j.Tesseract; import org.apache.commons.io.FilenameUtils; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import javax.imageio.ImageIO; @@ -26,7 +28,8 @@ @Service @Slf4j @RequiredArgsConstructor -public class TaxIncomeParser implements OcrParser { +@Order(1) +public class TaxIncomeParser implements FileParser { static final TaxIncomeZones TEMPLATE_2023 = new TaxIncomeZones(new Rectangle(120, 10, 400, 65), new Rectangle(17, 176, 200, 180), new Rectangle(250, 170, 300, 100), new Rectangle(226, 595, 325, 55)); static final TaxIncomeZones TEMPLATE_2020 = new TaxIncomeZones(new Rectangle(140, 40, 325, 65), new Rectangle(40, 155, 200, 180), new Rectangle(270, 130, 300, 100), new Rectangle(255, 570, 315, 55)); private final Pattern incomeYearPattern = Pattern.compile("revenus de (\\d{4})"); @@ -38,6 +41,9 @@ public class TaxIncomeParser implements OcrParser { private final TaxIncomeLeafParser taxIncomeLeafParser; private transient volatile Tesseract tesseract; + + + String fixNumber(String str){ return str.replaceAll("O", "0").replaceAll("[lI|]", "1").replaceAll("S", "5").replaceAll("\\s", ""); } @@ -140,6 +146,11 @@ public TaxIncomeMainFile parse(File file) { return result; } + @Override + public boolean shouldTryToApply(fr.dossierfacile.common.entity.File file) { + return (file.getDocument().getDocumentCategory() == DocumentCategory.TAX); + } + public record TaxIncomeZones(Rectangle zoneTitle, Rectangle zoneRef, Rectangle zoneAddress, Rectangle zoneRevenuPart) { diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/tools/PageExtractorModel.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/tools/PageExtractorModel.java new file mode 100644 index 000000000..6d9d4ca95 --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/tools/PageExtractorModel.java @@ -0,0 +1,37 @@ +package fr.dossierfacile.process.file.service.parsers.tools; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.dossierfacile.common.utils.MapperUtil; +import fr.dossierfacile.process.file.service.parsers.AbstractPDFParser; + +import java.awt.*; +import java.io.IOException; +import java.util.Map; +import java.util.TreeMap; + +public class PageExtractorModel { + private final JsonNode jsonNode; + + public PageExtractorModel(String jsonResourceModelPath) throws IOException { + this.jsonNode = MapperUtil.newObjectMapper().readTree(AbstractPDFParser.class.getResource(jsonResourceModelPath)); + } + + public double getDefaultWidth() { + return jsonNode.get("page").get("width").asDouble(); + } + public String getBackgroundImageMD5() { + return jsonNode.get("classification").get("background-image-md5").asText(); + } + public Map getNamedZones(double scale) { + Map map = new TreeMap(); + JsonNode attributesNode = jsonNode.get("zones"); + for (JsonNode attributeNode : attributesNode) { + String rectStr = attributeNode.get("rect").asText(); + String[] rectSplit = rectStr.split(","); + Rectangle rectangle = new Rectangle((int) (Integer.parseInt(rectSplit[0]) * scale), (int) (Integer.parseInt(rectSplit[1]) * scale), (int) (Integer.parseInt(rectSplit[2]) * scale), (int) (Integer.parseInt(rectSplit[3]) * scale)); + + map.put(attributeNode.get("name").asText(), rectangle); + } + return map; + } +} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/processors/FileParserProcessor.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/processors/FileParserProcessor.java new file mode 100644 index 000000000..b8dee9e6d --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/processors/FileParserProcessor.java @@ -0,0 +1,89 @@ +package fr.dossierfacile.process.file.service.processors; + +import fr.dossierfacile.common.entity.File; +import fr.dossierfacile.common.entity.ParsedFileAnalysis; +import fr.dossierfacile.common.entity.ocr.ParsedFile; +import fr.dossierfacile.common.enums.ParsedFileAnalysisStatus; +import fr.dossierfacile.common.repository.ParsedFileAnalysisRepository; +import fr.dossierfacile.process.file.repository.FileRepository; +import fr.dossierfacile.process.file.service.StorageFileLoaderService; +import fr.dossierfacile.process.file.service.parsers.FileParser; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import java.util.Comparator; +import java.util.List; + +@Slf4j +@Service +@AllArgsConstructor +public class FileParserProcessor implements Processor { + private StorageFileLoaderService storageFileLoaderService; + private final FileRepository fileRepository; + private final ParsedFileAnalysisRepository parsedFileAnalysisRepository; + + private final List> fileParsers; + + @PostConstruct + public void init() { + fileParsers.sort(Comparator.comparingInt(parser -> { + Order order = AnnotationUtils.findAnnotation(parser.getClass(), Order.class); + return order == null ? Integer.MAX_VALUE : order.value(); + })); + } + + /** + * Gets configured parsers list for the specified type of dffile + */ + private List> getParsers(File file) { + return fileParsers.stream().filter(parser -> parser.shouldTryToApply(file)).toList(); + } + + public File process(File dfFile) { + + List> parsers = getParsers(dfFile); + if (CollectionUtils.isEmpty(parsers)) { + log.debug("There is not parser associated to this kind of document"); + return dfFile; + } + + java.io.File file = storageFileLoaderService.getTemporaryFilePath(dfFile.getStorageFile()); + if (file == null) { + log.error("File reading Error"); + return dfFile; + } + try { + for (FileParser parser : parsers) { + try { + ParsedFile parsedDocument = parser.parse(file); + if (parsedDocument == null) { + log.warn("File {} has not been parsed", dfFile.getId()); + } else { + ParsedFileAnalysis parsedFileAnalysis = ParsedFileAnalysis.builder() + .analysisStatus(ParsedFileAnalysisStatus.COMPLETED) + .parsedFile(parsedDocument) + .file(dfFile) + .classification(parsedDocument.getClassification()) + .build(); + + parsedFileAnalysisRepository.save(parsedFileAnalysis); + dfFile.setParsedFileAnalysis(parsedFileAnalysis); + fileRepository.save(dfFile); + log.info("Successfully parse file {}", dfFile.getId()); + break; + } + } catch (Exception e) { + log.warn("Unable to parse file {}", dfFile.getId(), e); + } + } + } finally { + storageFileLoaderService.removeFileIfExist(file); + } + return dfFile; + } +} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/processors/OcrParserFileProcessor.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/processors/OcrParserFileProcessor.java deleted file mode 100644 index a167f27b9..000000000 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/processors/OcrParserFileProcessor.java +++ /dev/null @@ -1,88 +0,0 @@ -package fr.dossierfacile.process.file.service.processors; - -import fr.dossierfacile.common.entity.File; -import fr.dossierfacile.common.entity.ParsedFileAnalysis; -import fr.dossierfacile.common.entity.ocr.ParsedFile; -import fr.dossierfacile.common.enums.DocumentCategory; -import fr.dossierfacile.common.enums.ParsedFileAnalysisStatus; -import fr.dossierfacile.common.repository.ParsedFileAnalysisRepository; -import fr.dossierfacile.process.file.repository.FileRepository; -import fr.dossierfacile.process.file.service.ocr.GuaranteeVisaleParser; -import fr.dossierfacile.process.file.service.ocr.OcrParser; -import fr.dossierfacile.process.file.service.ocr.TaxIncomeLeafParser; -import fr.dossierfacile.process.file.service.ocr.TaxIncomeParser; -import fr.dossierfacile.process.file.service.StorageFileLoaderService; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static fr.dossierfacile.common.enums.DocumentSubCategory.CERTIFICATE_VISA; - -@Slf4j -@Service -@AllArgsConstructor -public class OcrParserFileProcessor implements Processor { - private StorageFileLoaderService storageFileLoaderService; - private final FileRepository fileRepository; - private final ParsedFileAnalysisRepository parsedFileAnalysisRepository; - private final TaxIncomeParser taxIncomeParser; - private final TaxIncomeLeafParser taxIncomeLeafParser; - private final GuaranteeVisaleParser guaranteeVisaleParser; - - /** - * Gets configured parsers list for the specified type of dffile - */ - private List getParsers(File file) { - if (file.getDocument().getDocumentCategory() == DocumentCategory.TAX) { - return Arrays.asList(taxIncomeParser, taxIncomeLeafParser); - } - if (file.getDocument().getDocumentCategory() == DocumentCategory.IDENTIFICATION - && file.getDocument().getDocumentSubCategory() == CERTIFICATE_VISA) - return Collections.singletonList(guaranteeVisaleParser); - return null; - } - - public File process(File dfFile) { - - List parsers = getParsers(dfFile); - if (CollectionUtils.isEmpty(parsers)) { - log.debug("There is not parser associateed to this kind of document"); - return dfFile; - } - - java.io.File file = storageFileLoaderService.getTemporaryFilePath(dfFile.getStorageFile()); - if (file == null) { - log.error("File reading Error"); - return dfFile; - } - try { - for (OcrParser parser : parsers) { - try { - ParsedFile parsedDocument = parser.parse(file); - ParsedFileAnalysis parsedFileAnalysis = ParsedFileAnalysis.builder() - .analysisStatus(ParsedFileAnalysisStatus.COMPLETED) - .parsedFile(parsedDocument) - .classification(parsedDocument.getClassification()) - .build(); - - parsedFileAnalysis.setFile(dfFile); - parsedFileAnalysisRepository.save(parsedFileAnalysis); - dfFile.setParsedFileAnalysis(parsedFileAnalysis); - fileRepository.save(dfFile); - log.info("Successfully parse file {}", dfFile.getId()); - break; - } catch (Exception e) { - log.warn("Unable to parse file {}", dfFile.getId()); - } - } - } finally { - storageFileLoaderService.removeFileIfExist(file); - } - return dfFile; - } -} diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/ImageUtils.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/ImageUtils.java new file mode 100644 index 000000000..b6c682d33 --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/ImageUtils.java @@ -0,0 +1,21 @@ +package fr.dossierfacile.process.file.util; + +import lombok.experimental.UtilityClass; +import org.springframework.util.DigestUtils; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +@UtilityClass +public class ImageUtils { + + public static String md5(BufferedImage image) throws IOException { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + ImageIO.write(image, "jpg", baos); + byte[] bytes = baos.toByteArray(); + return DigestUtils.md5DigestAsHex(bytes); + } + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/PersonNameComparator.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/PersonNameComparator.java index 0ba0efff5..4a1555942 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/PersonNameComparator.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/PersonNameComparator.java @@ -11,7 +11,7 @@ private static String normalizeName(String name) { if (name == null) return null; String normalized = Normalizer.normalize(name, Normalizer.Form.NFD); - return normalized.replace('-', ' ').replace('.', ' ') + return normalized.replace('-', ' ').replace('.', ' ').replace('\'', ' ') .replaceAll("[\\p{InCombiningDiacriticalMarks}]", "").toUpperCase().trim(); } public static boolean equalsWithNormalization(String fullName, String fullNameToCompare) { diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/QrCodeFileAnalysisCriteria.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/QrCodeFileAnalysisCriteria.java index 4640eb0f2..016752280 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/QrCodeFileAnalysisCriteria.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/QrCodeFileAnalysisCriteria.java @@ -34,7 +34,7 @@ public static boolean shouldBeAnalyzed(File file) { hasSubCategory(document, CDI, CDI_TRIAL, CDD, PUBLIC, CTT, RETIRED, STUDENT, UNEMPLOYED); case FINANCIAL -> hasSubCategory(document, SALARY, SCHOLARSHIP, SOCIAL_SERVICE, PENSION); case RESIDENCY -> hasSubCategory(document, GUEST, GUEST_PARENTS); - case IDENTIFICATION, IDENTIFICATION_LEGAL_PERSON, NULL -> false; + case IDENTIFICATION, IDENTIFICATION_LEGAL_PERSON, GUARANTEE_PROVIDER_CERTIFICATE, NULL -> false; }; } diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/TwoDDocUtil.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/TwoDDocUtil.java new file mode 100644 index 000000000..90962a47e --- /dev/null +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/util/TwoDDocUtil.java @@ -0,0 +1,18 @@ +package fr.dossierfacile.process.file.util; + +import lombok.experimental.UtilityClass; + +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; + +@UtilityClass +public class TwoDDocUtil { + public static LocalDate getLocalDateFrom2DDocHexDate(String hexDateFrom200) { + long dailyCount = Long.parseLong(hexDateFrom200, 16); + return LocalDate.of(2000, 1, 1).plusDays(dailyCount); + } + + public static String get2DDocHexDateFromLocalDate(LocalDate localDate) { + return String.format("%04X", LocalDate.of(2000, 1, 1).until(localDate, ChronoUnit.DAYS)); + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/main/resources/parsers/fasttN1ZT.json b/dossierfacile-process-file/src/main/resources/parsers/fasttN1ZT.json new file mode 100644 index 000000000..91e970490 --- /dev/null +++ b/dossierfacile-process-file/src/main/resources/parsers/fasttN1ZT.json @@ -0,0 +1,27 @@ +{ + "page": { + "width": "892" + }, + "classification": { + "name": "FASTT_N1_ZT", + "background-image-md5": "9180d5834b3af06a0cebea1985a84649" + }, + "zones": [ + { + "name": "visaNumber", + "rect": "232,416,256,30" + }, + { + "name": "lastName", + "rect": "232,478,256,30" + }, + { + "name": "firstName", + "rect": "232,540,256,30" + }, + { + "name": "validityDate", + "rect": "41,1086,138,20" + } + ] +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/main/resources/parsers/fasttN2ZT.json b/dossierfacile-process-file/src/main/resources/parsers/fasttN2ZT.json new file mode 100644 index 000000000..f61687499 --- /dev/null +++ b/dossierfacile-process-file/src/main/resources/parsers/fasttN2ZT.json @@ -0,0 +1,35 @@ +{ + "page": { + "width": "892" + }, + "classification": { + "name": "FASTT_N2_ZT", + "background-image-md5": "d18ff78c030a3dea810fd1dd97f44a0b" + }, + "zones": [ + { + "name": "visaNumber", + "rect": "230,391,256,30" + }, + { + "name": "lastName", + "rect": "230,438,256,30" + }, + { + "name": "firstName", + "rect": "230,486,256,30" + }, + { + "name": "lastName2", + "rect": "230,627,256,30" + }, + { + "name": "firstName2", + "rect": "230,675,256,30" + }, + { + "name": "validityDate", + "rect": "153,867,138,20" + } + ] +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ApiTesseractTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ApiTesseractTest.java index a0253c8e4..91fc0416f 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ApiTesseractTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ApiTesseractTest.java @@ -12,7 +12,7 @@ @Disabled @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.MOCK) -public class ApiTesseractTest { +class ApiTesseractTest { @Autowired private ApiTesseract apiTesseract; diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java index a37b1eef7..0824df29d 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java @@ -38,8 +38,8 @@ Document buildGuaranteeProviderFile() throws JsonProcessingException { "firstName": "Jean" } ], - "signed": true, - "status": "COMPLETE", + "signed": null, + "status": null, "visaNumber": "V11000000000", "deliveryDate": "01/12/2023", "validityDate": "02/03/2024", @@ -55,9 +55,10 @@ Document buildGuaranteeProviderFile() throws JsonProcessingException { .parsedFileAnalysis(parsedFileAnalysis) .build(); return Document.builder() - .tenant(tenant) + .tenant(null) + .guarantor(Guarantor.builder().tenant(tenant).build()) .documentCategory(DocumentCategory.IDENTIFICATION) - .documentSubCategory(DocumentSubCategory.CERTIFICATE_VISA) + .documentSubCategory(DocumentSubCategory.OTHER_GUARANTEE) .files(Arrays.asList(dfFile)) .build(); } @@ -90,13 +91,13 @@ void document_expired() throws Exception { Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.DENIED); Assertions.assertThat(report.getBrokenRules()).hasSize(1); - Assertions.assertThat(report.getBrokenRules().get(0)).matches(docRule -> docRule.getRule() == DocumentRule.R_GUARANTEE_EXIRED); + Assertions.assertThat(report.getBrokenRules().get(0)).matches(docRule -> docRule.getRule() == DocumentRule.R_GUARANTEE_EXPIRED); } @Test void document_wrong_firstname() throws Exception { Document document = buildGuaranteeProviderFile(); - document.getTenant().setFirstName("Michel"); + document.getGuarantor().getTenant().setFirstName("Michel"); ((GuaranteeProviderFile) document.getFiles().get(0).getParsedFileAnalysis().getParsedFile()) .setValidityDate(LocalDate.now().plusDays(15).format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))); DocumentAnalysisReport report = DocumentAnalysisReport.builder() diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/PublicPayslipRulesValidationServiceTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/PublicPayslipRulesValidationServiceTest.java new file mode 100644 index 000000000..ebb60ed8b --- /dev/null +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/PublicPayslipRulesValidationServiceTest.java @@ -0,0 +1,140 @@ +package fr.dossierfacile.process.file.service.documentrules; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.dossierfacile.common.entity.*; +import fr.dossierfacile.common.entity.ocr.PublicPayslipFile; +import fr.dossierfacile.common.enums.DocumentCategory; +import fr.dossierfacile.common.enums.DocumentSubCategory; +import fr.dossierfacile.common.enums.ParsedFileAnalysisStatus; +import fr.dossierfacile.common.enums.ParsedFileClassification; +import fr.dossierfacile.process.file.util.TwoDDocUtil; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.YearMonth; +import java.time.temporal.TemporalAdjusters; +import java.util.Arrays; +import java.util.LinkedList; + +class PublicPayslipRulesValidationServiceTest { + + private PublicPayslipRulesValidationService publicPayslipRVS = new PublicPayslipRulesValidationService(); + + private File buildValidDfFile(LocalDate date) throws JsonProcessingException { + BarCodeFileAnalysis barCodeFileAnalysis = BarCodeFileAnalysis.builder() + .verifiedData(new ObjectMapper() + .readValue(""" + { + "Fin de période": "{startHex}", + "Début de période": "{endHex}", + "Salaire net imposable": "3000,05", + "SIRET de l’employeur": "123456789000001", + "Date de début de contrat": "11111111", + "Cumul du salaire net imposable": "30000,10", + "Ligne 1 de la norme adresse postale du bénéficiaire de la prestation": "MR KALOUF JEAN" + } + """.replace("{startHex}", TwoDDocUtil.get2DDocHexDateFromLocalDate(date.with(TemporalAdjusters.firstDayOfMonth()))) + .replace("{endHex}", TwoDDocUtil.get2DDocHexDateFromLocalDate(date.with(TemporalAdjusters.lastDayOfMonth()))), + Object.class)) + .documentType(BarCodeDocumentType.PUBLIC_PAYSLIP) + .build(); + + PublicPayslipFile parsedFile = PublicPayslipFile.builder() + .fullname("MR KALOUF JEAN") + .month(YearMonth.from(date)) + .netTaxableIncome(3000.05) + .cumulativeNetTaxableIncome(30000.10) + .build(); + + ParsedFileAnalysis parsedFileAnalysis = ParsedFileAnalysis.builder().parsedFile(parsedFile) + .analysisStatus(ParsedFileAnalysisStatus.COMPLETED) + .classification(ParsedFileClassification.PUBLIC_PAYSLIP) + .build(); + + return File.builder() + .fileAnalysis(barCodeFileAnalysis) + .parsedFileAnalysis(parsedFileAnalysis) + .build(); + } + + + Document buildPublicPayslipDocument() throws JsonProcessingException { + Tenant tenant = Tenant.builder() + .firstName("Jean") + .lastName("KALOUF") + .build(); + + LocalDate currentDate = LocalDate.now(); + return Document.builder() + .tenant(tenant) + .monthlySum(3000) + .documentCategory(DocumentCategory.FINANCIAL) + .documentSubCategory(DocumentSubCategory.SALARY) + .files(Arrays.asList(buildValidDfFile(currentDate.minusMonths(1)), + buildValidDfFile(currentDate.minusMonths(2)), + buildValidDfFile(currentDate.minusMonths(3)))) + .build(); + } + + Document buildPublicPayslipDocumentWithWrongMonths() throws JsonProcessingException { + Tenant tenant = Tenant.builder() + .firstName("Jean") + .lastName("KALOUF") + .build(); + + LocalDate currentDate = LocalDate.now(); + return Document.builder() + .tenant(tenant) + .documentCategory(DocumentCategory.FINANCIAL) + .documentSubCategory(DocumentSubCategory.SALARY) + .files(Arrays.asList(buildValidDfFile(currentDate.minusMonths(3)), + buildValidDfFile(currentDate.minusMonths(4)), + buildValidDfFile(currentDate.minusMonths(5)))) + .build(); + } + + @Test + void document_full_test_ok() throws Exception { + Document document = buildPublicPayslipDocument(); + + DocumentAnalysisReport report = DocumentAnalysisReport.builder() + .document(document) + .brokenRules(new LinkedList<>()) + .build(); + publicPayslipRVS.process(document, report); + + Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.CHECKED); + } + + @Test + void document_full_test_wrong_month() throws Exception { + Document document = buildPublicPayslipDocumentWithWrongMonths(); + + DocumentAnalysisReport report = DocumentAnalysisReport.builder() + .document(document) + .brokenRules(new LinkedList<>()) + .build(); + publicPayslipRVS.process(document, report); + + Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.DENIED); + Assertions.assertThat(report.getBrokenRules()).hasSize(1); + Assertions.assertThat(report.getBrokenRules().get(0)).matches(docRule -> docRule.getRule() == DocumentRule.R_PAYSLIP_MONTHS); + } + + @Test + void document_full_test_wrong_average_amount() throws Exception { + Document document = buildPublicPayslipDocument(); + document.setMonthlySum(2400); + DocumentAnalysisReport report = DocumentAnalysisReport.builder() + .document(document) + .brokenRules(new LinkedList<>()) + .build(); + publicPayslipRVS.process(document, report); + + Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.DENIED); + Assertions.assertThat(report.getBrokenRules()).hasSize(1); + Assertions.assertThat(report.getBrokenRules().get(0)).matches(docRule -> docRule.getRule() == DocumentRule.R_PAYSLIP_AMOUNT_MISMATCHES); + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttParserTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttParserTest.java new file mode 100644 index 000000000..5cfbf9775 --- /dev/null +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttParserTest.java @@ -0,0 +1,20 @@ +package fr.dossierfacile.process.file.service.parsers; + +import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; + +@Disabled +class GuaranteeFasttParserTest { + private final GuaranteeFasttParser parser = new GuaranteeFasttParser(); + + @Test + void parse() { + File file = new File(this.getClass().getResource("/fasttN1ZT.pdf").getFile()); + + GuaranteeProviderFile doc = parser.parse(file); + System.out.print(doc); + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttV2ParserTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttV2ParserTest.java new file mode 100644 index 000000000..c5a4c7208 --- /dev/null +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeFasttV2ParserTest.java @@ -0,0 +1,27 @@ +package fr.dossierfacile.process.file.service.parsers; + +import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; + +@Disabled +class GuaranteeFasttV2ParserTest { + private final GuaranteeFasttV2Parser parser = new GuaranteeFasttV2Parser(); + + @Test + void parse() { + File file = new File(this.getClass().getResource("/fasttN2ZT.pdf").getFile()); + + GuaranteeProviderFile doc = parser.parse(file); + System.out.print(doc); + } + @Test + void parse_failed() { + File file = new File(this.getClass().getResource("/fasttN1ZT.pdf").getFile()); + + GuaranteeProviderFile doc = parser.parse(file); + System.out.print(doc); + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/GuaranteeVisaleParserTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeVisaleParserTest.java similarity index 71% rename from dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/GuaranteeVisaleParserTest.java rename to dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeVisaleParserTest.java index db9172b1e..a57a247d5 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/GuaranteeVisaleParserTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/GuaranteeVisaleParserTest.java @@ -1,16 +1,12 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; -import fr.dossierfacile.common.entity.ocr.TaxIncomeMainFile; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.File; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -public class GuaranteeVisaleParserTest { +class GuaranteeVisaleParserTest { private final GuaranteeVisaleParser visaleParser = new GuaranteeVisaleParser(); @Disabled diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/PublicPayslipFileParserTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/PublicPayslipFileParserTest.java new file mode 100644 index 000000000..6e97653cf --- /dev/null +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/PublicPayslipFileParserTest.java @@ -0,0 +1,24 @@ +package fr.dossierfacile.process.file.service.parsers; + +import fr.dossierfacile.common.entity.ocr.PublicPayslipFile; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; + +@Disabled +class PublicPayslipFileParserTest { + private final PublicPayslipParser parser = new PublicPayslipParser(); + + @Test + void parse() { + File file = new File(this.getClass().getResource("/documents/fake_payslip.pdf").getFile()); + + PublicPayslipFile doc = parser.parse(file); + + System.out.println(doc.getMonth()); + System.out.println(doc.getNetTaxableIncome()); + System.out.println(doc.getCumulativeNetTaxableIncome()); + System.out.println(doc.getFullname()); + } +} \ No newline at end of file diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeLeafParserTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeLeafParserTest.java similarity index 92% rename from dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeLeafParserTest.java rename to dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeLeafParserTest.java index b5f7dad3f..aaaba7fbb 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeLeafParserTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeLeafParserTest.java @@ -1,11 +1,11 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.regex.Matcher; -public class TaxIncomeLeafParserTest { +class TaxIncomeLeafParserTest { private final TaxIncomeLeafParser taxIncomeLeafParser = new TaxIncomeLeafParser(); diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeParserTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeParserTest.java similarity index 88% rename from dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeParserTest.java rename to dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeParserTest.java index e9aeeb33b..91215a429 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/ocr/TaxIncomeParserTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/parsers/TaxIncomeParserTest.java @@ -1,4 +1,4 @@ -package fr.dossierfacile.process.file.service.ocr; +package fr.dossierfacile.process.file.service.parsers; import fr.dossierfacile.common.entity.ocr.TaxIncomeMainFile; import org.junit.jupiter.api.Disabled; @@ -7,7 +7,7 @@ import java.io.File; @Disabled -public class TaxIncomeParserTest { +class TaxIncomeParserTest { private final TaxIncomeParser taxIncomeParser = new TaxIncomeParser(new TaxIncomeLeafParser()); @Test @@ -18,6 +18,5 @@ void parse() { TaxIncomeMainFile doc = taxIncomeParser.parse(file); System.out.print(doc); - } } \ No newline at end of file diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/PersonNameComparatorTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/PersonNameComparatorTest.java index e40efb7e6..164988fce 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/PersonNameComparatorTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/PersonNameComparatorTest.java @@ -44,6 +44,14 @@ void compare_name_should_be_ok_basc() { Assertions.assertEquals(true, PersonNameComparator.bearlyEqualsTo(fullName, givenLastName, givenFirstName)); } + @Test + void compare_name_should_be_ok_apostrophe() { + String givenFirstName = "Jean"; + String givenLastName = "M BOL"; + String fullName = "M'Bol Jean"; + Assertions.assertEquals(true, PersonNameComparator.bearlyEqualsTo(fullName, givenLastName, givenFirstName)); + } + @Test void compare_name_should_be_nok_reverse() { String givenFirstName = "Marche"; diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/TwoDDocUtilTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/TwoDDocUtilTest.java new file mode 100644 index 000000000..04ed5b68e --- /dev/null +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/util/TwoDDocUtilTest.java @@ -0,0 +1,18 @@ +package fr.dossierfacile.process.file.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +class TwoDDocUtilTest { + @Test + void check_date() { + Assertions.assertEquals(LocalDate.of(2023, 12, 1), TwoDDocUtil.getLocalDateFrom2DDocHexDate("221F")); + } + + @Test + void check_hex() { + Assertions.assertEquals("221F", TwoDDocUtil.get2DDocHexDateFromLocalDate(LocalDate.of(2023, 12, 1))); + } +} \ No newline at end of file diff --git a/dossierfacile-task-scheduler/pom.xml b/dossierfacile-task-scheduler/pom.xml index c2ffe7186..40543ea8c 100644 --- a/dossierfacile-task-scheduler/pom.xml +++ b/dossierfacile-task-scheduler/pom.xml @@ -15,7 +15,7 @@ ${packaging.type} - 19 + 21 1.18.30 diff --git a/system.properties b/system.properties index a7f513c02..0399015ce 100644 --- a/system.properties +++ b/system.properties @@ -1,2 +1,2 @@ -java.runtime.version=19 -maven.version=3.6.2 +java.runtime.version=21 +maven.version=3.9.5