Skip to content

Commit 5fadc0e

Browse files
authored
✨ Feat(process-file): add rule on number of pages for rent receipt (#840)
1 parent 5ac0d4e commit 5fadc0e

File tree

5 files changed

+63
-36
lines changed

5 files changed

+63
-36
lines changed

dossierfacile-common-library/src/main/java/fr/dossierfacile/common/entity/DocumentRule.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public enum DocumentRule {
3131
R_RENT_RECEIPT_NAME(Level.CRITICAL, "Nom/prénoms ne correspondent pas"),
3232
R_RENT_RECEIPT_MONTHS(Level.CRITICAL, "Les trois dernières quittances doivent être fournies (la plus récente doit être au pire M-2)"),
3333
R_RENT_RECEIPT_ADDRESS_SALARY(Level.WARN, "TODO. L'adresse de la location semble ne pas correspondre à l'adresse des bulletins de payes"),
34+
R_RENT_RECEIPT_NB_DOCUMENTS(Level.WARN, "Veuillez fournir 3 quittances de loyer ou préciser pourquoi vous n'êtes pas dans la possibilité de le faire"),
3435

3536
R_FRANCE_IDENTITE_NAMES(Level.CRITICAL, "Les noms et prénoms ne correspondent pas"),
3637
R_FRANCE_IDENTITE_STATUS(Level.CRITICAL, "Ce document n'a pas pu être validé par France Identité");

dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/configuration/DummyConfig.java

Lines changed: 0 additions & 15 deletions
This file was deleted.

dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/AnalyzeDocumentService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void processDocument(Long documentId) throws RetryableOperationException
5656
.document(document)
5757
.brokenRules(new LinkedList<>())
5858
.build();
59-
rulesValidationServices.stream().forEach(rulesService -> rulesService.process(document, report));
59+
rulesValidationServices.forEach(rulesService -> rulesService.process(document, report));
6060
document.setDocumentAnalysisReport(report);
6161
documentAnalysisReportRepository.save(report);
6262
documentRepository.save(document);// necessaire?

dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
@RequiredArgsConstructor
2020
@Slf4j
2121
public class RentalReceiptRulesValidationService implements RulesValidationService {
22+
static final int MIN_NUMBER_OF_RECEIPT = 3;
23+
2224
@Override
2325
public boolean shouldBeApplied(Document document) {
2426
return document.getDocumentCategory() == DocumentCategory.RESIDENCY
2527
&& document.getDocumentSubCategory() == DocumentSubCategory.TENANT
26-
&& !CollectionUtils.isEmpty(document.getFiles())
27-
&& document.getFiles().stream().anyMatch((f) -> f.getParsedFileAnalysis() != null
28-
&& f.getParsedFileAnalysis().getParsedFile() != null);
28+
&& !CollectionUtils.isEmpty(document.getFiles());
2929
}
3030

3131
/**
@@ -85,9 +85,7 @@ private boolean checkMonthsValidityRule(Document document) {
8585
.map(file -> ((RentalReceiptFile) file.getParsedFileAnalysis().getParsedFile()).getPeriod())
8686
.toList();
8787

88-
return expectedMonthsList.stream().anyMatch(
89-
expectedMonths -> expectedMonths.stream().allMatch(month -> presentMonths.contains(month))
90-
);
88+
return expectedMonthsList.stream().anyMatch(presentMonths::containsAll);
9189
}
9290

9391
private boolean checkAddressWithSalary(Document document) {
@@ -116,31 +114,42 @@ private boolean checkAddressWithSalary(Document document) {
116114

117115
@Override
118116
public DocumentAnalysisReport process(Document document, DocumentAnalysisReport report) {
117+
report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED);
119118

120-
try {
121-
if (CollectionUtils.isEmpty(document.getFiles()) || document.getFiles().stream()
122-
.anyMatch(f -> f.getParsedFileAnalysis() == null || f.getParsedFileAnalysis().getParsedFile() == null)
123-
) {
124-
report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED);
125-
return report;
126-
}
119+
if (CollectionUtils.isEmpty(document.getFiles())) {
120+
return report;
121+
}
127122

123+
if (document.getFiles().stream().mapToInt(File::getNumberOfPages).sum() < MIN_NUMBER_OF_RECEIPT) {
124+
log.error("Document number of pages mismatches :{}", document.getId());
125+
report.getBrokenRules().add(DocumentBrokenRule.builder()
126+
.rule(DocumentRule.R_RENT_RECEIPT_NB_DOCUMENTS)
127+
.message(DocumentRule.R_RENT_RECEIPT_NB_DOCUMENTS.getDefaultMessage())
128+
.build());
129+
report.setAnalysisStatus(DocumentAnalysisStatus.DENIED);
130+
}
131+
132+
if (document.getFiles().stream().anyMatch(f -> f.getParsedFileAnalysis() == null || f.getParsedFileAnalysis().getParsedFile() == null)) {
133+
return report;
134+
}
135+
136+
try {
128137
if (!checkNamesRule(document)) {
129-
log.error("Document names mismatches :" + document.getId());
138+
log.error("Document names mismatches :{}", document.getId());
130139
report.getBrokenRules().add(DocumentBrokenRule.builder()
131140
.rule(DocumentRule.R_RENT_RECEIPT_NAME)
132141
.message(DocumentRule.R_RENT_RECEIPT_NAME.getDefaultMessage())
133142
.build());
134143
report.setAnalysisStatus(DocumentAnalysisStatus.DENIED);
135144
} else if (!checkMonthsValidityRule(document)) {
136-
log.error("Document is expired :" + document.getId());
145+
log.error("Document is expired :{}", document.getId());
137146
report.getBrokenRules().add(DocumentBrokenRule.builder()
138147
.rule(DocumentRule.R_RENT_RECEIPT_MONTHS)
139148
.message(DocumentRule.R_RENT_RECEIPT_MONTHS.getDefaultMessage())
140149
.build());
141150
report.setAnalysisStatus(DocumentAnalysisStatus.DENIED);
142151
} else if (!checkAddressWithSalary(document)) {
143-
log.error("Document with wrong address :" + document.getId());
152+
log.error("Document with wrong address :{}", document.getId());
144153
report.getBrokenRules().add(DocumentBrokenRule.builder()
145154
.rule(DocumentRule.R_RENT_RECEIPT_ADDRESS_SALARY)
146155
.message(DocumentRule.R_RENT_RECEIPT_ADDRESS_SALARY.getDefaultMessage())

dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationServiceTest.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
import java.time.YearMonth;
1212
import java.time.temporal.ChronoField;
1313
import java.util.Arrays;
14+
import java.util.Collections;
1415
import java.util.LinkedList;
1516
import java.util.List;
1617

1718
class RentalReceiptRulesValidationServiceTest {
1819

1920
private final RentalReceiptRulesValidationService validationService = new RentalReceiptRulesValidationService();
2021

21-
private File buildValidDfFile(LocalDate period, LocalDate paymentDate) throws JsonProcessingException {
22+
private File buildValidDfFile(LocalDate period, LocalDate paymentDate) {
2223

2324
RentalReceiptFile parsedFile = RentalReceiptFile.builder()
2425
.period(YearMonth.from(period))
@@ -35,6 +36,7 @@ private File buildValidDfFile(LocalDate period, LocalDate paymentDate) throws Js
3536

3637
return File.builder()
3738
.parsedFileAnalysis(parsedFileAnalysis)
39+
.numberOfPages(1)
3840
.build();
3941
}
4042

@@ -49,15 +51,14 @@ Document buildRentalReceiptDocument() throws JsonProcessingException {
4951
tenant.setApartmentSharing(as);
5052

5153
LocalDate currentDate = LocalDate.now().with(ChronoField.DAY_OF_MONTH, 14);
52-
Document doc = Document.builder()
54+
return Document.builder()
5355
.tenant(tenant)
5456
.documentCategory(DocumentCategory.RESIDENCY)
5557
.documentSubCategory(DocumentSubCategory.TENANT)
5658
.files(Arrays.asList(buildValidDfFile(currentDate.minusMonths(2), currentDate),
5759
buildValidDfFile(currentDate.minusMonths(3), currentDate),
5860
buildValidDfFile(currentDate.minusMonths(4), currentDate)))
5961
.build();
60-
return doc;
6162
}
6263

6364
Document buildRentalReceiptDocumentWithWrongMonths() throws JsonProcessingException {
@@ -80,6 +81,24 @@ Document buildRentalReceiptDocumentWithWrongMonths() throws JsonProcessingExcept
8081
.build();
8182
}
8283

84+
Document buildRentalReceiptDocumentWithOneMonth() throws JsonProcessingException {
85+
Tenant tenant = Tenant.builder()
86+
.firstName("Jean")
87+
.lastName("DUPONT")
88+
.build();
89+
ApartmentSharing as = ApartmentSharing.builder().tenants(List.of(tenant)).build();
90+
as.setApplicationType(ApplicationType.ALONE);
91+
tenant.setApartmentSharing(as);
92+
93+
LocalDate currentDate = LocalDate.now();
94+
return Document.builder()
95+
.tenant(tenant)
96+
.documentCategory(DocumentCategory.RESIDENCY)
97+
.documentSubCategory(DocumentSubCategory.TENANT)
98+
.files(Collections.singletonList(buildValidDfFile(currentDate.minusMonths(1), currentDate)))
99+
.build();
100+
}
101+
83102
@Test
84103
void document_full_test_ok() throws Exception {
85104
Document document = buildRentalReceiptDocument();
@@ -105,7 +124,20 @@ void document_full_test_wrong_month() throws Exception {
105124

106125
Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.DENIED);
107126
Assertions.assertThat(report.getBrokenRules()).hasSize(1);
108-
Assertions.assertThat(report.getBrokenRules().get(0)).matches(docRule -> docRule.getRule() == DocumentRule.R_RENT_RECEIPT_MONTHS);
127+
Assertions.assertThat(report.getBrokenRules().getFirst()).matches(docRule -> docRule.getRule() == DocumentRule.R_RENT_RECEIPT_MONTHS);
109128
}
110129

130+
@Test
131+
void when_only_one_month_then_report_error() throws Exception {
132+
Document document = buildRentalReceiptDocumentWithOneMonth();
133+
DocumentAnalysisReport report = DocumentAnalysisReport.builder()
134+
.document(document)
135+
.brokenRules(new LinkedList<>())
136+
.build();
137+
validationService.process(document, report);
138+
139+
Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.DENIED);
140+
Assertions.assertThat(report.getBrokenRules()).hasSize(2);
141+
Assertions.assertThat(report.getBrokenRules().getFirst()).matches(docRule -> docRule.getRule() == DocumentRule.R_RENT_RECEIPT_NB_DOCUMENTS);
142+
}
111143
}

0 commit comments

Comments
 (0)