Compare commits
19 Commits
5fa4711a8f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db36727001 | ||
|
|
7a596f68bd | ||
|
|
f263d4f51a | ||
|
|
6f233193d4 | ||
|
|
13635e269b | ||
|
|
65a9d03c00 | ||
| 2d21a580de | |||
| 3feab6518e | |||
| 7fa862b755 | |||
|
|
1496c83b6f | ||
|
|
ee6e945bdb | ||
|
|
eac66ce25d | ||
|
|
69f740d6ed | ||
|
|
1b7700a368 | ||
|
|
c9615f349e | ||
|
|
ba31d6802e | ||
|
|
d66c013d0b | ||
|
|
ae7ada6b91 | ||
|
|
43678c8ae9 |
@@ -95,10 +95,12 @@ Ajouter à votre `pom.xml` :
|
||||
<dependency>
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-server-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>1.0.7</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
> ℹ️ **Version publiée Gitea Maven (2026-04-24)** : `1.0.7` — module autonome (pas de `unionflow-parent`), aligné Quarkus 3.27.3 LTS.
|
||||
|
||||
### Repository Gitea (Maven Registry)
|
||||
|
||||
Configurer `~/.m2/settings.xml` :
|
||||
@@ -543,6 +545,6 @@ Propriétaire - © 2026 Lions Club Côte d'Ivoire
|
||||
|
||||
---
|
||||
|
||||
**Version** : 2.0.0
|
||||
**Dernière mise à jour** : 2026-03-14
|
||||
**Version publiée Gitea Maven** : 1.0.7 (2026-04-24)
|
||||
**Dernière mise à jour** : 2026-04-24
|
||||
**Auteur** : Équipe UnionFlow
|
||||
|
||||
16414
docs/openapi.yaml
Normal file
16414
docs/openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,96 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>UnionFlow - Parent</name>
|
||||
<description>Plateforme complète de gestion d'union — POM parent partagé</description>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>gitea-lionsdev</id>
|
||||
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>gitea-lionsdev</id>
|
||||
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>gitea-lionsdev</id>
|
||||
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>true</enabled></snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.version>3.15.1</quarkus.platform.version>
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.34</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-server-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<parameters>true</parameters>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
53
pom.xml
53
pom.xml
@@ -4,36 +4,50 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath>parent-pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-server-api</artifactId>
|
||||
<version>1.0.10</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>UnionFlow Server API</name>
|
||||
<description>API définitions pour le serveur UnionFlow</description>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>gitea-lionsdev</id>
|
||||
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>gitea-lionsdev</id>
|
||||
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>true</enabled></snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<java.version>21</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven.compiler.release>${java.version}</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<quarkus.platform.version>3.15.1</quarkus.platform.version>
|
||||
<jackson.version>2.17.0</jackson.version>
|
||||
<quarkus.platform.version>3.27.3</quarkus.platform.version>
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<jackson.version>2.18.2</jackson.version>
|
||||
<validation-api.version>3.0.2</validation-api.version>
|
||||
<microprofile-openapi.version>3.1.1</microprofile-openapi.version>
|
||||
|
||||
<!-- Versions des plugins de qualité -->
|
||||
<jacoco.version>0.8.11</jacoco.version>
|
||||
<jacoco.version>0.8.12</jacoco.version>
|
||||
<checkstyle.version>10.12.4</checkstyle.version>
|
||||
<maven-checkstyle-plugin.version>3.3.1</maven-checkstyle-plugin.version>
|
||||
<junit.version>5.10.1</junit.version>
|
||||
<mockito.version>5.7.0</mockito.version>
|
||||
<assertj.version>3.24.2</assertj.version>
|
||||
<junit.version>5.11.4</junit.version>
|
||||
<mockito.version>5.14.2</mockito.version>
|
||||
<assertj.version>3.27.3</assertj.version>
|
||||
|
||||
<!-- Seuils de couverture Jacoco - 100% obligatoire -->
|
||||
<jacoco.line.coverage.minimum>1.00</jacoco.line.coverage.minimum>
|
||||
@@ -115,7 +129,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<version>1.18.36</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -126,16 +140,15 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<release>21</release>
|
||||
<encoding>UTF-8</encoding>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<version>1.18.36</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
@echo off
|
||||
REM Publie le parent pom + server-api sur le Gitea Package Registry
|
||||
REM Publie unionflow-server-api sur le Gitea Package Registry
|
||||
REM Usage : script\publish-api.bat
|
||||
REM Depuis : n'importe où dans le repo server-api
|
||||
REM Prérequis: credentials dans %USERPROFILE%\.m2\settings.xml (server id: gitea-lionsdev)
|
||||
|
||||
set REGISTRY_URL=https://git.lions.dev/api/packages/lionsdev/maven
|
||||
set REGISTRY_ID=gitea-lionsdev
|
||||
REM Depuis : n'importe ou dans le repo server-api
|
||||
REM Prerequis: credentials dans %USERPROFILE%\.m2\settings.xml (server id: gitea-lionsdev)
|
||||
REM
|
||||
REM Note : unionflow-parent n'existe plus (modules autonomes depuis Quarkus 3.27.3).
|
||||
|
||||
cd /d "%~dp0\.."
|
||||
|
||||
echo.
|
||||
echo [1/2] Publication du parent pom...
|
||||
call mvn deploy:deploy-file ^
|
||||
-DgroupId=dev.lions.unionflow ^
|
||||
-DartifactId=unionflow-parent ^
|
||||
-Dversion=1.0.0 ^
|
||||
-Dpackaging=pom ^
|
||||
-Dfile=parent-pom.xml ^
|
||||
-DrepositoryId=%REGISTRY_ID% ^
|
||||
-Durl=%REGISTRY_URL%
|
||||
if errorlevel 409 echo [WARN] Parent pom deja publie pour cette version, on continue.
|
||||
|
||||
echo.
|
||||
echo [2/2] Publication du server-api...
|
||||
echo Publication du server-api...
|
||||
call mvn deploy -DskipTests
|
||||
if errorlevel 409 echo [WARN] Server-api deja publie - incrementer la version pour republier.
|
||||
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
#!/bin/bash
|
||||
# Publie le parent pom + server-api sur le Gitea Package Registry
|
||||
# Publie unionflow-server-api sur le Gitea Package Registry
|
||||
# Usage : ./script/publish-api.sh
|
||||
# Depuis : n'importe où dans le repo server-api
|
||||
# Prérequis: credentials dans ~/.m2/settings.xml (server id: gitea-lionsdev)
|
||||
#
|
||||
# Note : unionflow-parent n'existe plus (les 3 modules sont autonomes
|
||||
# depuis la migration Quarkus 3.27.3). Ne publier que le module server-api.
|
||||
|
||||
set -e
|
||||
|
||||
REGISTRY_URL="https://git.lions.dev/api/packages/lionsdev/maven"
|
||||
REGISTRY_ID="gitea-lionsdev"
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
echo ""
|
||||
echo "[1/2] Publication du parent pom..."
|
||||
mvn deploy:deploy-file \
|
||||
-DgroupId=dev.lions.unionflow \
|
||||
-DartifactId=unionflow-parent \
|
||||
-Dversion=1.0.0 \
|
||||
-Dpackaging=pom \
|
||||
-Dfile=parent-pom.xml \
|
||||
-DrepositoryId="${REGISTRY_ID}" \
|
||||
-Durl="${REGISTRY_URL}" \
|
||||
|| echo "[WARN] Parent pom déjà publié pour cette version (409), on continue."
|
||||
|
||||
echo ""
|
||||
echo "[2/2] Publication du server-api..."
|
||||
echo "Publication du server-api..."
|
||||
mvn deploy -DskipTests \
|
||||
|| echo "[WARN] Server-api déjà publié pour cette version (409) - incrémenter la version pour republier."
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.lions.unionflow.server.api.dto.audit.response;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Vue d'une opération d'audit trail enrichi (Sprint 1, exposée Sprint 10).
|
||||
*
|
||||
* <p>Les payloads JSONB ({@code payloadAvant}, {@code payloadApres}, {@code metadata})
|
||||
* sont sérialisés en string ; le frontend les parse selon les besoins.
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 10)
|
||||
*/
|
||||
@Builder
|
||||
public record AuditTrailOperationResponse(
|
||||
UUID id,
|
||||
UUID userId,
|
||||
String userEmail,
|
||||
String roleActif,
|
||||
UUID organisationActiveId,
|
||||
String actionType,
|
||||
String entityType,
|
||||
UUID entityId,
|
||||
String description,
|
||||
String ipAddress,
|
||||
String userAgent,
|
||||
UUID requestId,
|
||||
String payloadAvant,
|
||||
String payloadApres,
|
||||
String metadata,
|
||||
Boolean sodCheckPassed,
|
||||
String sodViolations,
|
||||
LocalDateTime operationAt
|
||||
) {
|
||||
}
|
||||
@@ -1,13 +1,22 @@
|
||||
package dev.lions.unionflow.server.api.dto.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO d'erreur unifié retourné par tous les endpoints REST.
|
||||
* Remplace les ErrorResponse locales dupliquées dans chaque Resource.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public record ErrorResponse(String message, String error) {
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ErrorResponse {
|
||||
|
||||
private String message;
|
||||
private String error;
|
||||
|
||||
/** Constructeur pratique avec message uniquement (cas le plus courant). */
|
||||
public static ErrorResponse of(String message) {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package dev.lions.unionflow.server.api.dto.communication.response;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@@ -14,20 +17,23 @@ import java.util.UUID;
|
||||
* @version 1.0
|
||||
* @since 2026-03-16
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public record ConversationResponse(
|
||||
UUID id,
|
||||
String name,
|
||||
String description,
|
||||
ConversationType type,
|
||||
List<UUID> participantIds,
|
||||
UUID organisationId,
|
||||
MessageResponse lastMessage,
|
||||
int unreadCount,
|
||||
boolean isMuted,
|
||||
boolean isPinned,
|
||||
boolean isArchived,
|
||||
LocalDateTime createdAt,
|
||||
LocalDateTime updatedAt,
|
||||
String avatarUrl
|
||||
) {}
|
||||
public class ConversationResponse {
|
||||
private UUID id;
|
||||
private String name;
|
||||
private String description;
|
||||
private ConversationType type;
|
||||
private List<UUID> participantIds;
|
||||
private UUID organisationId;
|
||||
private MessageResponse lastMessage;
|
||||
private int unreadCount;
|
||||
private boolean muted;
|
||||
private boolean pinned;
|
||||
private boolean archived;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private String avatarUrl;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package dev.lions.unionflow.server.api.dto.communication.response;
|
||||
import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
|
||||
import dev.lions.unionflow.server.api.enums.communication.MessageStatus;
|
||||
import dev.lions.unionflow.server.api.enums.communication.MessageType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@@ -16,24 +19,27 @@ import java.util.UUID;
|
||||
* @version 1.0
|
||||
* @since 2026-03-16
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public record MessageResponse(
|
||||
UUID id,
|
||||
UUID conversationId,
|
||||
UUID senderId,
|
||||
String senderName,
|
||||
String senderAvatar,
|
||||
String content,
|
||||
MessageType type,
|
||||
MessageStatus status,
|
||||
MessagePriority priority,
|
||||
List<UUID> recipientIds,
|
||||
List<String> recipientRoles,
|
||||
UUID organisationId,
|
||||
LocalDateTime createdAt,
|
||||
LocalDateTime readAt,
|
||||
List<String> attachments,
|
||||
boolean isEdited,
|
||||
LocalDateTime editedAt,
|
||||
boolean isDeleted
|
||||
) {}
|
||||
public class MessageResponse {
|
||||
private UUID id;
|
||||
private UUID conversationId;
|
||||
private UUID senderId;
|
||||
private String senderName;
|
||||
private String senderAvatar;
|
||||
private String content;
|
||||
private MessageType type;
|
||||
private MessageStatus status;
|
||||
private MessagePriority priority;
|
||||
private List<UUID> recipientIds;
|
||||
private List<String> recipientRoles;
|
||||
private UUID organisationId;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime readAt;
|
||||
private List<String> attachments;
|
||||
private boolean edited;
|
||||
private LocalDateTime editedAt;
|
||||
private boolean deleted;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package dev.lions.unionflow.server.api.dto.compliance.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Snapshot KPI public (Sprint 17) — vue read-only pour autorités externes (BCEAO, ARTCI, CENTIF).
|
||||
*
|
||||
* <p>Sous-ensemble strictement filtré de la conformité : indicateurs agrégés uniquement,
|
||||
* jamais de données sensibles ({@code complianceOfficerId}, payloads détaillés, IDs membres,
|
||||
* informations PEP). L'autorité voit le score, l'état des obligations, les pourcentages
|
||||
* de couverture — pas l'intimité opérationnelle.
|
||||
*
|
||||
* <p>Diffusé via URL signée temporairement (HMAC-SHA256, expiry stricte).
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 17 — transparency réglementaire publique)
|
||||
*/
|
||||
@Builder
|
||||
public record KpiPublicSnapshot(
|
||||
/** Nom de l'organisation. */
|
||||
String organisationNom,
|
||||
|
||||
/** Référentiel comptable applicable (SYSCOHADA / SYCEBNL / PCSFD_UMOA). */
|
||||
String referentielComptable,
|
||||
|
||||
/** Score conformité agrégé 0-100. */
|
||||
int scoreGlobal,
|
||||
|
||||
/** Compliance Officer désigné (présence uniquement, pas l'identité). */
|
||||
boolean complianceOfficerDesigne,
|
||||
|
||||
/** Statut AG annuelle : OK / EN_ATTENTE / RETARD. */
|
||||
String agAnnuelleStatut,
|
||||
|
||||
/** Statut rapport AIRMS : OK / EN_ATTENTE. */
|
||||
String rapportAirmsStatut,
|
||||
|
||||
/** Nombre de dirigeants enrôlés CMU (sans liste). */
|
||||
int dirigeantsAvecCmu,
|
||||
|
||||
/** Pourcentage KYC à jour (membres). */
|
||||
BigDecimal tauxKycAJourPct,
|
||||
|
||||
/** Pourcentage formation LBC/FT (membres formés dans les 12 derniers mois). */
|
||||
BigDecimal tauxFormationLbcFtPct,
|
||||
|
||||
/** Pourcentage couverture UBO (Bénéficiaires Effectifs documentés). */
|
||||
BigDecimal couvertureUboPct,
|
||||
|
||||
/** Statut commissaire aux comptes (OPTIONNEL / OBLIGATOIRE). */
|
||||
String commissaireAuxComptesStatut,
|
||||
|
||||
/** Date de génération du snapshot. */
|
||||
LocalDateTime dateGeneration
|
||||
) {
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package dev.lions.unionflow.server.api.dto.cotisation.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
@@ -7,29 +11,32 @@ import java.util.UUID;
|
||||
/**
|
||||
* Réponse simplifiée pour les listes de cotisations.
|
||||
*
|
||||
* @param id Identifiant unique.
|
||||
* @param numeroReference Référence unique.
|
||||
* @param nomMembre Nom du membre.
|
||||
* @param montantDu Montant total dû.
|
||||
* @param montantPaye Montant déjà réglé.
|
||||
* @param statut Statut actuel (code).
|
||||
* @param statutLibelle Libellé du statut pour l'UI.
|
||||
* @param dateEcheance Date limite.
|
||||
* @param annee Année concernée.
|
||||
* @param actif Indique si l'entité est active.
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-02-22
|
||||
*/
|
||||
public record CotisationSummaryResponse(
|
||||
UUID id,
|
||||
String numeroReference,
|
||||
String nomMembre,
|
||||
BigDecimal montantDu,
|
||||
BigDecimal montantPaye,
|
||||
String statut,
|
||||
String statutLibelle,
|
||||
LocalDate dateEcheance,
|
||||
Integer annee,
|
||||
Boolean actif) {
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CotisationSummaryResponse {
|
||||
/** Identifiant unique. */
|
||||
private UUID id;
|
||||
/** Référence unique. */
|
||||
private String numeroReference;
|
||||
/** Nom du membre. */
|
||||
private String nomMembre;
|
||||
/** Montant total dû. */
|
||||
private BigDecimal montantDu;
|
||||
/** Montant déjà réglé. */
|
||||
private BigDecimal montantPaye;
|
||||
/** Statut actuel (code). */
|
||||
private String statut;
|
||||
/** Libellé du statut pour l'UI. */
|
||||
private String statutLibelle;
|
||||
/** Date limite. */
|
||||
private LocalDate dateEcheance;
|
||||
/** Année concernée. */
|
||||
private Integer annee;
|
||||
/** Indique si l'entité est active. */
|
||||
private Boolean actif;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package dev.lions.unionflow.server.api.dto.dashboard;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
@@ -10,39 +14,42 @@ import java.time.LocalDate;
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
*/
|
||||
public record MembreDashboardSyntheseResponse(
|
||||
String prenom,
|
||||
String nom,
|
||||
LocalDate dateInscription,
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MembreDashboardSyntheseResponse implements Serializable {
|
||||
|
||||
// Cotisations
|
||||
BigDecimal mesCotisationsPaiement,
|
||||
/** Total des cotisations payées sur l'année en cours (pour affichage dashboard). */
|
||||
BigDecimal totalCotisationsPayeesAnnee,
|
||||
/** Total des cotisations payées tout temps (pour la carte « Contribution Totale »). */
|
||||
BigDecimal totalCotisationsPayeesToutTemps,
|
||||
/** Nombre de cotisations PAYÉES (pour la carte « Cotisations »). */
|
||||
Integer nombreCotisationsPayees,
|
||||
String statutCotisations,
|
||||
/** Taux de cotisation en % (0-100). Calculé sur l'année courante ou toutes années si pas de cotisation 2026. */
|
||||
Integer tauxCotisationsPerso,
|
||||
/** Nombre TOTAL de cotisations (toutes années, tous statuts) — pour calcul du taux d'engagement. */
|
||||
Integer nombreCotisationsTotal,
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private LocalDate dateInscription;
|
||||
|
||||
// Epargne
|
||||
BigDecimal monSoldeEpargne,
|
||||
BigDecimal evolutionEpargneNombre,
|
||||
String evolutionEpargne,
|
||||
Integer objectifEpargne,
|
||||
// Cotisations
|
||||
private BigDecimal mesCotisationsPaiement;
|
||||
/** Total des cotisations payées sur l'année en cours (pour affichage dashboard). */
|
||||
private BigDecimal totalCotisationsPayeesAnnee;
|
||||
/** Total des cotisations payées tout temps (pour la carte « Contribution Totale »). */
|
||||
private BigDecimal totalCotisationsPayeesToutTemps;
|
||||
/** Nombre de cotisations PAYÉES (pour la carte « Cotisations »). */
|
||||
private Integer nombreCotisationsPayees;
|
||||
private String statutCotisations;
|
||||
/** Taux de cotisation en % (0-100). Calculé sur l'année courante ou toutes années si pas de cotisation 2026. */
|
||||
private Integer tauxCotisationsPerso;
|
||||
/** Nombre TOTAL de cotisations (toutes années, tous statuts) — pour calcul du taux d'engagement. */
|
||||
private Integer nombreCotisationsTotal;
|
||||
|
||||
// Evenements
|
||||
Integer mesEvenementsInscrits,
|
||||
Integer evenementsAVenir,
|
||||
Integer tauxParticipationPerso,
|
||||
// Epargne
|
||||
private BigDecimal monSoldeEpargne;
|
||||
private BigDecimal evolutionEpargneNombre;
|
||||
private String evolutionEpargne;
|
||||
private Integer objectifEpargne;
|
||||
|
||||
// Aides
|
||||
Integer mesDemandesAide,
|
||||
Integer aidesEnCours,
|
||||
Integer tauxAidesApprouvees) implements Serializable {
|
||||
// Evenements
|
||||
private Integer mesEvenementsInscrits;
|
||||
private Integer evenementsAVenir;
|
||||
private Integer tauxParticipationPerso;
|
||||
|
||||
// Aides
|
||||
private Integer mesDemandesAide;
|
||||
private Integer aidesEnCours;
|
||||
private Integer tauxAidesApprouvees;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.lions.unionflow.server.api.dto.delegation.request;
|
||||
|
||||
import jakarta.validation.constraints.Future;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête de création d'une délégation de rôle temporaire.
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 10 — service existant Sprint 2)
|
||||
*/
|
||||
@Builder
|
||||
public record CreateRoleDelegationRequest(
|
||||
@NotNull(message = "L'organisation est obligatoire")
|
||||
UUID organisationId,
|
||||
|
||||
@NotNull(message = "Le déléguant est obligatoire")
|
||||
UUID delegantUserId,
|
||||
|
||||
@NotNull(message = "Le délégataire est obligatoire")
|
||||
UUID delegataireUserId,
|
||||
|
||||
@NotBlank(message = "Le rôle délégué est obligatoire")
|
||||
@Pattern(regexp = "^[A-Z_]{3,50}$", message = "Format de rôle invalide (uppercase + underscore)")
|
||||
String roleDelegue,
|
||||
|
||||
@NotNull(message = "La date de début est obligatoire")
|
||||
LocalDateTime dateDebut,
|
||||
|
||||
@NotNull(message = "La date de fin est obligatoire")
|
||||
@Future(message = "La date de fin doit être future")
|
||||
LocalDateTime dateFin,
|
||||
|
||||
@Size(max = 500)
|
||||
String motif
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.lions.unionflow.server.api.dto.delegation.response;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Vue d'une délégation de rôle.
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 10)
|
||||
*/
|
||||
@Builder
|
||||
public record RoleDelegationResponse(
|
||||
UUID id,
|
||||
UUID organisationId,
|
||||
UUID delegantUserId,
|
||||
UUID delegataireUserId,
|
||||
String roleDelegue,
|
||||
LocalDateTime dateDebut,
|
||||
LocalDateTime dateFin,
|
||||
String motif,
|
||||
String statut,
|
||||
LocalDateTime dateRevocation,
|
||||
LocalDateTime dateCreation,
|
||||
boolean estActive
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package dev.lions.unionflow.server.api.dto.kyc;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* DTO de création ou mise à jour d'un dossier KYC/AML.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class KycDossierRequest {
|
||||
|
||||
@NotNull
|
||||
private String membreId;
|
||||
|
||||
@NotNull
|
||||
private TypePieceIdentite typePiece;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 50)
|
||||
private String numeroPiece;
|
||||
|
||||
/** Date d'expiration de la pièce d'identité. */
|
||||
private LocalDate dateExpirationPiece;
|
||||
|
||||
/** Justificatif de domicile — ID du fichier stocké (MinIO/S3). */
|
||||
@Size(max = 500)
|
||||
private String justifDomicileFileId;
|
||||
|
||||
/** Pièce d'identité recto — ID du fichier stocké. */
|
||||
@Size(max = 500)
|
||||
private String pieceIdentiteRectoFileId;
|
||||
|
||||
/** Pièce d'identité verso — ID du fichier stocké. */
|
||||
@Size(max = 500)
|
||||
private String pieceIdentiteVersoFileId;
|
||||
|
||||
/** Notes du validateur lors d'une approbation/refus manuel. */
|
||||
@Size(max = 1000)
|
||||
private String notesValidateur;
|
||||
|
||||
/** Indique si le membre est une Personne Exposée Politiquement (PEP). */
|
||||
private Boolean estPep;
|
||||
|
||||
/** Nationalité déclarée (ISO 3166-1 alpha-2). */
|
||||
@Size(max = 5)
|
||||
private String nationalite;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.lions.unionflow.server.api.dto.kyc;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.membre.NiveauRisqueKyc;
|
||||
import dev.lions.unionflow.server.api.enums.membre.StatutKyc;
|
||||
import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* DTO de réponse pour un dossier KYC/AML.
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class KycDossierResponse extends BaseDTO {
|
||||
|
||||
private UUID membreId;
|
||||
private String membreNomComplet;
|
||||
private String membreEmail;
|
||||
|
||||
private TypePieceIdentite typePiece;
|
||||
private String numeroPiece;
|
||||
private LocalDate dateExpirationPiece;
|
||||
|
||||
private String justifDomicileFileId;
|
||||
private String pieceIdentiteRectoFileId;
|
||||
private String pieceIdentiteVersoFileId;
|
||||
|
||||
private StatutKyc statut;
|
||||
private NiveauRisqueKyc niveauRisque;
|
||||
private int scoreRisque;
|
||||
|
||||
private boolean estPep;
|
||||
private String nationalite;
|
||||
|
||||
private LocalDateTime dateVerification;
|
||||
private UUID validateurId;
|
||||
private String notesValidateur;
|
||||
|
||||
/** Année de référence pour la rétention (partitionnement logique). */
|
||||
private int anneeReference;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package dev.lions.unionflow.server.api.dto.kyc.request;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Création d'un Bénéficiaire Effectif (UBO) — Instruction BCEAO 003-03-2025.
|
||||
*
|
||||
* <p>Lié à un {@code KycDossier} d'entreprise. Au moins un identifiant cible est requis :
|
||||
* {@code kycDossierId} pour KYC personne morale, ou {@code organisationCibleId} +
|
||||
* {@code membreId} pour membre individuel à risque.
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 10)
|
||||
*/
|
||||
@Builder
|
||||
public record CreateBeneficiaireEffectifRequest(
|
||||
UUID kycDossierId,
|
||||
UUID organisationCibleId,
|
||||
UUID membreId,
|
||||
|
||||
@NotBlank(message = "Le nom est obligatoire")
|
||||
@Size(max = 100)
|
||||
String nom,
|
||||
|
||||
@NotBlank(message = "Les prénoms sont obligatoires")
|
||||
@Size(max = 200)
|
||||
String prenoms,
|
||||
|
||||
@NotNull(message = "La date de naissance est obligatoire")
|
||||
LocalDate dateNaissance,
|
||||
|
||||
@Size(max = 200)
|
||||
String lieuNaissance,
|
||||
|
||||
@NotBlank(message = "La nationalité est obligatoire (ISO-3)")
|
||||
@Pattern(regexp = "^[A-Z]{3}$", message = "Code ISO-3 (ex: CIV, FRA)")
|
||||
String nationalite,
|
||||
|
||||
@Pattern(regexp = "^[A-Z]{3}$|^$", message = "Code ISO-3")
|
||||
String paysResidence,
|
||||
|
||||
TypePieceIdentite typePieceIdentite,
|
||||
|
||||
@Size(max = 50)
|
||||
String numeroPieceIdentite,
|
||||
|
||||
LocalDate dateExpirationPiece,
|
||||
|
||||
@DecimalMin(value = "0.00")
|
||||
@DecimalMax(value = "100.00")
|
||||
BigDecimal pourcentageCapital,
|
||||
|
||||
@DecimalMin(value = "0.00")
|
||||
@DecimalMax(value = "100.00")
|
||||
BigDecimal pourcentageDroitsVote,
|
||||
|
||||
@NotBlank(message = "La nature du contrôle est obligatoire")
|
||||
@Pattern(regexp = "^(DETENTION_CAPITAL|DROITS_VOTE|CONTROLE_DE_FAIT|BENEFICIAIRE_ULTIME|MANDAT_REPRESENTATION)$",
|
||||
message = "Nature du contrôle invalide")
|
||||
String natureControle,
|
||||
|
||||
Boolean estPep,
|
||||
@Size(max = 100) String pepCategorie,
|
||||
@Pattern(regexp = "^[A-Z]{3}$|^$") String pepPays,
|
||||
@Size(max = 200) String pepFonction,
|
||||
|
||||
Boolean presenceListesSanctions,
|
||||
@Size(max = 1000) String detailsListesSanctions
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package dev.lions.unionflow.server.api.dto.kyc.request;
|
||||
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Mise à jour partielle d'un Bénéficiaire Effectif (UBO).
|
||||
* Tous les champs sont optionnels — seul ce qui est fourni est mis à jour.
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 10)
|
||||
*/
|
||||
@Builder
|
||||
public record UpdateBeneficiaireEffectifRequest(
|
||||
@Size(max = 100) String nom,
|
||||
@Size(max = 200) String prenoms,
|
||||
LocalDate dateNaissance,
|
||||
@Size(max = 200) String lieuNaissance,
|
||||
@Pattern(regexp = "^[A-Z]{3}$|^$") String nationalite,
|
||||
@Pattern(regexp = "^[A-Z]{3}$|^$") String paysResidence,
|
||||
|
||||
@DecimalMin("0.00") @DecimalMax("100.00") BigDecimal pourcentageCapital,
|
||||
@DecimalMin("0.00") @DecimalMax("100.00") BigDecimal pourcentageDroitsVote,
|
||||
|
||||
@Pattern(regexp = "^(DETENTION_CAPITAL|DROITS_VOTE|CONTROLE_DE_FAIT|BENEFICIAIRE_ULTIME|MANDAT_REPRESENTATION)?$")
|
||||
String natureControle,
|
||||
|
||||
Boolean estPep,
|
||||
@Size(max = 100) String pepCategorie,
|
||||
@Pattern(regexp = "^[A-Z]{3}$|^$") String pepPays,
|
||||
@Size(max = 200) String pepFonction,
|
||||
|
||||
Boolean presenceListesSanctions,
|
||||
@Size(max = 1000) String detailsListesSanctions
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.lions.unionflow.server.api.dto.kyc.response;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Vue d'un Bénéficiaire Effectif (UBO).
|
||||
*
|
||||
* @since 2026-04-25 (Sprint 10)
|
||||
*/
|
||||
@Builder
|
||||
public record BeneficiaireEffectifResponse(
|
||||
UUID id,
|
||||
UUID kycDossierId,
|
||||
UUID organisationCibleId,
|
||||
UUID membreId,
|
||||
String nom,
|
||||
String prenoms,
|
||||
LocalDate dateNaissance,
|
||||
String lieuNaissance,
|
||||
String nationalite,
|
||||
String paysResidence,
|
||||
TypePieceIdentite typePieceIdentite,
|
||||
String numeroPieceIdentite,
|
||||
LocalDate dateExpirationPiece,
|
||||
BigDecimal pourcentageCapital,
|
||||
BigDecimal pourcentageDroitsVote,
|
||||
String natureControle,
|
||||
boolean estPep,
|
||||
String pepCategorie,
|
||||
String pepPays,
|
||||
String pepFonction,
|
||||
boolean presenceListesSanctions,
|
||||
String detailsListesSanctions,
|
||||
LocalDateTime dateCreation,
|
||||
LocalDateTime dateModification,
|
||||
Boolean actif
|
||||
) {
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package dev.lions.unionflow.server.api.dto.membre;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
@@ -18,57 +22,55 @@ import java.time.LocalDate;
|
||||
* <li>Capacité d'emprunt estimée (3× l'épargne — règle mutuelle classique)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param numeroMembre Numéro unique du membre sur la plateforme (ex: MUF-2026-001)
|
||||
* @param nomComplet Nom et prénom du membre
|
||||
* @param organisationNom Nom de l'organisation principale (ou null si aucune)
|
||||
* @param dateAdhesion Date d'inscription sur la plateforme
|
||||
* @param statutCompte Statut actuel du compte (ACTIF, SUSPENDU, etc.)
|
||||
*
|
||||
* @param soldeCotisations Total des cotisations payées (toutes années confondues)
|
||||
* @param soldeEpargne Solde disponible sur l'ensemble des comptes épargne actifs
|
||||
* @param soldeBloque Montant bloqué (garantie de prêt)
|
||||
* @param soldeTotalDisponible soldeCotisations + soldeEpargne - soldeBloque
|
||||
* @param encoursCreditTotal Montant total des prêts en cours (0 si fonctionnalité non encore activée)
|
||||
* @param capaciteEmprunt Capacité d'emprunt estimée (3 × soldeEpargne selon règle mutuelle standard)
|
||||
*
|
||||
* @param nombreCotisationsPayees Nombre de cotisations payées (historique complet)
|
||||
* @param nombreCotisationsTotal Nombre total de cotisations (payées + en attente + retard)
|
||||
* @param nombreCotisationsEnRetard Nombre de cotisations en retard
|
||||
* @param tauxEngagement Taux de paiement global en % (0-100)
|
||||
*
|
||||
* @param nombreComptesEpargne Nombre de comptes épargne actifs
|
||||
* @param dateCalcul Date/heure du calcul (pour information client)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
*/
|
||||
public record CompteAdherentResponse(
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CompteAdherentResponse implements Serializable {
|
||||
|
||||
// ── Identité ──────────────────────────────────────────────────────────
|
||||
String numeroMembre,
|
||||
String nomComplet,
|
||||
String organisationNom,
|
||||
LocalDate dateAdhesion,
|
||||
String statutCompte,
|
||||
// ── Identité ──────────────────────────────────────────────────────────
|
||||
/** Numéro unique du membre sur la plateforme (ex: MUF-2026-001) */
|
||||
private String numeroMembre;
|
||||
/** Nom et prénom du membre */
|
||||
private String nomComplet;
|
||||
/** Nom de l'organisation principale (ou null si aucune) */
|
||||
private String organisationNom;
|
||||
/** Date d'inscription sur la plateforme */
|
||||
private LocalDate dateAdhesion;
|
||||
/** Statut actuel du compte (ACTIF, SUSPENDU, etc.) */
|
||||
private String statutCompte;
|
||||
|
||||
// ── Soldes ────────────────────────────────────────────────────────────
|
||||
BigDecimal soldeCotisations,
|
||||
BigDecimal soldeEpargne,
|
||||
BigDecimal soldeBloque,
|
||||
BigDecimal soldeTotalDisponible,
|
||||
BigDecimal encoursCreditTotal,
|
||||
BigDecimal capaciteEmprunt,
|
||||
// ── Soldes ────────────────────────────────────────────────────────────
|
||||
/** Total des cotisations payées (toutes années confondues) */
|
||||
private BigDecimal soldeCotisations;
|
||||
/** Solde disponible sur l'ensemble des comptes épargne actifs */
|
||||
private BigDecimal soldeEpargne;
|
||||
/** Montant bloqué (garantie de prêt) */
|
||||
private BigDecimal soldeBloque;
|
||||
/** soldeCotisations + soldeEpargne - soldeBloque */
|
||||
private BigDecimal soldeTotalDisponible;
|
||||
/** Montant total des prêts en cours (0 si fonctionnalité non encore activée) */
|
||||
private BigDecimal encoursCreditTotal;
|
||||
/** Capacité d'emprunt estimée (3 × soldeEpargne selon règle mutuelle standard) */
|
||||
private BigDecimal capaciteEmprunt;
|
||||
|
||||
// ── Cotisations ───────────────────────────────────────────────────────
|
||||
Integer nombreCotisationsPayees,
|
||||
Integer nombreCotisationsTotal,
|
||||
Integer nombreCotisationsEnRetard,
|
||||
Integer tauxEngagement,
|
||||
// ── Cotisations ───────────────────────────────────────────────────────
|
||||
/** Nombre de cotisations payées (historique complet) */
|
||||
private Integer nombreCotisationsPayees;
|
||||
/** Nombre total de cotisations (payées + en attente + retard) */
|
||||
private Integer nombreCotisationsTotal;
|
||||
/** Nombre de cotisations en retard */
|
||||
private Integer nombreCotisationsEnRetard;
|
||||
/** Taux de paiement global en % (0-100) */
|
||||
private Integer tauxEngagement;
|
||||
|
||||
// ── Épargne ───────────────────────────────────────────────────────────
|
||||
Integer nombreComptesEpargne,
|
||||
// ── Épargne ───────────────────────────────────────────────────────────
|
||||
/** Nombre de comptes épargne actifs */
|
||||
private Integer nombreComptesEpargne;
|
||||
|
||||
// ── Méta ──────────────────────────────────────────────────────────────
|
||||
LocalDate dateCalcul
|
||||
|
||||
) implements Serializable {}
|
||||
// ── Méta ──────────────────────────────────────────────────────────────
|
||||
/** Date/heure du calcul (pour information client) */
|
||||
private LocalDate dateCalcul;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package dev.lions.unionflow.server.api.dto.membre.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -7,81 +11,56 @@ import java.util.UUID;
|
||||
/**
|
||||
* DTO de réponse résumé pour Membre (listes et optimisations).
|
||||
*
|
||||
* <p>Ce record expose des méthodes calculées pour la compatibilité JSF EL :
|
||||
* {@link #nomComplet()}, {@link #statut()}, {@link #typeMembre()}, etc.
|
||||
* <p>Classe JavaBean pour compatibilité JSF EL (EL cherche getXxx()).
|
||||
* Expose également des propriétés calculées (nomComplet, statut, typeMembre, etc.)
|
||||
*/
|
||||
public record MembreSummaryResponse(
|
||||
UUID id,
|
||||
String numeroMembre,
|
||||
String prenom,
|
||||
String nom,
|
||||
String email,
|
||||
String telephone,
|
||||
String profession,
|
||||
String statutCompte,
|
||||
String statutCompteLibelle,
|
||||
String statutCompteSeverity,
|
||||
Boolean actif,
|
||||
List<String> roles,
|
||||
UUID organisationId,
|
||||
String organisationNom,
|
||||
LocalDate dateAdhesion) {
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MembreSummaryResponse {
|
||||
|
||||
// ── Getters JavaBean pour compatibilité JSF EL (EL cherche getXxx()) ──────
|
||||
|
||||
public UUID getId() { return id; }
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public String getPrenom() { return prenom; }
|
||||
public String getNom() { return nom; }
|
||||
public String getEmail() { return email; }
|
||||
public String getTelephone() { return telephone; }
|
||||
public String getProfession() { return profession; }
|
||||
public String getStatutCompte() { return statutCompte; }
|
||||
public String getStatutCompteLibelle() { return statutCompteLibelle; }
|
||||
public String getStatutCompteSeverity() { return statutCompteSeverity; }
|
||||
public Boolean getActif() { return actif; }
|
||||
public boolean isActif() { return Boolean.TRUE.equals(actif); }
|
||||
public List<String> getRoles() { return roles; }
|
||||
public UUID getOrganisationId() { return organisationId; }
|
||||
public String getOrganisationNom() { return organisationNom; }
|
||||
public LocalDate getDateAdhesion() { return dateAdhesion; }
|
||||
|
||||
// Getters JavaBean pour les propriétés calculées
|
||||
public String getNomComplet() { return nomComplet(); }
|
||||
public String getStatut() { return statut(); }
|
||||
public String getStatutLibelle() { return statutLibelle(); }
|
||||
public String getStatutSeverity() { return statutSeverity(); }
|
||||
public String getStatutIcon() { return statutIcon(); }
|
||||
public String getTypeMembre() { return typeMembre(); }
|
||||
public String getTypeSeverity() { return typeSeverity(); }
|
||||
public String getTypeIcon() { return typeIcon(); }
|
||||
private UUID id;
|
||||
private String numeroMembre;
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private String profession;
|
||||
private String statutCompte;
|
||||
private String statutCompteLibelle;
|
||||
private String statutCompteSeverity;
|
||||
private Boolean actif;
|
||||
private List<String> roles;
|
||||
private UUID organisationId;
|
||||
private String organisationNom;
|
||||
private LocalDate dateAdhesion;
|
||||
|
||||
// ── Propriétés calculées pour la compatibilité JSF EL ──────────────────
|
||||
|
||||
/** Prénom + Nom concaténés. */
|
||||
public String nomComplet() {
|
||||
public String getNomComplet() {
|
||||
String p = prenom != null ? prenom.trim() : "";
|
||||
String n = nom != null ? nom.trim() : "";
|
||||
return (p + " " + n).trim();
|
||||
}
|
||||
|
||||
/** Alias de {@link #statutCompte()} pour #{membre.statut}. */
|
||||
public String statut() {
|
||||
/** Alias de {@link #getStatutCompte()} pour #{membre.statut}. */
|
||||
public String getStatut() {
|
||||
return statutCompte;
|
||||
}
|
||||
|
||||
/** Alias de {@link #statutCompteLibelle()} pour #{membre.statutLibelle}. */
|
||||
public String statutLibelle() {
|
||||
/** Alias de {@link #getStatutCompteLibelle()} pour #{membre.statutLibelle}. */
|
||||
public String getStatutLibelle() {
|
||||
return statutCompteLibelle;
|
||||
}
|
||||
|
||||
/** Alias de {@link #statutCompteSeverity()} pour #{membre.statutSeverity}. */
|
||||
public String statutSeverity() {
|
||||
/** Alias de {@link #getStatutCompteSeverity()} pour #{membre.statutSeverity}. */
|
||||
public String getStatutSeverity() {
|
||||
return statutCompteSeverity;
|
||||
}
|
||||
|
||||
/** Icône PrimeIcons calculée depuis {@link #statutCompte()}. */
|
||||
public String statutIcon() {
|
||||
/** Icône PrimeIcons calculée depuis {@link #getStatutCompte()}. */
|
||||
public String getStatutIcon() {
|
||||
if (statutCompte == null) return "pi pi-question-circle";
|
||||
return switch (statutCompte) {
|
||||
case "ACTIF" -> "pi pi-check-circle";
|
||||
@@ -92,8 +71,8 @@ public record MembreSummaryResponse(
|
||||
};
|
||||
}
|
||||
|
||||
/** Libellé du rôle principal calculé depuis {@link #roles()}. */
|
||||
public String typeMembre() {
|
||||
/** Libellé du rôle principal calculé depuis {@link #getRoles()}. */
|
||||
public String getTypeMembre() {
|
||||
if (roles == null || roles.isEmpty()) return "Membre";
|
||||
if (roles.contains("PRESIDENT")) return "Président";
|
||||
if (roles.contains("VICE_PRESIDENT")) return "Vice-Président";
|
||||
@@ -104,8 +83,8 @@ public record MembreSummaryResponse(
|
||||
return "Membre";
|
||||
}
|
||||
|
||||
/** Severity PrimeUI calculée depuis {@link #roles()}. */
|
||||
public String typeSeverity() {
|
||||
/** Severity PrimeUI calculée depuis {@link #getRoles()}. */
|
||||
public String getTypeSeverity() {
|
||||
if (roles == null || roles.isEmpty()) return "secondary";
|
||||
if (roles.contains("PRESIDENT")) return "primary";
|
||||
if (roles.contains("VICE_PRESIDENT")) return "primary";
|
||||
@@ -116,8 +95,13 @@ public record MembreSummaryResponse(
|
||||
return "secondary";
|
||||
}
|
||||
|
||||
/** Icône PrimeIcons calculée depuis {@link #roles()}. */
|
||||
public String typeIcon() {
|
||||
/** Retourne true si le membre est actif (null traité comme false). */
|
||||
public boolean isActif() {
|
||||
return actif != null && actif;
|
||||
}
|
||||
|
||||
/** Icône PrimeIcons calculée depuis {@link #getRoles()}. */
|
||||
public String getTypeIcon() {
|
||||
if (roles == null || roles.isEmpty()) return "pi pi-user";
|
||||
if (roles.contains("PRESIDENT")) return "pi pi-star";
|
||||
if (roles.contains("VICE_PRESIDENT")) return "pi pi-star";
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.request;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour bloquer un membre dans une organisation.
|
||||
*
|
||||
* <p>Le blocage est unilatéral et limité à une organisation.
|
||||
* Le membre bloqué ne peut plus envoyer de messages au bloqueur
|
||||
* dans cette organisation.
|
||||
*
|
||||
* @param membreABloquerId ID du membre à bloquer (obligatoire)
|
||||
* @param organisationId Organisation dans laquelle le blocage s'applique (obligatoire)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record BloquerMembreRequest(
|
||||
|
||||
@NotNull(message = "L'ID du membre à bloquer est obligatoire")
|
||||
UUID membreABloquerId,
|
||||
|
||||
@NotNull(message = "L'ID de l'organisation est obligatoire")
|
||||
UUID organisationId
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,35 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.request;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Démarre une conversation directe 1-1 entre le membre connecté
|
||||
* et un autre membre de la même organisation.
|
||||
*
|
||||
* <p>Si une conversation directe entre ces deux membres existe déjà
|
||||
* dans l'organisation, elle est réutilisée (idempotente).
|
||||
*
|
||||
* @param destinataireId ID du membre destinataire (obligatoire)
|
||||
* @param organisationId ID de l'organisation commune (obligatoire)
|
||||
* @param contenuInitial Premier message optionnel
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record DemarrerConversationDirecteRequest(
|
||||
|
||||
@NotNull(message = "L'ID du destinataire est obligatoire")
|
||||
UUID destinataireId,
|
||||
|
||||
@NotNull(message = "L'ID de l'organisation est obligatoire")
|
||||
UUID organisationId,
|
||||
|
||||
@Size(max = 2000, message = "Le message initial ne doit pas dépasser 2000 caractères")
|
||||
String contenuInitial
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,45 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Démarre une conversation avec un rôle officiel de l'organisation.
|
||||
*
|
||||
* <p>Le membre ne contacte pas une personne spécifique mais le "canal"
|
||||
* du rôle (ex: "Contacter le Trésorier"). Tous les membres portant ce
|
||||
* rôle voient et peuvent répondre — si le trésorier change, la conversation
|
||||
* continue avec le nouveau trésorier.
|
||||
*
|
||||
* <p>Si un canal pour ce rôle existe déjà dans l'organisation, il est réutilisé.
|
||||
*
|
||||
* @param organisationId ID de l'organisation (obligatoire)
|
||||
* @param roleCible Rôle visé : PRESIDENT | TRESORIER | SECRETAIRE | VICE_PRESIDENT | ADMIN
|
||||
* @param contenuInitial Premier message (obligatoire pour un canal rôle)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record DemarrerConversationRoleRequest(
|
||||
|
||||
@NotNull(message = "L'ID de l'organisation est obligatoire")
|
||||
UUID organisationId,
|
||||
|
||||
@NotBlank(message = "Le rôle cible est obligatoire")
|
||||
@Pattern(
|
||||
regexp = "^(PRESIDENT|TRESORIER|SECRETAIRE|VICE_PRESIDENT|ADMIN|ADMIN_ORGANISATION)$",
|
||||
message = "Rôle invalide. Valeurs : PRESIDENT, TRESORIER, SECRETAIRE, VICE_PRESIDENT, ADMIN, ADMIN_ORGANISATION"
|
||||
)
|
||||
String roleCible,
|
||||
|
||||
@NotBlank(message = "Le message initial est obligatoire pour contacter un rôle")
|
||||
@Size(max = 2000, message = "Le message ne doit pas dépasser 2000 caractères")
|
||||
String contenuInitial
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,47 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.request;
|
||||
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour envoyer un message dans une conversation existante.
|
||||
*
|
||||
* <p>La validation contextuelle (contenu OU urlFichier selon le type)
|
||||
* est effectuée dans le service.
|
||||
*
|
||||
* @param typeMessage TEXTE (défaut) | VOCAL | IMAGE | SYSTEME
|
||||
* @param contenu Texte du message (obligatoire pour TEXTE)
|
||||
* @param urlFichier URL du fichier (obligatoire pour VOCAL/IMAGE)
|
||||
* @param dureeAudio Durée en secondes (obligatoire pour VOCAL)
|
||||
* @param messageParentId ID du message auquel on répond (optionnel)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record EnvoyerMessageRequest(
|
||||
|
||||
@Pattern(
|
||||
regexp = "^(TEXTE|VOCAL|IMAGE|SYSTEME)$",
|
||||
message = "Type de message invalide. Valeurs : TEXTE, VOCAL, IMAGE, SYSTEME"
|
||||
)
|
||||
String typeMessage,
|
||||
|
||||
@Size(max = 4000, message = "Le message ne doit pas dépasser 4000 caractères")
|
||||
String contenu,
|
||||
|
||||
@Size(max = 500, message = "L'URL du fichier ne doit pas dépasser 500 caractères")
|
||||
String urlFichier,
|
||||
|
||||
@Min(value = 1, message = "La durée audio doit être supérieure à 0")
|
||||
@Max(value = 300, message = "La durée audio ne peut pas dépasser 300 secondes")
|
||||
Integer dureeAudio,
|
||||
|
||||
UUID messageParentId
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.request;
|
||||
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Mise à jour de la politique de communication d'une organisation.
|
||||
* Réservée aux administrateurs.
|
||||
*
|
||||
* @param typePolitique OUVERT | BUREAU_SEULEMENT | GROUPES_INTERNES
|
||||
* @param autoriserMembreVersMembre Autorise les échanges entre membres
|
||||
* @param autoriserMembreVersRole Autorise les échanges vers les rôles du bureau
|
||||
* @param autoriserNotesVocales Autorise les notes vocales
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record MettreAJourPolitiqueRequest(
|
||||
|
||||
@Pattern(
|
||||
regexp = "^(OUVERT|BUREAU_SEULEMENT|GROUPES_INTERNES)$",
|
||||
message = "Politique invalide. Valeurs : OUVERT, BUREAU_SEULEMENT, GROUPES_INTERNES"
|
||||
)
|
||||
String typePolitique,
|
||||
|
||||
Boolean autoriserMembreVersMembre,
|
||||
|
||||
Boolean autoriserMembreVersRole,
|
||||
|
||||
Boolean autoriserNotesVocales
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.response;
|
||||
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO de réponse pour la politique de communication d'une organisation.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ContactPolicyResponse {
|
||||
|
||||
private UUID id;
|
||||
private UUID organisationId;
|
||||
|
||||
/** OUVERT | BUREAU_SEULEMENT | GROUPES_INTERNES */
|
||||
private String typePolitique;
|
||||
|
||||
private boolean autoriserMembreVersMembre;
|
||||
private boolean autoriserMembreVersRole;
|
||||
private boolean autoriserNotesVocales;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.response;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO de réponse complète pour une conversation.
|
||||
* Inclut les derniers messages et la liste des participants.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ConversationResponse {
|
||||
|
||||
private UUID id;
|
||||
|
||||
/** DIRECTE | ROLE_CANAL | GROUPE */
|
||||
private String typeConversation;
|
||||
|
||||
/** Titre affiché (nom de l'autre participant ou du rôle). */
|
||||
private String titre;
|
||||
|
||||
/** ACTIVE | ARCHIVEE */
|
||||
private String statut;
|
||||
|
||||
/** Rôle cible pour les canaux rôle. */
|
||||
private String roleCible;
|
||||
|
||||
private UUID organisationId;
|
||||
private String organisationNom;
|
||||
|
||||
private LocalDateTime dateCreation;
|
||||
private LocalDateTime dernierMessageAt;
|
||||
private int nombreMessages;
|
||||
|
||||
/** Participants de la conversation. */
|
||||
private List<ParticipantResponse> participants;
|
||||
|
||||
/** Derniers messages (page 0). */
|
||||
private List<MessageResponse> messages;
|
||||
|
||||
/** Nombre de messages non lus pour le membre connecté. */
|
||||
private long nonLus;
|
||||
|
||||
// ── DTO interne pour les participants ─────────────────────────────────────
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public static class ParticipantResponse {
|
||||
private UUID membreId;
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private String roleDansConversation;
|
||||
private LocalDateTime luJusqua;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.response;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO résumé d'une conversation — utilisé dans la liste des conversations.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ConversationSummaryResponse {
|
||||
|
||||
private UUID id;
|
||||
|
||||
/** DIRECTE | ROLE_CANAL | GROUPE */
|
||||
private String typeConversation;
|
||||
|
||||
/**
|
||||
* Titre affiché dans la liste :
|
||||
* - Pour DIRECTE : "Prénom Nom" de l'autre participant
|
||||
* - Pour ROLE_CANAL : "Trésorier", "Président", etc.
|
||||
*/
|
||||
private String titre;
|
||||
|
||||
/** Statut : ACTIVE | ARCHIVEE */
|
||||
private String statut;
|
||||
|
||||
/** Aperçu du dernier message (max 100 caractères). */
|
||||
private String dernierMessageApercu;
|
||||
|
||||
/** Type du dernier message (pour afficher l'icône vocal/image). */
|
||||
private String dernierMessageType;
|
||||
|
||||
/** Horodatage du dernier message. */
|
||||
private LocalDateTime dernierMessageAt;
|
||||
|
||||
/** Nombre de messages non lus pour le membre connecté. */
|
||||
private long nonLus;
|
||||
|
||||
/** ID de l'organisation de la conversation. */
|
||||
private UUID organisationId;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.lions.unionflow.server.api.dto.messagerie.response;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO de réponse pour un message.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class MessageResponse {
|
||||
|
||||
private UUID id;
|
||||
|
||||
/** TEXTE | VOCAL | IMAGE | SYSTEME */
|
||||
private String typeMessage;
|
||||
|
||||
/** Texte du message (null si VOCAL/IMAGE). */
|
||||
private String contenu;
|
||||
|
||||
/** URL du fichier audio ou image. */
|
||||
private String urlFichier;
|
||||
|
||||
/** Durée en secondes (notes vocales uniquement). */
|
||||
private Integer dureeAudio;
|
||||
|
||||
/** True si le message a été supprimé par son auteur. */
|
||||
private boolean supprime;
|
||||
|
||||
// ── Expéditeur ────────────────────────────────────────────────────────────
|
||||
private UUID expediteurId;
|
||||
private String expediteurNom;
|
||||
private String expediteurPrenom;
|
||||
|
||||
// ── Réponse à un message ──────────────────────────────────────────────────
|
||||
private UUID messageParentId;
|
||||
/** Aperçu du message parent (premiers 100 caractères). */
|
||||
private String messageParentApercu;
|
||||
|
||||
// ── Horodatage ────────────────────────────────────────────────────────────
|
||||
private LocalDateTime dateEnvoi;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.lions.unionflow.server.api.dto.mutuelle.financier;
|
||||
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Paramètres financiers de la mutuelle")
|
||||
public class ParametresFinanciersMutuellRequest {
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "UUID de l'organisation")
|
||||
private String organisationId;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin(value = "1.0")
|
||||
@Schema(description = "Valeur nominale par défaut d'une part sociale (XOF)", example = "5000")
|
||||
private BigDecimal valeurNominaleParDefaut;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin(value = "0.0")
|
||||
@DecimalMax(value = "1.0")
|
||||
@Schema(description = "Taux d'intérêt annuel sur l'épargne (ex: 0.03 = 3%)", example = "0.03")
|
||||
private BigDecimal tauxInteretAnnuelEpargne;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin(value = "0.0")
|
||||
@DecimalMax(value = "1.0")
|
||||
@Schema(description = "Taux de dividende annuel sur les parts sociales (ex: 0.05 = 5%)", example = "0.05")
|
||||
private BigDecimal tauxDividendePartsAnnuel;
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "Périodicité du calcul des intérêts: MENSUEL, TRIMESTRIEL, ANNUEL", example = "MENSUEL")
|
||||
private String periodiciteCalcul;
|
||||
|
||||
@DecimalMin(value = "0.0")
|
||||
@Schema(description = "Solde minimum pour bénéficier des intérêts sur épargne", example = "10000")
|
||||
private BigDecimal seuilMinEpargneInterets;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.lions.unionflow.server.api.dto.mutuelle.financier;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import lombok.*;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Paramètres financiers d'une mutuelle")
|
||||
public class ParametresFinanciersMutuellResponse extends BaseDTO {
|
||||
|
||||
private String organisationId;
|
||||
private String organisationNom;
|
||||
private BigDecimal valeurNominaleParDefaut;
|
||||
private BigDecimal tauxInteretAnnuelEpargne;
|
||||
private BigDecimal tauxDividendePartsAnnuel;
|
||||
private String periodiciteCalcul;
|
||||
private BigDecimal seuilMinEpargneInterets;
|
||||
|
||||
@Schema(description = "Date du prochain calcul automatique des intérêts")
|
||||
private LocalDate prochaineCalculInterets;
|
||||
|
||||
@Schema(description = "Date du dernier calcul effectué")
|
||||
private LocalDate dernierCalculInterets;
|
||||
|
||||
@Schema(description = "Nombre de comptes épargne traités lors du dernier calcul")
|
||||
private Integer dernierNbComptesTraites;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package dev.lions.unionflow.server.api.dto.mutuelle.parts;
|
||||
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Ouverture d'un compte de parts sociales")
|
||||
public class ComptePartsSocialesRequest {
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "UUID du membre souscripteur")
|
||||
private String membreId;
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "UUID de l'organisation / mutuelle")
|
||||
private String organisationId;
|
||||
|
||||
@NotNull
|
||||
@Min(0)
|
||||
@Schema(description = "Nombre de parts souscrites à l'ouverture (0 = compte sans parts initiales)", example = "1")
|
||||
private Integer nombreParts;
|
||||
|
||||
@Schema(description = "Valeur nominale par part (XOF). Si absent, utilise la valeur configurée pour l'organisation.")
|
||||
@DecimalMin(value = "1.0")
|
||||
private BigDecimal valeurNominale;
|
||||
|
||||
@Schema(description = "Notes d'ouverture")
|
||||
private String notes;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.lions.unionflow.server.api.dto.mutuelle.parts;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.mutuelle.parts.StatutComptePartsSociales;
|
||||
import lombok.*;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Compte de parts sociales d'un membre")
|
||||
public class ComptePartsSocialesResponse extends BaseDTO {
|
||||
|
||||
private String membreId;
|
||||
private String membreNomComplet;
|
||||
private String organisationId;
|
||||
|
||||
@Schema(description = "Numéro de compte (ex: PS-MEG-00042)")
|
||||
private String numeroCompte;
|
||||
|
||||
@Schema(description = "Nombre de parts actuellement détenues")
|
||||
private Integer nombreParts;
|
||||
|
||||
@Schema(description = "Valeur nominale par part en devise de l'organisation")
|
||||
private BigDecimal valeurNominale;
|
||||
|
||||
@Schema(description = "Montant total du capital = nombreParts × valeurNominale")
|
||||
private BigDecimal montantTotal;
|
||||
|
||||
@Schema(description = "Cumul des dividendes reçus")
|
||||
private BigDecimal totalDividendesRecus;
|
||||
|
||||
private StatutComptePartsSociales statut;
|
||||
private LocalDate dateOuverture;
|
||||
private LocalDate dateDerniereOperation;
|
||||
private String notes;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.lions.unionflow.server.api.dto.mutuelle.parts;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.mutuelle.parts.TypeTransactionPartsSociales;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Transaction sur un compte de parts sociales")
|
||||
public class TransactionPartsSocialesRequest {
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "UUID du compte de parts sociales cible")
|
||||
private String compteId;
|
||||
|
||||
@NotNull
|
||||
private TypeTransactionPartsSociales typeTransaction;
|
||||
|
||||
@NotNull
|
||||
@Min(1)
|
||||
@Schema(description = "Nombre de parts concernées par la transaction")
|
||||
private Integer nombreParts;
|
||||
|
||||
@Schema(description = "Montant total en devise. Si absent, calculé depuis nombreParts × valeurNominale du compte.")
|
||||
@DecimalMin(value = "0.01")
|
||||
private BigDecimal montant;
|
||||
|
||||
@Schema(description = "Motif / libellé de la transaction")
|
||||
private String motif;
|
||||
|
||||
@Schema(description = "Référence externe (n° de reçu, bordereau, etc.)")
|
||||
private String referenceExterne;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package dev.lions.unionflow.server.api.dto.mutuelle.parts;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.mutuelle.parts.TypeTransactionPartsSociales;
|
||||
import lombok.*;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Transaction sur un compte de parts sociales")
|
||||
public class TransactionPartsSocialesResponse extends BaseDTO {
|
||||
|
||||
private String compteId;
|
||||
private String numeroCompte;
|
||||
private TypeTransactionPartsSociales typeTransaction;
|
||||
private String typeTransactionLibelle;
|
||||
|
||||
@Schema(description = "Nombre de parts impliquées")
|
||||
private Integer nombreParts;
|
||||
|
||||
@Schema(description = "Montant en devise")
|
||||
private BigDecimal montant;
|
||||
|
||||
@Schema(description = "Solde en parts avant la transaction")
|
||||
private Integer soldePartsAvant;
|
||||
|
||||
@Schema(description = "Solde en parts après la transaction")
|
||||
private Integer soldePartsApres;
|
||||
|
||||
private String motif;
|
||||
private String referenceExterne;
|
||||
private LocalDateTime dateTransaction;
|
||||
}
|
||||
@@ -2,9 +2,11 @@ package dev.lions.unionflow.server.api.dto.organisation.request;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Builder;
|
||||
|
||||
@@ -51,5 +53,13 @@ public record UpdateOrganisationRequest(
|
||||
@Size(max = 100) String pays,
|
||||
@Size(max = 20) String codePostal,
|
||||
Boolean organisationPublique,
|
||||
Boolean accepteNouveauxMembres) {
|
||||
Boolean accepteNouveauxMembres,
|
||||
|
||||
/** Référentiel comptable applicable (Sprint 1) — SYSCOHADA / SYCEBNL / PCSFD_UMOA. */
|
||||
@Pattern(regexp = "^(SYSCOHADA|SYCEBNL|PCSFD_UMOA)?$",
|
||||
message = "Référentiel comptable invalide")
|
||||
String referentielComptable,
|
||||
|
||||
/** UUID du Compliance Officer désigné (Instr. BCEAO 001-03-2025). */
|
||||
UUID complianceOfficerId) {
|
||||
}
|
||||
|
||||
@@ -46,28 +46,13 @@ public class OrganisationResponse extends BaseResponse {
|
||||
|
||||
// ── Classification ─────────────────────────
|
||||
private String typeOrganisation;
|
||||
/** Alias pour tri/filtre (type d'organisation) */
|
||||
private String typeAssociation;
|
||||
private String typeOrganisationLibelle;
|
||||
/** Libellé du type pour affichage (alias typeOrganisationLibelle, ex. p:tag) */
|
||||
private String typeLibelle;
|
||||
private String statut;
|
||||
private String statutLibelle;
|
||||
private String statutSeverity;
|
||||
private LocalDate dateFondation;
|
||||
private String numeroEnregistrement;
|
||||
|
||||
/**
|
||||
* Alias pour la vue (detail.xhtml, organisation-form.xhtml) : même valeur que numeroEnregistrement.
|
||||
*/
|
||||
public String getNumeroRegistre() {
|
||||
return getNumeroEnregistrement();
|
||||
}
|
||||
|
||||
public void setNumeroRegistre(String numeroRegistre) {
|
||||
setNumeroEnregistrement(numeroRegistre);
|
||||
}
|
||||
|
||||
// ── Géographie ─────────────────────────────
|
||||
private String adresse;
|
||||
private String quartier;
|
||||
@@ -81,13 +66,6 @@ public class OrganisationResponse extends BaseResponse {
|
||||
// ── Hiérarchie ─────────────────────────────
|
||||
private UUID organisationParenteId;
|
||||
private String organisationParenteNom;
|
||||
/** Alias pour la vue (detail.xhtml) : même valeur que organisationParenteNom. */
|
||||
public String getNomOrganisationParente() {
|
||||
return getOrganisationParenteNom();
|
||||
}
|
||||
public void setNomOrganisationParente(String nomOrganisationParente) {
|
||||
setOrganisationParenteNom(nomOrganisationParente);
|
||||
}
|
||||
private Integer niveauHierarchique;
|
||||
private Boolean estOrganisationRacine;
|
||||
|
||||
@@ -113,4 +91,11 @@ public class OrganisationResponse extends BaseResponse {
|
||||
// ── Paramètres ─────────────────────────────
|
||||
private Boolean organisationPublique;
|
||||
private Boolean accepteNouveauxMembres;
|
||||
|
||||
// ── Conformité (Sprint 1 — Instr. BCEAO + OHADA) ─────────────────────
|
||||
/** Référentiel comptable applicable : SYSCOHADA, SYCEBNL, PCSFD_UMOA. */
|
||||
private String referentielComptable;
|
||||
|
||||
/** UUID du Compliance Officer désigné (Instr. BCEAO 001-03-2025). */
|
||||
private UUID complianceOfficerId;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
package dev.lions.unionflow.server.api.dto.organisation.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Résumé d'une organisation pour les listes.
|
||||
* Classe JavaBean (pas un record) pour compatibilité JSF/EL (getNom() requis).
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @version 3.1
|
||||
* @since 2026-02-22
|
||||
*/
|
||||
public record OrganisationSummaryResponse(
|
||||
UUID id,
|
||||
String nom,
|
||||
String nomCourt,
|
||||
String typeOrganisation,
|
||||
String typeOrganisationLibelle,
|
||||
String statut,
|
||||
String statutLibelle,
|
||||
String statutSeverity,
|
||||
Integer nombreMembres,
|
||||
Boolean actif) {
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OrganisationSummaryResponse {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String nomCourt;
|
||||
private String typeOrganisation;
|
||||
private String typeOrganisationLibelle;
|
||||
private String statut;
|
||||
private String statutLibelle;
|
||||
private String statutSeverity;
|
||||
private Integer nombreMembres;
|
||||
private Boolean actif;
|
||||
private String ville;
|
||||
private String pays;
|
||||
}
|
||||
|
||||
@@ -3,29 +3,34 @@ package dev.lions.unionflow.server.api.dto.paiement.request;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requete de création d'un paiement.
|
||||
* Requête de création d'un paiement.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Builder
|
||||
public record CreatePaiementRequest(
|
||||
@NotBlank(message = "Le numéro de référence est obligatoire") String numeroReference,
|
||||
|
||||
@NotNull(message = "Le montant est obligatoire") @DecimalMin(value = "0.0", message = "Le montant doit être positif") BigDecimal montant,
|
||||
@NotBlank(message = "Le numéro de référence est obligatoire")
|
||||
String numeroReference,
|
||||
|
||||
@NotBlank(message = "Le code devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$", message = "Le code devise doit être un code ISO à 3 lettres") String codeDevise,
|
||||
@NotNull(message = "Le montant est obligatoire")
|
||||
@DecimalMin(value = "0.01", message = "Le montant doit être supérieur à 0")
|
||||
BigDecimal montant,
|
||||
|
||||
@NotBlank(message = "La méthode de paiement est obligatoire") String methodePaiement,
|
||||
@NotBlank(message = "Le code devise est obligatoire")
|
||||
String codeDevise,
|
||||
|
||||
String commentaire,
|
||||
@NotBlank(message = "La méthode de paiement est obligatoire")
|
||||
String methodePaiement,
|
||||
|
||||
@NotNull(message = "Le membre payeur est obligatoire") UUID membreId) {
|
||||
}
|
||||
String commentaire,
|
||||
|
||||
UUID membreId
|
||||
) {}
|
||||
|
||||
@@ -2,45 +2,25 @@ package dev.lions.unionflow.server.api.dto.paiement.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour déclarer un paiement manuel (espèces, virement, chèque).
|
||||
* Le paiement est créé avec le statut EN_ATTENTE_VALIDATION.
|
||||
* Le trésorier devra le valider via une page admin.
|
||||
*
|
||||
* @param cotisationId ID de la cotisation payée
|
||||
* @param methodePaiement Méthode de paiement (ESPECES, VIREMENT, CHEQUE, AUTRE)
|
||||
* @param reference Référence du paiement (numéro de transaction, numéro de chèque, etc.)
|
||||
* @param commentaire Commentaire optionnel
|
||||
* @param origineFonds Origine des fonds (LCB-FT) — obligatoire au-dessus du seuil configuré
|
||||
* @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
|
||||
* Requête de déclaration d'un paiement manuel (espèces, virement, chèque).
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-03-02
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Builder
|
||||
public record DeclarerPaiementManuelRequest(
|
||||
|
||||
@NotNull(message = "L'ID de la cotisation est obligatoire")
|
||||
UUID cotisationId,
|
||||
|
||||
@NotBlank(message = "La méthode de paiement est obligatoire")
|
||||
@Pattern(regexp = "^(ESPECES|VIREMENT|CHEQUE|AUTRE)$",
|
||||
message = "Méthode de paiement invalide. Valeurs autorisées : ESPECES, VIREMENT, CHEQUE, AUTRE")
|
||||
String methodePaiement,
|
||||
|
||||
@Size(max = 100, message = "La référence ne doit pas dépasser 100 caractères")
|
||||
/** Référence externe (numéro de chèque, référence virement, etc.) */
|
||||
String reference,
|
||||
|
||||
@Size(max = 500, message = "Le commentaire ne doit pas dépasser 500 caractères")
|
||||
String commentaire,
|
||||
|
||||
String origineFonds,
|
||||
|
||||
String justificationLcbFt
|
||||
) {
|
||||
}
|
||||
String commentaire
|
||||
) {}
|
||||
|
||||
@@ -1,40 +1,22 @@
|
||||
package dev.lions.unionflow.server.api.dto.paiement.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour initier un paiement en ligne via un gateway (Wave, Orange, Free Money, Carte).
|
||||
*
|
||||
* @param cotisationId ID de la cotisation à payer
|
||||
* @param methodePaiement Méthode de paiement (WAVE, ORANGE_MONEY, FREE_MONEY, CARTE_BANCAIRE)
|
||||
* @param numeroTelephone Numéro de téléphone pour Wave/Orange/Free (format: 221771234567)
|
||||
* @param origineFonds Origine des fonds (LCB-FT) — obligatoire au-dessus du seuil configuré
|
||||
* @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
|
||||
* Requête d'initiation de paiement en ligne via Wave, Orange Money, Free Money ou carte bancaire.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-03-02
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Builder
|
||||
public record InitierPaiementEnLigneRequest(
|
||||
|
||||
@NotNull(message = "L'ID de la cotisation est obligatoire")
|
||||
UUID cotisationId,
|
||||
|
||||
@NotBlank(message = "La méthode de paiement est obligatoire")
|
||||
@Pattern(regexp = "^(WAVE|ORANGE_MONEY|FREE_MONEY|CARTE_BANCAIRE)$",
|
||||
message = "Méthode de paiement invalide. Valeurs autorisées : WAVE, ORANGE_MONEY, FREE_MONEY, CARTE_BANCAIRE")
|
||||
@NotNull(message = "La méthode de paiement est obligatoire")
|
||||
String methodePaiement,
|
||||
|
||||
/** Optionnel sur le web (QR code sans restriction de payeur). Obligatoire sur mobile. */
|
||||
@Pattern(regexp = "^\\d{9,15}$", message = "Numéro de téléphone invalide (9-15 chiffres)")
|
||||
String numeroTelephone,
|
||||
|
||||
String origineFonds,
|
||||
|
||||
String justificationLcbFt
|
||||
) {
|
||||
}
|
||||
String numeroTelephone
|
||||
) {}
|
||||
|
||||
@@ -2,23 +2,52 @@ package dev.lions.unionflow.server.api.dto.paiement.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Réponse du polling de statut d'une IntentionPaiement Wave.
|
||||
* Utilisée par le web pour savoir si le paiement est confirmé.
|
||||
* Réponse au polling du statut d'une intention de paiement Wave.
|
||||
*
|
||||
* <p>Utilisée par le deep link de retour (mobile) et le polling web (QR code).
|
||||
* Quand {@code statut} vaut {@code COMPLETEE}, la cotisation est automatiquement
|
||||
* marquée PAYEE et {@code confirme} vaut {@code true}.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public record IntentionStatutResponse(
|
||||
UUID intentionId,
|
||||
public class IntentionStatutResponse {
|
||||
|
||||
/** UUID de l'intention de paiement (clé de polling) */
|
||||
private UUID intentionId;
|
||||
|
||||
/** INITIEE | EN_COURS | COMPLETEE | EXPIREE | ECHOUEE */
|
||||
String statut,
|
||||
/** URL à encoder en QR code (wave_launch_url Wave Checkout) */
|
||||
String waveLaunchUrl,
|
||||
String waveCheckoutSessionId,
|
||||
private String statut;
|
||||
|
||||
/** Raccourci : {@code true} si statut == COMPLETEE */
|
||||
private boolean confirme;
|
||||
|
||||
/** URL Wave — pour régénérer le QR code si la session est toujours active */
|
||||
private String waveLaunchUrl;
|
||||
|
||||
/** ID de session Wave (cos-xxx) */
|
||||
private String waveCheckoutSessionId;
|
||||
|
||||
/** ID de transaction Wave (TCN...) — disponible quand COMPLETEE */
|
||||
String waveTransactionId,
|
||||
BigDecimal montant,
|
||||
String referenceCotisation,
|
||||
String message
|
||||
) {}
|
||||
private String waveTransactionId;
|
||||
|
||||
/** Montant du paiement */
|
||||
private BigDecimal montant;
|
||||
|
||||
/** Référence de la cotisation concernée */
|
||||
private String referenceCotisation;
|
||||
|
||||
/** Message lisible pour l'utilisateur */
|
||||
private String message;
|
||||
}
|
||||
|
||||
@@ -2,76 +2,45 @@ package dev.lions.unionflow.server.api.dto.paiement.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO de réponse pour l'initiation d'un paiement en ligne via un gateway.
|
||||
* Retourne l'URL de redirection vers le gateway (Wave, Orange, Free Money, Carte).
|
||||
* DTO de réponse pour l'initiation d'un paiement en ligne (Wave, Orange Money, etc.).
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-03-02
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class PaiementGatewayResponse {
|
||||
/**
|
||||
* ID de la transaction créée
|
||||
*/
|
||||
|
||||
/** ID interne du paiement ou de l'intention créé. */
|
||||
private UUID transactionId;
|
||||
|
||||
/**
|
||||
* URL de redirection vers le gateway de paiement
|
||||
*/
|
||||
/** URL de redirection vers la page de paiement du gateway. */
|
||||
private String redirectUrl;
|
||||
|
||||
/**
|
||||
* Montant à payer (en FCFA)
|
||||
*/
|
||||
private BigDecimal montant;
|
||||
|
||||
/**
|
||||
* Statut de la transaction (EN_ATTENTE, VALIDE, ECHOUE)
|
||||
*/
|
||||
private String statut;
|
||||
|
||||
/**
|
||||
* Méthode de paiement (WAVE, ORANGE_MONEY, FREE_MONEY, CARTE_BANCAIRE)
|
||||
*/
|
||||
private String methodePaiement;
|
||||
|
||||
/**
|
||||
* Référence de la cotisation
|
||||
*/
|
||||
private String referenceCotisation;
|
||||
|
||||
/**
|
||||
* Message d'information pour l'utilisateur
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* URL Wave pour ouvrir l'app Wave (redirection automatique membre).
|
||||
* Présent lorsque methodePaiement = WAVE.
|
||||
*/
|
||||
/** URL spécifique Wave (wave_launch_url) pour deep-link vers l'app Wave. */
|
||||
private String waveLaunchUrl;
|
||||
|
||||
/**
|
||||
* ID de session Checkout Wave (cos-xxx). Pour réconciliation / webhook.
|
||||
*/
|
||||
/** ID de la session Wave Checkout. */
|
||||
private String waveCheckoutSessionId;
|
||||
|
||||
/**
|
||||
* Référence client (UUID intention) pour le deep link de retour.
|
||||
*/
|
||||
/** Référence client envoyée à Wave (intention UUID). */
|
||||
private String clientReference;
|
||||
|
||||
private BigDecimal montant;
|
||||
|
||||
/** Statut initial (EN_ATTENTE). */
|
||||
private String statut;
|
||||
|
||||
private String methodePaiement;
|
||||
|
||||
/** Numéro de référence de la cotisation associée. */
|
||||
private String referenceCotisation;
|
||||
|
||||
/** Message d'information à afficher à l'utilisateur. */
|
||||
private String message;
|
||||
}
|
||||
|
||||
@@ -16,36 +16,39 @@ import lombok.Setter;
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class PaiementResponse extends BaseResponse {
|
||||
|
||||
private String numeroReference;
|
||||
|
||||
private BigDecimal montant;
|
||||
private String codeDevise;
|
||||
|
||||
private String methodePaiement;
|
||||
private String methodePaiementLibelle;
|
||||
|
||||
private String statutPaiement;
|
||||
private String statutPaiementLibelle;
|
||||
private String statutPaiementSeverity;
|
||||
|
||||
private LocalDateTime datePaiement;
|
||||
private LocalDateTime dateValidation;
|
||||
|
||||
private String validateur;
|
||||
|
||||
private String referenceExterne;
|
||||
private String urlPreuve;
|
||||
private String commentaire;
|
||||
|
||||
// Informations relatives au payeur
|
||||
private UUID membreId;
|
||||
private String membreNom;
|
||||
|
||||
// Intégration Wave
|
||||
private UUID transactionWaveId;
|
||||
|
||||
// LCB-FT (Lutte Contre le Blanchiment et Financement du Terrorisme)
|
||||
private String origineFonds;
|
||||
private String justificationLcbFt;
|
||||
}
|
||||
|
||||
@@ -5,20 +5,20 @@ import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* DTO de réponse résumé pour un paiement.
|
||||
* Utilisé principalement pour l'affichage de listes.
|
||||
* DTO résumé pour les listes de paiements.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
public record PaiementSummaryResponse(
|
||||
UUID id,
|
||||
String numeroReference,
|
||||
BigDecimal montant,
|
||||
String codeDevise,
|
||||
String methodePaiementLibelle,
|
||||
String statutPaiement,
|
||||
String statutPaiementLibelle,
|
||||
String statutPaiementSeverity,
|
||||
LocalDateTime datePaiement) {
|
||||
}
|
||||
UUID id,
|
||||
String numeroReference,
|
||||
BigDecimal montant,
|
||||
String codeDevise,
|
||||
String methodePaiementLibelle,
|
||||
String statutPaiement,
|
||||
String statutPaiementLibelle,
|
||||
String statutPaiementSeverity,
|
||||
LocalDateTime datePaiement
|
||||
) {}
|
||||
|
||||
@@ -52,5 +52,17 @@ public record CreateTypeReferenceRequest(
|
||||
Boolean estSysteme,
|
||||
|
||||
/** UUID de l'organisation (null = global). */
|
||||
UUID organisationId) {
|
||||
UUID organisationId,
|
||||
|
||||
/**
|
||||
* Catégorie fonctionnelle (ex: FINANCIER_SOLIDAIRE).
|
||||
* Obligatoire pour domaine=TYPE_ORGANISATION.
|
||||
*/
|
||||
@Size(max = 50) String categorie,
|
||||
|
||||
/**
|
||||
* Modules métier CSV (ex: "MEMBRES,COTISATIONS,TONTINE,FINANCE").
|
||||
* Obligatoire pour domaine=TYPE_ORGANISATION.
|
||||
*/
|
||||
String modulesRequis) {
|
||||
}
|
||||
|
||||
@@ -41,5 +41,11 @@ public record UpdateTypeReferenceRequest(
|
||||
Boolean estDefaut,
|
||||
|
||||
/** Nouvel état actif/inactif (optionnel). */
|
||||
Boolean actif) {
|
||||
Boolean actif,
|
||||
|
||||
/** Nouvelle catégorie fonctionnelle (optionnel). */
|
||||
@Size(max = 50) String categorie,
|
||||
|
||||
/** Nouveaux modules requis CSV (optionnel). */
|
||||
String modulesRequis) {
|
||||
}
|
||||
|
||||
@@ -60,4 +60,19 @@ public class TypeReferenceResponse extends BaseResponse {
|
||||
|
||||
/** UUID de l'organisation (null = global). */
|
||||
private UUID organisationId;
|
||||
|
||||
/**
|
||||
* Catégorie fonctionnelle du type d'organisation.
|
||||
* Valeurs: ASSOCIATIF, FINANCIER_SOLIDAIRE, RELIGIEUX, PROFESSIONNEL, RESEAU_FEDERATION.
|
||||
* Uniquement pertinent pour domaine=TYPE_ORGANISATION.
|
||||
*/
|
||||
private String categorie;
|
||||
|
||||
/**
|
||||
* Modules métier activés pour ce type d'organisation (CSV).
|
||||
* Exemple: "MEMBRES,COTISATIONS,TONTINE,FINANCE"
|
||||
* Utilisé pour initialiser Organisation.modulesActifs à la création.
|
||||
* Uniquement pertinent pour domaine=TYPE_ORGANISATION.
|
||||
*/
|
||||
private String modulesRequis;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour déclarer un versement manuel (espèces, virement, chèque).
|
||||
*
|
||||
* <p>Le versement est créé avec le statut {@code EN_ATTENTE_VALIDATION}.
|
||||
* Le trésorier de l'organisation devra le valider via la page admin.
|
||||
*
|
||||
* @param cotisationId ID de la cotisation réglée (obligatoire)
|
||||
* @param methodePaiement Mode de règlement : ESPECES | VIREMENT | CHEQUE | AUTRE
|
||||
* @param reference Référence libre (numéro de chèque, bordereau de virement…)
|
||||
* @param commentaire Commentaire optionnel
|
||||
* @param origineFonds Origine des fonds — obligatoire au-delà du seuil LCB-FT
|
||||
* @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record DeclarerVersementManuelRequest(
|
||||
|
||||
@NotNull(message = "L'ID de la cotisation est obligatoire")
|
||||
UUID cotisationId,
|
||||
|
||||
@NotBlank(message = "La méthode de règlement est obligatoire")
|
||||
@Pattern(
|
||||
regexp = "^(ESPECES|VIREMENT|CHEQUE|AUTRE)$",
|
||||
message = "Méthode invalide. Valeurs autorisées : ESPECES, VIREMENT, CHEQUE, AUTRE"
|
||||
)
|
||||
String methodePaiement,
|
||||
|
||||
@Size(max = 100, message = "La référence ne doit pas dépasser 100 caractères")
|
||||
String reference,
|
||||
|
||||
@Size(max = 500, message = "Le commentaire ne doit pas dépasser 500 caractères")
|
||||
String commentaire,
|
||||
|
||||
String origineFonds,
|
||||
|
||||
String justificationLcbFt
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.request;
|
||||
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour initier un dépôt sur compte épargne via Wave.
|
||||
*
|
||||
* <p>Même flux que le versement de cotisation : Wave s'ouvre sur le même téléphone,
|
||||
* le membre confirme avec son PIN Wave, puis retour automatique dans UnionFlow.
|
||||
*
|
||||
* @param compteId ID du compte épargne cible (obligatoire)
|
||||
* @param montant Montant à déposer, en FCFA (obligatoire, > 0)
|
||||
* @param numeroTelephone Numéro Wave du membre, pré-rempli depuis le profil
|
||||
* @param origineFonds Origine des fonds — obligatoire au-delà du seuil LCB-FT
|
||||
* @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record InitierDepotEpargneRequest(
|
||||
|
||||
@NotNull(message = "L'ID du compte épargne est obligatoire")
|
||||
UUID compteId,
|
||||
|
||||
@NotNull(message = "Le montant est obligatoire")
|
||||
@DecimalMin(value = "0.01", message = "Le montant doit être supérieur à 0")
|
||||
BigDecimal montant,
|
||||
|
||||
@Pattern(regexp = "^\\d{9,15}$", message = "Numéro de téléphone invalide (9-15 chiffres)")
|
||||
String numeroTelephone,
|
||||
|
||||
String origineFonds,
|
||||
|
||||
String justificationLcbFt
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,39 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.request;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import java.util.UUID;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* Requête pour initier un versement via Wave Mobile Money.
|
||||
*
|
||||
* <p>Wave est la seule méthode de paiement en ligne active. Le numéro de
|
||||
* téléphone est pré-rempli depuis le profil du membre (même téléphone qu'UnionFlow),
|
||||
* ce qui permet à Wave de s'ouvrir directement avec toutes les informations.
|
||||
*
|
||||
* @param cotisationId ID de la cotisation à régler (obligatoire)
|
||||
* @param numeroTelephone Numéro Wave du membre, pré-rempli depuis le profil
|
||||
* (9-15 chiffres, optionnel sur web QR code)
|
||||
* @param origineFonds Origine des fonds — obligatoire au-delà du seuil LCB-FT
|
||||
* @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Builder
|
||||
public record InitierVersementWaveRequest(
|
||||
|
||||
@NotNull(message = "L'ID de la cotisation est obligatoire")
|
||||
UUID cotisationId,
|
||||
|
||||
/** Optionnel sur web (QR code sans restriction de payeur). Obligatoire sur mobile. */
|
||||
@Pattern(regexp = "^\\d{9,15}$", message = "Numéro de téléphone invalide (9-15 chiffres)")
|
||||
String numeroTelephone,
|
||||
|
||||
String origineFonds,
|
||||
|
||||
String justificationLcbFt
|
||||
|
||||
) {}
|
||||
@@ -0,0 +1,59 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Réponse à l'initiation d'un versement Wave.
|
||||
*
|
||||
* <p>Contient le {@code waveLaunchUrl} permettant à {@code url_launcher}
|
||||
* d'ouvrir l'application Wave directement sur le téléphone du membre avec
|
||||
* le montant et le numéro pré-remplis. Le {@code clientReference} (UUID
|
||||
* de l'intention) est utilisé dans le deep link de retour :
|
||||
* {@code unionflow://payment?result=success&ref={clientReference}}.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class VersementGatewayResponse {
|
||||
|
||||
/** ID du versement créé */
|
||||
private UUID versementId;
|
||||
|
||||
/** URL Wave pour {@code url_launcher} — ouvre l'app Wave sur le même téléphone */
|
||||
private String waveLaunchUrl;
|
||||
|
||||
/** ID de session Checkout Wave (cos-xxx) — pour le polling et la réconciliation webhook */
|
||||
private String waveCheckoutSessionId;
|
||||
|
||||
/**
|
||||
* UUID de l'intention — utilisé comme paramètre {@code ref} dans le deep link retour
|
||||
* {@code unionflow://payment?result=success&ref={clientReference}}
|
||||
*/
|
||||
private String clientReference;
|
||||
|
||||
/** Montant du versement en FCFA */
|
||||
private BigDecimal montant;
|
||||
|
||||
/** Statut initial : EN_ATTENTE */
|
||||
private String statut;
|
||||
|
||||
/** Référence de la cotisation concernée */
|
||||
private String referenceCotisation;
|
||||
|
||||
/** Message d'information pour l'utilisateur */
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.response;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseResponse;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO de réponse détaillée pour un versement.
|
||||
*
|
||||
* <p>Un versement est l'acte de régler une cotisation. Il peut être effectué
|
||||
* via Wave (deep link natif) ou manuellement (espèces, virement, chèque).
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class VersementResponse extends BaseResponse {
|
||||
|
||||
/** Référence unique du versement (ex: VRS-2026-XXXXXXXXXXXX) */
|
||||
private String numeroReference;
|
||||
|
||||
// ── Montant ───────────────────────────────────────────────────────────────
|
||||
|
||||
private BigDecimal montant;
|
||||
private String codeDevise;
|
||||
|
||||
// ── Méthode ───────────────────────────────────────────────────────────────
|
||||
|
||||
/** WAVE | ESPECES | VIREMENT | CHEQUE | AUTRE */
|
||||
private String methodePaiement;
|
||||
private String methodePaiementLibelle;
|
||||
|
||||
// ── Statut ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** EN_ATTENTE | EN_COURS | CONFIRME | ECHEC | EN_ATTENTE_VALIDATION | ANNULE */
|
||||
private String statutPaiement;
|
||||
private String statutPaiementLibelle;
|
||||
private String statutPaiementSeverity;
|
||||
|
||||
// ── Dates ─────────────────────────────────────────────────────────────────
|
||||
|
||||
private LocalDateTime datePaiement;
|
||||
private LocalDateTime dateValidation;
|
||||
|
||||
// ── Validation (paiement manuel) ──────────────────────────────────────────
|
||||
|
||||
private String validateur;
|
||||
|
||||
// ── Traçabilité ───────────────────────────────────────────────────────────
|
||||
|
||||
/** ID transaction Wave (TCN...) ou référence chèque/virement */
|
||||
private String referenceExterne;
|
||||
private String urlPreuve;
|
||||
private String commentaire;
|
||||
|
||||
// ── Payeur ────────────────────────────────────────────────────────────────
|
||||
|
||||
private UUID membreId;
|
||||
private String membreNom;
|
||||
|
||||
/** Numéro Wave utilisé pour ce versement */
|
||||
private String numeroTelephone;
|
||||
|
||||
// ── Intégration Wave ─────────────────────────────────────────────────────
|
||||
|
||||
private UUID transactionWaveId;
|
||||
|
||||
// ── LCB-FT ───────────────────────────────────────────────────────────────
|
||||
|
||||
private String origineFonds;
|
||||
private String justificationLcbFt;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Réponse au polling du statut d'un versement Wave.
|
||||
*
|
||||
* <p>Utilisée par le deep link de retour (mobile) et le polling web.
|
||||
* Quand {@code statut} vaut {@code COMPLETEE}, la cotisation est automatiquement
|
||||
* marquée PAYEE et {@code confirme} vaut {@code true}.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class VersementStatutResponse {
|
||||
|
||||
/** UUID de l'intention Wave (clé de polling) */
|
||||
private UUID intentionId;
|
||||
|
||||
/** INITIEE | EN_COURS | COMPLETEE | EXPIREE | ECHOUEE */
|
||||
private String statut;
|
||||
|
||||
/** Raccourci : {@code true} si statut == COMPLETEE */
|
||||
private boolean confirme;
|
||||
|
||||
/** URL Wave — pour régénérer le QR code si la session est toujours active */
|
||||
private String waveLaunchUrl;
|
||||
|
||||
/** ID de session Wave (cos-xxx) */
|
||||
private String waveCheckoutSessionId;
|
||||
|
||||
/** ID de transaction Wave (TCN...) — disponible quand COMPLETEE */
|
||||
private String waveTransactionId;
|
||||
|
||||
/** Montant du versement */
|
||||
private BigDecimal montant;
|
||||
|
||||
/** Référence de la cotisation concernée */
|
||||
private String referenceCotisation;
|
||||
|
||||
/** Message lisible pour l'utilisateur */
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package dev.lions.unionflow.server.api.dto.versement.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO résumé d'un versement — utilisé dans les listes.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VersementSummaryResponse {
|
||||
private UUID id;
|
||||
private String numeroReference;
|
||||
private BigDecimal montant;
|
||||
private String codeDevise;
|
||||
private String methodePaiementLibelle;
|
||||
private String statutPaiement;
|
||||
private String statutPaiementLibelle;
|
||||
private String statutPaiementSeverity;
|
||||
private LocalDateTime datePaiement;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.lions.unionflow.server.api.enums.membre;
|
||||
|
||||
/**
|
||||
* Niveau de risque LCB-FT calculé par le service KYC/AML.
|
||||
* Détermine les contrôles additionnels applicables au membre.
|
||||
*/
|
||||
public enum NiveauRisqueKyc {
|
||||
|
||||
/** Risque faible — profil standard, pas de signalement. */
|
||||
FAIBLE("Risque faible", 0, 39),
|
||||
|
||||
/** Risque moyen — surveillance accrue, revue annuelle. */
|
||||
MOYEN("Risque moyen", 40, 69),
|
||||
|
||||
/** Risque élevé — due diligence renforcée, approbation manuelle. */
|
||||
ELEVE("Risque élevé", 70, 89),
|
||||
|
||||
/** Risque très élevé — blocage automatique, signalement GIABA. */
|
||||
CRITIQUE("Risque critique", 90, 100);
|
||||
|
||||
private final String libelle;
|
||||
private final int scoreMin;
|
||||
private final int scoreMax;
|
||||
|
||||
NiveauRisqueKyc(String libelle, int scoreMin, int scoreMax) {
|
||||
this.libelle = libelle;
|
||||
this.scoreMin = scoreMin;
|
||||
this.scoreMax = scoreMax;
|
||||
}
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public int getScoreMin() { return scoreMin; }
|
||||
public int getScoreMax() { return scoreMax; }
|
||||
|
||||
public static NiveauRisqueKyc fromScore(int score) {
|
||||
for (NiveauRisqueKyc niveau : values()) {
|
||||
if (score >= niveau.scoreMin && score <= niveau.scoreMax) {
|
||||
return niveau;
|
||||
}
|
||||
}
|
||||
return CRITIQUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package dev.lions.unionflow.server.api.enums.membre;
|
||||
|
||||
/**
|
||||
* Type de pièce d'identité pour le dossier KYC — conformité GIABA/BCEAO LCB-FT.
|
||||
*/
|
||||
public enum TypePieceIdentite {
|
||||
|
||||
CNI("Carte Nationale d'Identité"),
|
||||
PASSEPORT("Passeport"),
|
||||
TITRE_SEJOUR("Titre de séjour"),
|
||||
CARTE_CONSULAIRE("Carte consulaire"),
|
||||
PERMIS_CONDUIRE("Permis de conduire"),
|
||||
AUTRE("Autre pièce officielle");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypePieceIdentite(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.lions.unionflow.server.api.enums.messagerie;
|
||||
|
||||
/**
|
||||
* Statut d'une conversation.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
public enum StatutConversation {
|
||||
|
||||
/** Conversation active — messages entrants autorisés. */
|
||||
ACTIVE,
|
||||
|
||||
/** Conversation archivée — lecture seule, plus de nouveaux messages. */
|
||||
ARCHIVEE
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package dev.lions.unionflow.server.api.enums.messagerie;
|
||||
|
||||
/**
|
||||
* Type de contenu d'un message.
|
||||
*
|
||||
* <p>Les notes vocales (VOCAL) sont critiques pour l'inclusivité :
|
||||
* les membres analphabètes peuvent communiquer par audio exactement
|
||||
* comme sur WhatsApp (bouton maintenir pour parler).
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
public enum TypeContenu {
|
||||
|
||||
/** Message texte classique. */
|
||||
TEXTE,
|
||||
|
||||
/**
|
||||
* Note vocale — fichier audio Opus/AAC stocké sur object storage.
|
||||
* Champs associés : {@code urlFichier} + {@code dureeAudio} (secondes).
|
||||
*/
|
||||
VOCAL,
|
||||
|
||||
/**
|
||||
* Image — JPEG/PNG stockée sur object storage.
|
||||
* Champ associé : {@code urlFichier}.
|
||||
*/
|
||||
IMAGE,
|
||||
|
||||
/**
|
||||
* Message système généré automatiquement (ex: "La conversation a été archivée").
|
||||
*/
|
||||
SYSTEME
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.lions.unionflow.server.api.enums.messagerie;
|
||||
|
||||
/**
|
||||
* Type de conversation dans la messagerie instantanée.
|
||||
*
|
||||
* <p>La politique de l'organisation détermine quels types sont autorisés.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
public enum TypeConversation {
|
||||
|
||||
/**
|
||||
* Conversation directe 1-1 entre deux membres de la même organisation.
|
||||
* Autorisée par défaut dans toutes les organisations.
|
||||
*/
|
||||
DIRECTE,
|
||||
|
||||
/**
|
||||
* Canal vers un rôle officiel (PRESIDENT, TRESORIER, SECRETAIRE…).
|
||||
* Le membre contacte la "boîte" du rôle, pas une personne spécifique.
|
||||
* Tous les membres du rôle voient et peuvent répondre.
|
||||
*/
|
||||
ROLE_CANAL,
|
||||
|
||||
/**
|
||||
* Conversation de groupe — réservé V2.
|
||||
*/
|
||||
GROUPE
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.lions.unionflow.server.api.enums.messagerie;
|
||||
|
||||
/**
|
||||
* Politique de communication configurable par l'administrateur d'organisation.
|
||||
*
|
||||
* <p>Valeurs par défaut selon le type d'organisation :
|
||||
* <ul>
|
||||
* <li>Tontine (≤30 membres) → {@code OUVERT}</li>
|
||||
* <li>Association (30–500) → {@code OUVERT}</li>
|
||||
* <li>Mutuelle (50–5000) → {@code BUREAU_SEULEMENT}</li>
|
||||
* <li>Coopérative → {@code OUVERT}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 4.0
|
||||
* @since 2026-04-13
|
||||
*/
|
||||
public enum TypePolitiqueCommunication {
|
||||
|
||||
/**
|
||||
* Tous les membres peuvent se contacter entre eux et contacter le bureau.
|
||||
* Mode par défaut pour les petites structures (tontines, associations).
|
||||
*/
|
||||
OUVERT,
|
||||
|
||||
/**
|
||||
* Les membres ne peuvent contacter que les rôles du bureau
|
||||
* (Président, Trésorier, Secrétaire).
|
||||
* Recommandé pour les mutuelles et grandes organisations.
|
||||
*/
|
||||
BUREAU_SEULEMENT,
|
||||
|
||||
/**
|
||||
* Communication uniquement au sein des groupes/comités internes.
|
||||
* Pour les coopératives avec plusieurs sections.
|
||||
*/
|
||||
GROUPES_INTERNES
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.lions.unionflow.server.api.enums.mutuelle.parts;
|
||||
|
||||
public enum StatutComptePartsSociales {
|
||||
ACTIF("Compte actif"),
|
||||
SUSPENDU("Compte suspendu"),
|
||||
CLOS("Compte clôturé — parts rachetées");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
StatutComptePartsSociales(String libelle) { this.libelle = libelle; }
|
||||
public String getLibelle() { return libelle; }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.lions.unionflow.server.api.enums.mutuelle.parts;
|
||||
|
||||
public enum TypeTransactionPartsSociales {
|
||||
SOUSCRIPTION("Souscription de parts sociales"),
|
||||
SOUSCRIPTION_IMPORT("Import historique — souscription"),
|
||||
CESSION_PARTIELLE("Cession partielle de parts"),
|
||||
RACHAT_TOTAL("Rachat total (clôture)"),
|
||||
PAIEMENT_DIVIDENDE("Versement de dividendes / intérêts sur parts"),
|
||||
CORRECTION("Correction administrative");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeTransactionPartsSociales(String libelle) { this.libelle = libelle; }
|
||||
public String getLibelle() { return libelle; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dev.lions.unionflow.server.api.payment;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Requête d'initiation d'un checkout — abstraction provider-agnostique.
|
||||
*/
|
||||
public record CheckoutRequest(
|
||||
BigDecimal amount,
|
||||
String currency,
|
||||
String customerPhone,
|
||||
String customerEmail,
|
||||
/** Référence interne UnionFlow (souscription, cotisation, transaction épargne...). */
|
||||
String reference,
|
||||
String successUrl,
|
||||
String cancelUrl,
|
||||
Map<String, String> metadata
|
||||
) {
|
||||
public CheckoutRequest {
|
||||
if (amount == null || amount.signum() <= 0) throw new IllegalArgumentException("amount doit être positif");
|
||||
if (currency == null || currency.isBlank()) throw new IllegalArgumentException("currency obligatoire");
|
||||
if (reference == null || reference.isBlank()) throw new IllegalArgumentException("reference obligatoire");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.lions.unionflow.server.api.payment;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Résultat d'une initiation de session de paiement.
|
||||
*/
|
||||
public record CheckoutSession(
|
||||
String externalId,
|
||||
String checkoutUrl,
|
||||
Instant expiresAt,
|
||||
Map<String, String> providerMetadata
|
||||
) {}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.lions.unionflow.server.api.payment;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* Événement de paiement normalisé reçu via webhook ou polling.
|
||||
*/
|
||||
public record PaymentEvent(
|
||||
String externalId,
|
||||
String reference,
|
||||
PaymentStatus status,
|
||||
BigDecimal amountConfirmed,
|
||||
String transactionCode,
|
||||
Instant occurredAt
|
||||
) {}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dev.lions.unionflow.server.api.payment;
|
||||
|
||||
/**
|
||||
* Exception levée par les implémentations PaymentProvider.
|
||||
*/
|
||||
public class PaymentException extends RuntimeException {
|
||||
|
||||
private final String providerCode;
|
||||
private final int httpStatus;
|
||||
|
||||
public PaymentException(String providerCode, String message, int httpStatus) {
|
||||
super("[" + providerCode + "] " + message);
|
||||
this.providerCode = providerCode;
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public PaymentException(String providerCode, String message, int httpStatus, Throwable cause) {
|
||||
super("[" + providerCode + "] " + message, cause);
|
||||
this.providerCode = providerCode;
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public String getProviderCode() { return providerCode; }
|
||||
public int getHttpStatus() { return httpStatus; }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.lions.unionflow.server.api.payment;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Abstraction unifiée pour tous les providers de paiement UnionFlow.
|
||||
*
|
||||
* <p>Implémentations disponibles : Wave, Orange Money, MTN MoMo, Moov Money, PI-SPI (BCEAO).
|
||||
* Chaque provider est un bean CDI {@code @ApplicationScoped} découvert via
|
||||
* {@code @Any Instance<PaymentProvider>} dans le registry.
|
||||
*/
|
||||
public interface PaymentProvider {
|
||||
|
||||
/** Code unique du provider — utilisé comme discriminant dans la config et les routes webhook. */
|
||||
String getProviderCode();
|
||||
|
||||
/**
|
||||
* Initie une session de paiement et retourne l'URL de checkout.
|
||||
*
|
||||
* @throws PaymentException si le provider est indisponible ou la requête invalide
|
||||
*/
|
||||
CheckoutSession initiateCheckout(CheckoutRequest request) throws PaymentException;
|
||||
|
||||
/**
|
||||
* Interroge le statut d'un paiement par son identifiant provider.
|
||||
*
|
||||
* @throws PaymentException si le provider est indisponible
|
||||
*/
|
||||
PaymentStatus getStatus(String externalId) throws PaymentException;
|
||||
|
||||
/**
|
||||
* Traite un webhook entrant et vérifie sa signature.
|
||||
*
|
||||
* @param rawBody payload brut HTTP body
|
||||
* @param headers en-têtes HTTP (inclut la signature)
|
||||
* @throws PaymentException si la signature est invalide ou le payload malformé
|
||||
*/
|
||||
PaymentEvent processWebhook(String rawBody, Map<String, String> headers) throws PaymentException;
|
||||
|
||||
/** Devises supportées — par défaut XOF uniquement. */
|
||||
default Set<String> getSupportedCurrencies() {
|
||||
return Set.of("XOF");
|
||||
}
|
||||
|
||||
/** Indique si ce provider supporte les remboursements. */
|
||||
default boolean supportsRefund() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Health check rapide (ping API provider). */
|
||||
default boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.lions.unionflow.server.api.payment;
|
||||
|
||||
public enum PaymentStatus {
|
||||
INITIATED,
|
||||
PROCESSING,
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
CANCELLED,
|
||||
EXPIRED
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package dev.lions.unionflow.server.api.dto.agricole;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.agricole.StatutCampagneAgricole;
|
||||
import java.math.BigDecimal;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CampagneAgricoleDTOTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new CampagneAgricoleDTO()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
CampagneAgricoleDTO dto = new CampagneAgricoleDTO();
|
||||
dto.setOrganisationCoopId("org-1");
|
||||
dto.setDesignation("Campagne Arachide 2026");
|
||||
dto.setTypeCulturePrincipale("Arachide");
|
||||
dto.setSurfaceTotaleEstimeeHectares(new BigDecimal("100.5"));
|
||||
dto.setVolumePrevisionnelTonnes(new BigDecimal("50"));
|
||||
dto.setVolumeReelTonnes(new BigDecimal("48"));
|
||||
dto.setStatut(StatutCampagneAgricole.RECOLTE);
|
||||
|
||||
assertThat(dto.getOrganisationCoopId()).isEqualTo("org-1");
|
||||
assertThat(dto.getDesignation()).isEqualTo("Campagne Arachide 2026");
|
||||
assertThat(dto.getTypeCulturePrincipale()).isEqualTo("Arachide");
|
||||
assertThat(dto.getSurfaceTotaleEstimeeHectares()).isEqualByComparingTo("100.5");
|
||||
assertThat(dto.getVolumePrevisionnelTonnes()).isEqualByComparingTo("50");
|
||||
assertThat(dto.getVolumeReelTonnes()).isEqualByComparingTo("48");
|
||||
assertThat(dto.getStatut()).isEqualTo(StatutCampagneAgricole.RECOLTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
CampagneAgricoleDTO dto = CampagneAgricoleDTO.builder()
|
||||
.designation("Test")
|
||||
.statut(StatutCampagneAgricole.PREPARATION)
|
||||
.build();
|
||||
assertThat(dto.getDesignation()).isEqualTo("Test");
|
||||
assertThat(dto.getStatut()).isEqualTo(StatutCampagneAgricole.PREPARATION);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.lions.unionflow.server.api.dto.audit.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AuditTrailOperationResponseTest {
|
||||
|
||||
@Test
|
||||
void testBuilder_AllFields() {
|
||||
UUID id = UUID.randomUUID();
|
||||
UUID userId = UUID.randomUUID();
|
||||
UUID orgId = UUID.randomUUID();
|
||||
UUID entityId = UUID.randomUUID();
|
||||
UUID requestId = UUID.randomUUID();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
AuditTrailOperationResponse r = AuditTrailOperationResponse.builder()
|
||||
.id(id).userId(userId).userEmail("a@b.com").roleActif("TRESORIER")
|
||||
.organisationActiveId(orgId)
|
||||
.actionType("PAYMENT_INITIATED").entityType("Paiement").entityId(entityId)
|
||||
.description("Paiement initié")
|
||||
.ipAddress("192.168.1.1").userAgent("Mozilla").requestId(requestId)
|
||||
.payloadAvant("{}").payloadApres("{\"k\":1}").metadata("{\"src\":\"web\"}")
|
||||
.sodCheckPassed(true).sodViolations(null)
|
||||
.operationAt(now)
|
||||
.build();
|
||||
|
||||
assertThat(r.id()).isEqualTo(id);
|
||||
assertThat(r.userId()).isEqualTo(userId);
|
||||
assertThat(r.userEmail()).isEqualTo("a@b.com");
|
||||
assertThat(r.roleActif()).isEqualTo("TRESORIER");
|
||||
assertThat(r.organisationActiveId()).isEqualTo(orgId);
|
||||
assertThat(r.actionType()).isEqualTo("PAYMENT_INITIATED");
|
||||
assertThat(r.entityType()).isEqualTo("Paiement");
|
||||
assertThat(r.entityId()).isEqualTo(entityId);
|
||||
assertThat(r.description()).isEqualTo("Paiement initié");
|
||||
assertThat(r.ipAddress()).isEqualTo("192.168.1.1");
|
||||
assertThat(r.userAgent()).isEqualTo("Mozilla");
|
||||
assertThat(r.requestId()).isEqualTo(requestId);
|
||||
assertThat(r.payloadAvant()).isEqualTo("{}");
|
||||
assertThat(r.payloadApres()).isEqualTo("{\"k\":1}");
|
||||
assertThat(r.metadata()).isEqualTo("{\"src\":\"web\"}");
|
||||
assertThat(r.sodCheckPassed()).isTrue();
|
||||
assertThat(r.sodViolations()).isNull();
|
||||
assertThat(r.operationAt()).isEqualTo(now);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder_NullFields() {
|
||||
AuditTrailOperationResponse r = AuditTrailOperationResponse.builder().build();
|
||||
assertThat(r.id()).isNull();
|
||||
assertThat(r.sodCheckPassed()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCodeToString() {
|
||||
UUID id = UUID.randomUUID();
|
||||
AuditTrailOperationResponse a = AuditTrailOperationResponse.builder().id(id).build();
|
||||
AuditTrailOperationResponse b = AuditTrailOperationResponse.builder().id(id).build();
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
assertThat(a.toString()).contains("AuditTrailOperationResponse");
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class LoginRequestTest {
|
||||
LoginRequest request = LoginRequest.builder()
|
||||
.username("test@test.com")
|
||||
.password("test123")
|
||||
.typeCompte("ADMIN_ENTITE")
|
||||
.typeCompte("ADMIN_ORGANISATION")
|
||||
.rememberMe(false)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.lions.unionflow.server.api.dto.ayantdroit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.ayantdroit.LienParente;
|
||||
import java.time.LocalDate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AyantDroitRequestTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new AyantDroitRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
AyantDroitRequest req = new AyantDroitRequest();
|
||||
req.setMembrePrincipalId("m-1");
|
||||
req.setPrenom("Alice");
|
||||
req.setNom("Dupont");
|
||||
req.setDateNaissance(LocalDate.of(2000, 1, 15));
|
||||
req.setSexe("F");
|
||||
req.setPieceIdentite("CNI-123");
|
||||
req.setLienParente(LienParente.CONJOINT);
|
||||
req.setJustificatifLienId("doc-1");
|
||||
|
||||
assertThat(req.getMembrePrincipalId()).isEqualTo("m-1");
|
||||
assertThat(req.getPrenom()).isEqualTo("Alice");
|
||||
assertThat(req.getNom()).isEqualTo("Dupont");
|
||||
assertThat(req.getDateNaissance()).isEqualTo(LocalDate.of(2000, 1, 15));
|
||||
assertThat(req.getSexe()).isEqualTo("F");
|
||||
assertThat(req.getLienParente()).isEqualTo(LienParente.CONJOINT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
AyantDroitRequest req = AyantDroitRequest.builder()
|
||||
.membrePrincipalId("m-2")
|
||||
.prenom("Bob")
|
||||
.lienParente(LienParente.ENFANT)
|
||||
.build();
|
||||
assertThat(req.getMembrePrincipalId()).isEqualTo("m-2");
|
||||
assertThat(req.getLienParente()).isEqualTo(LienParente.ENFANT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCode() {
|
||||
AyantDroitRequest r1 = AyantDroitRequest.builder().membrePrincipalId("x").prenom("A").build();
|
||||
AyantDroitRequest r2 = AyantDroitRequest.builder().membrePrincipalId("x").prenom("A").build();
|
||||
assertThat(r1).isEqualTo(r2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.lions.unionflow.server.api.dto.ayantdroit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.ayantdroit.LienParente;
|
||||
import dev.lions.unionflow.server.api.enums.ayantdroit.StatutAyantDroit;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AyantDroitResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new AyantDroitResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
AyantDroitResponse resp = new AyantDroitResponse();
|
||||
resp.setMembrePrincipalId("m-1");
|
||||
resp.setNumeroCarteBeneficiaire("CB-001");
|
||||
resp.setPrenom("Alice");
|
||||
resp.setNom("Dupont");
|
||||
resp.setDateNaissance(LocalDate.of(2000, 1, 1));
|
||||
resp.setAgeActuel(26);
|
||||
resp.setLienParente(LienParente.ENFANT);
|
||||
resp.setPourcentageCouvertureSante(new BigDecimal("80.0"));
|
||||
resp.setStatut(StatutAyantDroit.ACTIF);
|
||||
|
||||
assertThat(resp.getMembrePrincipalId()).isEqualTo("m-1");
|
||||
assertThat(resp.getNumeroCarteBeneficiaire()).isEqualTo("CB-001");
|
||||
assertThat(resp.getPrenom()).isEqualTo("Alice");
|
||||
assertThat(resp.getAgeActuel()).isEqualTo(26);
|
||||
assertThat(resp.getLienParente()).isEqualTo(LienParente.ENFANT);
|
||||
assertThat(resp.getStatut()).isEqualTo(StatutAyantDroit.ACTIF);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
AyantDroitResponse resp = AyantDroitResponse.builder()
|
||||
.prenom("Bob")
|
||||
.statut(StatutAyantDroit.INACTIF)
|
||||
.build();
|
||||
assertThat(resp.getPrenom()).isEqualTo("Bob");
|
||||
assertThat(resp.getStatut()).isEqualTo(StatutAyantDroit.INACTIF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.lions.unionflow.server.api.dto.backup.request;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DisplayName("Tests CreateBackupRequest")
|
||||
class CreateBackupRequestTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new CreateBackupRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
CreateBackupRequest req = new CreateBackupRequest();
|
||||
req.setName("backup-2026");
|
||||
req.setDescription("Full backup");
|
||||
req.setType("MANUAL");
|
||||
req.setIncludeDatabase(true);
|
||||
req.setIncludeFiles(false);
|
||||
req.setIncludeConfiguration(true);
|
||||
|
||||
assertThat(req.getName()).isEqualTo("backup-2026");
|
||||
assertThat(req.getDescription()).isEqualTo("Full backup");
|
||||
assertThat(req.getType()).isEqualTo("MANUAL");
|
||||
assertThat(req.getIncludeDatabase()).isTrue();
|
||||
assertThat(req.getIncludeFiles()).isFalse();
|
||||
assertThat(req.getIncludeConfiguration()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
CreateBackupRequest req = CreateBackupRequest.builder()
|
||||
.name("test")
|
||||
.type("AUTO")
|
||||
.includeDatabase(true)
|
||||
.build();
|
||||
assertThat(req.getName()).isEqualTo("test");
|
||||
assertThat(req.getType()).isEqualTo("AUTO");
|
||||
assertThat(req.getIncludeDatabase()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCode() {
|
||||
CreateBackupRequest r1 = CreateBackupRequest.builder().name("x").build();
|
||||
CreateBackupRequest r2 = CreateBackupRequest.builder().name("x").build();
|
||||
assertThat(r1).isEqualTo(r2);
|
||||
assertThat(r1.hashCode()).isEqualTo(r2.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.lions.unionflow.server.api.dto.backup.request;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DisplayName("Tests RestoreBackupRequest")
|
||||
class RestoreBackupRequestTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new RestoreBackupRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
UUID id = UUID.randomUUID();
|
||||
RestoreBackupRequest req = new RestoreBackupRequest();
|
||||
req.setBackupId(id);
|
||||
req.setRestoreDatabase(true);
|
||||
req.setRestoreFiles(false);
|
||||
req.setRestoreConfiguration(true);
|
||||
req.setCreateRestorePoint(false);
|
||||
|
||||
assertThat(req.getBackupId()).isEqualTo(id);
|
||||
assertThat(req.getRestoreDatabase()).isTrue();
|
||||
assertThat(req.getRestoreFiles()).isFalse();
|
||||
assertThat(req.getRestoreConfiguration()).isTrue();
|
||||
assertThat(req.getCreateRestorePoint()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
UUID id = UUID.randomUUID();
|
||||
RestoreBackupRequest req = RestoreBackupRequest.builder()
|
||||
.backupId(id)
|
||||
.restoreDatabase(true)
|
||||
.createRestorePoint(true)
|
||||
.build();
|
||||
assertThat(req.getBackupId()).isEqualTo(id);
|
||||
assertThat(req.getRestoreDatabase()).isTrue();
|
||||
assertThat(req.getCreateRestorePoint()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCode() {
|
||||
UUID id = UUID.randomUUID();
|
||||
RestoreBackupRequest r1 = RestoreBackupRequest.builder().backupId(id).build();
|
||||
RestoreBackupRequest r2 = RestoreBackupRequest.builder().backupId(id).build();
|
||||
assertThat(r1).isEqualTo(r2);
|
||||
assertThat(r1.hashCode()).isEqualTo(r2.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package dev.lions.unionflow.server.api.dto.backup.request;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DisplayName("Tests UpdateBackupConfigRequest")
|
||||
class UpdateBackupConfigRequestTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new UpdateBackupConfigRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
UpdateBackupConfigRequest req = new UpdateBackupConfigRequest();
|
||||
req.setAutoBackupEnabled(true);
|
||||
req.setFrequency("DAILY");
|
||||
req.setRetention("30 jours");
|
||||
req.setRetentionDays(30);
|
||||
req.setBackupTime("02:00");
|
||||
req.setIncludeDatabase(true);
|
||||
req.setIncludeFiles(true);
|
||||
req.setIncludeConfiguration(false);
|
||||
|
||||
assertThat(req.getAutoBackupEnabled()).isTrue();
|
||||
assertThat(req.getFrequency()).isEqualTo("DAILY");
|
||||
assertThat(req.getRetention()).isEqualTo("30 jours");
|
||||
assertThat(req.getRetentionDays()).isEqualTo(30);
|
||||
assertThat(req.getBackupTime()).isEqualTo("02:00");
|
||||
assertThat(req.getIncludeDatabase()).isTrue();
|
||||
assertThat(req.getIncludeFiles()).isTrue();
|
||||
assertThat(req.getIncludeConfiguration()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
UpdateBackupConfigRequest req = UpdateBackupConfigRequest.builder()
|
||||
.autoBackupEnabled(false)
|
||||
.frequency("WEEKLY")
|
||||
.retentionDays(90)
|
||||
.build();
|
||||
assertThat(req.getAutoBackupEnabled()).isFalse();
|
||||
assertThat(req.getFrequency()).isEqualTo("WEEKLY");
|
||||
assertThat(req.getRetentionDays()).isEqualTo(90);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package dev.lions.unionflow.server.api.dto.backup.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DisplayName("Tests BackupConfigResponse")
|
||||
class BackupConfigResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new BackupConfigResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
LocalDateTime last = LocalDateTime.now().minusDays(1);
|
||||
LocalDateTime next = LocalDateTime.now().plusDays(1);
|
||||
BackupConfigResponse resp = new BackupConfigResponse();
|
||||
resp.setAutoBackupEnabled(true);
|
||||
resp.setFrequency("DAILY");
|
||||
resp.setRetention("7 jours");
|
||||
resp.setRetentionDays(7);
|
||||
resp.setBackupTime("03:00");
|
||||
resp.setIncludeDatabase(true);
|
||||
resp.setIncludeFiles(false);
|
||||
resp.setIncludeConfiguration(true);
|
||||
resp.setLastBackup(last);
|
||||
resp.setNextScheduledBackup(next);
|
||||
resp.setTotalBackups(5);
|
||||
resp.setTotalSizeBytes(1024L);
|
||||
resp.setTotalSizeFormatted("1 KB");
|
||||
|
||||
assertThat(resp.getAutoBackupEnabled()).isTrue();
|
||||
assertThat(resp.getFrequency()).isEqualTo("DAILY");
|
||||
assertThat(resp.getRetention()).isEqualTo("7 jours");
|
||||
assertThat(resp.getRetentionDays()).isEqualTo(7);
|
||||
assertThat(resp.getBackupTime()).isEqualTo("03:00");
|
||||
assertThat(resp.getIncludeDatabase()).isTrue();
|
||||
assertThat(resp.getIncludeFiles()).isFalse();
|
||||
assertThat(resp.getLastBackup()).isEqualTo(last);
|
||||
assertThat(resp.getNextScheduledBackup()).isEqualTo(next);
|
||||
assertThat(resp.getTotalBackups()).isEqualTo(5);
|
||||
assertThat(resp.getTotalSizeBytes()).isEqualTo(1024L);
|
||||
assertThat(resp.getTotalSizeFormatted()).isEqualTo("1 KB");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
BackupConfigResponse resp = BackupConfigResponse.builder()
|
||||
.frequency("HOURLY")
|
||||
.totalBackups(10)
|
||||
.build();
|
||||
assertThat(resp.getFrequency()).isEqualTo("HOURLY");
|
||||
assertThat(resp.getTotalBackups()).isEqualTo(10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.lions.unionflow.server.api.dto.backup.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DisplayName("Tests BackupResponse")
|
||||
class BackupResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new BackupResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
UUID id = UUID.randomUUID();
|
||||
LocalDateTime created = LocalDateTime.now();
|
||||
BackupResponse resp = new BackupResponse();
|
||||
resp.setId(id);
|
||||
resp.setName("full-backup");
|
||||
resp.setDescription("Full backup");
|
||||
resp.setType("MANUAL");
|
||||
resp.setSizeBytes(2048L);
|
||||
resp.setSizeFormatted("2 KB");
|
||||
resp.setStatus("COMPLETED");
|
||||
resp.setCreatedAt(created);
|
||||
resp.setCreatedBy("admin");
|
||||
resp.setIncludesDatabase(true);
|
||||
resp.setIncludesFiles(false);
|
||||
resp.setIncludesConfiguration(true);
|
||||
resp.setFilePath("/backups/test.tar.gz");
|
||||
resp.setErrorMessage(null);
|
||||
|
||||
assertThat(resp.getId()).isEqualTo(id);
|
||||
assertThat(resp.getName()).isEqualTo("full-backup");
|
||||
assertThat(resp.getType()).isEqualTo("MANUAL");
|
||||
assertThat(resp.getSizeBytes()).isEqualTo(2048L);
|
||||
assertThat(resp.getSizeFormatted()).isEqualTo("2 KB");
|
||||
assertThat(resp.getStatus()).isEqualTo("COMPLETED");
|
||||
assertThat(resp.getCreatedAt()).isEqualTo(created);
|
||||
assertThat(resp.getCreatedBy()).isEqualTo("admin");
|
||||
assertThat(resp.getIncludesDatabase()).isTrue();
|
||||
assertThat(resp.getIncludesFiles()).isFalse();
|
||||
assertThat(resp.getFilePath()).isEqualTo("/backups/test.tar.gz");
|
||||
assertThat(resp.getErrorMessage()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
BackupResponse resp = BackupResponse.builder()
|
||||
.name("test")
|
||||
.status("PENDING")
|
||||
.build();
|
||||
assertThat(resp.getName()).isEqualTo("test");
|
||||
assertThat(resp.getStatus()).isEqualTo("PENDING");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCode() {
|
||||
BackupResponse r1 = BackupResponse.builder().name("a").build();
|
||||
BackupResponse r2 = BackupResponse.builder().name("a").build();
|
||||
assertThat(r1).isEqualTo(r2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package dev.lions.unionflow.server.api.dto.collectefonds;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.collectefonds.StatutCampagneCollecte;
|
||||
import java.math.BigDecimal;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CampagneCollecteResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new CampagneCollecteResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
CampagneCollecteResponse resp = new CampagneCollecteResponse();
|
||||
resp.setOrganisationId("org-1");
|
||||
resp.setTitre("Collecte Ramadan");
|
||||
resp.setCourteDescription("Aide aux familles");
|
||||
resp.setObjectifFinancier(new BigDecimal("1000000"));
|
||||
resp.setMontantCollecteActuel(new BigDecimal("500000"));
|
||||
resp.setNombreDonateurs(50);
|
||||
resp.setStatut(StatutCampagneCollecte.EN_COURS);
|
||||
resp.setEstPublique(true);
|
||||
|
||||
assertThat(resp.getOrganisationId()).isEqualTo("org-1");
|
||||
assertThat(resp.getTitre()).isEqualTo("Collecte Ramadan");
|
||||
assertThat(resp.getObjectifFinancier()).isEqualByComparingTo("1000000");
|
||||
assertThat(resp.getMontantCollecteActuel()).isEqualByComparingTo("500000");
|
||||
assertThat(resp.getNombreDonateurs()).isEqualTo(50);
|
||||
assertThat(resp.getStatut()).isEqualTo(StatutCampagneCollecte.EN_COURS);
|
||||
assertThat(resp.getEstPublique()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
CampagneCollecteResponse resp = CampagneCollecteResponse.builder()
|
||||
.titre("Test")
|
||||
.statut(StatutCampagneCollecte.ATTEINTE)
|
||||
.build();
|
||||
assertThat(resp.getTitre()).isEqualTo("Test");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package dev.lions.unionflow.server.api.dto.collectefonds;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ContributionCollecteDTOTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new ContributionCollecteDTO()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
ContributionCollecteDTO dto = new ContributionCollecteDTO();
|
||||
dto.setCampagneId("camp-1");
|
||||
dto.setMembreDonateurId("m-1");
|
||||
dto.setAliasDonateur("Donateur Anonyme");
|
||||
dto.setEstAnonyme(true);
|
||||
dto.setMontantSoutien(new BigDecimal("10000"));
|
||||
dto.setMessageSoutien("Bon courage");
|
||||
|
||||
assertThat(dto.getCampagneId()).isEqualTo("camp-1");
|
||||
assertThat(dto.getMembreDonateurId()).isEqualTo("m-1");
|
||||
assertThat(dto.getAliasDonateur()).isEqualTo("Donateur Anonyme");
|
||||
assertThat(dto.getEstAnonyme()).isTrue();
|
||||
assertThat(dto.getMontantSoutien()).isEqualByComparingTo("10000");
|
||||
assertThat(dto.getMessageSoutien()).isEqualTo("Bon courage");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
ContributionCollecteDTO dto = ContributionCollecteDTO.builder()
|
||||
.campagneId("c-1")
|
||||
.montantSoutien(new BigDecimal("5000"))
|
||||
.build();
|
||||
assertThat(dto.getCampagneId()).isEqualTo("c-1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package dev.lions.unionflow.server.api.dto.common;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ErrorResponseTest {
|
||||
|
||||
@Test
|
||||
void testOf_messageUniquement() {
|
||||
ErrorResponse response = ErrorResponse.of("Une erreur est survenue");
|
||||
|
||||
assertThat(response.getMessage()).isEqualTo("Une erreur est survenue");
|
||||
assertThat(response.getError()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOfError_errorUniquement() {
|
||||
ErrorResponse response = ErrorResponse.ofError("NOT_FOUND");
|
||||
|
||||
assertThat(response.getMessage()).isNull();
|
||||
assertThat(response.getError()).isEqualTo("NOT_FOUND");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructeurComplet() {
|
||||
ErrorResponse response = new ErrorResponse("Message d'erreur", "VALIDATION_ERROR");
|
||||
|
||||
assertThat(response.getMessage()).isEqualTo("Message d'erreur");
|
||||
assertThat(response.getError()).isEqualTo("VALIDATION_ERROR");
|
||||
}
|
||||
}
|
||||
@@ -40,28 +40,28 @@ class ConversationResponseTest {
|
||||
.organisationId(orgId)
|
||||
.lastMessage(lastMessage)
|
||||
.unreadCount(5)
|
||||
.isMuted(true)
|
||||
.isPinned(false)
|
||||
.isArchived(false)
|
||||
.muted(true)
|
||||
.pinned(false)
|
||||
.archived(false)
|
||||
.createdAt(createdAt)
|
||||
.updatedAt(updatedAt)
|
||||
.avatarUrl("https://example.com/avatar.jpg")
|
||||
.build();
|
||||
|
||||
assertThat(response.id()).isEqualTo(id);
|
||||
assertThat(response.name()).isEqualTo("Conversation Test");
|
||||
assertThat(response.description()).isEqualTo("Description test");
|
||||
assertThat(response.type()).isEqualTo(ConversationType.GROUP);
|
||||
assertThat(response.participantIds()).containsExactly(participant1, participant2);
|
||||
assertThat(response.organisationId()).isEqualTo(orgId);
|
||||
assertThat(response.lastMessage()).isEqualTo(lastMessage);
|
||||
assertThat(response.unreadCount()).isEqualTo(5);
|
||||
assertThat(response.getId()).isEqualTo(id);
|
||||
assertThat(response.getName()).isEqualTo("Conversation Test");
|
||||
assertThat(response.getDescription()).isEqualTo("Description test");
|
||||
assertThat(response.getType()).isEqualTo(ConversationType.GROUP);
|
||||
assertThat(response.getParticipantIds()).containsExactly(participant1, participant2);
|
||||
assertThat(response.getOrganisationId()).isEqualTo(orgId);
|
||||
assertThat(response.getLastMessage()).isEqualTo(lastMessage);
|
||||
assertThat(response.getUnreadCount()).isEqualTo(5);
|
||||
assertThat(response.isMuted()).isTrue();
|
||||
assertThat(response.isPinned()).isFalse();
|
||||
assertThat(response.isArchived()).isFalse();
|
||||
assertThat(response.createdAt()).isEqualTo(createdAt);
|
||||
assertThat(response.updatedAt()).isEqualTo(updatedAt);
|
||||
assertThat(response.avatarUrl()).isEqualTo("https://example.com/avatar.jpg");
|
||||
assertThat(response.getCreatedAt()).isEqualTo(createdAt);
|
||||
assertThat(response.getUpdatedAt()).isEqualTo(updatedAt);
|
||||
assertThat(response.getAvatarUrl()).isEqualTo("https://example.com/avatar.jpg");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,20 +69,20 @@ class ConversationResponseTest {
|
||||
void testBuilderWithNulls() {
|
||||
ConversationResponse response = ConversationResponse.builder().build();
|
||||
|
||||
assertThat(response.id()).isNull();
|
||||
assertThat(response.name()).isNull();
|
||||
assertThat(response.description()).isNull();
|
||||
assertThat(response.type()).isNull();
|
||||
assertThat(response.participantIds()).isNull();
|
||||
assertThat(response.organisationId()).isNull();
|
||||
assertThat(response.lastMessage()).isNull();
|
||||
assertThat(response.unreadCount()).isEqualTo(0);
|
||||
assertThat(response.getId()).isNull();
|
||||
assertThat(response.getName()).isNull();
|
||||
assertThat(response.getDescription()).isNull();
|
||||
assertThat(response.getType()).isNull();
|
||||
assertThat(response.getParticipantIds()).isNull();
|
||||
assertThat(response.getOrganisationId()).isNull();
|
||||
assertThat(response.getLastMessage()).isNull();
|
||||
assertThat(response.getUnreadCount()).isEqualTo(0);
|
||||
assertThat(response.isMuted()).isFalse();
|
||||
assertThat(response.isPinned()).isFalse();
|
||||
assertThat(response.isArchived()).isFalse();
|
||||
assertThat(response.createdAt()).isNull();
|
||||
assertThat(response.updatedAt()).isNull();
|
||||
assertThat(response.avatarUrl()).isNull();
|
||||
assertThat(response.getCreatedAt()).isNull();
|
||||
assertThat(response.getUpdatedAt()).isNull();
|
||||
assertThat(response.getAvatarUrl()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -51,28 +51,28 @@ class MessageResponseTest {
|
||||
.createdAt(createdAt)
|
||||
.readAt(readAt)
|
||||
.attachments(List.of("file1.pdf", "file2.png"))
|
||||
.isEdited(true)
|
||||
.edited(true)
|
||||
.editedAt(editedAt)
|
||||
.isDeleted(false)
|
||||
.deleted(false)
|
||||
.build();
|
||||
|
||||
assertThat(response.id()).isEqualTo(id);
|
||||
assertThat(response.conversationId()).isEqualTo(conversationId);
|
||||
assertThat(response.senderId()).isEqualTo(senderId);
|
||||
assertThat(response.senderName()).isEqualTo("John Doe");
|
||||
assertThat(response.senderAvatar()).isEqualTo("https://example.com/avatar.jpg");
|
||||
assertThat(response.content()).isEqualTo("Message content");
|
||||
assertThat(response.type()).isEqualTo(MessageType.INDIVIDUAL);
|
||||
assertThat(response.status()).isEqualTo(MessageStatus.READ);
|
||||
assertThat(response.priority()).isEqualTo(MessagePriority.HIGH);
|
||||
assertThat(response.recipientIds()).containsExactly(recipient1, recipient2);
|
||||
assertThat(response.recipientRoles()).containsExactly("ADMIN", "USER");
|
||||
assertThat(response.organisationId()).isEqualTo(orgId);
|
||||
assertThat(response.createdAt()).isEqualTo(createdAt);
|
||||
assertThat(response.readAt()).isEqualTo(readAt);
|
||||
assertThat(response.attachments()).containsExactly("file1.pdf", "file2.png");
|
||||
assertThat(response.getId()).isEqualTo(id);
|
||||
assertThat(response.getConversationId()).isEqualTo(conversationId);
|
||||
assertThat(response.getSenderId()).isEqualTo(senderId);
|
||||
assertThat(response.getSenderName()).isEqualTo("John Doe");
|
||||
assertThat(response.getSenderAvatar()).isEqualTo("https://example.com/avatar.jpg");
|
||||
assertThat(response.getContent()).isEqualTo("Message content");
|
||||
assertThat(response.getType()).isEqualTo(MessageType.INDIVIDUAL);
|
||||
assertThat(response.getStatus()).isEqualTo(MessageStatus.READ);
|
||||
assertThat(response.getPriority()).isEqualTo(MessagePriority.HIGH);
|
||||
assertThat(response.getRecipientIds()).containsExactly(recipient1, recipient2);
|
||||
assertThat(response.getRecipientRoles()).containsExactly("ADMIN", "USER");
|
||||
assertThat(response.getOrganisationId()).isEqualTo(orgId);
|
||||
assertThat(response.getCreatedAt()).isEqualTo(createdAt);
|
||||
assertThat(response.getReadAt()).isEqualTo(readAt);
|
||||
assertThat(response.getAttachments()).containsExactly("file1.pdf", "file2.png");
|
||||
assertThat(response.isEdited()).isTrue();
|
||||
assertThat(response.editedAt()).isEqualTo(editedAt);
|
||||
assertThat(response.getEditedAt()).isEqualTo(editedAt);
|
||||
assertThat(response.isDeleted()).isFalse();
|
||||
}
|
||||
|
||||
@@ -81,23 +81,23 @@ class MessageResponseTest {
|
||||
void testBuilderWithNulls() {
|
||||
MessageResponse response = MessageResponse.builder().build();
|
||||
|
||||
assertThat(response.id()).isNull();
|
||||
assertThat(response.conversationId()).isNull();
|
||||
assertThat(response.senderId()).isNull();
|
||||
assertThat(response.senderName()).isNull();
|
||||
assertThat(response.senderAvatar()).isNull();
|
||||
assertThat(response.content()).isNull();
|
||||
assertThat(response.type()).isNull();
|
||||
assertThat(response.status()).isNull();
|
||||
assertThat(response.priority()).isNull();
|
||||
assertThat(response.recipientIds()).isNull();
|
||||
assertThat(response.recipientRoles()).isNull();
|
||||
assertThat(response.organisationId()).isNull();
|
||||
assertThat(response.createdAt()).isNull();
|
||||
assertThat(response.readAt()).isNull();
|
||||
assertThat(response.attachments()).isNull();
|
||||
assertThat(response.getId()).isNull();
|
||||
assertThat(response.getConversationId()).isNull();
|
||||
assertThat(response.getSenderId()).isNull();
|
||||
assertThat(response.getSenderName()).isNull();
|
||||
assertThat(response.getSenderAvatar()).isNull();
|
||||
assertThat(response.getContent()).isNull();
|
||||
assertThat(response.getType()).isNull();
|
||||
assertThat(response.getStatus()).isNull();
|
||||
assertThat(response.getPriority()).isNull();
|
||||
assertThat(response.getRecipientIds()).isNull();
|
||||
assertThat(response.getRecipientRoles()).isNull();
|
||||
assertThat(response.getOrganisationId()).isNull();
|
||||
assertThat(response.getCreatedAt()).isNull();
|
||||
assertThat(response.getReadAt()).isNull();
|
||||
assertThat(response.getAttachments()).isNull();
|
||||
assertThat(response.isEdited()).isFalse();
|
||||
assertThat(response.editedAt()).isNull();
|
||||
assertThat(response.getEditedAt()).isNull();
|
||||
assertThat(response.isDeleted()).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.lions.unionflow.server.api.dto.compliance.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class KpiPublicSnapshotTest {
|
||||
|
||||
@Test
|
||||
void testBuilder_AllFields() {
|
||||
LocalDateTime now = LocalDateTime.of(2026, 4, 25, 12, 0);
|
||||
KpiPublicSnapshot s = KpiPublicSnapshot.builder()
|
||||
.organisationNom("Mutuelle Test")
|
||||
.referentielComptable("SYCEBNL")
|
||||
.scoreGlobal(82)
|
||||
.complianceOfficerDesigne(true)
|
||||
.agAnnuelleStatut("OK")
|
||||
.rapportAirmsStatut("EN_ATTENTE")
|
||||
.dirigeantsAvecCmu(3)
|
||||
.tauxKycAJourPct(new BigDecimal("85.5"))
|
||||
.tauxFormationLbcFtPct(new BigDecimal("70.0"))
|
||||
.couvertureUboPct(new BigDecimal("60.0"))
|
||||
.commissaireAuxComptesStatut("OPTIONNEL")
|
||||
.dateGeneration(now)
|
||||
.build();
|
||||
|
||||
assertThat(s.organisationNom()).isEqualTo("Mutuelle Test");
|
||||
assertThat(s.referentielComptable()).isEqualTo("SYCEBNL");
|
||||
assertThat(s.scoreGlobal()).isEqualTo(82);
|
||||
assertThat(s.complianceOfficerDesigne()).isTrue();
|
||||
assertThat(s.agAnnuelleStatut()).isEqualTo("OK");
|
||||
assertThat(s.rapportAirmsStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(s.dirigeantsAvecCmu()).isEqualTo(3);
|
||||
assertThat(s.tauxKycAJourPct()).isEqualByComparingTo("85.5");
|
||||
assertThat(s.tauxFormationLbcFtPct()).isEqualByComparingTo("70.0");
|
||||
assertThat(s.couvertureUboPct()).isEqualByComparingTo("60.0");
|
||||
assertThat(s.commissaireAuxComptesStatut()).isEqualTo("OPTIONNEL");
|
||||
assertThat(s.dateGeneration()).isEqualTo(now);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder_NullDefaults() {
|
||||
KpiPublicSnapshot empty = KpiPublicSnapshot.builder().build();
|
||||
assertThat(empty.organisationNom()).isNull();
|
||||
assertThat(empty.scoreGlobal()).isZero();
|
||||
assertThat(empty.complianceOfficerDesigne()).isFalse();
|
||||
assertThat(empty.dirigeantsAvecCmu()).isZero();
|
||||
assertThat(empty.tauxKycAJourPct()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCodeToString() {
|
||||
LocalDateTime t = LocalDateTime.of(2026, 4, 25, 10, 0);
|
||||
KpiPublicSnapshot a = KpiPublicSnapshot.builder()
|
||||
.organisationNom("Org").scoreGlobal(80).dateGeneration(t).build();
|
||||
KpiPublicSnapshot b = KpiPublicSnapshot.builder()
|
||||
.organisationNom("Org").scoreGlobal(80).dateGeneration(t).build();
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
assertThat(a.toString()).contains("KpiPublicSnapshot");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.lions.unionflow.server.api.dto.comptabilite.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
|
||||
import java.math.BigDecimal;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CompteComptableResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new CompteComptableResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
CompteComptableResponse resp = new CompteComptableResponse();
|
||||
resp.setNumeroCompte("401000");
|
||||
resp.setLibelle("Fournisseurs");
|
||||
resp.setTypeCompte(TypeCompteComptable.PASSIF);
|
||||
resp.setClasseComptable(4);
|
||||
resp.setSoldeInitial(new BigDecimal("0"));
|
||||
resp.setSoldeActuel(new BigDecimal("500000"));
|
||||
resp.setCompteCollectif(true);
|
||||
resp.setCompteAnalytique(false);
|
||||
resp.setDescription("Compte fournisseurs");
|
||||
|
||||
assertThat(resp.getNumeroCompte()).isEqualTo("401000");
|
||||
assertThat(resp.getLibelle()).isEqualTo("Fournisseurs");
|
||||
assertThat(resp.getTypeCompte()).isEqualTo(TypeCompteComptable.PASSIF);
|
||||
assertThat(resp.getClasseComptable()).isEqualTo(4);
|
||||
assertThat(resp.getSoldeActuel()).isEqualByComparingTo("500000");
|
||||
assertThat(resp.getCompteCollectif()).isTrue();
|
||||
assertThat(resp.getCompteAnalytique()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
CompteComptableResponse resp = CompteComptableResponse.builder()
|
||||
.numeroCompte("501000")
|
||||
.typeCompte(TypeCompteComptable.ACTIF)
|
||||
.build();
|
||||
assertThat(resp.getNumeroCompte()).isEqualTo("501000");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.lions.unionflow.server.api.dto.comptabilite.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class EcritureComptableResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new EcritureComptableResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
UUID journalId = UUID.randomUUID();
|
||||
EcritureComptableResponse resp = new EcritureComptableResponse();
|
||||
resp.setNumeroPiece("PIECE-001");
|
||||
resp.setDateEcriture(LocalDate.of(2026, 1, 15));
|
||||
resp.setLibelle("Cotisation membre");
|
||||
resp.setReference("REF-001");
|
||||
resp.setPointe(false);
|
||||
resp.setMontantDebit(new BigDecimal("50000"));
|
||||
resp.setMontantCredit(new BigDecimal("50000"));
|
||||
resp.setJournalId(journalId);
|
||||
resp.setLignes(List.of());
|
||||
|
||||
assertThat(resp.getNumeroPiece()).isEqualTo("PIECE-001");
|
||||
assertThat(resp.getDateEcriture()).isEqualTo(LocalDate.of(2026, 1, 15));
|
||||
assertThat(resp.getLibelle()).isEqualTo("Cotisation membre");
|
||||
assertThat(resp.getMontantDebit()).isEqualByComparingTo("50000");
|
||||
assertThat(resp.getJournalId()).isEqualTo(journalId);
|
||||
assertThat(resp.getLignes()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
EcritureComptableResponse resp = EcritureComptableResponse.builder()
|
||||
.numeroPiece("P-002")
|
||||
.montantDebit(new BigDecimal("1000"))
|
||||
.build();
|
||||
assertThat(resp.getNumeroPiece()).isEqualTo("P-002");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package dev.lions.unionflow.server.api.dto.comptabilite.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
|
||||
import java.time.LocalDate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class JournalComptableResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new JournalComptableResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
JournalComptableResponse resp = new JournalComptableResponse();
|
||||
resp.setCode("JC-001");
|
||||
resp.setLibelle("Journal Caisse");
|
||||
resp.setTypeJournal(TypeJournalComptable.CAISSE);
|
||||
resp.setDateDebut(LocalDate.of(2026, 1, 1));
|
||||
resp.setDateFin(LocalDate.of(2026, 12, 31));
|
||||
resp.setStatut("OUVERT");
|
||||
resp.setDescription("Journal de caisse principale");
|
||||
|
||||
assertThat(resp.getCode()).isEqualTo("JC-001");
|
||||
assertThat(resp.getLibelle()).isEqualTo("Journal Caisse");
|
||||
assertThat(resp.getTypeJournal()).isEqualTo(TypeJournalComptable.CAISSE);
|
||||
assertThat(resp.getStatut()).isEqualTo("OUVERT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
JournalComptableResponse resp = JournalComptableResponse.builder()
|
||||
.code("JB-001")
|
||||
.typeJournal(TypeJournalComptable.BANQUE)
|
||||
.build();
|
||||
assertThat(resp.getCode()).isEqualTo("JB-001");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.lions.unionflow.server.api.dto.comptabilite.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LigneEcritureResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new LigneEcritureResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
UUID ecritureId = UUID.randomUUID();
|
||||
UUID compteId = UUID.randomUUID();
|
||||
LigneEcritureResponse resp = new LigneEcritureResponse();
|
||||
resp.setNumeroLigne(1);
|
||||
resp.setMontantDebit(new BigDecimal("25000"));
|
||||
resp.setMontantCredit(BigDecimal.ZERO);
|
||||
resp.setLibelle("Ligne débit");
|
||||
resp.setReference("REF-L1");
|
||||
resp.setEcritureId(ecritureId);
|
||||
resp.setCompteComptableId(compteId);
|
||||
|
||||
assertThat(resp.getNumeroLigne()).isEqualTo(1);
|
||||
assertThat(resp.getMontantDebit()).isEqualByComparingTo("25000");
|
||||
assertThat(resp.getLibelle()).isEqualTo("Ligne débit");
|
||||
assertThat(resp.getEcritureId()).isEqualTo(ecritureId);
|
||||
assertThat(resp.getCompteComptableId()).isEqualTo(compteId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
LigneEcritureResponse resp = LigneEcritureResponse.builder()
|
||||
.numeroLigne(2)
|
||||
.montantCredit(new BigDecimal("25000"))
|
||||
.build();
|
||||
assertThat(resp.getNumeroLigne()).isEqualTo(2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.lions.unionflow.server.api.dto.config.request;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ParametresLcbFtRequestTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new ParametresLcbFtRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
ParametresLcbFtRequest req = new ParametresLcbFtRequest();
|
||||
req.setOrganisationId("org-1");
|
||||
req.setMontantSeuilJustification(new BigDecimal("500000"));
|
||||
req.setMontantSeuilValidationManuelle(new BigDecimal("1000000"));
|
||||
req.setCodeDevise("XOF");
|
||||
req.setNotes("Paramètres UEMOA");
|
||||
|
||||
assertThat(req.getOrganisationId()).isEqualTo("org-1");
|
||||
assertThat(req.getMontantSeuilJustification()).isEqualByComparingTo("500000");
|
||||
assertThat(req.getMontantSeuilValidationManuelle()).isEqualByComparingTo("1000000");
|
||||
assertThat(req.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(req.getNotes()).isEqualTo("Paramètres UEMOA");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
ParametresLcbFtRequest req = ParametresLcbFtRequest.builder()
|
||||
.codeDevise("XOF")
|
||||
.montantSeuilJustification(new BigDecimal("300000"))
|
||||
.build();
|
||||
assertThat(req.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCode() {
|
||||
ParametresLcbFtRequest r1 = ParametresLcbFtRequest.builder().codeDevise("XOF").build();
|
||||
ParametresLcbFtRequest r2 = ParametresLcbFtRequest.builder().codeDevise("XOF").build();
|
||||
assertThat(r1).isEqualTo(r2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.lions.unionflow.server.api.dto.config.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ConfigurationResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new ConfigurationResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
ConfigurationResponse resp = new ConfigurationResponse();
|
||||
resp.setCle("smtp.host");
|
||||
resp.setValeur("mail.example.com");
|
||||
resp.setType("STRING");
|
||||
resp.setCategorie("EMAIL");
|
||||
resp.setDescription("Serveur SMTP");
|
||||
resp.setModifiable(true);
|
||||
resp.setVisible(true);
|
||||
resp.setMetadonnees(Map.of("env", "prod"));
|
||||
|
||||
assertThat(resp.getCle()).isEqualTo("smtp.host");
|
||||
assertThat(resp.getValeur()).isEqualTo("mail.example.com");
|
||||
assertThat(resp.getType()).isEqualTo("STRING");
|
||||
assertThat(resp.getCategorie()).isEqualTo("EMAIL");
|
||||
assertThat(resp.getModifiable()).isTrue();
|
||||
assertThat(resp.getMetadonnees()).containsEntry("env", "prod");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
ConfigurationResponse resp = ConfigurationResponse.builder()
|
||||
.cle("key1")
|
||||
.valeur("val1")
|
||||
.build();
|
||||
assertThat(resp.getCle()).isEqualTo("key1");
|
||||
assertThat(resp.getValeur()).isEqualTo("val1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.lions.unionflow.server.api.dto.config.response;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ParametresLcbFtResponseTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new ParametresLcbFtResponse()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
ParametresLcbFtResponse resp = new ParametresLcbFtResponse();
|
||||
resp.setOrganisationId("org-1");
|
||||
resp.setOrganisationNom("Association Test");
|
||||
resp.setMontantSeuilJustification(new BigDecimal("500000"));
|
||||
resp.setMontantSeuilValidationManuelle(new BigDecimal("1000000"));
|
||||
resp.setCodeDevise("XOF");
|
||||
resp.setNotes("Notes");
|
||||
resp.setEstParametrePlateforme(false);
|
||||
|
||||
assertThat(resp.getOrganisationId()).isEqualTo("org-1");
|
||||
assertThat(resp.getOrganisationNom()).isEqualTo("Association Test");
|
||||
assertThat(resp.getMontantSeuilJustification()).isEqualByComparingTo("500000");
|
||||
assertThat(resp.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(resp.getEstParametrePlateforme()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
ParametresLcbFtResponse resp = ParametresLcbFtResponse.builder()
|
||||
.codeDevise("XOF")
|
||||
.estParametrePlateforme(true)
|
||||
.build();
|
||||
assertThat(resp.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(resp.getEstParametrePlateforme()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -228,6 +228,28 @@ class CotisationResponseTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Alias getMethodePaiementLibelle")
|
||||
class AliasMethodePaiement {
|
||||
|
||||
@Test
|
||||
@DisplayName("getMethodePaiementLibelle retourne modePaiementLibelle")
|
||||
void getMethodePaiementLibelle_retourneModePaiementLibelle() {
|
||||
CotisationResponse r = CotisationResponse.builder()
|
||||
.modePaiementLibelle("Wave Money")
|
||||
.build();
|
||||
|
||||
assertThat(r.getMethodePaiementLibelle()).isEqualTo("Wave Money");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getMethodePaiementLibelle retourne null si non renseigné")
|
||||
void getMethodePaiementLibelle_null() {
|
||||
CotisationResponse r = CotisationResponse.builder().build();
|
||||
assertThat(r.getMethodePaiementLibelle()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Builder complet")
|
||||
class BuilderComplet {
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour CotisationSummaryResponse (record).
|
||||
* Tests unitaires pour CotisationSummaryResponse.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
@@ -51,16 +51,16 @@ class CotisationSummaryResponseTest {
|
||||
);
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.id()).isEqualTo(id);
|
||||
assertThat(response.numeroReference()).isEqualTo("COT-2026-001");
|
||||
assertThat(response.nomMembre()).isEqualTo("Jean Dupont");
|
||||
assertThat(response.montantDu()).isEqualTo(new BigDecimal("50000.00"));
|
||||
assertThat(response.montantPaye()).isEqualTo(new BigDecimal("30000.00"));
|
||||
assertThat(response.statut()).isEqualTo("EN_COURS");
|
||||
assertThat(response.statutLibelle()).isEqualTo("Paiement en cours");
|
||||
assertThat(response.dateEcheance()).isEqualTo(LocalDate.of(2026, 12, 31));
|
||||
assertThat(response.annee()).isEqualTo(2026);
|
||||
assertThat(response.actif()).isTrue();
|
||||
assertThat(response.getId()).isEqualTo(id);
|
||||
assertThat(response.getNumeroReference()).isEqualTo("COT-2026-001");
|
||||
assertThat(response.getNomMembre()).isEqualTo("Jean Dupont");
|
||||
assertThat(response.getMontantDu()).isEqualTo(new BigDecimal("50000.00"));
|
||||
assertThat(response.getMontantPaye()).isEqualTo(new BigDecimal("30000.00"));
|
||||
assertThat(response.getStatut()).isEqualTo("EN_COURS");
|
||||
assertThat(response.getStatutLibelle()).isEqualTo("Paiement en cours");
|
||||
assertThat(response.getDateEcheance()).isEqualTo(LocalDate.of(2026, 12, 31));
|
||||
assertThat(response.getAnnee()).isEqualTo(2026);
|
||||
assertThat(response.getActif()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -80,16 +80,16 @@ class CotisationSummaryResponseTest {
|
||||
);
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.id()).isNull();
|
||||
assertThat(response.numeroReference()).isNull();
|
||||
assertThat(response.nomMembre()).isNull();
|
||||
assertThat(response.montantDu()).isNull();
|
||||
assertThat(response.montantPaye()).isNull();
|
||||
assertThat(response.statut()).isNull();
|
||||
assertThat(response.statutLibelle()).isNull();
|
||||
assertThat(response.dateEcheance()).isNull();
|
||||
assertThat(response.annee()).isNull();
|
||||
assertThat(response.actif()).isNull();
|
||||
assertThat(response.getId()).isNull();
|
||||
assertThat(response.getNumeroReference()).isNull();
|
||||
assertThat(response.getNomMembre()).isNull();
|
||||
assertThat(response.getMontantDu()).isNull();
|
||||
assertThat(response.getMontantPaye()).isNull();
|
||||
assertThat(response.getStatut()).isNull();
|
||||
assertThat(response.getStatutLibelle()).isNull();
|
||||
assertThat(response.getDateEcheance()).isNull();
|
||||
assertThat(response.getAnnee()).isNull();
|
||||
assertThat(response.getActif()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,8 +213,8 @@ class CotisationSummaryResponseTest {
|
||||
true
|
||||
);
|
||||
|
||||
assertThat(response.montantDu()).isEqualTo(response.montantPaye());
|
||||
assertThat(response.statut()).isEqualTo("PAYE");
|
||||
assertThat(response.getMontantDu()).isEqualTo(response.getMontantPaye());
|
||||
assertThat(response.getStatut()).isEqualTo("PAYE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -233,8 +233,8 @@ class CotisationSummaryResponseTest {
|
||||
true
|
||||
);
|
||||
|
||||
assertThat(response.montantPaye()).isLessThan(response.montantDu());
|
||||
assertThat(response.statut()).isEqualTo("EN_COURS");
|
||||
assertThat(response.getMontantPaye()).isLessThan(response.getMontantDu());
|
||||
assertThat(response.getStatut()).isEqualTo("EN_COURS");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -253,8 +253,8 @@ class CotisationSummaryResponseTest {
|
||||
true
|
||||
);
|
||||
|
||||
assertThat(response.montantPaye()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(response.statut()).isEqualTo("IMPAYE");
|
||||
assertThat(response.getMontantPaye()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(response.getStatut()).isEqualTo("IMPAYE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -275,8 +275,8 @@ class CotisationSummaryResponseTest {
|
||||
true
|
||||
);
|
||||
|
||||
assertThat(response.dateEcheance()).isBefore(LocalDate.now());
|
||||
assertThat(response.statut()).isEqualTo("RETARD");
|
||||
assertThat(response.getDateEcheance()).isBefore(LocalDate.now());
|
||||
assertThat(response.getStatut()).isEqualTo("RETARD");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.lions.unionflow.server.api.dto.culte;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.culte.TypeDonReligieux;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DonReligieuxDTOTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new DonReligieuxDTO()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
LocalDateTime date = LocalDateTime.now();
|
||||
DonReligieuxDTO dto = new DonReligieuxDTO();
|
||||
dto.setInstitutionId("mosque-1");
|
||||
dto.setFideleId("m-1");
|
||||
dto.setTypeDon(TypeDonReligieux.ZAKAT);
|
||||
dto.setMontant(new BigDecimal("25000"));
|
||||
dto.setDateEncaissement(date);
|
||||
dto.setPeriodeOuNatureAssociee("Ramadan 2026");
|
||||
|
||||
assertThat(dto.getInstitutionId()).isEqualTo("mosque-1");
|
||||
assertThat(dto.getFideleId()).isEqualTo("m-1");
|
||||
assertThat(dto.getTypeDon()).isEqualTo(TypeDonReligieux.ZAKAT);
|
||||
assertThat(dto.getMontant()).isEqualByComparingTo("25000");
|
||||
assertThat(dto.getDateEncaissement()).isEqualTo(date);
|
||||
assertThat(dto.getPeriodeOuNatureAssociee()).isEqualTo("Ramadan 2026");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
DonReligieuxDTO dto = DonReligieuxDTO.builder()
|
||||
.institutionId("church-1")
|
||||
.typeDon(TypeDonReligieux.DIME)
|
||||
.build();
|
||||
assertThat(dto.getInstitutionId()).isEqualTo("church-1");
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import org.junit.jupiter.api.Test;
|
||||
class MembreDashboardSyntheseResponseTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Record MembreDashboardSyntheseResponse : construction et accesseurs")
|
||||
void record_constructionAndAccessors() {
|
||||
@DisplayName("MembreDashboardSyntheseResponse : construction et getters")
|
||||
void constructionAndGetters() {
|
||||
MembreDashboardSyntheseResponse dto = new MembreDashboardSyntheseResponse(
|
||||
"Jean",
|
||||
"Dupont",
|
||||
@@ -35,20 +35,20 @@ class MembreDashboardSyntheseResponseTest {
|
||||
100
|
||||
);
|
||||
|
||||
assertThat(dto.prenom()).isEqualTo("Jean");
|
||||
assertThat(dto.nom()).isEqualTo("Dupont");
|
||||
assertThat(dto.dateInscription()).isEqualTo(LocalDate.of(2023, 1, 15));
|
||||
assertThat(dto.mesCotisationsPaiement()).isEqualByComparingTo(BigDecimal.valueOf(50000));
|
||||
assertThat(dto.totalCotisationsPayeesAnnee()).isEqualByComparingTo(BigDecimal.valueOf(150000));
|
||||
assertThat(dto.totalCotisationsPayeesToutTemps()).isEqualByComparingTo(BigDecimal.valueOf(200000));
|
||||
assertThat(dto.nombreCotisationsPayees()).isEqualTo(5);
|
||||
assertThat(dto.statutCotisations()).isEqualTo("À jour");
|
||||
assertThat(dto.tauxCotisationsPerso()).isEqualTo(100);
|
||||
assertThat(dto.monSoldeEpargne()).isEqualByComparingTo(BigDecimal.valueOf(250000));
|
||||
assertThat(dto.objectifEpargne()).isEqualTo(500000);
|
||||
assertThat(dto.mesEvenementsInscrits()).isEqualTo(3);
|
||||
assertThat(dto.tauxParticipationPerso()).isEqualTo(75);
|
||||
assertThat(dto.mesDemandesAide()).isEqualTo(1);
|
||||
assertThat(dto.tauxAidesApprouvees()).isEqualTo(100);
|
||||
assertThat(dto.getPrenom()).isEqualTo("Jean");
|
||||
assertThat(dto.getNom()).isEqualTo("Dupont");
|
||||
assertThat(dto.getDateInscription()).isEqualTo(LocalDate.of(2023, 1, 15));
|
||||
assertThat(dto.getMesCotisationsPaiement()).isEqualByComparingTo(BigDecimal.valueOf(50000));
|
||||
assertThat(dto.getTotalCotisationsPayeesAnnee()).isEqualByComparingTo(BigDecimal.valueOf(150000));
|
||||
assertThat(dto.getTotalCotisationsPayeesToutTemps()).isEqualByComparingTo(BigDecimal.valueOf(200000));
|
||||
assertThat(dto.getNombreCotisationsPayees()).isEqualTo(5);
|
||||
assertThat(dto.getStatutCotisations()).isEqualTo("À jour");
|
||||
assertThat(dto.getTauxCotisationsPerso()).isEqualTo(100);
|
||||
assertThat(dto.getMonSoldeEpargne()).isEqualByComparingTo(BigDecimal.valueOf(250000));
|
||||
assertThat(dto.getObjectifEpargne()).isEqualTo(500000);
|
||||
assertThat(dto.getMesEvenementsInscrits()).isEqualTo(3);
|
||||
assertThat(dto.getTauxParticipationPerso()).isEqualTo(75);
|
||||
assertThat(dto.getMesDemandesAide()).isEqualTo(1);
|
||||
assertThat(dto.getTauxAidesApprouvees()).isEqualTo(100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package dev.lions.unionflow.server.api.dto.dashboard;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MonthlyStatDTOTest {
|
||||
|
||||
@Test
|
||||
void testConstructeurParDefaut() {
|
||||
assertThat(new MonthlyStatDTO()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSettersEtGetters() {
|
||||
MonthlyStatDTO dto = new MonthlyStatDTO();
|
||||
dto.setMonth("2026-01");
|
||||
dto.setTotalMembers(150);
|
||||
dto.setActiveMembers(120);
|
||||
dto.setContributionAmount(500000.0);
|
||||
dto.setEventsCount(3);
|
||||
dto.setEngagementRate(80.0);
|
||||
dto.setNewMembers(10);
|
||||
dto.setContributionsCount(100);
|
||||
|
||||
assertThat(dto.getMonth()).isEqualTo("2026-01");
|
||||
assertThat(dto.getTotalMembers()).isEqualTo(150);
|
||||
assertThat(dto.getActiveMembers()).isEqualTo(120);
|
||||
assertThat(dto.getContributionAmount()).isEqualTo(500000.0);
|
||||
assertThat(dto.getEventsCount()).isEqualTo(3);
|
||||
assertThat(dto.getEngagementRate()).isEqualTo(80.0);
|
||||
assertThat(dto.getNewMembers()).isEqualTo(10);
|
||||
assertThat(dto.getContributionsCount()).isEqualTo(100);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
MonthlyStatDTO dto = MonthlyStatDTO.builder()
|
||||
.month("2026-03")
|
||||
.totalMembers(200)
|
||||
.contributionAmount(750000.0)
|
||||
.build();
|
||||
assertThat(dto.getMonth()).isEqualTo("2026-03");
|
||||
assertThat(dto.getTotalMembers()).isEqualTo(200);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCode() {
|
||||
MonthlyStatDTO d1 = MonthlyStatDTO.builder().month("2026-01").totalMembers(100).build();
|
||||
MonthlyStatDTO d2 = MonthlyStatDTO.builder().month("2026-01").totalMembers(100).build();
|
||||
assertThat(d1).isEqualTo(d2);
|
||||
assertThat(d1.hashCode()).isEqualTo(d2.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package dev.lions.unionflow.server.api.dto.delegation.request;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CreateRoleDelegationRequestTest {
|
||||
|
||||
private Validator validator;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
|
||||
validator = factory.getValidator();
|
||||
}
|
||||
|
||||
private CreateRoleDelegationRequest.CreateRoleDelegationRequestBuilder valide() {
|
||||
return CreateRoleDelegationRequest.builder()
|
||||
.organisationId(UUID.randomUUID())
|
||||
.delegantUserId(UUID.randomUUID())
|
||||
.delegataireUserId(UUID.randomUUID())
|
||||
.roleDelegue("TRESORIER")
|
||||
.dateDebut(LocalDateTime.now().plusHours(1))
|
||||
.dateFin(LocalDateTime.now().plusDays(14));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder_AllFields() {
|
||||
UUID org = UUID.randomUUID();
|
||||
UUID delegant = UUID.randomUUID();
|
||||
UUID delegataire = UUID.randomUUID();
|
||||
LocalDateTime debut = LocalDateTime.of(2026, 5, 1, 9, 0);
|
||||
LocalDateTime fin = LocalDateTime.of(2026, 5, 15, 18, 0);
|
||||
|
||||
CreateRoleDelegationRequest req = CreateRoleDelegationRequest.builder()
|
||||
.organisationId(org).delegantUserId(delegant).delegataireUserId(delegataire)
|
||||
.roleDelegue("TRESORIER").dateDebut(debut).dateFin(fin).motif("Congé")
|
||||
.build();
|
||||
|
||||
assertThat(req.organisationId()).isEqualTo(org);
|
||||
assertThat(req.delegantUserId()).isEqualTo(delegant);
|
||||
assertThat(req.delegataireUserId()).isEqualTo(delegataire);
|
||||
assertThat(req.roleDelegue()).isEqualTo("TRESORIER");
|
||||
assertThat(req.dateDebut()).isEqualTo(debut);
|
||||
assertThat(req.dateFin()).isEqualTo(fin);
|
||||
assertThat(req.motif()).isEqualTo("Congé");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidation_ChampsObligatoires() {
|
||||
CreateRoleDelegationRequest req = CreateRoleDelegationRequest.builder().build();
|
||||
Set<ConstraintViolation<CreateRoleDelegationRequest>> v = validator.validate(req);
|
||||
assertThat(v).anyMatch(x -> x.getPropertyPath().toString().equals("organisationId"));
|
||||
assertThat(v).anyMatch(x -> x.getPropertyPath().toString().equals("delegantUserId"));
|
||||
assertThat(v).anyMatch(x -> x.getPropertyPath().toString().equals("delegataireUserId"));
|
||||
assertThat(v).anyMatch(x -> x.getPropertyPath().toString().equals("roleDelegue"));
|
||||
assertThat(v).anyMatch(x -> x.getPropertyPath().toString().equals("dateDebut"));
|
||||
assertThat(v).anyMatch(x -> x.getPropertyPath().toString().equals("dateFin"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidation_RoleFormatInvalide() {
|
||||
CreateRoleDelegationRequest req = valide().roleDelegue("admin-org").build();
|
||||
assertThat(validator.validate(req))
|
||||
.anyMatch(v -> v.getPropertyPath().toString().equals("roleDelegue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidation_DateFinPassee() {
|
||||
CreateRoleDelegationRequest req = valide()
|
||||
.dateFin(LocalDateTime.now().minusDays(1)).build();
|
||||
assertThat(validator.validate(req))
|
||||
.anyMatch(v -> v.getPropertyPath().toString().equals("dateFin"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidation_Valide() {
|
||||
assertThat(validator.validate(valide().motif("OK").build())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashCodeToString() {
|
||||
UUID org = UUID.randomUUID();
|
||||
UUID d1 = UUID.randomUUID();
|
||||
UUID d2 = UUID.randomUUID();
|
||||
LocalDateTime debut = LocalDateTime.now().plusHours(1);
|
||||
LocalDateTime fin = LocalDateTime.now().plusDays(7);
|
||||
CreateRoleDelegationRequest a = CreateRoleDelegationRequest.builder()
|
||||
.organisationId(org).delegantUserId(d1).delegataireUserId(d2)
|
||||
.roleDelegue("TRESORIER").dateDebut(debut).dateFin(fin).build();
|
||||
CreateRoleDelegationRequest b = CreateRoleDelegationRequest.builder()
|
||||
.organisationId(org).delegantUserId(d1).delegataireUserId(d2)
|
||||
.roleDelegue("TRESORIER").dateDebut(debut).dateFin(fin).build();
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
assertThat(a.toString()).contains("CreateRoleDelegationRequest");
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user