diff --git a/dossierfacile-api-owner/README.md b/dossierfacile-api-owner/README.md
new file mode 100644
index 000000000..866695089
--- /dev/null
+++ b/dossierfacile-api-owner/README.md
@@ -0,0 +1,9 @@
+# API Propriétaire (dossierfacile-api-owner)
+
+## Description
+API REST dédiée à l'espace propriétaires, permettant la gestion et la consultation des dossiers des locataires.
+
+## Fonctionnalités principales
+- Création et gestion des comptes propriétaires
+- Partage de ses propriétés avec les candidats locataires
+- Consultation des dossiers partagés par les locataires
\ No newline at end of file
diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/user/OwnerMapper.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/user/OwnerMapper.java
index 1b6365dfe..ba2ee22f1 100644
--- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/user/OwnerMapper.java
+++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/user/OwnerMapper.java
@@ -5,8 +5,11 @@
import fr.dossierfacile.common.entity.ApartmentSharing;
import fr.dossierfacile.common.entity.Owner;
import fr.dossierfacile.common.entity.Property;
+import fr.dossierfacile.common.enums.TenantFileStatus;
+
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
+import org.mapstruct.Named;
import org.springframework.stereotype.Component;
@Component
@@ -20,7 +23,15 @@ public abstract class OwnerMapper {
@Mapping( target="totalGuarantorSalary", expression="java(apartmentSharing.totalGuarantorSalary())" )
public abstract ApartmentSharingModel apartmentSharingToApartmentSharingModel(ApartmentSharing apartmentSharing);
- @Mapping( target="propertyApartmentSharingCount", expression="java(property.getPropertiesApartmentSharing().size())" )
- @Mapping( source="dpeDate", target="dpeDate", dateFormat="yyyy-MM-dd")
+ @Mapping( source="property", target="propertyApartmentSharingCount", qualifiedByName="validApplicationsCount" )
+ @Mapping( source="dpeDate", target="dpeDate", dateFormat="yyyy-MM-dd" )
public abstract LightPropertyModel toLightPropertyModel(Property property);
+
+ @Named("validApplicationsCount")
+ public static int getValidApplicationsCount(Property property) {
+ long count = property.getPropertiesApartmentSharing().stream()
+ .filter(p -> !p.getApartmentSharing().getStatus().equals(TenantFileStatus.ARCHIVED))
+ .count();
+ return (int) count;
+ }
}
diff --git a/dossierfacile-api-owner/src/main/resources/application.properties b/dossierfacile-api-owner/src/main/resources/application.properties
index 03a33190f..6d4223c0b 100644
--- a/dossierfacile-api-owner/src/main/resources/application.properties
+++ b/dossierfacile-api-owner/src/main/resources/application.properties
@@ -38,7 +38,7 @@ logging.level.root=info
logging.file.path=logs
logging.logstash.destination=
-application.api.version=3
+application.api.version=4
application.name=api-owner
environment=
diff --git a/dossierfacile-api-tenant/README.md b/dossierfacile-api-tenant/README.md
new file mode 100644
index 000000000..eed8c9677
--- /dev/null
+++ b/dossierfacile-api-tenant/README.md
@@ -0,0 +1,14 @@
+# API Locataire (dossierfacile-api-tenant)
+
+## Description
+API REST dédiée aux locataires, permettant la gestion des dossiers de location.
+API REST dédiée aux utilisateurs de DossierFacile (DFC), permettant la visualisation des informations des locataires.
+
+## Fonctionnalités principales
+- Création et gestion de comptes locataires
+- Téléversement et gestion des justificatifs
+- Création et modification de dossiers
+- Partage de dossiers
+
+## Documentation de l'API DFC
+La documentation Swagger est accessible [ici](https://api-preprod.dossierfacile.fr/swagger-ui/index.html?urls.primaryName=API%20DFC).
\ No newline at end of file
diff --git a/dossierfacile-api-tenant/pom.xml b/dossierfacile-api-tenant/pom.xml
index 8c3b128f9..48acbc8a6 100644
--- a/dossierfacile-api-tenant/pom.xml
+++ b/dossierfacile-api-tenant/pom.xml
@@ -31,7 +31,7 @@
org.keycloak
keycloak-admin-client
- 26.0.2
+ 26.0.3
org.springframework.boot
diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/CustomAppender.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/CustomAppender.java
new file mode 100644
index 000000000..46d10885b
--- /dev/null
+++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/CustomAppender.java
@@ -0,0 +1,61 @@
+package fr.dossierfacile.api.front.log;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.classic.spi.IThrowableProxy;
+import ch.qos.logback.classic.spi.StackTraceElementProxy;
+import ch.qos.logback.core.AppenderBase;
+import ch.qos.logback.core.Context;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class CustomAppender extends AppenderBase {
+ private static final Map> logsByRequestId = new ConcurrentHashMap<>();
+
+ @Override
+ protected void append(ILoggingEvent eventObject) {
+ String requestId = MDC.get("request_id");
+ if (requestId != null) {
+ String message = eventObject.getFormattedMessage();
+
+ if (eventObject.getLevel().isGreaterOrEqual(Level.ERROR)) {
+ IThrowableProxy throwableProxy = eventObject.getThrowableProxy();
+ if (throwableProxy != null) {
+ StringBuilder stackTrace = new StringBuilder();
+ for (StackTraceElementProxy line : throwableProxy.getStackTraceElementProxyArray()) {
+ stackTrace.append(line).append("\n");
+ }
+ message += "\n" + stackTrace;
+ }
+ }
+
+ LogModel log = new LogModel(message, eventObject.getLevel());
+ logsByRequestId.computeIfAbsent(requestId, id -> new ArrayList<>())
+ .add(log);
+ }
+ }
+
+ public static List getLogsForRequest(String requestId) {
+ return logsByRequestId.getOrDefault(requestId, List.of());
+ }
+
+ public static void clearLogsForRequest(String requestId) {
+ logsByRequestId.remove(requestId);
+ }
+
+ public static void attachToRootLogger() {
+ Logger rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+ CustomAppender customAppender = new CustomAppender();
+ customAppender.setName("CUSTOM");
+ Context context = rootLogger.getLoggerContext();
+ customAppender.setContext(context);
+ customAppender.start();
+ rootLogger.addAppender(customAppender);
+ }
+}
diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/GlobalExceptionHandler.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/GlobalExceptionHandler.java
new file mode 100644
index 000000000..6dd39131d
--- /dev/null
+++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/GlobalExceptionHandler.java
@@ -0,0 +1,18 @@
+package fr.dossierfacile.api.front.log;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity handleException(Exception e) {
+ log.error("Unhandled exception: ", e);
+ return new ResponseEntity<>("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+}
\ No newline at end of file
diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogAggregationFilter.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogAggregationFilter.java
new file mode 100644
index 000000000..d372efb0b
--- /dev/null
+++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogAggregationFilter.java
@@ -0,0 +1,72 @@
+package fr.dossierfacile.api.front.log;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.logstash.logback.appender.LogstashTcpSocketAppender;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class LogAggregationFilter extends OncePerRequestFilter {
+ private LogstashTcpSocketAppender logstashAppender;
+
+ @PostConstruct
+ public void init() {
+ Logger rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+ logstashAppender = (LogstashTcpSocketAppender) rootLogger.getAppender("LOGSTASH");
+ if (logstashAppender == null) {
+ throw new IllegalStateException("Logstash appender (LOGSTASH) not found in Logback configuration.");
+ }
+ }
+
+ @Override
+ protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, FilterChain filterChain)
+ throws ServletException, IOException {
+ String requestId = MDC.get("request_id");
+ try {
+ filterChain.doFilter(request, response);
+ } finally {
+ List logs = CustomAppender.getLogsForRequest(requestId);
+ String logMessage = logs.stream().map(LogModel::getMessage).collect(Collectors.joining());
+
+ String enrichedLogs = String.format(
+ "Request completed: URI:%s, Method:%s, Status:%d, Logs:%s",
+ request.getRequestURI(),
+ request.getMethod(),
+ response.getStatus(),
+ logMessage
+ );
+
+ Level logLevel = logs.stream().map(LogModel::getLevel).max(Comparator.comparingInt(Level::toInt)).orElse(Level.INFO);
+
+ LoggingEvent enrichedEvent = new LoggingEvent();
+ enrichedEvent.setTimeStamp(System.currentTimeMillis());
+ enrichedEvent.setLoggerName("AggregatedHttpLogger");
+ enrichedEvent.setLevel(logLevel);
+ enrichedEvent.setThreadName(Thread.currentThread().getName());
+ enrichedEvent.setMessage(enrichedLogs);
+
+ LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+ enrichedEvent.setLoggerContext(loggerContext);
+
+ logstashAppender.doAppend(enrichedEvent);
+
+ CustomAppender.clearLogsForRequest(requestId);
+ }
+ }
+}
diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogConfiguration.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogConfiguration.java
new file mode 100644
index 000000000..893bee565
--- /dev/null
+++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogConfiguration.java
@@ -0,0 +1,14 @@
+package fr.dossierfacile.api.front.log;
+
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Component
+public class LogConfiguration {
+
+ @PostConstruct
+ public void setupCustomLogging() {
+ CustomAppender.attachToRootLogger();
+ }
+}
\ No newline at end of file
diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogModel.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogModel.java
new file mode 100644
index 000000000..4b5f255ea
--- /dev/null
+++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/log/LogModel.java
@@ -0,0 +1,15 @@
+package fr.dossierfacile.api.front.log;
+
+import ch.qos.logback.classic.Level;
+import lombok.Getter;
+
+@Getter
+public class LogModel {
+ String message;
+ Level level;
+
+ public LogModel(String message, Level level) {
+ this.message = message;
+ this.level = level;
+ }
+}
diff --git a/dossierfacile-api-tenant/src/main/resources/application.properties b/dossierfacile-api-tenant/src/main/resources/application.properties
index 4040ee54e..0ec58c92a 100644
--- a/dossierfacile-api-tenant/src/main/resources/application.properties
+++ b/dossierfacile-api-tenant/src/main/resources/application.properties
@@ -77,7 +77,7 @@ logging.logstash.destination=
# Swagger
springdoc.api-docs.groups.enabled=true
-application.api.version=3
+application.api.version=4
application.name=api-tenant
application.base.url=
tenant.base.url=
diff --git a/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml b/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml
index 135363ba8..d353f25e5 100644
--- a/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml
+++ b/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml
@@ -56,9 +56,11 @@
+
+
diff --git a/dossierfacile-api-watermark/src/main/resources/application.properties b/dossierfacile-api-watermark/src/main/resources/application.properties
index 9b97b9cd2..bf339cfad 100644
--- a/dossierfacile-api-watermark/src/main/resources/application.properties
+++ b/dossierfacile-api-watermark/src/main/resources/application.properties
@@ -44,6 +44,6 @@ logging.logstash.destination=
file.retention.days=1
cron.process.cleanup=0 0 0 * * ?
-application.api.version=3
+application.api.version=4
application.name=api-watermark
environment=
\ No newline at end of file
diff --git a/dossierfacile-bo/src/main/resources/application.properties b/dossierfacile-bo/src/main/resources/application.properties
index 73623e218..a105893cd 100644
--- a/dossierfacile-bo/src/main/resources/application.properties
+++ b/dossierfacile-bo/src/main/resources/application.properties
@@ -66,7 +66,7 @@ logging.level.root=info
logging.file.path=logs
logging.logstash.destination=
-application.api.version=3
+application.api.version=4
application.name=bo
environment=
application.base.url=
diff --git a/dossierfacile-common-library/README.md b/dossierfacile-common-library/README.md
index 752b99ac9..083874315 100644
--- a/dossierfacile-common-library/README.md
+++ b/dossierfacile-common-library/README.md
@@ -1,3 +1,10 @@
-# DossierFacile-common-library
+# Bibliothèque commune (dossierfacile-common-library)
-This project contains shared models, repositories, mappers, services, ... used by Dossier-Facile's services.
\ No newline at end of file
+## Description
+Bibliothèque partagée contenant les composants communs utilisés par les différents services du projet.
+
+## Composants principaux
+- Entités JPA communes
+- Services partagés
+- Configurations communes
+- Ressources utilitaires
\ No newline at end of file
diff --git a/dossierfacile-pdf-generator/README.md b/dossierfacile-pdf-generator/README.md
index 822e1c9db..472569f0d 100644
--- a/dossierfacile-pdf-generator/README.md
+++ b/dossierfacile-pdf-generator/README.md
@@ -1,37 +1,8 @@
-# Dossier-Facile-Pdf-Generator
-Dossier Facile PDF Generator
+# Générateur de fichiers PDF (dossierfacile-pdf-generator)
+## Description
+Service dédié à la génération de documents PDF.
-# Install and run
-
-To build: `mvn clean install`
-To run: `mvn spring-boot:run `
-
-## Requirements
-- running DossierFacile database
-- running rabbitMQ service
-
-## Configure
-
-We use Github package to store common library `dossierfacile-common-library` .
-Thus you need to authenticate yourself to get it on github package.
-
-Configure the following environement variables:
-```
-GITHUB_USERNAME
-GITHUB_TOKEN
-```
-Or use your global maven settings: .m2/settings.xml
-```
-
- ...
-
-
- github
- GITHUB_USERNAME
- GITHUB_TOKEN
-
-
- ...
-
-```
\ No newline at end of file
+## Fonctionnalités principales
+- Conversion de documents et fichiers en PDF avec filigrane
+- Génération de dossiers de location au format PDF
\ No newline at end of file
diff --git a/dossierfacile-pdf-generator/src/main/resources/application.properties b/dossierfacile-pdf-generator/src/main/resources/application.properties
index 1f25fb767..a319a406a 100644
--- a/dossierfacile-pdf-generator/src/main/resources/application.properties
+++ b/dossierfacile-pdf-generator/src/main/resources/application.properties
@@ -40,7 +40,7 @@ logging.level.root=info
logging.file.path=logs
logging.logstash.destination=
-application.api.version=3
+application.api.version=4
application.name=pdf-generator
environment=
diff --git a/dossierfacile-process-file/README.md b/dossierfacile-process-file/README.md
new file mode 100644
index 000000000..35c24221a
--- /dev/null
+++ b/dossierfacile-process-file/README.md
@@ -0,0 +1,9 @@
+# Service de traitement asynchrone des fichiers et docuemnts (dossierfacile-process-file)
+
+## Description
+Service responsable du traitement asynchrone des documents et des fichiers.
+
+## Fonctionnalités principales
+- Miniaturisation des fichiers
+- Extraction des données (OCR, lecture 2D Doc, ...)
+- Analyse des documents
\ No newline at end of file
diff --git a/dossierfacile-process-file/src/main/resources/application.properties b/dossierfacile-process-file/src/main/resources/application.properties
index bcc7e09f1..893fcecfd 100644
--- a/dossierfacile-process-file/src/main/resources/application.properties
+++ b/dossierfacile-process-file/src/main/resources/application.properties
@@ -41,7 +41,7 @@ logging.level.root=info
logging.file.path=logs
logging.logstash.destination=
-application.api.version=3
+application.api.version=4
application.name=process-file
environment=
diff --git a/dossierfacile-task-scheduler/README.md b/dossierfacile-task-scheduler/README.md
new file mode 100644
index 000000000..1f5dc7f61
--- /dev/null
+++ b/dossierfacile-task-scheduler/README.md
@@ -0,0 +1,11 @@
+# Service de gestion des tâches asynchrones (dossierfacile-task-scheduler)
+
+## Description
+Module responsable de la planification et de l'exécution des tâches récurrentes dans DossierFacile.
+
+## Tâches principales
+- Vérification de la disponibilité de l'API de l'ADEME
+- Gestion des documents en erreur dans les dossiers (tentative de génération, suppression)
+- Gestion de la synchronisation des fichiers sur les stockages
+- Nettoyage des fichiers sur les stockages
+- Gestion des opérations asynchrones sur les comptes (messages de warning, archivage, suppression)
diff --git a/dossierfacile-task-scheduler/src/main/resources/application.properties b/dossierfacile-task-scheduler/src/main/resources/application.properties
index d1b19f9c6..68a1a6cd9 100644
--- a/dossierfacile-task-scheduler/src/main/resources/application.properties
+++ b/dossierfacile-task-scheduler/src/main/resources/application.properties
@@ -57,6 +57,6 @@ logging.level.root=info
logging.file.path=logs
logging.logstash.destination=
-application.api.version=3
+application.api.version=4
application.name=task-scheduler
environment=
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index b07e9656a..eb1c84b8a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,7 @@
${java.version}
1.6.2
1.18.34
- 22.0.5
+ 26.0.3
2.17.1
0.0.1-SNAPSHOT
7.4