Skip to content

Commit

Permalink
feat: Parsed and analysis tax documents for validation automation
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabien authored and fabiengo committed Dec 6, 2023
1 parent b6c99d7 commit 8f1658c
Show file tree
Hide file tree
Showing 57 changed files with 1,403 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import fr.dossierfacile.api.front.service.interfaces.TenantStatusService;
import fr.dossierfacile.api.front.util.TransactionalUtil;
import fr.dossierfacile.common.entity.Document;
import fr.dossierfacile.common.entity.DocumentAnalysisReport;
import fr.dossierfacile.common.entity.File;
import fr.dossierfacile.common.entity.Person;
import fr.dossierfacile.common.entity.StorageFile;
import fr.dossierfacile.common.entity.Tenant;
import fr.dossierfacile.common.enums.DocumentCategory;
import fr.dossierfacile.common.enums.DocumentStatus;
import fr.dossierfacile.common.enums.TenantFileStatus;
import fr.dossierfacile.common.repository.DocumentAnalysisReportRepository;
import fr.dossierfacile.common.repository.StorageFileRepository;
import fr.dossierfacile.common.service.interfaces.DocumentHelperService;
import lombok.RequiredArgsConstructor;
Expand All @@ -38,6 +40,7 @@
public class DocumentServiceImpl implements DocumentService {

private final DocumentRepository documentRepository;
private final DocumentAnalysisReportRepository documentAnalysisReportRepository;
private final StorageFileRepository storageFileRepository;
private final TenantStatusService tenantStatusService;
private final ApartmentSharingService apartmentSharingService;
Expand Down Expand Up @@ -137,9 +140,22 @@ public void resetValidatedDocumentsStatusOfSpecifiedCategoriesToToProcess(List<D
@Override
public void addFile(MultipartFile multipartFile, Document document) throws IOException {
File file = documentHelperService.addFile(multipartFile, document);
markDocumentAsEdited(document);

TransactionalUtil.afterCommit(() -> {
minifyFileProducer.minifyFile(file.getId());
producer.analyzeFile(file);
});
}

@Override
public void markDocumentAsEdited(Document document) {
document.setLastModifiedDate(LocalDateTime.now());
if ( document.getDocumentAnalysisReport() != null) {
documentAnalysisReportRepository.delete(document.getDocumentAnalysisReport());
document.setDocumentAnalysisReport(null);
}
documentRepository.save(document);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Service
@AllArgsConstructor
@Slf4j
Expand All @@ -34,6 +36,8 @@ public Document delete(Long id, Tenant tenant) {

logService.saveDocumentEditedLog(document, tenant);

documentService.markDocumentAsEdited(document);

if (document.getFiles().isEmpty()) {
documentService.delete(document);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ public interface DocumentService {
void addFile(MultipartFile multipartFile, Document document) throws IOException;

void delete(Document document);

void markDocumentAsEdited(Document document);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.gouv.bo.dto;

import fr.dossierfacile.common.entity.DocumentAnalysisReport;
import fr.dossierfacile.common.entity.DocumentDeniedReasons;
import fr.dossierfacile.common.enums.DocumentCategory;
import fr.dossierfacile.common.enums.DocumentSubCategory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<html lang="en"
layout:decorator="bo/layout-bo"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:th="http://www.thymeleaf.org">
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>DossierFacile</title>
</head>
Expand Down Expand Up @@ -718,7 +719,6 @@ <h4 style="font-weight: bold;">ABSENT</h4>
<div th:if="${document.getCustomText()!=null}">
<span th:text="${'Custom text: '+document.getCustomText()}"></span>
</div>

<ul>
<li style="margin-top: 5px" th:each="file : ${filesByDocument.get(document.getId())}">
<a th:href="${'/files/' + file.getId()}"
Expand All @@ -736,6 +736,15 @@ <h4 style="font-weight: bold;">ABSENT</h4>
</span>
</li>
</ul>
<div sec:authorize="hasRole('ROLE_ADMIN')" th:if="${document.getDocumentAnalysisReport()!=null}">
<hr/>Admin| Statuts de la vérification automatique:
<span th:text="${document.getDocumentAnalysisReport().getAnalysisStatus}"></span>
<ul>
<li style="margin-top: 5px" th:each="rule : ${document.getDocumentAnalysisReport().getBrokenRules()}">
<span style="font-size:smaller" th:text="' ' + ${rule.message}"></span>
</li>
</ul>
</div>
<div th:if="${document.avisDetected}">
- Attention, un avis de situation a été détecté !
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
public class FileAnalysisCriteria {

public static boolean shouldBeAnalyzed(File file) {
if (file == null)
return false;
Document document = file.getDocument();
return switch (document.getDocumentCategory()) {
case TAX -> hasSubCategory(document, MY_NAME);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package fr.dossierfacile.common.converter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import fr.dossierfacile.common.entity.ocr.ParsedFile;
import fr.dossierfacile.common.enums.ParsedFileClassification;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.io.IOException;

@Converter
public class ParsedFileConverter implements AttributeConverter<ParsedFile, String> {
private static final ObjectMapper objectMapper = new ObjectMapper();

@Override
public String convertToDatabaseColumn(ParsedFile object) {
if (object == null) {
return null;
}
try {
return objectMapper.writeValueAsString(object);
} catch (IOException e) {
throw new IllegalArgumentException("Error converting ParsedFile to JSON", e);
}
}

@Override
public ParsedFile convertToEntityAttribute(String dbData) {
if (dbData == null) {
return null;
}
try {
// get classification
JsonNode jsonNode = objectMapper.readTree(dbData);
ParsedFileClassification classification = ParsedFileClassification.valueOf(jsonNode.get("classification").asText());

return objectMapper.treeToValue(jsonNode, classification.getClassificationClass());
} catch (IOException e) {
throw new IllegalArgumentException("Error converting JSON to ParsedFile", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import lombok.ToString;
import org.hibernate.Hibernate;

import javax.annotation.Nullable;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
Expand Down Expand Up @@ -65,6 +66,10 @@ public class Document implements Serializable {
@Column(name = "creation_date")
private LocalDateTime creationDateTime = LocalDateTime.now();

@Builder.Default
@Column(name = "last_modified_date")
private LocalDateTime lastModifiedDate = LocalDateTime.now();

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "guarantor_id")
@ToString.Exclude
Expand Down Expand Up @@ -111,6 +116,10 @@ public class Document implements Serializable {
@Builder.Default
private Boolean avisDetected = false;

@Nullable
@OneToOne(mappedBy= "document", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private DocumentAnalysisReport documentAnalysisReport;

@Basic(fetch = FetchType.LAZY)
public boolean isLocked() {
return locked;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package fr.dossierfacile.common.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Type;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import java.util.List;

@Data
@Builder
@Entity
@Table(name = "document_analysis_report")
@AllArgsConstructor
@NoArgsConstructor
public class DocumentAnalysisReport {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne(targetEntity = Document.class, fetch = FetchType.LAZY)
@JoinColumn(name = "document_id")
private Document document;

@Enumerated(EnumType.STRING)
private DocumentAnalysisStatus analysisStatus;

@Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
private List<DocumentBrokenRule> brokenRules;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package fr.dossierfacile.common.entity;

public enum DocumentAnalysisStatus {
DENIED,
CHECKED,
UNDEFINED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fr.dossierfacile.common.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Embeddable;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;

@Embeddable
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DocumentBrokenRule {

@Enumerated(EnumType.STRING)
private DocumentRule rule;

private String message;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package fr.dossierfacile.common.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@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.WARN, "Les noms et prénoms ne correspondent pas");

public enum Level{
CRITICAL, WARN
}

private final Level level;
private final String defaultMessage;

}

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public class File implements Serializable {
@OneToOne(mappedBy = "file", fetch = FetchType.LAZY)
private BarCodeFileAnalysis fileAnalysis;

@Nullable
@OneToOne(mappedBy= "file", fetch = FetchType.LAZY)
private ParsedFileAnalysis parsedFileAnalysis;

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package fr.dossierfacile.common.entity;

import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import fr.dossierfacile.common.converter.ParsedFileConverter;
import fr.dossierfacile.common.entity.ocr.ParsedFile;
import fr.dossierfacile.common.enums.ParsedFileAnalysisStatus;
import fr.dossierfacile.common.enums.ParsedFileClassification;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.ColumnTransformer;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;

import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Data
@Builder
@Entity
@Table(name = "parsed_file_analysis")
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@AllArgsConstructor
@NoArgsConstructor
public class ParsedFileAnalysis {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne(targetEntity = File.class, fetch = FetchType.LAZY)
@JoinColumn(name = "file_id")
private File file;

@Enumerated(EnumType.STRING)
private ParsedFileAnalysisStatus analysisStatus;

@Enumerated(EnumType.STRING)
private ParsedFileClassification classification;

@Column(columnDefinition = "jsonb")
@Convert(converter = ParsedFileConverter.class)
@ColumnTransformer(write = "?::jsonb")
private ParsedFile parsedFile;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package fr.dossierfacile.common.entity.ocr;

public interface ParsedFile {
String getClassification();
}
Loading

0 comments on commit 8f1658c

Please sign in to comment.