feat: DTOs KYC/messagerie/mutuelle/parts/versement/payment + enrichissement paiement

## Nouveaux packages DTO / enums
- dto/kyc/ : NiveauRisqueKyc, TypePieceIdentite, KycDossier DTOs
- dto/messagerie/ : conversation/message DTOs + enums (TypeConversation, etc.)
- dto/mutuelle/financier/ : ParametresFinanciersMutuelle DTOs
- dto/mutuelle/parts/ : ComptePartsSociales, TransactionPartsSociales DTOs
- dto/versement/ : Versement DTOs
- payment/ : PaymentProvider, PaymentStatus, PaymentException,
  CheckoutRequest, CheckoutSession, PaymentEvent (SPI paiement unifié)

## Paiement enrichi
- CreatePaiementRequest, DeclarerPaiementManuelRequest, InitierPaiementEnLigneRequest
- IntentionStatutResponse, PaiementGatewayResponse, PaiementResponse, PaiementSummaryResponse
- Tests correspondants mis à jour

## Tests nouveaux
- DTOs agricole, ayant-droit, backup tests
- Tous les nouveaux DTOs KYC/messagerie/mutuelle/versement/payment

## Build
- pom.xml : version 1.0.5, parent-pom.xml aligné
- script/publish-api.sh : version bumped

164 fichiers, +8 481 insertions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
dahoud
2026-04-21 12:44:49 +00:00
parent eac66ce25d
commit ee6e945bdb
164 changed files with 8408 additions and 1473 deletions

View File

@@ -6,7 +6,7 @@
<groupId>dev.lions.unionflow</groupId>
<artifactId>unionflow-parent</artifactId>
<version>1.0.4</version>
<version>1.0.5</version>
<packaging>pom</packaging>
<name>UnionFlow - Parent</name>
@@ -33,12 +33,11 @@
</repositories>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.release>21</maven.compiler.release>
<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>
<quarkus.platform.version>3.20.0</quarkus.platform.version>
<lombok.version>1.18.36</lombok.version>
</properties>
<dependencyManagement>
@@ -72,8 +71,7 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>17</source>
<target>17</target>
<release>21</release>
<encoding>UTF-8</encoding>
<parameters>true</parameters>
<annotationProcessorPaths>

25
pom.xml
View File

@@ -7,7 +7,7 @@
<parent>
<groupId>dev.lions.unionflow</groupId>
<artifactId>unionflow-parent</artifactId>
<version>1.0.4</version>
<version>1.0.5</version>
<relativePath>parent-pom.xml</relativePath>
</parent>
@@ -18,22 +18,20 @@
<description>API définitions pour le serveur UnionFlow</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<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.20.0</quarkus.platform.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 +113,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 +124,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>

View File

@@ -16,7 +16,7 @@ echo "[1/2] Publication du parent pom..."
mvn deploy:deploy-file \
-DgroupId=dev.lions.unionflow \
-DartifactId=unionflow-parent \
-Dversion=1.0.0 \
-Dversion=1.0.5 \
-Dpackaging=pom \
-Dfile=parent-pom.xml \
-DrepositoryId="${REGISTRY_ID}" \

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -1,31 +1,53 @@
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;
import java.math.BigDecimal;
import java.util.UUID;
/**
* 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 class IntentionStatutResponse {
/** UUID de l'intention de paiement (clé de polling) */
private UUID intentionId;
/** INITIEE | EN_COURS | COMPLETEE | EXPIREE | ECHOUEE */
private String statut;
/** URL à encoder en QR code (wave_launch_url Wave Checkout) */
/** 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 paiement */
private BigDecimal montant;
/** Référence de la cotisation concernée */
private String referenceCotisation;
/** Message lisible pour l'utilisateur */
private String message;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -1,31 +1,24 @@
package dev.lions.unionflow.server.api.dto.paiement.response;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
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
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PaiementSummaryResponse {
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;
}
public record PaiementSummaryResponse(
UUID id,
String numeroReference,
BigDecimal montant,
String codeDevise,
String methodePaiementLibelle,
String statutPaiement,
String statutPaiementLibelle,
String statutPaiementSeverity,
LocalDateTime datePaiement
) {}

View File

@@ -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
) {}

View File

@@ -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, &gt; 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
) {}

View File

@@ -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
) {}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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 (30500) → {@code OUVERT}</li>
* <li>Mutuelle (505000) → {@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
}

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

@@ -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");
}
}

View File

@@ -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
) {}

View File

@@ -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
) {}

View File

@@ -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; }
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,10 @@
package dev.lions.unionflow.server.api.payment;
public enum PaymentStatus {
INITIATED,
PROCESSING,
SUCCESS,
FAILED,
CANCELLED,
EXPIRED
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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();
}
}

View File

@@ -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");
}
}

View File

@@ -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());
}
}

View File

@@ -0,0 +1,46 @@
package dev.lions.unionflow.server.api.dto.document.response;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.document.TypeDocument;
import org.junit.jupiter.api.Test;
class DocumentResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new DocumentResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
DocumentResponse resp = new DocumentResponse();
resp.setNomFichier("contrat.pdf");
resp.setNomOriginal("contrat_original.pdf");
resp.setCheminStockage("/storage/docs/contrat.pdf");
resp.setTypeMime("application/pdf");
resp.setTailleOctets(204800L);
resp.setTypeDocument(TypeDocument.CONTRAT);
resp.setHashMd5("abc123");
resp.setHashSha256("def456");
resp.setDescription("Contrat membre");
resp.setNombreTelechargements(5);
resp.setTailleFormatee("200 KB");
assertThat(resp.getNomFichier()).isEqualTo("contrat.pdf");
assertThat(resp.getTypeMime()).isEqualTo("application/pdf");
assertThat(resp.getTailleOctets()).isEqualTo(204800L);
assertThat(resp.getTypeDocument()).isEqualTo(TypeDocument.CONTRAT);
assertThat(resp.getNombreTelechargements()).isEqualTo(5);
assertThat(resp.getTailleFormatee()).isEqualTo("200 KB");
}
@Test
void testBuilder() {
DocumentResponse resp = DocumentResponse.builder()
.nomFichier("test.pdf")
.typeDocument(TypeDocument.PIECE_JUSTIFICATIVE)
.build();
assertThat(resp.getNomFichier()).isEqualTo("test.pdf");
}
}

View File

@@ -0,0 +1,43 @@
package dev.lions.unionflow.server.api.dto.document.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class PieceJointeResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new PieceJointeResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID docId = UUID.randomUUID();
UUID entiteId = UUID.randomUUID();
PieceJointeResponse resp = new PieceJointeResponse();
resp.setOrdre(1);
resp.setLibelle("Pièce jointe 1");
resp.setCommentaire("Document obligatoire");
resp.setDocumentId(docId);
resp.setTypeEntiteRattachee("COTISATION");
resp.setEntiteRattacheeId(entiteId);
assertThat(resp.getOrdre()).isEqualTo(1);
assertThat(resp.getLibelle()).isEqualTo("Pièce jointe 1");
assertThat(resp.getCommentaire()).isEqualTo("Document obligatoire");
assertThat(resp.getDocumentId()).isEqualTo(docId);
assertThat(resp.getTypeEntiteRattachee()).isEqualTo("COTISATION");
assertThat(resp.getEntiteRattacheeId()).isEqualTo(entiteId);
}
@Test
void testBuilder() {
PieceJointeResponse resp = PieceJointeResponse.builder()
.ordre(2)
.libelle("Autre pièce")
.build();
assertThat(resp.getOrdre()).isEqualTo(2);
}
}

View File

@@ -0,0 +1,47 @@
package dev.lions.unionflow.server.api.dto.favoris.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class FavoriResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new FavoriResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID userId = UUID.randomUUID();
FavoriResponse resp = new FavoriResponse();
resp.setUtilisateurId(userId);
resp.setTypeFavori("PAGE");
resp.setTitre("Dashboard");
resp.setDescription("Tableau de bord principal");
resp.setUrl("/dashboard");
resp.setIcon("pi pi-home");
resp.setCouleur("#3B82F6");
resp.setCategorie("NAVIGATION");
resp.setOrdre(1);
resp.setNbVisites(42);
resp.setEstPlusUtilise(true);
assertThat(resp.getUtilisateurId()).isEqualTo(userId);
assertThat(resp.getTypeFavori()).isEqualTo("PAGE");
assertThat(resp.getTitre()).isEqualTo("Dashboard");
assertThat(resp.getUrl()).isEqualTo("/dashboard");
assertThat(resp.getNbVisites()).isEqualTo(42);
assertThat(resp.getEstPlusUtilise()).isTrue();
}
@Test
void testBuilder() {
FavoriResponse resp = FavoriResponse.builder()
.titre("Membres")
.url("/membres")
.build();
assertThat(resp.getTitre()).isEqualTo("Membres");
}
}

View File

@@ -0,0 +1,41 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.request;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
class ApproveTransactionRequestTest {
@Test
void testConstructeurParDefaut() {
assertThat(new ApproveTransactionRequest()).isNotNull();
}
@Test
void testSettersEtGetters() {
ApproveTransactionRequest req = new ApproveTransactionRequest();
req.setComment("Approuvé après vérification");
assertThat(req.getComment()).isEqualTo("Approuvé après vérification");
}
@Test
void testBuilder() {
ApproveTransactionRequest req = ApproveTransactionRequest.builder()
.comment("OK")
.build();
assertThat(req.getComment()).isEqualTo("OK");
}
@Test
void testCommentNull() {
ApproveTransactionRequest req = new ApproveTransactionRequest();
assertThat(req.getComment()).isNull();
}
@Test
void testEqualsHashCode() {
ApproveTransactionRequest r1 = ApproveTransactionRequest.builder().comment("c").build();
ApproveTransactionRequest r2 = ApproveTransactionRequest.builder().comment("c").build();
assertThat(r1).isEqualTo(r2);
}
}

View File

@@ -0,0 +1,38 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.request;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
class CreateBudgetLineRequestTest {
@Test
void testConstructeurParDefaut() {
assertThat(new CreateBudgetLineRequest()).isNotNull();
}
@Test
void testSettersEtGetters() {
CreateBudgetLineRequest req = new CreateBudgetLineRequest();
req.setCategory("CONTRIBUTIONS");
req.setName("Cotisations mensuelles");
req.setDescription("Lignes cotisations");
req.setAmountPlanned(new BigDecimal("500000"));
req.setNotes("Notes budget");
assertThat(req.getCategory()).isEqualTo("CONTRIBUTIONS");
assertThat(req.getName()).isEqualTo("Cotisations mensuelles");
assertThat(req.getAmountPlanned()).isEqualByComparingTo("500000");
assertThat(req.getNotes()).isEqualTo("Notes budget");
}
@Test
void testBuilder() {
CreateBudgetLineRequest req = CreateBudgetLineRequest.builder()
.category("SAVINGS")
.amountPlanned(new BigDecimal("100000"))
.build();
assertThat(req.getCategory()).isEqualTo("SAVINGS");
}
}

View File

@@ -0,0 +1,49 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.request;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class CreateBudgetRequestTest {
@Test
void testConstructeurParDefaut() {
CreateBudgetRequest req = new CreateBudgetRequest();
assertThat(req).isNotNull();
assertThat(req.getLines()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID orgId = UUID.randomUUID();
CreateBudgetRequest req = new CreateBudgetRequest();
req.setName("Budget 2026");
req.setDescription("Budget annuel");
req.setOrganizationId(orgId);
req.setPeriod("ANNUAL");
req.setYear(2026);
req.setMonth(null);
req.setCurrency("XOF");
req.setLines(new ArrayList<>());
assertThat(req.getName()).isEqualTo("Budget 2026");
assertThat(req.getOrganizationId()).isEqualTo(orgId);
assertThat(req.getPeriod()).isEqualTo("ANNUAL");
assertThat(req.getYear()).isEqualTo(2026);
assertThat(req.getCurrency()).isEqualTo("XOF");
assertThat(req.getLines()).isEmpty();
}
@Test
void testBuilder() {
CreateBudgetRequest req = CreateBudgetRequest.builder()
.name("Budget Q1")
.period("QUARTERLY")
.year(2026)
.build();
assertThat(req.getName()).isEqualTo("Budget Q1");
assertThat(req.getLines()).isNotNull();
}
}

View File

@@ -0,0 +1,35 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.request;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
class RejectTransactionRequestTest {
@Test
void testConstructeurParDefaut() {
assertThat(new RejectTransactionRequest()).isNotNull();
}
@Test
void testSettersEtGetters() {
RejectTransactionRequest req = new RejectTransactionRequest();
req.setReason("Montant incorrect, pièce justificative manquante");
assertThat(req.getReason()).isEqualTo("Montant incorrect, pièce justificative manquante");
}
@Test
void testBuilder() {
RejectTransactionRequest req = RejectTransactionRequest.builder()
.reason("Raison du rejet")
.build();
assertThat(req.getReason()).isEqualTo("Raison du rejet");
}
@Test
void testEqualsHashCode() {
RejectTransactionRequest r1 = RejectTransactionRequest.builder().reason("r").build();
RejectTransactionRequest r2 = RejectTransactionRequest.builder().reason("r").build();
assertThat(r1).isEqualTo(r2);
}
}

View File

@@ -0,0 +1,45 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.LocalDateTime;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class ApproverActionResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new ApproverActionResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID id = UUID.randomUUID();
UUID approverId = UUID.randomUUID();
LocalDateTime decided = LocalDateTime.now();
ApproverActionResponse resp = new ApproverActionResponse();
resp.setId(id);
resp.setApproverId(approverId);
resp.setApproverName("John Doe");
resp.setApproverRole("TRESORIER");
resp.setDecision("APPROVED");
resp.setComment("OK");
resp.setDecidedAt(decided);
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getApproverId()).isEqualTo(approverId);
assertThat(resp.getApproverName()).isEqualTo("John Doe");
assertThat(resp.getDecision()).isEqualTo("APPROVED");
assertThat(resp.getDecidedAt()).isEqualTo(decided);
}
@Test
void testBuilder() {
ApproverActionResponse resp = ApproverActionResponse.builder()
.decision("REJECTED")
.comment("Insufficient funds")
.build();
assertThat(resp.getDecision()).isEqualTo("REJECTED");
}
}

View File

@@ -0,0 +1,45 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class BudgetLineResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new BudgetLineResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID id = UUID.randomUUID();
BudgetLineResponse resp = new BudgetLineResponse();
resp.setId(id);
resp.setCategory("CONTRIBUTIONS");
resp.setName("Cotisations");
resp.setAmountPlanned(new BigDecimal("500000"));
resp.setAmountRealized(new BigDecimal("480000"));
resp.setRealizationRate(96.0);
resp.setVariance(new BigDecimal("20000"));
resp.setIsOverBudget(false);
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getCategory()).isEqualTo("CONTRIBUTIONS");
assertThat(resp.getAmountPlanned()).isEqualByComparingTo("500000");
assertThat(resp.getAmountRealized()).isEqualByComparingTo("480000");
assertThat(resp.getRealizationRate()).isEqualTo(96.0);
assertThat(resp.getIsOverBudget()).isFalse();
}
@Test
void testBuilder() {
BudgetLineResponse resp = BudgetLineResponse.builder()
.category("SAVINGS")
.amountPlanned(new BigDecimal("100000"))
.build();
assertThat(resp.getCategory()).isEqualTo("SAVINGS");
}
}

View File

@@ -0,0 +1,56 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class BudgetResponseTest {
@Test
void testConstructeurParDefaut() {
BudgetResponse resp = new BudgetResponse();
assertThat(resp).isNotNull();
assertThat(resp.getLines()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID id = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
BudgetResponse resp = new BudgetResponse();
resp.setId(id);
resp.setName("Budget 2026");
resp.setOrganizationId(orgId);
resp.setPeriod("ANNUAL");
resp.setYear(2026);
resp.setStatus("ACTIVE");
resp.setTotalPlanned(new BigDecimal("1000000"));
resp.setTotalRealized(new BigDecimal("950000"));
resp.setCurrency("XOF");
resp.setRealizationRate(95.0);
resp.setIsOverBudget(false);
resp.setIsActive(true);
resp.setStartDate(LocalDate.of(2026, 1, 1));
resp.setEndDate(LocalDate.of(2026, 12, 31));
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getName()).isEqualTo("Budget 2026");
assertThat(resp.getTotalPlanned()).isEqualByComparingTo("1000000");
assertThat(resp.getIsActive()).isTrue();
}
@Test
void testBuilder() {
BudgetResponse resp = BudgetResponse.builder()
.name("Budget Q1")
.status("DRAFT")
.currency("XOF")
.build();
assertThat(resp.getName()).isEqualTo("Budget Q1");
assertThat(resp.getLines()).isNotNull();
}
}

View File

@@ -0,0 +1,53 @@
package dev.lions.unionflow.server.api.dto.finance_workflow.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class TransactionApprovalResponseTest {
@Test
void testConstructeurParDefaut() {
TransactionApprovalResponse resp = new TransactionApprovalResponse();
assertThat(resp).isNotNull();
assertThat(resp.getApprovers()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID id = UUID.randomUUID();
UUID txId = UUID.randomUUID();
TransactionApprovalResponse resp = new TransactionApprovalResponse();
resp.setId(id);
resp.setTransactionId(txId);
resp.setTransactionType("CONTRIBUTION");
resp.setAmount(new BigDecimal("50000"));
resp.setCurrency("XOF");
resp.setRequiredLevel("LEVEL1");
resp.setStatus("PENDING");
resp.setApprovalCount(1);
resp.setRequiredApprovals(2);
resp.setHasAllApprovals(false);
resp.setIsPending(true);
resp.setIsCompleted(false);
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getTransactionType()).isEqualTo("CONTRIBUTION");
assertThat(resp.getAmount()).isEqualByComparingTo("50000");
assertThat(resp.getStatus()).isEqualTo("PENDING");
assertThat(resp.getHasAllApprovals()).isFalse();
assertThat(resp.getIsPending()).isTrue();
}
@Test
void testBuilder() {
TransactionApprovalResponse resp = TransactionApprovalResponse.builder()
.status("APPROVED")
.currency("XOF")
.build();
assertThat(resp.getStatus()).isEqualTo("APPROVED");
assertThat(resp.getApprovers()).isNotNull();
}
}

View File

@@ -0,0 +1,38 @@
package dev.lions.unionflow.server.api.dto.gouvernance;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.gouvernance.NiveauEchelon;
import org.junit.jupiter.api.Test;
class EchelonOrganigrammeDTOTest {
@Test
void testConstructeurParDefaut() {
assertThat(new EchelonOrganigrammeDTO()).isNotNull();
}
@Test
void testSettersEtGetters() {
EchelonOrganigrammeDTO dto = new EchelonOrganigrammeDTO();
dto.setOrganisationId("org-1");
dto.setEchelonParentId("org-parent");
dto.setNiveau(NiveauEchelon.NATIONAL);
dto.setDesignation("Bureau National");
dto.setZoneGeographiqueOuDelegation("Sénégal");
assertThat(dto.getOrganisationId()).isEqualTo("org-1");
assertThat(dto.getEchelonParentId()).isEqualTo("org-parent");
assertThat(dto.getNiveau()).isEqualTo(NiveauEchelon.NATIONAL);
assertThat(dto.getDesignation()).isEqualTo("Bureau National");
assertThat(dto.getZoneGeographiqueOuDelegation()).isEqualTo("Sénégal");
}
@Test
void testBuilder() {
EchelonOrganigrammeDTO dto = EchelonOrganigrammeDTO.builder()
.designation("Section Dakar")
.niveau(NiveauEchelon.REGIONAL)
.build();
assertThat(dto.getDesignation()).isEqualTo("Section Dakar");
}
}

View File

@@ -0,0 +1,45 @@
package dev.lions.unionflow.server.api.dto.kyc;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite;
import java.time.LocalDate;
import org.junit.jupiter.api.Test;
class KycDossierRequestTest {
@Test
void testBuilder() {
KycDossierRequest req = KycDossierRequest.builder()
.membreId("m-1")
.typePiece(TypePieceIdentite.CNI)
.numeroPiece("CNI-001")
.dateExpirationPiece(LocalDate.of(2030, 12, 31))
.justifDomicileFileId("file-1")
.pieceIdentiteRectoFileId("file-recto")
.pieceIdentiteVersoFileId("file-verso")
.notesValidateur("Dossier complet")
.estPep(false)
.nationalite("SN")
.build();
assertThat(req.getMembreId()).isEqualTo("m-1");
assertThat(req.getTypePiece()).isEqualTo(TypePieceIdentite.CNI);
assertThat(req.getNumeroPiece()).isEqualTo("CNI-001");
assertThat(req.getDateExpirationPiece()).isEqualTo(LocalDate.of(2030, 12, 31));
assertThat(req.getJustifDomicileFileId()).isEqualTo("file-1");
assertThat(req.getEstPep()).isFalse();
assertThat(req.getNationalite()).isEqualTo("SN");
}
@Test
void testBuilderMinimal() {
KycDossierRequest req = KycDossierRequest.builder()
.membreId("m-2")
.typePiece(TypePieceIdentite.PASSEPORT)
.numeroPiece("PASS-001")
.build();
assertThat(req.getMembreId()).isEqualTo("m-2");
assertThat(req.getTypePiece()).isEqualTo(TypePieceIdentite.PASSEPORT);
}
}

View File

@@ -0,0 +1,45 @@
package dev.lions.unionflow.server.api.dto.kyc;
import static org.assertj.core.api.Assertions.assertThat;
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 java.time.LocalDate;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class KycDossierResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new KycDossierResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID membreId = UUID.randomUUID();
KycDossierResponse resp = new KycDossierResponse();
resp.setMembreId(membreId);
resp.setMembreNomComplet("Alice Dupont");
resp.setMembreEmail("alice@test.com");
resp.setTypePiece(TypePieceIdentite.CNI);
resp.setNumeroPiece("CNI-001");
resp.setDateExpirationPiece(LocalDate.of(2030, 12, 31));
resp.setStatut(StatutKyc.VERIFIE);
resp.setNiveauRisque(NiveauRisqueKyc.FAIBLE);
resp.setScoreRisque(15);
resp.setEstPep(false);
resp.setNationalite("SN");
resp.setAnneeReference(2026);
assertThat(resp.getMembreId()).isEqualTo(membreId);
assertThat(resp.getMembreNomComplet()).isEqualTo("Alice Dupont");
assertThat(resp.getTypePiece()).isEqualTo(TypePieceIdentite.CNI);
assertThat(resp.getStatut()).isEqualTo(StatutKyc.VERIFIE);
assertThat(resp.getNiveauRisque()).isEqualTo(NiveauRisqueKyc.FAIBLE);
assertThat(resp.getScoreRisque()).isEqualTo(15);
assertThat(resp.isEstPep()).isFalse();
assertThat(resp.getAnneeReference()).isEqualTo(2026);
}
}

View File

@@ -0,0 +1,51 @@
package dev.lions.unionflow.server.api.dto.lcbft;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;
class AlerteLcbFtResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new AlerteLcbFtResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
LocalDateTime date = LocalDateTime.now();
AlerteLcbFtResponse resp = new AlerteLcbFtResponse();
resp.setId("alerte-1");
resp.setOrganisationId("org-1");
resp.setOrganisationNom("Association Test");
resp.setMembreId("m-1");
resp.setMembreNomComplet("Alice Dupont");
resp.setTypeAlerte("SEUIL_DEPASSE");
resp.setDateAlerte(date);
resp.setDescription("Dépassement de seuil");
resp.setMontant(new BigDecimal("600000"));
resp.setSeuil(new BigDecimal("500000"));
resp.setSeverite("HAUTE");
resp.setTraitee(false);
assertThat(resp.getId()).isEqualTo("alerte-1");
assertThat(resp.getOrganisationNom()).isEqualTo("Association Test");
assertThat(resp.getTypeAlerte()).isEqualTo("SEUIL_DEPASSE");
assertThat(resp.getMontant()).isEqualByComparingTo("600000");
assertThat(resp.getSeverite()).isEqualTo("HAUTE");
assertThat(resp.getTraitee()).isFalse();
}
@Test
void testBuilder() {
AlerteLcbFtResponse resp = AlerteLcbFtResponse.builder()
.typeAlerte("PEP")
.severite("CRITIQUE")
.traitee(true)
.build();
assertThat(resp.getTypeAlerte()).isEqualTo("PEP");
assertThat(resp.getTraitee()).isTrue();
}
}

View File

@@ -0,0 +1,139 @@
package dev.lions.unionflow.server.api.dto.membre.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class MembreSummaryResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new MembreSummaryResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
UUID id = UUID.randomUUID();
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setId(id);
resp.setNumeroMembre("MEM-001");
resp.setPrenom("Alice");
resp.setNom("Dupont");
resp.setEmail("alice@test.com");
resp.setStatutCompte("ACTIF");
resp.setActif(true);
resp.setRoles(List.of("MEMBRE"));
resp.setDateAdhesion(LocalDate.of(2025, 1, 1));
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getNumeroMembre()).isEqualTo("MEM-001");
assertThat(resp.getPrenom()).isEqualTo("Alice");
assertThat(resp.getStatutCompte()).isEqualTo("ACTIF");
assertThat(resp.isActif()).isTrue();
}
@Test
void testGetNomComplet() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setPrenom("Alice");
resp.setNom("Dupont");
assertThat(resp.getNomComplet()).isEqualTo("Alice Dupont");
}
@Test
void testGetNomCompletNullPrenom() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setPrenom(null);
resp.setNom("Dupont");
assertThat(resp.getNomComplet()).isEqualTo("Dupont");
}
@Test
void testGetStatutAliases() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setStatutCompte("SUSPENDU");
resp.setStatutCompteLibelle("Suspendu");
resp.setStatutCompteSeverity("warning");
assertThat(resp.getStatut()).isEqualTo("SUSPENDU");
assertThat(resp.getStatutLibelle()).isEqualTo("Suspendu");
assertThat(resp.getStatutSeverity()).isEqualTo("warning");
}
@Test
void testGetStatutIcon() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setStatutCompte("ACTIF");
assertThat(resp.getStatutIcon()).isEqualTo("pi pi-check-circle");
resp.setStatutCompte("SUSPENDU");
assertThat(resp.getStatutIcon()).isEqualTo("pi pi-ban");
resp.setStatutCompte("RADIE");
assertThat(resp.getStatutIcon()).isEqualTo("pi pi-times-circle");
resp.setStatutCompte("INACTIF");
assertThat(resp.getStatutIcon()).isEqualTo("pi pi-pause-circle");
resp.setStatutCompte("INCONNU");
assertThat(resp.getStatutIcon()).isEqualTo("pi pi-question-circle");
resp.setStatutCompte(null);
assertThat(resp.getStatutIcon()).isEqualTo("pi pi-question-circle");
}
@Test
void testGetTypeMembre() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setRoles(null);
assertThat(resp.getTypeMembre()).isEqualTo("Membre");
resp.setRoles(List.of("PRESIDENT"));
assertThat(resp.getTypeMembre()).isEqualTo("Président");
resp.setRoles(List.of("TRESORIER"));
assertThat(resp.getTypeMembre()).isEqualTo("Trésorier");
resp.setRoles(List.of("SECRETAIRE"));
assertThat(resp.getTypeMembre()).isEqualTo("Secrétaire");
resp.setRoles(List.of("VICE_PRESIDENT"));
assertThat(resp.getTypeMembre()).isEqualTo("Vice-Président");
resp.setRoles(List.of("ADMIN_ORGANISATION"));
assertThat(resp.getTypeMembre()).isEqualTo("Administrateur");
resp.setRoles(List.of("MODERATEUR"));
assertThat(resp.getTypeMembre()).isEqualTo("Modérateur");
resp.setRoles(List.of("AUTRE"));
assertThat(resp.getTypeMembre()).isEqualTo("Membre");
}
@Test
void testGetTypeSeverity() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setRoles(List.of("PRESIDENT"));
assertThat(resp.getTypeSeverity()).isEqualTo("primary");
resp.setRoles(List.of("ADMIN_ORGANISATION"));
assertThat(resp.getTypeSeverity()).isEqualTo("danger");
resp.setRoles(null);
assertThat(resp.getTypeSeverity()).isEqualTo("secondary");
}
@Test
void testGetTypeIcon() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setRoles(List.of("PRESIDENT"));
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-star");
resp.setRoles(List.of("TRESORIER"));
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-wallet");
resp.setRoles(List.of("SECRETAIRE"));
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-file-edit");
resp.setRoles(List.of("ADMIN_ORGANISATION"));
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-shield");
resp.setRoles(List.of("MODERATEUR"));
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-wrench");
resp.setRoles(List.of("AUTRE"));
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-user");
resp.setRoles(null);
assertThat(resp.getTypeIcon()).isEqualTo("pi pi-user");
}
@Test
void testIsActifNull() {
MembreSummaryResponse resp = new MembreSummaryResponse();
resp.setActif(null);
assertThat(resp.isActif()).isFalse();
}
}

View File

@@ -0,0 +1,71 @@
package dev.lions.unionflow.server.api.dto.messagerie.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("BloquerMembreRequest")
class BloquerMembreRequestTest {
@Test
@DisplayName("builder — tous les champs renseignés")
void builder_allFields() {
UUID membreId = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
BloquerMembreRequest req = BloquerMembreRequest.builder()
.membreABloquerId(membreId)
.organisationId(orgId)
.build();
assertThat(req.membreABloquerId()).isEqualTo(membreId);
assertThat(req.organisationId()).isEqualTo(orgId);
}
@Test
@DisplayName("constructeur canonique record")
void canonicalConstructor() {
UUID membreId = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
BloquerMembreRequest req = new BloquerMembreRequest(membreId, orgId);
assertThat(req.membreABloquerId()).isEqualTo(membreId);
assertThat(req.organisationId()).isEqualTo(orgId);
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID m = UUID.randomUUID();
UUID o = UUID.randomUUID();
BloquerMembreRequest a = new BloquerMembreRequest(m, o);
BloquerMembreRequest b = new BloquerMembreRequest(m, o);
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("equals — données différentes")
void equals_differentData() {
BloquerMembreRequest a = new BloquerMembreRequest(UUID.randomUUID(), UUID.randomUUID());
BloquerMembreRequest b = new BloquerMembreRequest(UUID.randomUUID(), UUID.randomUUID());
assertThat(a).isNotEqualTo(b);
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
BloquerMembreRequest req = BloquerMembreRequest.builder()
.membreABloquerId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.build();
assertThat(req.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,93 @@
package dev.lions.unionflow.server.api.dto.messagerie.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("DemarrerConversationDirecteRequest")
class DemarrerConversationDirecteRequestTest {
@Test
@DisplayName("builder — tous les champs renseignés")
void builder_allFields() {
UUID destinataireId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
DemarrerConversationDirecteRequest req = DemarrerConversationDirecteRequest.builder()
.destinataireId(destinataireId)
.organisationId(organisationId)
.contenuInitial("Bonjour, comment puis-je vous aider ?")
.build();
assertThat(req.destinataireId()).isEqualTo(destinataireId);
assertThat(req.organisationId()).isEqualTo(organisationId);
assertThat(req.contenuInitial()).isEqualTo("Bonjour, comment puis-je vous aider ?");
}
@Test
@DisplayName("builder — contenuInitial optionnel null")
void builder_contenuInitialNull() {
UUID destinataireId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
DemarrerConversationDirecteRequest req = DemarrerConversationDirecteRequest.builder()
.destinataireId(destinataireId)
.organisationId(organisationId)
.build();
assertThat(req.destinataireId()).isEqualTo(destinataireId);
assertThat(req.organisationId()).isEqualTo(organisationId);
assertThat(req.contenuInitial()).isNull();
}
@Test
@DisplayName("constructeur canonique record")
void canonicalConstructor() {
UUID destinataireId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
DemarrerConversationDirecteRequest req = new DemarrerConversationDirecteRequest(
destinataireId, organisationId, "Premier message");
assertThat(req.destinataireId()).isEqualTo(destinataireId);
assertThat(req.organisationId()).isEqualTo(organisationId);
assertThat(req.contenuInitial()).isEqualTo("Premier message");
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID d = UUID.randomUUID();
UUID o = UUID.randomUUID();
DemarrerConversationDirecteRequest a = new DemarrerConversationDirecteRequest(d, o, "msg");
DemarrerConversationDirecteRequest b = new DemarrerConversationDirecteRequest(d, o, "msg");
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("equals — données différentes")
void equals_differentData() {
DemarrerConversationDirecteRequest a = new DemarrerConversationDirecteRequest(
UUID.randomUUID(), UUID.randomUUID(), null);
DemarrerConversationDirecteRequest b = new DemarrerConversationDirecteRequest(
UUID.randomUUID(), UUID.randomUUID(), null);
assertThat(a).isNotEqualTo(b);
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
DemarrerConversationDirecteRequest req = DemarrerConversationDirecteRequest.builder()
.destinataireId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.build();
assertThat(req.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,90 @@
package dev.lions.unionflow.server.api.dto.messagerie.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;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@DisplayName("DemarrerConversationRoleRequest")
class DemarrerConversationRoleRequestTest {
@Test
@DisplayName("builder — tous les champs renseignés")
void builder_allFields() {
UUID organisationId = UUID.randomUUID();
DemarrerConversationRoleRequest req = DemarrerConversationRoleRequest.builder()
.organisationId(organisationId)
.roleCible("TRESORIER")
.contenuInitial("Bonjour Trésorier")
.build();
assertThat(req.organisationId()).isEqualTo(organisationId);
assertThat(req.roleCible()).isEqualTo("TRESORIER");
assertThat(req.contenuInitial()).isEqualTo("Bonjour Trésorier");
}
@Test
@DisplayName("constructeur canonique record")
void canonicalConstructor() {
UUID organisationId = UUID.randomUUID();
DemarrerConversationRoleRequest req = new DemarrerConversationRoleRequest(
organisationId, "PRESIDENT", "Demande urgente");
assertThat(req.organisationId()).isEqualTo(organisationId);
assertThat(req.roleCible()).isEqualTo("PRESIDENT");
assertThat(req.contenuInitial()).isEqualTo("Demande urgente");
}
@ParameterizedTest
@ValueSource(strings = {"PRESIDENT", "TRESORIER", "SECRETAIRE", "VICE_PRESIDENT", "ADMIN", "ADMIN_ORGANISATION"})
@DisplayName("tous les rôles valides acceptés")
void allValidRoles(String role) {
DemarrerConversationRoleRequest req = DemarrerConversationRoleRequest.builder()
.organisationId(UUID.randomUUID())
.roleCible(role)
.contenuInitial("message")
.build();
assertThat(req.roleCible()).isEqualTo(role);
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID org = UUID.randomUUID();
DemarrerConversationRoleRequest a = new DemarrerConversationRoleRequest(org, "TRESORIER", "msg");
DemarrerConversationRoleRequest b = new DemarrerConversationRoleRequest(org, "TRESORIER", "msg");
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("equals — données différentes")
void equals_differentData() {
DemarrerConversationRoleRequest a = new DemarrerConversationRoleRequest(
UUID.randomUUID(), "TRESORIER", "msg");
DemarrerConversationRoleRequest b = new DemarrerConversationRoleRequest(
UUID.randomUUID(), "PRESIDENT", "msg");
assertThat(a).isNotEqualTo(b);
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
DemarrerConversationRoleRequest req = DemarrerConversationRoleRequest.builder()
.organisationId(UUID.randomUUID())
.roleCible("SECRETAIRE")
.contenuInitial("test")
.build();
assertThat(req.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,120 @@
package dev.lions.unionflow.server.api.dto.messagerie.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;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@DisplayName("EnvoyerMessageRequest")
class EnvoyerMessageRequestTest {
@Test
@DisplayName("builder — message texte")
void builder_messageTexte() {
EnvoyerMessageRequest req = EnvoyerMessageRequest.builder()
.typeMessage("TEXTE")
.contenu("Bonjour à tous !")
.build();
assertThat(req.typeMessage()).isEqualTo("TEXTE");
assertThat(req.contenu()).isEqualTo("Bonjour à tous !");
assertThat(req.urlFichier()).isNull();
assertThat(req.dureeAudio()).isNull();
assertThat(req.messageParentId()).isNull();
}
@Test
@DisplayName("builder — note vocale")
void builder_noteVocale() {
EnvoyerMessageRequest req = EnvoyerMessageRequest.builder()
.typeMessage("VOCAL")
.urlFichier("https://storage.example.com/audio/note.opus")
.dureeAudio(45)
.build();
assertThat(req.typeMessage()).isEqualTo("VOCAL");
assertThat(req.urlFichier()).isEqualTo("https://storage.example.com/audio/note.opus");
assertThat(req.dureeAudio()).isEqualTo(45);
assertThat(req.contenu()).isNull();
}
@Test
@DisplayName("builder — image")
void builder_image() {
EnvoyerMessageRequest req = EnvoyerMessageRequest.builder()
.typeMessage("IMAGE")
.urlFichier("https://storage.example.com/img/photo.jpg")
.build();
assertThat(req.typeMessage()).isEqualTo("IMAGE");
assertThat(req.urlFichier()).isEqualTo("https://storage.example.com/img/photo.jpg");
}
@Test
@DisplayName("builder — réponse à un message parent")
void builder_avecMessageParent() {
UUID parentId = UUID.randomUUID();
EnvoyerMessageRequest req = EnvoyerMessageRequest.builder()
.typeMessage("TEXTE")
.contenu("Oui, c'est exact !")
.messageParentId(parentId)
.build();
assertThat(req.messageParentId()).isEqualTo(parentId);
}
@Test
@DisplayName("builder — tous les champs null (aucune contrainte record)")
void builder_allNull() {
EnvoyerMessageRequest req = EnvoyerMessageRequest.builder().build();
assertThat(req.typeMessage()).isNull();
assertThat(req.contenu()).isNull();
assertThat(req.urlFichier()).isNull();
assertThat(req.dureeAudio()).isNull();
assertThat(req.messageParentId()).isNull();
}
@ParameterizedTest
@ValueSource(strings = {"TEXTE", "VOCAL", "IMAGE", "SYSTEME"})
@DisplayName("tous les types de message valides")
void allValidTypes(String type) {
EnvoyerMessageRequest req = new EnvoyerMessageRequest(type, null, null, null, null);
assertThat(req.typeMessage()).isEqualTo(type);
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID parentId = UUID.randomUUID();
EnvoyerMessageRequest a = new EnvoyerMessageRequest("TEXTE", "bonjour", null, null, parentId);
EnvoyerMessageRequest b = new EnvoyerMessageRequest("TEXTE", "bonjour", null, null, parentId);
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("equals — données différentes")
void equals_differentData() {
EnvoyerMessageRequest a = new EnvoyerMessageRequest("TEXTE", "bonjour", null, null, null);
EnvoyerMessageRequest b = new EnvoyerMessageRequest("VOCAL", null, "url", 30, null);
assertThat(a).isNotEqualTo(b);
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
EnvoyerMessageRequest req = EnvoyerMessageRequest.builder()
.typeMessage("TEXTE")
.contenu("test")
.build();
assertThat(req.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,101 @@
package dev.lions.unionflow.server.api.dto.messagerie.request;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@DisplayName("MettreAJourPolitiqueRequest")
class MettreAJourPolitiqueRequestTest {
@Test
@DisplayName("builder — tous les champs renseignés")
void builder_allFields() {
MettreAJourPolitiqueRequest req = MettreAJourPolitiqueRequest.builder()
.typePolitique("OUVERT")
.autoriserMembreVersMembre(true)
.autoriserMembreVersRole(true)
.autoriserNotesVocales(false)
.build();
assertThat(req.typePolitique()).isEqualTo("OUVERT");
assertThat(req.autoriserMembreVersMembre()).isTrue();
assertThat(req.autoriserMembreVersRole()).isTrue();
assertThat(req.autoriserNotesVocales()).isFalse();
}
@Test
@DisplayName("builder — tous les champs null (mise à jour partielle)")
void builder_allNull() {
MettreAJourPolitiqueRequest req = MettreAJourPolitiqueRequest.builder().build();
assertThat(req.typePolitique()).isNull();
assertThat(req.autoriserMembreVersMembre()).isNull();
assertThat(req.autoriserMembreVersRole()).isNull();
assertThat(req.autoriserNotesVocales()).isNull();
}
@Test
@DisplayName("builder — mise à jour partielle (typePolitique uniquement)")
void builder_partialUpdate_typeOnly() {
MettreAJourPolitiqueRequest req = MettreAJourPolitiqueRequest.builder()
.typePolitique("BUREAU_SEULEMENT")
.build();
assertThat(req.typePolitique()).isEqualTo("BUREAU_SEULEMENT");
assertThat(req.autoriserMembreVersMembre()).isNull();
assertThat(req.autoriserMembreVersRole()).isNull();
assertThat(req.autoriserNotesVocales()).isNull();
}
@ParameterizedTest
@ValueSource(strings = {"OUVERT", "BUREAU_SEULEMENT", "GROUPES_INTERNES"})
@DisplayName("toutes les politiques valides")
void allValidPolicies(String politique) {
MettreAJourPolitiqueRequest req = new MettreAJourPolitiqueRequest(politique, null, null, null);
assertThat(req.typePolitique()).isEqualTo(politique);
}
@Test
@DisplayName("constructeur canonique record")
void canonicalConstructor() {
MettreAJourPolitiqueRequest req = new MettreAJourPolitiqueRequest(
"GROUPES_INTERNES", false, true, true);
assertThat(req.typePolitique()).isEqualTo("GROUPES_INTERNES");
assertThat(req.autoriserMembreVersMembre()).isFalse();
assertThat(req.autoriserMembreVersRole()).isTrue();
assertThat(req.autoriserNotesVocales()).isTrue();
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
MettreAJourPolitiqueRequest a = new MettreAJourPolitiqueRequest("OUVERT", true, true, true);
MettreAJourPolitiqueRequest b = new MettreAJourPolitiqueRequest("OUVERT", true, true, true);
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("equals — données différentes")
void equals_differentData() {
MettreAJourPolitiqueRequest a = new MettreAJourPolitiqueRequest("OUVERT", true, true, true);
MettreAJourPolitiqueRequest b = new MettreAJourPolitiqueRequest("BUREAU_SEULEMENT", false, false, false);
assertThat(a).isNotEqualTo(b);
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
MettreAJourPolitiqueRequest req = MettreAJourPolitiqueRequest.builder()
.typePolitique("OUVERT")
.build();
assertThat(req.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,113 @@
package dev.lions.unionflow.server.api.dto.messagerie.response;
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("ContactPolicyResponse")
class ContactPolicyResponseTest {
@Test
@DisplayName("builder — politique OUVERT (valeurs par défaut)")
void builder_politiqueOuvert() {
UUID id = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
ContactPolicyResponse resp = ContactPolicyResponse.builder()
.id(id)
.organisationId(orgId)
.typePolitique("OUVERT")
.autoriserMembreVersMembre(true)
.autoriserMembreVersRole(true)
.autoriserNotesVocales(true)
.build();
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getOrganisationId()).isEqualTo(orgId);
assertThat(resp.getTypePolitique()).isEqualTo("OUVERT");
assertThat(resp.isAutoriserMembreVersMembre()).isTrue();
assertThat(resp.isAutoriserMembreVersRole()).isTrue();
assertThat(resp.isAutoriserNotesVocales()).isTrue();
}
@Test
@DisplayName("builder — politique BUREAU_SEULEMENT restrictive")
void builder_politiqueBureauSeulement() {
ContactPolicyResponse resp = ContactPolicyResponse.builder()
.typePolitique("BUREAU_SEULEMENT")
.autoriserMembreVersMembre(false)
.autoriserMembreVersRole(true)
.autoriserNotesVocales(false)
.build();
assertThat(resp.getTypePolitique()).isEqualTo("BUREAU_SEULEMENT");
assertThat(resp.isAutoriserMembreVersMembre()).isFalse();
assertThat(resp.isAutoriserMembreVersRole()).isTrue();
assertThat(resp.isAutoriserNotesVocales()).isFalse();
}
@Test
@DisplayName("builder — politique GROUPES_INTERNES")
void builder_politiqueGroupesInternes() {
ContactPolicyResponse resp = ContactPolicyResponse.builder()
.typePolitique("GROUPES_INTERNES")
.autoriserMembreVersMembre(true)
.autoriserMembreVersRole(true)
.autoriserNotesVocales(true)
.build();
assertThat(resp.getTypePolitique()).isEqualTo("GROUPES_INTERNES");
}
@Test
@DisplayName("constructeur no-args — valeurs par défaut")
void noArgsConstructor_defaults() {
ContactPolicyResponse resp = new ContactPolicyResponse();
assertThat(resp.getId()).isNull();
assertThat(resp.getOrganisationId()).isNull();
assertThat(resp.getTypePolitique()).isNull();
assertThat(resp.isAutoriserMembreVersMembre()).isFalse();
assertThat(resp.isAutoriserMembreVersRole()).isFalse();
assertThat(resp.isAutoriserNotesVocales()).isFalse();
}
@Test
@DisplayName("setters et getters fonctionnent")
void settersGetters() {
ContactPolicyResponse resp = new ContactPolicyResponse();
UUID id = UUID.randomUUID();
resp.setId(id);
resp.setTypePolitique("OUVERT");
resp.setAutoriserNotesVocales(true);
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getTypePolitique()).isEqualTo("OUVERT");
assertThat(resp.isAutoriserNotesVocales()).isTrue();
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID id = UUID.randomUUID();
UUID org = UUID.randomUUID();
ContactPolicyResponse a = ContactPolicyResponse.builder().id(id).organisationId(org).typePolitique("OUVERT").build();
ContactPolicyResponse b = ContactPolicyResponse.builder().id(id).organisationId(org).typePolitique("OUVERT").build();
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
ContactPolicyResponse resp = ContactPolicyResponse.builder()
.id(UUID.randomUUID())
.typePolitique("OUVERT")
.build();
assertThat(resp.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,140 @@
package dev.lions.unionflow.server.api.dto.messagerie.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("ConversationResponse")
class ConversationResponseTest {
@Test
@DisplayName("builder — conversation directe avec messages et participants")
void builder_conversationComplète() {
UUID id = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
LocalDateTime dateCreation = LocalDateTime.of(2026, 4, 1, 9, 0);
ConversationResponse.ParticipantResponse p1 = ConversationResponse.ParticipantResponse.builder()
.membreId(UUID.randomUUID())
.prenom("Alice")
.nom("Dupont")
.roleDansConversation("INITIATEUR")
.build();
MessageResponse msg = MessageResponse.builder()
.id(UUID.randomUUID())
.typeMessage("TEXTE")
.contenu("Bonjour !")
.build();
ConversationResponse resp = ConversationResponse.builder()
.id(id)
.typeConversation("DIRECTE")
.titre("Alice Dupont")
.statut("ACTIVE")
.organisationId(orgId)
.organisationNom("Association Lions")
.dateCreation(dateCreation)
.nombreMessages(1)
.participants(List.of(p1))
.messages(List.of(msg))
.nonLus(0L)
.build();
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getTypeConversation()).isEqualTo("DIRECTE");
assertThat(resp.getTitre()).isEqualTo("Alice Dupont");
assertThat(resp.getStatut()).isEqualTo("ACTIVE");
assertThat(resp.getOrganisationId()).isEqualTo(orgId);
assertThat(resp.getOrganisationNom()).isEqualTo("Association Lions");
assertThat(resp.getDateCreation()).isEqualTo(dateCreation);
assertThat(resp.getNombreMessages()).isEqualTo(1);
assertThat(resp.getParticipants()).hasSize(1);
assertThat(resp.getMessages()).hasSize(1);
assertThat(resp.getNonLus()).isZero();
}
@Test
@DisplayName("builder — canal rôle")
void builder_canalRole() {
ConversationResponse resp = ConversationResponse.builder()
.typeConversation("ROLE_CANAL")
.roleCible("TRESORIER")
.titre("Trésorier")
.statut("ACTIVE")
.build();
assertThat(resp.getTypeConversation()).isEqualTo("ROLE_CANAL");
assertThat(resp.getRoleCible()).isEqualTo("TRESORIER");
assertThat(resp.getTitre()).isEqualTo("Trésorier");
}
@Test
@DisplayName("constructeur no-args — valeurs par défaut")
void noArgsConstructor_defaults() {
ConversationResponse resp = new ConversationResponse();
assertThat(resp.getId()).isNull();
assertThat(resp.getParticipants()).isNull();
assertThat(resp.getMessages()).isNull();
assertThat(resp.getNonLus()).isZero();
assertThat(resp.getNombreMessages()).isZero();
}
@Test
@DisplayName("ParticipantResponse builder — tous les champs")
void participantResponse_builder() {
UUID membreId = UUID.randomUUID();
LocalDateTime luJusqua = LocalDateTime.now();
ConversationResponse.ParticipantResponse p = ConversationResponse.ParticipantResponse.builder()
.membreId(membreId)
.prenom("Bob")
.nom("Martin")
.roleDansConversation("PARTICIPANT")
.luJusqua(luJusqua)
.build();
assertThat(p.getMembreId()).isEqualTo(membreId);
assertThat(p.getPrenom()).isEqualTo("Bob");
assertThat(p.getNom()).isEqualTo("Martin");
assertThat(p.getRoleDansConversation()).isEqualTo("PARTICIPANT");
assertThat(p.getLuJusqua()).isEqualTo(luJusqua);
}
@Test
@DisplayName("ParticipantResponse no-args — valeurs nulles")
void participantResponse_noArgsConstructor() {
ConversationResponse.ParticipantResponse p = new ConversationResponse.ParticipantResponse();
assertThat(p.getMembreId()).isNull();
assertThat(p.getPrenom()).isNull();
assertThat(p.getLuJusqua()).isNull();
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID id = UUID.randomUUID();
ConversationResponse a = ConversationResponse.builder().id(id).titre("Alice").build();
ConversationResponse b = ConversationResponse.builder().id(id).titre("Alice").build();
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
ConversationResponse resp = ConversationResponse.builder()
.id(UUID.randomUUID())
.typeConversation("DIRECTE")
.build();
assertThat(resp.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,102 @@
package dev.lions.unionflow.server.api.dto.messagerie.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("ConversationSummaryResponse")
class ConversationSummaryResponseTest {
@Test
@DisplayName("builder — conversation directe")
void builder_conversationDirecte() {
UUID id = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
LocalDateTime dernierMsg = LocalDateTime.of(2026, 4, 13, 14, 0);
ConversationSummaryResponse resp = ConversationSummaryResponse.builder()
.id(id)
.typeConversation("DIRECTE")
.titre("Alice Dupont")
.statut("ACTIVE")
.dernierMessageApercu("Bonjour !")
.dernierMessageType("TEXTE")
.dernierMessageAt(dernierMsg)
.nonLus(3L)
.organisationId(orgId)
.build();
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getTypeConversation()).isEqualTo("DIRECTE");
assertThat(resp.getTitre()).isEqualTo("Alice Dupont");
assertThat(resp.getStatut()).isEqualTo("ACTIVE");
assertThat(resp.getDernierMessageApercu()).isEqualTo("Bonjour !");
assertThat(resp.getDernierMessageType()).isEqualTo("TEXTE");
assertThat(resp.getDernierMessageAt()).isEqualTo(dernierMsg);
assertThat(resp.getNonLus()).isEqualTo(3L);
assertThat(resp.getOrganisationId()).isEqualTo(orgId);
}
@Test
@DisplayName("builder — canal rôle (Trésorier)")
void builder_canalRole() {
ConversationSummaryResponse resp = ConversationSummaryResponse.builder()
.typeConversation("ROLE_CANAL")
.titre("Trésorier")
.statut("ACTIVE")
.nonLus(0L)
.build();
assertThat(resp.getTypeConversation()).isEqualTo("ROLE_CANAL");
assertThat(resp.getTitre()).isEqualTo("Trésorier");
assertThat(resp.getNonLus()).isZero();
}
@Test
@DisplayName("constructeur no-args — valeurs par défaut")
void noArgsConstructor_defaults() {
ConversationSummaryResponse resp = new ConversationSummaryResponse();
assertThat(resp.getId()).isNull();
assertThat(resp.getTypeConversation()).isNull();
assertThat(resp.getNonLus()).isZero();
}
@Test
@DisplayName("setters et getters fonctionnent")
void settersGetters() {
ConversationSummaryResponse resp = new ConversationSummaryResponse();
resp.setTitre("Bob Martin");
resp.setStatut("ARCHIVEE");
resp.setNonLus(5L);
assertThat(resp.getTitre()).isEqualTo("Bob Martin");
assertThat(resp.getStatut()).isEqualTo("ARCHIVEE");
assertThat(resp.getNonLus()).isEqualTo(5L);
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID id = UUID.randomUUID();
ConversationSummaryResponse a = ConversationSummaryResponse.builder().id(id).titre("Alice").build();
ConversationSummaryResponse b = ConversationSummaryResponse.builder().id(id).titre("Alice").build();
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
ConversationSummaryResponse resp = ConversationSummaryResponse.builder()
.id(UUID.randomUUID())
.typeConversation("DIRECTE")
.build();
assertThat(resp.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,134 @@
package dev.lions.unionflow.server.api.dto.messagerie.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("MessageResponse")
class MessageResponseTest {
@Test
@DisplayName("builder — message texte complet")
void builder_messageTexte() {
UUID id = UUID.randomUUID();
UUID expediteurId = UUID.randomUUID();
LocalDateTime dateEnvoi = LocalDateTime.of(2026, 4, 13, 10, 30);
MessageResponse resp = MessageResponse.builder()
.id(id)
.typeMessage("TEXTE")
.contenu("Bonjour tout le monde !")
.supprime(false)
.expediteurId(expediteurId)
.expediteurNom("Dupont")
.expediteurPrenom("Alice")
.dateEnvoi(dateEnvoi)
.build();
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getTypeMessage()).isEqualTo("TEXTE");
assertThat(resp.getContenu()).isEqualTo("Bonjour tout le monde !");
assertThat(resp.isSupprime()).isFalse();
assertThat(resp.getExpediteurId()).isEqualTo(expediteurId);
assertThat(resp.getExpediteurNom()).isEqualTo("Dupont");
assertThat(resp.getExpediteurPrenom()).isEqualTo("Alice");
assertThat(resp.getDateEnvoi()).isEqualTo(dateEnvoi);
}
@Test
@DisplayName("builder — note vocale")
void builder_noteVocale() {
MessageResponse resp = MessageResponse.builder()
.typeMessage("VOCAL")
.urlFichier("https://storage.example.com/audio/note.opus")
.dureeAudio(67)
.supprime(false)
.build();
assertThat(resp.getTypeMessage()).isEqualTo("VOCAL");
assertThat(resp.getUrlFichier()).isEqualTo("https://storage.example.com/audio/note.opus");
assertThat(resp.getDureeAudio()).isEqualTo(67);
assertThat(resp.getContenu()).isNull();
}
@Test
@DisplayName("builder — message supprimé")
void builder_messageSupprime() {
MessageResponse resp = MessageResponse.builder()
.typeMessage("TEXTE")
.contenu("[Message supprimé]")
.supprime(true)
.build();
assertThat(resp.isSupprime()).isTrue();
assertThat(resp.getContenu()).isEqualTo("[Message supprimé]");
}
@Test
@DisplayName("builder — réponse à un message parent")
void builder_avecParent() {
UUID parentId = UUID.randomUUID();
MessageResponse resp = MessageResponse.builder()
.typeMessage("TEXTE")
.contenu("Tout à fait !")
.messageParentId(parentId)
.messageParentApercu("Êtes-vous disponible demain ?")
.build();
assertThat(resp.getMessageParentId()).isEqualTo(parentId);
assertThat(resp.getMessageParentApercu()).isEqualTo("Êtes-vous disponible demain ?");
}
@Test
@DisplayName("constructeur no-args — valeurs par défaut")
void noArgsConstructor_defaults() {
MessageResponse resp = new MessageResponse();
assertThat(resp.getId()).isNull();
assertThat(resp.getTypeMessage()).isNull();
assertThat(resp.getContenu()).isNull();
assertThat(resp.isSupprime()).isFalse();
}
@Test
@DisplayName("setters et getters fonctionnent")
void settersGetters() {
MessageResponse resp = new MessageResponse();
UUID id = UUID.randomUUID();
resp.setId(id);
resp.setTypeMessage("IMAGE");
resp.setUrlFichier("https://img.example.com/photo.jpg");
resp.setSupprime(false);
assertThat(resp.getId()).isEqualTo(id);
assertThat(resp.getTypeMessage()).isEqualTo("IMAGE");
assertThat(resp.getUrlFichier()).isEqualTo("https://img.example.com/photo.jpg");
}
@Test
@DisplayName("equals et hashCode — même données")
void equalsHashCode_sameData() {
UUID id = UUID.randomUUID();
MessageResponse a = MessageResponse.builder().id(id).typeMessage("TEXTE").build();
MessageResponse b = MessageResponse.builder().id(id).typeMessage("TEXTE").build();
assertThat(a).isEqualTo(b);
assertThat(a.hashCode()).isEqualTo(b.hashCode());
}
@Test
@DisplayName("toString non null")
void toString_nonNull() {
MessageResponse resp = MessageResponse.builder()
.id(UUID.randomUUID())
.typeMessage("TEXTE")
.contenu("hello")
.build();
assertThat(resp.toString()).isNotNull().isNotEmpty();
}
}

View File

@@ -0,0 +1,44 @@
package dev.lions.unionflow.server.api.dto.mutuelle.credit;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit;
import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.api.Test;
class DemandeCreditRequestTest {
@Test
void testConstructeurParDefaut() {
assertThat(new DemandeCreditRequest()).isNotNull();
}
@Test
void testSettersEtGetters() {
DemandeCreditRequest req = new DemandeCreditRequest();
req.setMembreId("m-1");
req.setTypeCredit(TypeCredit.CONSOMMATION);
req.setMontantDemande(new BigDecimal("500000"));
req.setDureeMois(12);
req.setCompteLieId("compte-1");
req.setJustificationDetaillee("Pour achat équipement");
req.setDocumentIds(List.of("doc-1", "doc-2"));
assertThat(req.getMembreId()).isEqualTo("m-1");
assertThat(req.getTypeCredit()).isEqualTo(TypeCredit.CONSOMMATION);
assertThat(req.getMontantDemande()).isEqualByComparingTo("500000");
assertThat(req.getDureeMois()).isEqualTo(12);
assertThat(req.getDocumentIds()).hasSize(2);
}
@Test
void testBuilder() {
DemandeCreditRequest req = DemandeCreditRequest.builder()
.membreId("m-2")
.typeCredit(TypeCredit.URGENCE)
.montantDemande(new BigDecimal("100000"))
.build();
assertThat(req.getMembreId()).isEqualTo("m-2");
}
}

View File

@@ -0,0 +1,44 @@
package dev.lions.unionflow.server.api.dto.mutuelle.credit;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutDemandeCredit;
import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
class DemandeCreditResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new DemandeCreditResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
DemandeCreditResponse resp = new DemandeCreditResponse();
resp.setNumeroDossier("CREDIT-001");
resp.setMembreId("m-1");
resp.setTypeCredit(TypeCredit.CONSOMMATION);
resp.setMontantDemande(new BigDecimal("500000"));
resp.setMontantApprouve(new BigDecimal("450000"));
resp.setDureeMoisDemande(12);
resp.setDureeMoisApprouvee(10);
resp.setTauxInteretAnnuel(new BigDecimal("0.12"));
resp.setStatut(StatutDemandeCredit.APPROUVEE);
assertThat(resp.getNumeroDossier()).isEqualTo("CREDIT-001");
assertThat(resp.getTypeCredit()).isEqualTo(TypeCredit.CONSOMMATION);
assertThat(resp.getMontantApprouve()).isEqualByComparingTo("450000");
assertThat(resp.getStatut()).isEqualTo(StatutDemandeCredit.APPROUVEE);
}
@Test
void testBuilder() {
DemandeCreditResponse resp = DemandeCreditResponse.builder()
.numeroDossier("CREDIT-002")
.statut(StatutDemandeCredit.SOUMISE)
.build();
assertThat(resp.getNumeroDossier()).isEqualTo("CREDIT-002");
}
}

View File

@@ -0,0 +1,44 @@
package dev.lions.unionflow.server.api.dto.mutuelle.credit;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutEcheanceCredit;
import java.math.BigDecimal;
import java.time.LocalDate;
import org.junit.jupiter.api.Test;
class EcheanceCreditDTOTest {
@Test
void testConstructeurParDefaut() {
assertThat(new EcheanceCreditDTO()).isNotNull();
}
@Test
void testSettersEtGetters() {
EcheanceCreditDTO dto = new EcheanceCreditDTO();
dto.setDemandeCreditId("credit-1");
dto.setOrdre(1);
dto.setDateEcheancePrevue(LocalDate.of(2026, 2, 1));
dto.setCapitalAmorti(new BigDecimal("40000"));
dto.setInteretsDeLaPeriode(new BigDecimal("5000"));
dto.setMontantTotalExigible(new BigDecimal("45000"));
dto.setCapitalRestantDu(new BigDecimal("460000"));
dto.setMontantRegle(new BigDecimal("45000"));
dto.setStatut(StatutEcheanceCredit.PAYEE);
assertThat(dto.getDemandeCreditId()).isEqualTo("credit-1");
assertThat(dto.getOrdre()).isEqualTo(1);
assertThat(dto.getCapitalAmorti()).isEqualByComparingTo("40000");
assertThat(dto.getStatut()).isEqualTo(StatutEcheanceCredit.PAYEE);
}
@Test
void testBuilder() {
EcheanceCreditDTO dto = EcheanceCreditDTO.builder()
.ordre(2)
.statut(StatutEcheanceCredit.A_VENIR)
.build();
assertThat(dto.getOrdre()).isEqualTo(2);
}
}

View File

@@ -0,0 +1,45 @@
package dev.lions.unionflow.server.api.dto.mutuelle.credit;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeGarantie;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
class GarantieDemandeDTOTest {
@Test
void testConstructeurParDefaut() {
assertThat(new GarantieDemandeDTO()).isNotNull();
}
@Test
void testSettersEtGetters() {
GarantieDemandeDTO dto = new GarantieDemandeDTO();
dto.setTypeGarantie(TypeGarantie.EPARGNE_BLOQUEE);
dto.setValeurEstimee(new BigDecimal("200000"));
dto.setReferenceOuDescription("Compte épargne MEC-001");
dto.setDocumentPreuveId("doc-1");
assertThat(dto.getTypeGarantie()).isEqualTo(TypeGarantie.EPARGNE_BLOQUEE);
assertThat(dto.getValeurEstimee()).isEqualByComparingTo("200000");
assertThat(dto.getReferenceOuDescription()).isEqualTo("Compte épargne MEC-001");
assertThat(dto.getDocumentPreuveId()).isEqualTo("doc-1");
}
@Test
void testBuilder() {
GarantieDemandeDTO dto = GarantieDemandeDTO.builder()
.typeGarantie(TypeGarantie.CAUTION_SOLIDAIRE)
.referenceOuDescription("Caution membre M-002")
.build();
assertThat(dto.getTypeGarantie()).isEqualTo(TypeGarantie.CAUTION_SOLIDAIRE);
}
@Test
void testEqualsHashCode() {
GarantieDemandeDTO d1 = GarantieDemandeDTO.builder().typeGarantie(TypeGarantie.EPARGNE_BLOQUEE).referenceOuDescription("r").build();
GarantieDemandeDTO d2 = GarantieDemandeDTO.builder().typeGarantie(TypeGarantie.EPARGNE_BLOQUEE).referenceOuDescription("r").build();
assertThat(d1).isEqualTo(d2);
}
}

View File

@@ -0,0 +1,37 @@
package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
import org.junit.jupiter.api.Test;
class CompteEpargneRequestTest {
@Test
void testConstructeurParDefaut() {
assertThat(new CompteEpargneRequest()).isNotNull();
}
@Test
void testSettersEtGetters() {
CompteEpargneRequest req = new CompteEpargneRequest();
req.setMembreId("m-1");
req.setOrganisationId("org-1");
req.setTypeCompte(TypeCompteEpargne.EPARGNE_LIBRE);
req.setNotesOuverture("Ouverture initiale");
assertThat(req.getMembreId()).isEqualTo("m-1");
assertThat(req.getOrganisationId()).isEqualTo("org-1");
assertThat(req.getTypeCompte()).isEqualTo(TypeCompteEpargne.EPARGNE_LIBRE);
assertThat(req.getNotesOuverture()).isEqualTo("Ouverture initiale");
}
@Test
void testBuilder() {
CompteEpargneRequest req = CompteEpargneRequest.builder()
.membreId("m-2")
.typeCompte(TypeCompteEpargne.EPARGNE_BLOQUEE)
.build();
assertThat(req.getTypeCompte()).isEqualTo(TypeCompteEpargne.EPARGNE_BLOQUEE);
}
}

View File

@@ -0,0 +1,44 @@
package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.StatutCompteEpargne;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
import java.math.BigDecimal;
import java.time.LocalDate;
import org.junit.jupiter.api.Test;
class CompteEpargneResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new CompteEpargneResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
CompteEpargneResponse resp = new CompteEpargneResponse();
resp.setMembreId("m-1");
resp.setOrganisationId("org-1");
resp.setNumeroCompte("MEC-001");
resp.setTypeCompte(TypeCompteEpargne.EPARGNE_LIBRE);
resp.setSoldeActuel(new BigDecimal("250000"));
resp.setSoldeBloque(new BigDecimal("50000"));
resp.setStatut(StatutCompteEpargne.ACTIF);
resp.setDateOuverture(LocalDate.of(2025, 1, 1));
assertThat(resp.getNumeroCompte()).isEqualTo("MEC-001");
assertThat(resp.getTypeCompte()).isEqualTo(TypeCompteEpargne.EPARGNE_LIBRE);
assertThat(resp.getSoldeActuel()).isEqualByComparingTo("250000");
assertThat(resp.getStatut()).isEqualTo(StatutCompteEpargne.ACTIF);
}
@Test
void testBuilder() {
CompteEpargneResponse resp = CompteEpargneResponse.builder()
.numeroCompte("MEC-002")
.statut(StatutCompteEpargne.CLOTURE)
.build();
assertThat(resp.getNumeroCompte()).isEqualTo("MEC-002");
}
}

View File

@@ -0,0 +1,41 @@
package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
class TransactionEpargneRequestTest {
@Test
void testConstructeurParDefaut() {
assertThat(new TransactionEpargneRequest()).isNotNull();
}
@Test
void testSettersEtGetters() {
TransactionEpargneRequest req = new TransactionEpargneRequest();
req.setCompteId("compte-1");
req.setTypeTransaction(TypeTransactionEpargne.DEPOT);
req.setMontant(new BigDecimal("50000"));
req.setMotif("Dépôt mensuel");
req.setOrigineFonds("Salaire");
req.setPieceJustificativeId("doc-1");
assertThat(req.getCompteId()).isEqualTo("compte-1");
assertThat(req.getTypeTransaction()).isEqualTo(TypeTransactionEpargne.DEPOT);
assertThat(req.getMontant()).isEqualByComparingTo("50000");
assertThat(req.getOrigineFonds()).isEqualTo("Salaire");
}
@Test
void testBuilder() {
TransactionEpargneRequest req = TransactionEpargneRequest.builder()
.compteId("compte-2")
.typeTransaction(TypeTransactionEpargne.RETRAIT)
.montant(new BigDecimal("20000"))
.build();
assertThat(req.getTypeTransaction()).isEqualTo(TypeTransactionEpargne.RETRAIT);
}
}

View File

@@ -0,0 +1,46 @@
package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;
class TransactionEpargneResponseTest {
@Test
void testConstructeurParDefaut() {
assertThat(new TransactionEpargneResponse()).isNotNull();
}
@Test
void testSettersEtGetters() {
LocalDateTime date = LocalDateTime.now();
TransactionEpargneResponse resp = new TransactionEpargneResponse();
resp.setCompteId("compte-1");
resp.setType(TypeTransactionEpargne.DEPOT);
resp.setMontant(new BigDecimal("50000"));
resp.setSoldeAvant(new BigDecimal("200000"));
resp.setSoldeApres(new BigDecimal("250000"));
resp.setMotif("Dépôt");
resp.setDateTransaction(date);
resp.setStatutExecution(StatutTransactionWave.REUSSIE);
assertThat(resp.getCompteId()).isEqualTo("compte-1");
assertThat(resp.getType()).isEqualTo(TypeTransactionEpargne.DEPOT);
assertThat(resp.getMontant()).isEqualByComparingTo("50000");
assertThat(resp.getSoldeApres()).isEqualByComparingTo("250000");
assertThat(resp.getStatutExecution()).isEqualTo(StatutTransactionWave.REUSSIE);
}
@Test
void testBuilder() {
TransactionEpargneResponse resp = TransactionEpargneResponse.builder()
.compteId("c-1")
.type(TypeTransactionEpargne.TRANSFERT_ENTRANT)
.build();
assertThat(resp.getType()).isEqualTo(TypeTransactionEpargne.TRANSFERT_ENTRANT);
}
}

Some files were not shown because too many files have changed in this diff Show More