Compare commits

...

5 Commits

Author SHA1 Message Date
dahoud
5fa4711a8f feat(api): DTOs v3.0 — membre computed fields, CreateMembreRequest builder, souscription DTOs, RBAC enums enrichis
- MembreResponse: ajout getInitiales(), getDateAdhesionFormatee(), getStatut(), getSeverity() computed
- CotisationResponse: alias getMethodePaiementLibelle()
- CreateMembreRequest: builder pattern, organisationId UUID
- Nouveaux DTOs souscription: FormuleAbonnementResponse, SouscriptionDemandeRequest, SouscriptionStatutResponse
- Nouveaux enums: PlageMembres, StatutValidationSouscription, TypeOrganisationFacturation
- StatutMembre enrichi (RADIE, ARCHIVE, INVITE, EN_ATTENTE_VALIDATION)
- TypeOrganisation, TypeFormule, StatutSouscription mis à jour
2026-04-07 20:51:10 +00:00
dahoud
fb14bac741 test(communication): atteindre 100% de couverture API
Ajout de tests unitaires complets pour le module communication :
- 4 tests enum (ConversationType, MessageType, MessageStatus, MessagePriority)
- 4 tests DTO (ConversationResponse, MessageResponse, CreateConversationRequest, SendMessageRequest)

Résultat : 100% couverture sur unionflow-server-api
- Instructions : 17 436 / 17 436 (100%)
- Branches : 1 725 / 1 725 (100%)
- Lignes : 2 924 / 2 924 (100%)
- Méthodes : 1 017 / 1 017 (100%)
- Classes : 186 / 186 (100%)

2911 tests passent avec succès.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-18 01:50:27 +00:00
dahoud
98cffc4243 feat(api): T004 - ajout champs LCB-FT dans PaiementResponse
- Ajout origineFonds (String)
- Ajout justificationLcbFt (String)

Spec 001-mutuelles-anti-blanchiment - Phase 1 API
Task T004 complétée : DTOs intentions paiement étendus pour LCB-FT
2026-03-17 10:50:26 +00:00
dahoud
cbf911caa8 feat(api): DTOs et enums pour système de messagerie
Ajout des DTOs et enums nécessaires au système de communication/messaging.

Enums (communication):
- ConversationType: INDIVIDUAL, GROUP, BROADCAST, ANNOUNCEMENT
- MessageType: INDIVIDUAL, BROADCAST, TARGETED, SYSTEM
- MessageStatus: SENT, DELIVERED, READ, FAILED
- MessagePriority: NORMAL, HIGH, URGENT

DTOs Request:
- CreateConversationRequest: name, description, type, participantIds, organisationId
- SendMessageRequest: conversationId, content, type, priority, recipientIds, etc.

DTOs Response:
- ConversationResponse: données complètes conversation + lastMessage + unreadCount
- MessageResponse: données complètes message

Tâche: #60 - Communication Backend (Part 1/2 - API)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-16 06:35:30 +00:00
dahoud
bc7e4b92e9 feat(api): ajout organisationId à CreateMembreRequest
Ajoute le champ organisationId (UUID, optionnel) au DTO CreateMembreRequest
pour supporter la création de membres par ADMIN_ORGANISATION dans une
organisation spécifique.

CreateMembreRequest.java:
- Ajout import java.util.UUID
- Ajout paramètre organisationId dans le record
- Mise à jour javadoc avec description du champ

TestDataFactory.java:
- Ajout null comme dernierparamètre (organisationId) dans
  createCreateMembreRequest() pour compatibilité avec le nouveau DTO

Spec: admin-org-membres-import-quota.md
Tâche: #56 - Implémenter Spec Admin Import Membres

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-16 06:08:22 +00:00
171 changed files with 19341 additions and 451 deletions

276
CLASSES_SANS_TESTS.md Normal file
View File

@@ -0,0 +1,276 @@
# Classes sans Tests - UnionFlow Server API
**Date d'analyse**: 2026-03-15
**Couverture globale**: 72% (4635 instructions manquées sur 16697)
**Classes sans tests**: 91 classes (0% de couverture)
---
## 1. DTOs REQUEST (dev.lions.unionflow.server.api.dto)
### 1.1 Solidarité (8 classes - 0%)
- `dev.lions.unionflow.server.api.dto.solidarite.request.CreateCommentaireAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.CreateDemandeAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.CreateEvaluationAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.CreatePropositionAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.UpdateCommentaireAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.UpdateDemandeAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.UpdateEvaluationAideRequest`
- `dev.lions.unionflow.server.api.dto.solidarite.request.UpdatePropositionAideRequest`
### 1.2 Comptabilité (8 classes - 0%)
- `dev.lions.unionflow.server.api.dto.comptabilite.request.CreateCompteComptableRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.CreateEcritureComptableRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.CreateJournalComptableRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.CreateLigneEcritureRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.UpdateCompteComptableRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.UpdateEcritureComptableRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.UpdateJournalComptableRequest`
- `dev.lions.unionflow.server.api.dto.comptabilite.request.UpdateLigneEcritureRequest`
### 1.3 Paiement (4 classes - 0%)
- `dev.lions.unionflow.server.api.dto.paiement.request.CreatePaiementRequest`
- `dev.lions.unionflow.server.api.dto.paiement.request.DeclarerPaiementManuelRequest`
- `dev.lions.unionflow.server.api.dto.paiement.request.InitierDepotEpargneRequest`
- `dev.lions.unionflow.server.api.dto.paiement.request.InitierPaiementEnLigneRequest`
### 1.4 Notification (4 classes - 0%)
- `dev.lions.unionflow.server.api.dto.notification.request.CreateNotificationRequest`
- `dev.lions.unionflow.server.api.dto.notification.request.CreateTemplateNotificationRequest`
- `dev.lions.unionflow.server.api.dto.notification.request.UpdateNotificationRequest`
- `dev.lions.unionflow.server.api.dto.notification.request.UpdateTemplateNotificationRequest`
### 1.5 Document (4 classes - 0%)
- `dev.lions.unionflow.server.api.dto.document.request.CreateDocumentRequest`
- `dev.lions.unionflow.server.api.dto.document.request.CreatePieceJointeRequest`
- `dev.lions.unionflow.server.api.dto.document.request.UpdateDocumentRequest`
- `dev.lions.unionflow.server.api.dto.document.request.UpdatePieceJointeRequest`
### 1.6 Abonnement (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.abonnement.request.CreateAbonnementRequest`
- `dev.lions.unionflow.server.api.dto.abonnement.request.UpdateAbonnementRequest`
### 1.7 Événement (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.evenement.request.CreateEvenementRequest`
- `dev.lions.unionflow.server.api.dto.evenement.request.UpdateEvenementRequest`
### 1.8 Formule Abonnement (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.formuleabonnement.request.CreateFormuleAbonnementRequest`
- `dev.lions.unionflow.server.api.dto.formuleabonnement.request.UpdateFormuleAbonnementRequest`
### 1.9 Organisation (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.organisation.request.CreateOrganisationRequest`
- `dev.lions.unionflow.server.api.dto.organisation.request.UpdateOrganisationRequest`
### 1.10 Adresse (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.adresse.request.CreateAdresseRequest`
- `dev.lions.unionflow.server.api.dto.adresse.request.UpdateAdresseRequest`
### 1.11 Membre (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.membre.request.CreateMembreRequest`
- `dev.lions.unionflow.server.api.dto.membre.request.UpdateMembreRequest`
### 1.12 Cotisation (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.cotisation.request.CreateCotisationRequest`
- `dev.lions.unionflow.server.api.dto.cotisation.request.UpdateCotisationRequest`
### 1.13 Référence (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.reference.request.CreateTypeReferenceRequest`
- `dev.lions.unionflow.server.api.dto.reference.request.UpdateTypeReferenceRequest`
### 1.14 Suggestion (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.suggestion.request.CreateSuggestionRequest`
- `dev.lions.unionflow.server.api.dto.suggestion.request.UpdateSuggestionRequest`
### 1.15 Finance (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.finance.request.CreateAdhesionRequest`
- `dev.lions.unionflow.server.api.dto.finance.request.UpdateAdhesionRequest`
### 1.16 User (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.user.request.CreateUserRequest`
- `dev.lions.unionflow.server.api.dto.user.request.UpdateUserRequest`
### 1.17 Configuration (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.config.request.CreateConfigurationRequest`
- `dev.lions.unionflow.server.api.dto.config.request.UpdateConfigurationRequest`
### 1.18 Ticket (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.ticket.request.CreateTicketRequest`
- `dev.lions.unionflow.server.api.dto.ticket.request.UpdateTicketRequest`
### 1.19 Rôle (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.role.request.CreateRoleRequest`
- `dev.lions.unionflow.server.api.dto.role.request.UpdateRoleRequest`
### 1.20 Admin (1 classe - 0%)
- `dev.lions.unionflow.server.api.dto.admin.request.CreateAdminRequest`
### 1.21 Favoris (1 classe - 0%)
- `dev.lions.unionflow.server.api.dto.favoris.request.CreateFavoriRequest`
---
## 2. DTOs RESPONSE (dev.lions.unionflow.server.api.dto)
### 2.1 Paiement (1 classe - 0%)
- `dev.lions.unionflow.server.api.dto.paiement.response.PaiementGatewayResponse`
### 2.2 Cotisation (1 classe - 0%)
- `dev.lions.unionflow.server.api.dto.cotisation.response.CotisationSummaryResponse`
### 2.3 Adresse (1 classe - 0%)
- `dev.lions.unionflow.server.api.dto.adresse.response.AdresseResponse`
### 2.4 Admin (1 classe - 0%)
- `dev.lions.unionflow.server.api.dto.admin.response.AdminResponse`
---
## 3. AUTRES DTOs
### 3.1 Wave (2 classes - 0%)
- `dev.lions.unionflow.server.api.dto.wave.CompteWaveDTO`
- `dev.lions.unionflow.server.api.dto.wave.TransactionWaveDTO`
---
## 4. ENUMS (dev.lions.unionflow.server.api.enums)
### 4.1 Mutuelle - Crédit (4 classes - 0%)
- `dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutDemandeCredit`
- `dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutEcheanceCredit`
- `dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit`
- `dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeGarantie`
### 4.2 Mutuelle - Épargne (3 classes - 0%)
- `dev.lions.unionflow.server.api.enums.mutuelle.epargne.StatutCompteEpargne`
- `dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne`
- `dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne`
### 4.3 Vote (3 classes - 0%)
- `dev.lions.unionflow.server.api.enums.vote.ModeScrutin`
- `dev.lions.unionflow.server.api.enums.vote.StatutVote`
- `dev.lions.unionflow.server.api.enums.vote.TypeVote`
### 4.4 Tontine (3 classes - 0%)
- `dev.lions.unionflow.server.api.enums.tontine.FrequenceTour`
- `dev.lions.unionflow.server.api.enums.tontine.StatutTontine`
- `dev.lions.unionflow.server.api.enums.tontine.TypeTontine`
### 4.5 Ayant Droit (2 classes - 0%)
- `dev.lions.unionflow.server.api.enums.ayantdroit.StatutAyantDroit`
- `dev.lions.unionflow.server.api.enums.ayantdroit.TypeAyantDroit`
### 4.6 Agricole (1 classe - 0%)
- `dev.lions.unionflow.server.api.enums.agricole.StatutCampagneAgricole`
### 4.7 Collecte de Fonds (1 classe - 0%)
- `dev.lions.unionflow.server.api.enums.collectefonds.StatutCampagneCollecte`
### 4.8 Culte (1 classe - 0%)
- `dev.lions.unionflow.server.api.enums.culte.TypeDonReligieux`
### 4.9 ONG (1 classe - 0%)
- `dev.lions.unionflow.server.api.enums.ong.StatutProjetOng`
### 4.10 Gouvernance (1 classe - 0%)
- `dev.lions.unionflow.server.api.enums.gouvernance.NiveauEchelon`
### 4.11 Registre (1 classe - 0%)
- `dev.lions.unionflow.server.api.enums.registre.StatutAgrement`
---
## RÉCAPITULATIF PAR CATÉGORIE
| Catégorie | Nombre de classes | % du total |
|-----------|-------------------|------------|
| **DTO Requests** | **62 classes** | **68%** |
| **Enums** | **21 classes** | **23%** |
| **DTO Responses** | **4 classes** | **4%** |
| **Autres DTOs** | **2 classes** | **2%** |
| **Autres** | **2 classes** | **2%** |
| **TOTAL** | **91 classes** | **100%** |
---
## PRIORITÉS DE TEST
### P0 - Haute Priorité (Core Business)
1. **Solidarité** (8 requests) - Module métier principal
2. **Comptabilité** (8 requests) - Gestion financière critique
3. **Paiement** (4 requests + 1 response) - Transactions financières
4. **Mutuelle Crédit** (4 enums) - Microfinance core
5. **Mutuelle Épargne** (3 enums) - Microfinance core
### P1 - Priorité Moyenne (Features importantes)
6. **Notification** (4 requests) - Communication système
7. **Document** (4 requests) - Gestion documentaire
8. **Événement** (2 requests) - Gestion événementielle
9. **Organisation** (2 requests) - Structure organisationnelle
10. **Membre** (2 requests) - Gestion des utilisateurs
### P2 - Priorité Basse (Features secondaires)
11. **Abonnement** (2 requests) - Gestion des abonnements
12. **Tontine** (3 enums) - Feature spécifique
13. **Vote** (3 enums) - Feature spécifique
14. **Autres requests** (20 requests restants)
15. **Enums divers** (11 enums restants)
---
## PLAN D'ACTION
### Étape 1: Tests DTOs Request (62 classes)
- Tester getters/setters
- Tester validations Jakarta Bean Validation
- Tester méthodes equals/hashCode/toString si présentes
### Étape 2: Tests DTOs Response (4 classes)
- Tester constructeurs et builders
- Tester sérialisation JSON
### Étape 3: Tests Enums (21 classes)
- Tester valueOf() et values()
- Tester getters de valeurs
- Tester méthodes utilitaires (fromString, etc.)
### Étape 4: Tests Autres (4 classes)
- Tests spécifiques selon le type de classe
---
## TEMPLATES DE TEST RECOMMANDÉS
### Pour DTOs Request:
```java
@Test
void testCreateXxxRequest_AllFields() {
var request = new CreateXxxRequest();
// Set all fields
// Assert all fields
}
@Test
void testCreateXxxRequest_Validation() {
var request = new CreateXxxRequest();
// Test @NotNull, @Size, etc.
}
```
### Pour Enums:
```java
@Test
void testEnumValues() {
assertEquals(3, TypeXxx.values().length);
}
@Test
void testEnumValueOf() {
assertEquals(TypeXxx.VALUE1, TypeXxx.valueOf("VALUE1"));
}
```
---
**Objectif**: Atteindre **100% de couverture** sur le module unionflow-server-api.

169
analyze_jacoco.py Normal file
View File

@@ -0,0 +1,169 @@
#!/usr/bin/env python3
"""Script pour analyser le rapport JaCoCo et extraire les classes sans tests."""
import os
import re
from pathlib import Path
from html.parser import HTMLParser
class JaCoCoParser(HTMLParser):
def __init__(self):
super().__init__()
self.current_package = ""
self.classes = []
self.in_tbody = False
self.current_row = {}
self.current_cell = ""
self.cell_index = 0
def handle_starttag(self, tag, attrs):
if tag == "tbody":
self.in_tbody = True
elif tag == "tr" and self.in_tbody:
self.current_row = {}
self.cell_index = 0
elif tag == "td" and self.in_tbody:
self.current_cell = ""
elif tag == "a" and self.in_tbody:
for attr, value in attrs:
if attr == "href" and value.endswith(".html"):
self.current_row["href"] = value
def handle_endtag(self, tag):
if tag == "tbody":
self.in_tbody = False
elif tag == "tr" and self.in_tbody and self.current_row:
if "coverage" in self.current_row and self.current_row["coverage"] == "0 %":
self.classes.append(self.current_row.copy())
elif tag == "td" and self.in_tbody:
self.cell_index += 1
def handle_data(self, data):
if self.in_tbody:
data = data.strip()
if data and self.cell_index == 0:
self.current_row["name"] = data
elif data and "%" in data:
self.current_row["coverage"] = data
def analyze_package(package_path, package_name):
"""Analyse un fichier index.html de package."""
index_file = os.path.join(package_path, "index.html")
if not os.path.exists(index_file):
return []
with open(index_file, 'r', encoding='utf-8') as f:
content = f.read()
parser = JaCoCoParser()
parser.current_package = package_name
parser.feed(content)
classes = []
for row in parser.classes:
if "name" in row:
classes.append({
"package": package_name,
"class": row["name"],
"coverage": row.get("coverage", "0 %")
})
return classes
def main():
jacoco_dir = Path("target/site/jacoco")
if not jacoco_dir.exists():
print(f"Erreur: Le répertoire {jacoco_dir} n'existe pas.")
print("Veuillez exécuter 'mvn clean test' pour générer le rapport JaCoCo.")
return
# Collecter tous les packages
all_classes = []
for package_dir in jacoco_dir.iterdir():
if package_dir.is_dir() and not package_dir.name.startswith("."):
package_name = package_dir.name.replace("/", ".")
classes = analyze_package(package_dir, package_name)
all_classes.extend(classes)
# Trier par package et type
dto_requests = []
dto_responses = []
dto_other = []
enums = []
others = []
for cls in all_classes:
pkg = cls["package"]
name = cls["class"]
if "enums" in pkg:
enums.append(cls)
elif "dto" in pkg:
if ".request" in pkg:
dto_requests.append(cls)
elif ".response" in pkg:
dto_responses.append(cls)
else:
dto_other.append(cls)
else:
others.append(cls)
# Afficher les résultats
print("=" * 80)
print("CLASSES SANS TESTS (0% de couverture)")
print("=" * 80)
print()
if dto_requests:
print("1. DTOs REQUEST (dev.lions.unionflow.server.api.dto)")
print("-" * 80)
for cls in sorted(dto_requests, key=lambda x: (x["package"], x["class"])):
print(f" {cls['package']}.{cls['class']}")
print(f" Type: DTO Request | Couverture: {cls['coverage']}")
print()
if dto_responses:
print("2. DTOs RESPONSE (dev.lions.unionflow.server.api.dto)")
print("-" * 80)
for cls in sorted(dto_responses, key=lambda x: (x["package"], x["class"])):
print(f" {cls['package']}.{cls['class']}")
print(f" Type: DTO Response | Couverture: {cls['coverage']}")
print()
if dto_other:
print("3. AUTRES DTOs")
print("-" * 80)
for cls in sorted(dto_other, key=lambda x: (x["package"], x["class"])):
print(f" {cls['package']}.{cls['class']}")
print(f" Type: DTO | Couverture: {cls['coverage']}")
print()
if enums:
print("4. ENUMS (dev.lions.unionflow.server.api.enums)")
print("-" * 80)
for cls in sorted(enums, key=lambda x: (x["package"], x["class"])):
print(f" {cls['package']}.{cls['class']}")
print(f" Type: Enum | Couverture: {cls['coverage']}")
print()
if others:
print("5. AUTRES")
print("-" * 80)
for cls in sorted(others, key=lambda x: (x["package"], x["class"])):
print(f" {cls['package']}.{cls['class']}")
print(f" Type: Autre | Couverture: {cls['coverage']}")
print()
print("=" * 80)
print(f"TOTAL: {len(all_classes)} classes sans tests")
print(f" - DTO Requests: {len(dto_requests)}")
print(f" - DTO Responses: {len(dto_responses)}")
print(f" - Autres DTOs: {len(dto_other)}")
print(f" - Enums: {len(enums)}")
print(f" - Autres: {len(others)}")
print("=" * 80)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,21 @@
package dev.lions.unionflow.server.api.dto.common;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* DTO d'erreur unifié retourné par tous les endpoints REST.
* Remplace les ErrorResponse locales dupliquées dans chaque Resource.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public record ErrorResponse(String message, String error) {
/** Constructeur pratique avec message uniquement (cas le plus courant). */
public static ErrorResponse of(String message) {
return new ErrorResponse(message, null);
}
/** Constructeur pratique avec les deux champs (compatibilité avec l'ancien format). */
public static ErrorResponse ofError(String error) {
return new ErrorResponse(null, error);
}
}

View File

@@ -0,0 +1,27 @@
package dev.lions.unionflow.server.api.dto.communication.request;
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import java.util.List;
import java.util.UUID;
/**
* Request DTO pour créer une conversation
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
@Builder
public record CreateConversationRequest(
@NotBlank @Size(max = 255) String name,
@Size(max = 1000) String description,
@NotNull ConversationType type,
@NotEmpty List<UUID> participantIds,
UUID organisationId
) {}

View File

@@ -0,0 +1,29 @@
package dev.lions.unionflow.server.api.dto.communication.request;
import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
import dev.lions.unionflow.server.api.enums.communication.MessageType;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import java.util.List;
import java.util.UUID;
/**
* Request DTO pour envoyer un message
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
@Builder
public record SendMessageRequest(
@NotNull UUID conversationId,
@NotBlank @Size(max = 10000) String content,
MessageType type,
MessagePriority priority,
List<UUID> recipientIds,
List<String> recipientRoles,
List<String> attachments
) {}

View File

@@ -0,0 +1,33 @@
package dev.lions.unionflow.server.api.dto.communication.response;
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
import lombok.Builder;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
/**
* Response DTO pour Conversation
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
@Builder
public record ConversationResponse(
UUID id,
String name,
String description,
ConversationType type,
List<UUID> participantIds,
UUID organisationId,
MessageResponse lastMessage,
int unreadCount,
boolean isMuted,
boolean isPinned,
boolean isArchived,
LocalDateTime createdAt,
LocalDateTime updatedAt,
String avatarUrl
) {}

View File

@@ -0,0 +1,39 @@
package dev.lions.unionflow.server.api.dto.communication.response;
import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
import dev.lions.unionflow.server.api.enums.communication.MessageStatus;
import dev.lions.unionflow.server.api.enums.communication.MessageType;
import lombok.Builder;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
/**
* Response DTO pour Message
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
@Builder
public record MessageResponse(
UUID id,
UUID conversationId,
UUID senderId,
String senderName,
String senderAvatar,
String content,
MessageType type,
MessageStatus status,
MessagePriority priority,
List<UUID> recipientIds,
List<String> recipientRoles,
UUID organisationId,
LocalDateTime createdAt,
LocalDateTime readAt,
List<String> attachments,
boolean isEdited,
LocalDateTime editedAt,
boolean isDeleted
) {}

View File

@@ -96,6 +96,32 @@ public class CotisationResponse extends BaseResponse {
private Long joursRetard;
private Boolean enRetard;
// === MÉTHODES DE FORMATAGE ===
public String getMontantDuFormatte() {
if (montantDu == null) return "0 FCFA";
return String.format(java.util.Locale.US, "%,.0f %s", montantDu, codeDevise != null ? codeDevise : "FCFA");
}
public String getMontantPayeFormatte() {
if (montantPaye == null) return "0 FCFA";
return String.format(java.util.Locale.US, "%,.0f %s", montantPaye, codeDevise != null ? codeDevise : "FCFA");
}
public String getMontantRestantFormatte() {
if (montantRestant == null) return "0 FCFA";
return String.format(java.util.Locale.US, "%,.0f %s", montantRestant, codeDevise != null ? codeDevise : "FCFA");
}
public boolean isMontantRestantPositif() {
return montantRestant != null && montantRestant.signum() > 0;
}
/** Alias de {@link #modePaiementLibelle} pour #{cotisation.methodePaiementLibelle}. */
public String getMethodePaiementLibelle() {
return modePaiementLibelle;
}
// Informations de paiement
private String methodePaiement; // WAVE_MONEY, VIREMENT, ESPECES, CARTE, MOBILE_MONEY
private String referencePaiement; // Référence externe du paiement

View File

@@ -5,6 +5,7 @@ import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
@@ -151,10 +152,82 @@ public class EvenementResponse extends BaseResponse {
return typeEvenement != null ? typeEvenement.getLibelle() : "Non défini";
}
public String getTypeEvenementIcon() {
if (typeEvenement == null) return "pi pi-calendar";
return switch (typeEvenement) {
case ASSEMBLEE_GENERALE -> "pi pi-building";
case FORMATION -> "pi pi-book";
case REUNION_BUREAU -> "pi pi-users";
case CONFERENCE -> "pi pi-microphone";
case ATELIER -> "pi pi-wrench";
case CEREMONIE -> "pi pi-flag";
case ACTIVITE_SOCIALE, ACTION_CARITATIVE, AUTRE -> "pi pi-calendar";
};
}
public String getTypeEvenementSeverity() {
if (typeEvenement == null) return "secondary";
return switch (typeEvenement) {
case ASSEMBLEE_GENERALE -> "warning";
case FORMATION -> "info";
case ACTIVITE_SOCIALE, ACTION_CARITATIVE, REUNION_BUREAU, CONFERENCE, ATELIER, CEREMONIE, AUTRE -> "secondary";
};
}
public String getStatutLibelle() {
return statut != null ? statut.getLibelle() : "Non défini";
}
public String getStatutSeverity() {
if (statut == null) return "secondary";
return switch (statut) {
case PLANIFIE -> "info";
case EN_COURS -> "success";
case TERMINE, CONFIRME -> "secondary";
case ANNULE -> "danger";
case REPORTE -> "warning";
};
}
public String getDateDebutFormatee() {
return dateDebut != null ? dateDebut.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : "";
}
public String getHeureDebutFormatee() {
return heureDebut != null ? heureDebut.format(DateTimeFormatter.ofPattern("HH:mm")) : "";
}
public String getHeureFinFormatee() {
return heureFin != null ? heureFin.format(DateTimeFormatter.ofPattern("HH:mm")) : "";
}
public String getStatutIcon() {
if (statut == null) return "pi pi-question";
return switch (statut) {
case PLANIFIE -> "pi pi-clock";
case CONFIRME -> "pi pi-check-circle";
case EN_COURS -> "pi pi-play";
case TERMINE -> "pi pi-check";
case ANNULE -> "pi pi-times";
case REPORTE -> "pi pi-refresh";
};
}
public String getPrioriteSeverity() {
if (priorite == null) return "secondary";
return switch (priorite) {
case CRITIQUE -> "danger";
case HAUTE -> "warning";
case NORMALE -> "info";
case BASSE -> "secondary";
};
}
public String getBudgetFormate() {
if (budget == null) return "";
return String.format(java.util.Locale.US, "%,.0f %s", budget, codeDevise != null ? codeDevise : "FCFA");
}
public String getPrioriteLibelle() {
return priorite != null ? priorite.getLibelle() : "Normale";
}

View File

@@ -0,0 +1,42 @@
package dev.lions.unionflow.server.api.dto.lcbft;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* DTO de réponse pour une alerte LCB-FT.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-15
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AlerteLcbFtResponse {
private String id;
private String organisationId;
private String organisationNom;
private String membreId;
private String membreNomComplet;
private String typeAlerte;
private LocalDateTime dateAlerte;
private String description;
private String details;
private BigDecimal montant;
private BigDecimal seuil;
private String typeOperation;
private String transactionRef;
private String severite;
private Boolean traitee;
private LocalDateTime dateTraitement;
private String traitePar;
private String commentaireTraitement;
}

View File

@@ -5,6 +5,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDate;
import java.util.UUID;
import lombok.Builder;
@@ -31,6 +32,7 @@ import lombok.Builder;
* @param nationalite nationalité
* @param typeIdentite type pièce d'identité
* @param numeroIdentite numéro d'identité
* @param organisationId ID de l'organisation (obligatoire pour ADMIN_ORGANISATION)
*/
@Builder
public record CreateMembreRequest(
@@ -38,12 +40,13 @@ public record CreateMembreRequest(
@NotBlank @Size(max = 100) String nom,
@NotBlank @Email @Size(max = 255) String email,
@Size(max = 20) String telephone,
@Size(max = 13) String telephoneWave,
@Size(max = 20) String telephoneWave,
@NotNull LocalDate dateNaissance,
@Size(max = 100) String profession,
@Size(max = 500) String photoUrl,
@Size(max = 50) String statutMatrimonial,
@Size(max = 100) String nationalite,
@Size(max = 50) String typeIdentite,
@Size(max = 100) String numeroIdentite) {
@Size(max = 100) String numeroIdentite,
UUID organisationId) {
}

View File

@@ -14,7 +14,7 @@ public record UpdateMembreRequest(
@NotBlank @Size(max = 100) String nom,
@NotBlank @Email @Size(max = 255) String email,
@Size(max = 20) String telephone,
@Size(max = 13) String telephoneWave,
@Size(max = 20) String telephoneWave,
@NotNull LocalDate dateNaissance,
@Size(max = 100) String profession,
@Size(max = 500) String photoUrl,

View File

@@ -2,6 +2,7 @@ package dev.lions.unionflow.server.api.dto.membre.response;
import dev.lions.unionflow.server.api.dto.base.BaseResponse;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.List;
import lombok.AllArgsConstructor;
@@ -65,6 +66,71 @@ public class MembreResponse extends BaseResponse {
// ── Adhésion (contexte organisation) ───────
private UUID organisationId;
private String associationNom;
private String organisationNom;
private LocalDate dateAdhesion;
// ── Adresse principale ─────────────────────
private String adresse;
private String ville;
private String codePostal;
// ── Notes / biographie ─────────────────────
private String notes;
// ── Statistiques ───────────────────────────
private int nombreEvenementsParticipes;
// ── Provisionnement (retourné une seule fois à la création) ────
/** Mot de passe temporaire généré lors du provisionnement Keycloak.
* Null pour toutes les autres opérations. L'utilisateur devra le changer à la première connexion. */
private String motDePasseTemporaire;
// ── Méthodes calculées pour la compatibilité JSF EL ────────────
/** Initiales (première lettre prénom + première lettre nom) pour les avatars JSF. */
public String getInitiales() {
String p = (prenom != null && !prenom.isEmpty()) ? prenom.substring(0, 1).toUpperCase() : "";
String n = (nom != null && !nom.isEmpty()) ? nom.substring(0, 1).toUpperCase() : "";
return p + n;
}
/** Date d'adhésion formatée "dd/MM/yyyy" pour #{membre.dateAdhesionFormatee}. */
public String getDateAdhesionFormatee() {
if (dateAdhesion == null) return null;
return dateAdhesion.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
/** Alias de statutCompte pour #{membre.statut}. */
public String getStatut() {
return statutCompte;
}
/** Alias de statutCompteSeverity pour #{membre.statutSeverity}. */
public String getStatutSeverity() {
return statutCompteSeverity;
}
/** Libellé du rôle principal calculé depuis les rôles. */
public String getTypeMembre() {
if (roles == null || roles.isEmpty()) return "Membre";
if (roles.contains("PRESIDENT")) return "Président";
if (roles.contains("VICE_PRESIDENT")) return "Vice-Président";
if (roles.contains("SECRETAIRE")) return "Secrétaire";
if (roles.contains("TRESORIER")) return "Trésorier";
if (roles.contains("ADMIN_ORGANISATION")) return "Administrateur";
if (roles.contains("MODERATEUR")) return "Modérateur";
return "Membre";
}
/** Severity PrimeUI calculée depuis les rôles. */
public String getTypeSeverity() {
if (roles == null || roles.isEmpty()) return "secondary";
if (roles.contains("PRESIDENT")) return "primary";
if (roles.contains("VICE_PRESIDENT")) return "primary";
if (roles.contains("SECRETAIRE")) return "info";
if (roles.contains("TRESORIER")) return "warning";
if (roles.contains("ADMIN_ORGANISATION")) return "danger";
if (roles.contains("MODERATEUR")) return "warning";
return "secondary";
}
}

View File

@@ -1,10 +1,14 @@
package dev.lions.unionflow.server.api.dto.membre.response;
import java.util.UUID;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
/**
* DTO de réponse résumé pour Membre (listes et optimisations).
*
* <p>Ce record expose des méthodes calculées pour la compatibilité JSF EL :
* {@link #nomComplet()}, {@link #statut()}, {@link #typeMembre()}, etc.
*/
public record MembreSummaryResponse(
UUID id,
@@ -20,5 +24,107 @@ public record MembreSummaryResponse(
Boolean actif,
List<String> roles,
UUID organisationId,
String associationNom) {
String organisationNom,
LocalDate dateAdhesion) {
// ── Getters JavaBean pour compatibilité JSF EL (EL cherche getXxx()) ──────
public UUID getId() { return id; }
public String getNumeroMembre() { return numeroMembre; }
public String getPrenom() { return prenom; }
public String getNom() { return nom; }
public String getEmail() { return email; }
public String getTelephone() { return telephone; }
public String getProfession() { return profession; }
public String getStatutCompte() { return statutCompte; }
public String getStatutCompteLibelle() { return statutCompteLibelle; }
public String getStatutCompteSeverity() { return statutCompteSeverity; }
public Boolean getActif() { return actif; }
public boolean isActif() { return Boolean.TRUE.equals(actif); }
public List<String> getRoles() { return roles; }
public UUID getOrganisationId() { return organisationId; }
public String getOrganisationNom() { return organisationNom; }
public LocalDate getDateAdhesion() { return dateAdhesion; }
// Getters JavaBean pour les propriétés calculées
public String getNomComplet() { return nomComplet(); }
public String getStatut() { return statut(); }
public String getStatutLibelle() { return statutLibelle(); }
public String getStatutSeverity() { return statutSeverity(); }
public String getStatutIcon() { return statutIcon(); }
public String getTypeMembre() { return typeMembre(); }
public String getTypeSeverity() { return typeSeverity(); }
public String getTypeIcon() { return typeIcon(); }
// ── Propriétés calculées pour la compatibilité JSF EL ──────────────────
/** Prénom + Nom concaténés. */
public String nomComplet() {
String p = prenom != null ? prenom.trim() : "";
String n = nom != null ? nom.trim() : "";
return (p + " " + n).trim();
}
/** Alias de {@link #statutCompte()} pour #{membre.statut}. */
public String statut() {
return statutCompte;
}
/** Alias de {@link #statutCompteLibelle()} pour #{membre.statutLibelle}. */
public String statutLibelle() {
return statutCompteLibelle;
}
/** Alias de {@link #statutCompteSeverity()} pour #{membre.statutSeverity}. */
public String statutSeverity() {
return statutCompteSeverity;
}
/** Icône PrimeIcons calculée depuis {@link #statutCompte()}. */
public String statutIcon() {
if (statutCompte == null) return "pi pi-question-circle";
return switch (statutCompte) {
case "ACTIF" -> "pi pi-check-circle";
case "INACTIF" -> "pi pi-pause-circle";
case "SUSPENDU" -> "pi pi-ban";
case "RADIE" -> "pi pi-times-circle";
default -> "pi pi-question-circle";
};
}
/** Libellé du rôle principal calculé depuis {@link #roles()}. */
public String typeMembre() {
if (roles == null || roles.isEmpty()) return "Membre";
if (roles.contains("PRESIDENT")) return "Président";
if (roles.contains("VICE_PRESIDENT")) return "Vice-Président";
if (roles.contains("SECRETAIRE")) return "Secrétaire";
if (roles.contains("TRESORIER")) return "Trésorier";
if (roles.contains("ADMIN_ORGANISATION")) return "Administrateur";
if (roles.contains("MODERATEUR")) return "Modérateur";
return "Membre";
}
/** Severity PrimeUI calculée depuis {@link #roles()}. */
public String typeSeverity() {
if (roles == null || roles.isEmpty()) return "secondary";
if (roles.contains("PRESIDENT")) return "primary";
if (roles.contains("VICE_PRESIDENT")) return "primary";
if (roles.contains("SECRETAIRE")) return "info";
if (roles.contains("TRESORIER")) return "warning";
if (roles.contains("ADMIN_ORGANISATION")) return "danger";
if (roles.contains("MODERATEUR")) return "warning";
return "secondary";
}
/** Icône PrimeIcons calculée depuis {@link #roles()}. */
public String typeIcon() {
if (roles == null || roles.isEmpty()) return "pi pi-user";
if (roles.contains("PRESIDENT")) return "pi pi-star";
if (roles.contains("VICE_PRESIDENT")) return "pi pi-star";
if (roles.contains("SECRETAIRE")) return "pi pi-file-edit";
if (roles.contains("TRESORIER")) return "pi pi-wallet";
if (roles.contains("ADMIN_ORGANISATION")) return "pi pi-shield";
if (roles.contains("MODERATEUR")) return "pi pi-wrench";
return "pi pi-user";
}
}

View File

@@ -70,5 +70,12 @@ public record CreateOrganisationRequest(
@Size(max = 1000) String partenaires,
@Size(max = 1000) String notes,
BigDecimal latitude,
BigDecimal longitude) {
BigDecimal longitude,
@Size(max = 500) String adresse,
@Size(max = 100) String ville,
@Size(max = 100) String region,
@Size(max = 100) String pays,
@Size(max = 20) String codePostal,
Boolean organisationPublique,
Boolean accepteNouveauxMembres) {
}

View File

@@ -44,5 +44,12 @@ public record UpdateOrganisationRequest(
@Size(max = 1000) String partenaires,
@Size(max = 1000) String notes,
BigDecimal latitude,
BigDecimal longitude) {
BigDecimal longitude,
@Size(max = 500) String adresse,
@Size(max = 100) String ville,
@Size(max = 100) String region,
@Size(max = 100) String pays,
@Size(max = 20) String codePostal,
Boolean organisationPublique,
Boolean accepteNouveauxMembres) {
}

View File

@@ -29,7 +29,7 @@ public record InitierPaiementEnLigneRequest(
message = "Méthode de paiement invalide. Valeurs autorisées : WAVE, ORANGE_MONEY, FREE_MONEY, CARTE_BANCAIRE")
String methodePaiement,
@NotBlank(message = "Le numéro de téléphone est obligatoire")
/** 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,

View File

@@ -0,0 +1,24 @@
package dev.lions.unionflow.server.api.dto.paiement.response;
import java.math.BigDecimal;
import java.util.UUID;
import lombok.Builder;
/**
* Réponse du polling de statut d'une IntentionPaiement Wave.
* Utilisée par le web pour savoir si le paiement est confirmé.
*/
@Builder
public record IntentionStatutResponse(
UUID intentionId,
/** INITIEE | EN_COURS | COMPLETEE | EXPIREE | ECHOUEE */
String statut,
/** URL à encoder en QR code (wave_launch_url Wave Checkout) */
String waveLaunchUrl,
String waveCheckoutSessionId,
/** ID de transaction Wave (TCN...) — disponible quand COMPLETEE */
String waveTransactionId,
BigDecimal montant,
String referenceCotisation,
String message
) {}

View File

@@ -44,4 +44,8 @@ public class PaiementResponse extends BaseResponse {
// Intégration Wave
private UUID transactionWaveId;
// LCB-FT (Lutte Contre le Blanchiment et Financement du Terrorisme)
private String origineFonds;
private String justificationLcbFt;
}

View File

@@ -0,0 +1,128 @@
package dev.lions.unionflow.server.api.dto.souscription;
import java.math.BigDecimal;
/**
* Représentation publique d'une formule d'abonnement UnionFlow.
*
* <p>Retournée par le endpoint {@code GET /api/souscriptions/formules} (PermitAll).
* Les prix affichés sont les prix de base avant application des coefficients
* de type d'organisation et de période.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-30
*/
public class FormuleAbonnementResponse {
/** Code de la formule : BASIC, STANDARD, PREMIUM */
private String code;
/** Libellé court de la formule */
private String libelle;
/** Description marketing de la formule */
private String description;
/** Code de la plage de membres : PETITE, MOYENNE, GRANDE, TRES_GRANDE */
private String plage;
/** Libellé de la plage (ex: "Petite structure (1100 membres)") */
private String plageLibelle;
/** Nombre minimum de membres pour cette plage */
private int minMembres;
/**
* Nombre maximum de membres pour cette plage.
* -1 signifie illimité (TRES_GRANDE).
*/
private int maxMembres;
/** Prix mensuel de base en XOF (sans remise de période ni coefficient) */
private BigDecimal prixMensuel;
/** Prix annuel équivalent (prixMensuel × 12 × coefficient annuel) */
private BigDecimal prixAnnuel;
/** Ordre d'affichage dans le catalogue */
private int ordreAffichage;
// ── Champs Option C ───────────────────────────────────────────────────────
/** Nom commercial du plan (MICRO, DECOUVERTE, ESSENTIEL, AVANCE, PROFESSIONNEL, ENTERPRISE) */
private String planCommercial;
/** Niveau de reporting (BASIQUE, STANDARD, AVANCE) */
private String niveauReporting;
/** Accès à l'API REST inclus */
private boolean apiAccess;
/** Module fédération multi-org inclus (ENTERPRISE) */
private boolean federationAccess;
/** Support prioritaire inclus */
private boolean supportPrioritaire;
/** SLA garanti (ex: "99.0%", "99.9%") */
private String slaGaranti;
/** Nombre maximum d'administrateurs (-1 = illimité) */
private int maxAdmins;
public FormuleAbonnementResponse() {}
// ─── Getters & Setters ───────────────────────────────────────────────────────
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getPlage() { return plage; }
public void setPlage(String plage) { this.plage = plage; }
public String getPlageLibelle() { return plageLibelle; }
public void setPlageLibelle(String plageLibelle) { this.plageLibelle = plageLibelle; }
public int getMinMembres() { return minMembres; }
public void setMinMembres(int minMembres) { this.minMembres = minMembres; }
public int getMaxMembres() { return maxMembres; }
public void setMaxMembres(int maxMembres) { this.maxMembres = maxMembres; }
public BigDecimal getPrixMensuel() { return prixMensuel; }
public void setPrixMensuel(BigDecimal prixMensuel) { this.prixMensuel = prixMensuel; }
public BigDecimal getPrixAnnuel() { return prixAnnuel; }
public void setPrixAnnuel(BigDecimal prixAnnuel) { this.prixAnnuel = prixAnnuel; }
public int getOrdreAffichage() { return ordreAffichage; }
public void setOrdreAffichage(int ordreAffichage) { this.ordreAffichage = ordreAffichage; }
public String getPlanCommercial() { return planCommercial; }
public void setPlanCommercial(String planCommercial) { this.planCommercial = planCommercial; }
public String getNiveauReporting() { return niveauReporting; }
public void setNiveauReporting(String niveauReporting) { this.niveauReporting = niveauReporting; }
public boolean isApiAccess() { return apiAccess; }
public void setApiAccess(boolean apiAccess) { this.apiAccess = apiAccess; }
public boolean isFederationAccess() { return federationAccess; }
public void setFederationAccess(boolean federationAccess) { this.federationAccess = federationAccess; }
public boolean isSupportPrioritaire() { return supportPrioritaire; }
public void setSupportPrioritaire(boolean supportPrioritaire) { this.supportPrioritaire = supportPrioritaire; }
public String getSlaGaranti() { return slaGaranti; }
public void setSlaGaranti(String slaGaranti) { this.slaGaranti = slaGaranti; }
public int getMaxAdmins() { return maxAdmins; }
public void setMaxAdmins(int maxAdmins) { this.maxAdmins = maxAdmins; }
}

View File

@@ -0,0 +1,79 @@
package dev.lions.unionflow.server.api.dto.souscription;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
* Requête de création d'une demande de souscription UnionFlow.
*
* <p>Envoyée par l'ADMIN_ORGANISATION lors de l'onboarding pour sélectionner
* la formule, la plage de membres, la période et le type de son organisation.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-30
*/
public class SouscriptionDemandeRequest {
/** Niveau de formule : BASIC, STANDARD, PREMIUM */
@NotBlank(message = "Le type de formule est obligatoire")
private String typeFormule;
/** Tranche de membres : PETITE, MOYENNE, GRANDE, TRES_GRANDE */
@NotBlank(message = "La plage de membres est obligatoire")
private String plageMembres;
/** Périodicité de facturation : MENSUEL, TRIMESTRIEL, SEMESTRIEL, ANNUEL */
@NotBlank(message = "Le type de période est obligatoire")
private String typePeriode;
/** Type d'organisation pour le calcul du coefficient : ASSOCIATION, MUTUELLE, COOPERATIVE, FEDERATION
* Optionnel — si absent, le service le dérive depuis l'entité Organisation. */
private String typeOrganisation;
/** UUID de l'organisation concernée */
@NotNull(message = "L'identifiant de l'organisation est obligatoire")
private String organisationId;
public SouscriptionDemandeRequest() {}
public String getTypeFormule() {
return typeFormule;
}
public void setTypeFormule(String typeFormule) {
this.typeFormule = typeFormule;
}
public String getPlageMembres() {
return plageMembres;
}
public void setPlageMembres(String plageMembres) {
this.plageMembres = plageMembres;
}
public String getTypePeriode() {
return typePeriode;
}
public void setTypePeriode(String typePeriode) {
this.typePeriode = typePeriode;
}
public String getTypeOrganisation() {
return typeOrganisation;
}
public void setTypeOrganisation(String typeOrganisation) {
this.typeOrganisation = typeOrganisation;
}
public String getOrganisationId() {
return organisationId;
}
public void setOrganisationId(String organisationId) {
this.organisationId = organisationId;
}
}

View File

@@ -0,0 +1,155 @@
package dev.lions.unionflow.server.api.dto.souscription;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* Réponse décrivant l'état courant d'une souscription UnionFlow.
*
* <p>Retournée par les endpoints de création de demande, de consultation
* et d'initiation du paiement Wave.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-30
*/
public class SouscriptionStatutResponse {
private String souscriptionId;
private String statutValidation;
private String statutLibelle;
private String typeFormule;
private String plageMembres;
private String plageLibelle;
private String typePeriode;
private String typeOrganisation;
private BigDecimal montantTotal;
private BigDecimal montantMensuelBase;
private BigDecimal coefficientApplique;
private String waveSessionId;
/** URL Wave à ouvrir dans le navigateur/WebView pour initier le paiement. */
private String waveLaunchUrl;
private LocalDate dateDebut;
private LocalDate dateFin;
private LocalDate dateValidation;
private String commentaireRejet;
private String organisationId;
private String organisationNom;
// ── Quota & features (Option C) ─────────────────────────────────────────
private Integer quotaMax;
private Integer quotaUtilise;
private Integer quotaRestant;
private boolean quotaDepasse;
private String planCommercial;
private boolean apiAccess;
private boolean federationAccess;
private boolean supportPrioritaire;
private String slaGaranti;
private Integer maxAdmins;
private String niveauReporting;
/** Nombre de jours avant expiration (négatif = déjà expiré) */
private long joursAvantExpiration;
/** Statut de la souscription : ACTIVE, EXPIREE, SUSPENDUE, EN_ATTENTE, RESILIEE */
private String statut;
public SouscriptionStatutResponse() {}
// ─── Getters & Setters ───────────────────────────────────────────────────────
public String getSouscriptionId() { return souscriptionId; }
public void setSouscriptionId(String souscriptionId) { this.souscriptionId = souscriptionId; }
public String getStatutValidation() { return statutValidation; }
public void setStatutValidation(String statutValidation) { this.statutValidation = statutValidation; }
public String getStatutLibelle() { return statutLibelle; }
public void setStatutLibelle(String statutLibelle) { this.statutLibelle = statutLibelle; }
public String getTypeFormule() { return typeFormule; }
public void setTypeFormule(String typeFormule) { this.typeFormule = typeFormule; }
public String getPlageMembres() { return plageMembres; }
public void setPlageMembres(String plageMembres) { this.plageMembres = plageMembres; }
public String getPlageLibelle() { return plageLibelle; }
public void setPlageLibelle(String plageLibelle) { this.plageLibelle = plageLibelle; }
public String getTypePeriode() { return typePeriode; }
public void setTypePeriode(String typePeriode) { this.typePeriode = typePeriode; }
public String getTypeOrganisation() { return typeOrganisation; }
public void setTypeOrganisation(String typeOrganisation) { this.typeOrganisation = typeOrganisation; }
public BigDecimal getMontantTotal() { return montantTotal; }
public void setMontantTotal(BigDecimal montantTotal) { this.montantTotal = montantTotal; }
public BigDecimal getMontantMensuelBase() { return montantMensuelBase; }
public void setMontantMensuelBase(BigDecimal montantMensuelBase) { this.montantMensuelBase = montantMensuelBase; }
public BigDecimal getCoefficientApplique() { return coefficientApplique; }
public void setCoefficientApplique(BigDecimal coefficientApplique) { this.coefficientApplique = coefficientApplique; }
public String getWaveSessionId() { return waveSessionId; }
public void setWaveSessionId(String waveSessionId) { this.waveSessionId = waveSessionId; }
public String getWaveLaunchUrl() { return waveLaunchUrl; }
public void setWaveLaunchUrl(String waveLaunchUrl) { this.waveLaunchUrl = waveLaunchUrl; }
public LocalDate getDateDebut() { return dateDebut; }
public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
public LocalDate getDateFin() { return dateFin; }
public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }
public LocalDate getDateValidation() { return dateValidation; }
public void setDateValidation(LocalDate dateValidation) { this.dateValidation = dateValidation; }
public String getCommentaireRejet() { return commentaireRejet; }
public void setCommentaireRejet(String commentaireRejet) { this.commentaireRejet = commentaireRejet; }
public String getOrganisationId() { return organisationId; }
public void setOrganisationId(String organisationId) { this.organisationId = organisationId; }
public String getOrganisationNom() { return organisationNom; }
public void setOrganisationNom(String organisationNom) { this.organisationNom = organisationNom; }
public Integer getQuotaMax() { return quotaMax; }
public void setQuotaMax(Integer quotaMax) { this.quotaMax = quotaMax; }
public Integer getQuotaUtilise() { return quotaUtilise; }
public void setQuotaUtilise(Integer quotaUtilise) { this.quotaUtilise = quotaUtilise; }
public Integer getQuotaRestant() { return quotaRestant; }
public void setQuotaRestant(Integer quotaRestant) { this.quotaRestant = quotaRestant; }
public boolean isQuotaDepasse() { return quotaDepasse; }
public void setQuotaDepasse(boolean quotaDepasse) { this.quotaDepasse = quotaDepasse; }
public String getPlanCommercial() { return planCommercial; }
public void setPlanCommercial(String planCommercial) { this.planCommercial = planCommercial; }
public boolean isApiAccess() { return apiAccess; }
public void setApiAccess(boolean apiAccess) { this.apiAccess = apiAccess; }
public boolean isFederationAccess() { return federationAccess; }
public void setFederationAccess(boolean federationAccess) { this.federationAccess = federationAccess; }
public boolean isSupportPrioritaire() { return supportPrioritaire; }
public void setSupportPrioritaire(boolean supportPrioritaire) { this.supportPrioritaire = supportPrioritaire; }
public String getSlaGaranti() { return slaGaranti; }
public void setSlaGaranti(String slaGaranti) { this.slaGaranti = slaGaranti; }
public Integer getMaxAdmins() { return maxAdmins; }
public void setMaxAdmins(Integer maxAdmins) { this.maxAdmins = maxAdmins; }
public String getNiveauReporting() { return niveauReporting; }
public void setNiveauReporting(String niveauReporting) { this.niveauReporting = niveauReporting; }
public long getJoursAvantExpiration() { return joursAvantExpiration; }
public void setJoursAvantExpiration(long joursAvantExpiration) { this.joursAvantExpiration = joursAvantExpiration; }
public String getStatut() { return statut; }
public void setStatut(String statut) { this.statut = statut; }
}

View File

@@ -1,129 +0,0 @@
package dev.lions.unionflow.server.api.dto.system.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* Response contenant les métriques système en temps réel
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SystemMetricsResponse {
// Métriques CPU
private Double cpuUsagePercent;
private Integer availableProcessors;
private Double systemLoadAverage;
// Métriques mémoire
private Long totalMemoryBytes;
private Long usedMemoryBytes;
private Long freeMemoryBytes;
private Long maxMemoryBytes;
private Double memoryUsagePercent;
private String totalMemoryFormatted; // ex: "8.0 GB"
private String usedMemoryFormatted; // ex: "5.4 GB"
private String freeMemoryFormatted; // ex: "2.6 GB"
// Métriques disque
private Long totalDiskBytes;
private Long usedDiskBytes;
private Long freeDiskBytes;
private Double diskUsagePercent;
private String totalDiskFormatted; // ex: "500 GB"
private String usedDiskFormatted; // ex: "225 GB"
private String freeDiskFormatted; // ex: "275 GB"
// Métriques utilisateurs
private Integer activeUsersCount; // Utilisateurs connectés actuellement
private Integer totalUsersCount; // Total utilisateurs dans le système
private Integer activeSessionsCount; // Sessions actives
private Integer failedLoginAttempts24h; // Échecs login dernières 24h
// Métriques API
private Long apiRequestsLastHour; // Requêtes API dernière heure
private Long apiRequestsToday; // Requêtes API aujourd'hui
private Double averageResponseTimeMs; // Temps réponse moyen (ms)
private Long totalRequestsCount; // Total requêtes depuis démarrage
// Métriques base de données
private Integer dbConnectionPoolSize; // Taille pool connexions
private Integer dbActiveConnections; // Connexions actives
private Integer dbIdleConnections; // Connexions en attente
private Boolean dbHealthy; // État santé DB
// Métriques erreurs et logs
private Integer criticalErrorsCount; // Erreurs critiques
private Integer warningsCount; // Avertissements
private Integer infoLogsCount; // Logs info
private Integer debugLogsCount; // Logs debug
private Long totalLogsCount; // Total logs
// Métriques réseau
private Double networkBytesReceivedPerSec; // Octets reçus/sec
private Double networkBytesSentPerSec; // Octets envoyés/sec
private String networkInFormatted; // ex: "12.5 MB/s"
private String networkOutFormatted; // ex: "8.2 MB/s"
// Métriques système
private String systemStatus; // OPERATIONAL, DEGRADED, MAINTENANCE, DOWN
private Long uptimeMillis; // Uptime en ms
private String uptimeFormatted; // ex: "5j 12h 34m"
private LocalDateTime startTime; // Date/heure démarrage
private LocalDateTime currentTime; // Date/heure actuelle
private String javaVersion; // Version Java
private String quarkusVersion; // Version Quarkus
private String applicationVersion; // Version application
// Métriques maintenance
private LocalDateTime lastBackup; // Dernière sauvegarde
private LocalDateTime nextScheduledMaintenance; // Prochaine maintenance
private LocalDateTime lastMaintenance; // Dernière maintenance
// URLs et configuration réseau
private String apiBaseUrl; // URL API
private String authServerUrl; // URL serveur auth (Keycloak)
private String cdnUrl; // URL CDN (si applicable)
// Statistiques de stockage (cache)
private Long totalCacheSizeBytes;
private String totalCacheSizeFormatted; // ex: "450 MB"
private Integer totalCacheEntries;
/**
* Helper pour formater les bytes en taille lisible
*/
public static String formatBytes(long bytes) {
if (bytes < 1024) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(1024));
String pre = "KMGTPE".charAt(exp - 1) + "";
return String.format(java.util.Locale.US, "%.1f %sB", bytes / Math.pow(1024, exp), pre);
}
/**
* Helper pour formater l'uptime
*/
public static String formatUptime(long millis) {
long seconds = millis / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
hours = hours % 24;
minutes = minutes % 60;
if (days > 0) {
return String.format("%dj %dh %dm", days, hours, minutes);
} else if (hours > 0) {
return String.format("%dh %dm", hours, minutes);
} else {
return String.format("%dm", minutes);
}
}
}

View File

@@ -0,0 +1,64 @@
package dev.lions.unionflow.server.api.enums.abonnement;
/**
* Tranches de taille d'organisation pour le calcul tarifaire UnionFlow.
*
* <p>Chaque plage définit un intervalle [min, max] de membres.
* La plage TRES_GRANDE est sans limite supérieure (Integer.MAX_VALUE).
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-30
*/
public enum PlageMembres {
PETITE("Petite structure (1100 membres)", 1, 100),
MOYENNE("Moyenne structure (101500 membres)", 101, 500),
GRANDE("Grande structure (5012 000 membres)", 501, 2000),
TRES_GRANDE("Très grande structure (2 000+ membres)", 2001, Integer.MAX_VALUE);
private final String libelle;
private final int min;
private final int max;
PlageMembres(String libelle, int min, int max) {
this.libelle = libelle;
this.min = min;
this.max = max;
}
/**
* Détermine la plage tarifaire correspondant à un nombre de membres donné.
*
* @param nombre nombre de membres de l'organisation
* @return la plage correspondante (TRES_GRANDE si aucune ne correspond)
*/
public static PlageMembres fromNombreMembres(int nombre) {
for (PlageMembres p : values()) {
if (nombre >= p.min && nombre <= p.max) {
return p;
}
}
return TRES_GRANDE;
}
public String getLibelle() {
return libelle;
}
public int getMin() {
return min;
}
/**
* Retourne le max de membres pour la plage.
* Retourne -1 pour TRES_GRANDE (illimité) afin de faciliter la sérialisation JSON.
*/
public int getMaxAffichage() {
return this == TRES_GRANDE ? -1 : max;
}
public int getMax() {
return max;
}
}

View File

@@ -1,6 +1,7 @@
package dev.lions.unionflow.server.api.enums.abonnement;
public enum StatutSouscription {
EN_ATTENTE("En attente de validation"),
ACTIVE("Active"),
EXPIREE("Expirée"),
SUSPENDUE("Suspendue — quota dépassé ou impayé"),

View File

@@ -0,0 +1,43 @@
package dev.lions.unionflow.server.api.enums.abonnement;
/**
* Cycle de vie de validation d'une souscription UnionFlow.
*
* <p>Transitions valides :
* <pre>
* EN_ATTENTE_PAIEMENT → PAIEMENT_INITIE → PAIEMENT_CONFIRME → VALIDEE
* ↘ REJETEE
* </pre>
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-30
*/
public enum StatutValidationSouscription {
EN_ATTENTE_PAIEMENT("En attente de paiement — souscription créée"),
PAIEMENT_INITIE("Paiement initié — session Wave ouverte"),
PAIEMENT_CONFIRME("Paiement confirmé — en attente de validation SuperAdmin"),
VALIDEE("Validée — compte activé"),
REJETEE("Rejetée — souscription refusée");
private final String libelle;
StatutValidationSouscription(String libelle) {
this.libelle = libelle;
}
public String getLibelle() {
return libelle;
}
/** Indique si la souscription est dans un état terminal (non modifiable). */
public boolean isTerminal() {
return this == VALIDEE || this == REJETEE;
}
/** Indique si un paiement Wave peut être initié depuis cet état. */
public boolean peutInitierPaiement() {
return this == EN_ATTENTE_PAIEMENT;
}
}

View File

@@ -1,17 +1,23 @@
package dev.lions.unionflow.server.api.enums.abonnement;
/**
* Énumération des types de formules d'abonnement UnionFlow
* Niveaux de formule d'abonnement UnionFlow.
*
* <p>Trois niveaux disponibles, chacun applicable à toutes les plages de taille
* ({@link PlageMembres}). Les prix de base sont définis dans la matrice tarifaire
* et varient selon la plage et le type d'organisation.
*
* <p>Migration depuis l'ancien enum : STARTER→BASIC, CRYSTAL supprimé.
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-10
* @version 2.0
* @since 2026-03-30
*/
public enum TypeFormule {
STARTER("Starter — 1 à 50 membres — 5 000 XOF/mois"),
STANDARD("Standard — 51 à 200 membres — 7 000 XOF/mois"),
PREMIUM("Premium — 201 à 500 membres — 9 000 XOF/mois"),
CRYSTAL("Crystal — 501+ membres — 10 000 XOF/mois");
BASIC("Basic"),
STANDARD("Standard"),
PREMIUM("Premium");
private final String libelle;

View File

@@ -0,0 +1,51 @@
package dev.lions.unionflow.server.api.enums.abonnement;
import java.math.BigDecimal;
/**
* Catégorie tarifaire d'une organisation pour le calcul du prix de souscription.
*
* <p>Distinct de {@code TypeOrganisation} (catégorisation métier).
* Chaque valeur porte deux coefficients multiplicateurs :
* <ul>
* <li>{@code coefficientBase} — appliqué aux formules BASIC et STANDARD</li>
* <li>{@code coefficientPremium} — appliqué uniquement à la formule PREMIUM</li>
* </ul>
*
* <p>Exemple : FEDERATION paye le tarif normal (×1.0) en BASIC/STANDARD
* mais un coefficient ×1.5 en PREMIUM (fonctionnalités multi-entités).
*/
public enum TypeOrganisationFacturation {
ASSOCIATION("Association / ONG locale", new BigDecimal("1.0"), new BigDecimal("1.0")),
MUTUELLE("Mutuelle (santé, fonctionnaires, scolaires)", new BigDecimal("1.2"), new BigDecimal("1.2")),
COOPERATIVE("Coopérative / Microfinance", new BigDecimal("1.3"), new BigDecimal("1.3")),
FEDERATION("Fédération / Grande ONG", new BigDecimal("1.0"), new BigDecimal("1.5"));
private final String libelle;
private final BigDecimal coefficientBase;
private final BigDecimal coefficientPremium;
TypeOrganisationFacturation(String libelle, BigDecimal coefficientBase, BigDecimal coefficientPremium) {
this.libelle = libelle;
this.coefficientBase = coefficientBase;
this.coefficientPremium = coefficientPremium;
}
/**
* Retourne le coefficient tarifaire approprié selon le code de formule.
*
* @param typeFormule code de la formule (BASIC, STANDARD, PREMIUM)
* @return coefficient multiplicateur du prix mensuel de base
*/
public BigDecimal getCoefficient(String typeFormule) {
if ("PREMIUM".equals(typeFormule) && this == FEDERATION) {
return coefficientPremium;
}
return coefficientBase;
}
public String getLibelle() { return libelle; }
public BigDecimal getCoefficientBase() { return coefficientBase; }
public BigDecimal getCoefficientPremium() { return coefficientPremium; }
}

View File

@@ -1,12 +1,50 @@
package dev.lions.unionflow.server.api.enums.abonnement;
import java.math.BigDecimal;
/**
* Périodes d'abonnement UnionFlow avec remises associées.
*
* <p>Le {@code coefficient} est multiplié par le prix mensuel de base,
* puis par le nombre de mois pour obtenir le montant total.
*
* <ul>
* <li>MENSUEL : prix normal × 1 mois</li>
* <li>TRIMESTRIEL : prix × 0.95 × 3 mois (5% de remise)</li>
* <li>SEMESTRIEL : prix × 0.90 × 6 mois (10% de remise)</li>
* <li>ANNUEL : prix × 0.80 × 12 mois (20% de remise, équivaut à 2 mois offerts)</li>
* </ul>
*
* @author UnionFlow Team
* @version 2.0
* @since 2026-03-30
*/
public enum TypePeriodeAbonnement {
MENSUEL("Mensuel"),
ANNUEL("Annuel — 2 mois offerts");
MENSUEL("Mensuel", 1, new BigDecimal("1.00")),
TRIMESTRIEL("Trimestriel — 5% de remise", 3, new BigDecimal("0.95")),
SEMESTRIEL("Semestriel — 10% de remise", 6, new BigDecimal("0.90")),
ANNUEL("Annuel — 20% de remise (2 mois offerts)", 12, new BigDecimal("0.80"));
private final String libelle;
private final int nombreMois;
private final BigDecimal coefficient;
TypePeriodeAbonnement(String libelle) { this.libelle = libelle; }
TypePeriodeAbonnement(String libelle, int nombreMois, BigDecimal coefficient) {
this.libelle = libelle;
this.nombreMois = nombreMois;
this.coefficient = coefficient;
}
public String getLibelle() { return libelle; }
public String getLibelle() {
return libelle;
}
public int getNombreMois() {
return nombreMois;
}
public BigDecimal getCoefficient() {
return coefficient;
}
}

View File

@@ -0,0 +1,30 @@
package dev.lions.unionflow.server.api.enums.communication;
/**
* Type de conversation dans le système de messagerie
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
public enum ConversationType {
/**
* Conversation individuelle (1-1)
*/
INDIVIDUAL,
/**
* Conversation de groupe
*/
GROUP,
/**
* Canal broadcast (lecture seule pour la plupart)
*/
BROADCAST,
/**
* Canal d'annonces organisation
*/
ANNOUNCEMENT
}

View File

@@ -0,0 +1,25 @@
package dev.lions.unionflow.server.api.enums.communication;
/**
* Priorité du message
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
public enum MessagePriority {
/**
* Priorité normale
*/
NORMAL,
/**
* Priorité élevée (important)
*/
HIGH,
/**
* Priorité urgente (critique)
*/
URGENT
}

View File

@@ -0,0 +1,30 @@
package dev.lions.unionflow.server.api.enums.communication;
/**
* Statut de lecture du message
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
public enum MessageStatus {
/**
* Envoyé mais non lu
*/
SENT,
/**
* Livré (reçu par le serveur)
*/
DELIVERED,
/**
* Lu par le destinataire
*/
READ,
/**
* Échec d'envoi
*/
FAILED
}

View File

@@ -0,0 +1,30 @@
package dev.lions.unionflow.server.api.enums.communication;
/**
* Type de message
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-16
*/
public enum MessageType {
/**
* Message individuel (membre à membre)
*/
INDIVIDUAL,
/**
* Broadcast organisation (OrgAdmin → tous)
*/
BROADCAST,
/**
* Message ciblé par rôle (Moderator → groupe)
*/
TARGETED,
/**
* Notification système
*/
SYSTEM
}

View File

@@ -10,6 +10,7 @@ package dev.lions.unionflow.server.api.enums.document;
public enum TypeDocument {
IDENTITE("Pièce d'Identité"),
JUSTIFICATIF_DOMICILE("Justificatif de Domicile"),
PIECE_JUSTIFICATIVE("Pièce Justificative"),
PHOTO("Photo"),
CONTRAT("Contrat"),
FACTURE("Facture"),

View File

@@ -8,6 +8,7 @@ package dev.lions.unionflow.server.api.enums.membre;
* @since 2025-01-10
*/
public enum StatutMembre {
INVITE("Invité — en attente d'acceptation"),
EN_ATTENTE_VALIDATION("En attente de validation"),
ACTIF("Actif"),
INACTIF("Inactif — cotisations en retard"),
@@ -15,7 +16,8 @@ public enum StatutMembre {
DEMISSIONNAIRE("Démissionnaire"),
RADIE("Radié — exclusion définitive"),
HONORAIRE("Honoraire — sans cotisation obligatoire"),
DECEDE("Décédé — archivage / gestion ayants droit");
DECEDE("Décédé — archivage / gestion ayants droit"),
ARCHIVE("Archivé — données conservées, accès révoqué");
private final String libelle;

View File

@@ -1,21 +1,26 @@
package dev.lions.unionflow.server.api.enums.organisation;
/**
* Énumération des types d'organisations supportés par UnionFlow
* Types d'organisations supportées par UnionFlow.
*
* <p>Utilisé pour la <strong>catégorisation métier</strong> des organisations
* (Lions Club, Mutuelle santé, ONG, etc.). Ne pas confondre avec
* {@link TypeOrganisationFacturation} qui porte les coefficients tarifaires.
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-10
*/
public enum TypeOrganisation {
ASSOCIATION("Association"),
MUTUELLE_EPARGNE_CREDIT("Mutuelle d'épargne et de crédit"),
MUTUELLE_SANTE("Mutuelle de santé"),
TONTINE("Tontine / épargne rotative"),
ONG("ONG / Association humanitaire"),
COOPERATIVE_AGRICOLE("Coopérative agricole / production"),
ASSOCIATION_PROFESSIONNELLE("Association professionnelle / Ordre"),
ASSOCIATION_COMMUNAUTAIRE("Association communautaire / quartier"),
COOPERATIVE_AGRICOLE("Coopérative agricole"),
ASSOCIATION_PROFESSIONNELLE("Association professionnelle"),
ASSOCIATION_COMMUNAUTAIRE("Association communautaire"),
ORGANISATION_RELIGIEUSE("Organisation religieuse"),
FEDERATION("Fédération / Union d'associations"),
SYNDICAT("Syndicat non partisan"),

View File

@@ -40,13 +40,14 @@ public final class TestDataFactory {
String email) {
return new MembreSummaryResponse(
UUID.randomUUID(), numero, prenom, nom, email, "0102030405", "Profession", "ACTIF", "Actif", "success", true,
List.of("MEMBRE"), null, null);
List.of("MEMBRE"), null, null, null);
}
public static CreateMembreRequest createCreateMembreRequest(int age) {
return new CreateMembreRequest(
"Jean", "Dupont", "jean@example.com", "0102030405", "+22501020304",
LocalDate.now().minusYears(age), "Profession", "photo.jpg", "CELIBATAIRE", "Ivoirienne", "CNI", "123456789");
LocalDate.now().minusYears(age), "Profession", "photo.jpg", "CELIBATAIRE", "Ivoirienne", "CNI", "123456789",
null); // organisationId - optional
}
// ===== MEMBRE SEARCH CRITERIA =====

View File

@@ -0,0 +1,307 @@
package dev.lions.unionflow.server.api.dto.abonnement.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateAbonnementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID organisationId = UUID.randomUUID();
UUID formulaireId = UUID.randomUUID();
UUID responsableId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now();
LocalDate dateFin = LocalDate.now().plusMonths(12);
LocalDate dateProchainePeriode = LocalDate.now().plusMonths(1);
LocalDate dateFinEssai = LocalDate.now().plusDays(30);
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(organisationId)
.nomOrganisation("Test Org")
.formulaireId(formulaireId)
.codeFormule("PREMIUM")
.nomFormule("Premium Formula")
.typeFormule(TypeFormule.PREMIUM)
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(dateDebut)
.dateFin(dateFin)
.dateProchainePeriode(dateProchainePeriode)
.montant(new BigDecimal("10000.00"))
.devise("XOF")
.remise(new BigDecimal("10.00"))
.montantFinal(new BigDecimal("9000.00"))
.renouvellementAutomatique(true)
.periodeEssaiUtilisee(true)
.dateFinEssai(dateFinEssai)
.maxMembres(100)
.nombreMembresActuels(50)
.espaceStockageGB(new BigDecimal("100.00"))
.espaceStockageUtilise(new BigDecimal("25.50"))
.supportTechnique(true)
.niveauSupport("PREMIUM")
.fonctionnalitesAvancees(true)
.apiAccess(true)
.rapportsPersonnalises(true)
.integrationsTierces(true)
.responsableId(responsableId)
.nomResponsable("John Doe")
.emailResponsable("john@example.com")
.telephoneResponsable("+221771234567")
.modePaiementPrefere("WAVE_MONEY")
.numeroPaiementMobile("+221771234567")
.historiquePaiements("Paiements réguliers")
.notes("Notes importantes")
.alertesActivees(true)
.notificationsEmail(true)
.notificationsSMS(true)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("ABO-2026-TEST1234");
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.nomOrganisation()).isEqualTo("Test Org");
assertThat(request.formulaireId()).isEqualTo(formulaireId);
assertThat(request.codeFormule()).isEqualTo("PREMIUM");
assertThat(request.nomFormule()).isEqualTo("Premium Formula");
assertThat(request.typeFormule()).isEqualTo(TypeFormule.PREMIUM);
assertThat(request.statut()).isEqualTo(StatutAbonnement.ACTIF);
assertThat(request.typeAbonnement()).isEqualTo(TypePeriodeAbonnement.MENSUEL);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.dateFin()).isEqualTo(dateFin);
assertThat(request.dateProchainePeriode()).isEqualTo(dateProchainePeriode);
assertThat(request.montant()).isEqualByComparingTo(new BigDecimal("10000.00"));
assertThat(request.devise()).isEqualTo("XOF");
assertThat(request.remise()).isEqualByComparingTo(new BigDecimal("10.00"));
assertThat(request.montantFinal()).isEqualByComparingTo(new BigDecimal("9000.00"));
assertThat(request.renouvellementAutomatique()).isTrue();
assertThat(request.periodeEssaiUtilisee()).isTrue();
assertThat(request.dateFinEssai()).isEqualTo(dateFinEssai);
assertThat(request.maxMembres()).isEqualTo(100);
assertThat(request.nombreMembresActuels()).isEqualTo(50);
assertThat(request.espaceStockageGB()).isEqualByComparingTo(new BigDecimal("100.00"));
assertThat(request.espaceStockageUtilise()).isEqualByComparingTo(new BigDecimal("25.50"));
assertThat(request.supportTechnique()).isTrue();
assertThat(request.niveauSupport()).isEqualTo("PREMIUM");
assertThat(request.fonctionnalitesAvancees()).isTrue();
assertThat(request.apiAccess()).isTrue();
assertThat(request.rapportsPersonnalises()).isTrue();
assertThat(request.integrationsTierces()).isTrue();
assertThat(request.responsableId()).isEqualTo(responsableId);
assertThat(request.nomResponsable()).isEqualTo("John Doe");
assertThat(request.emailResponsable()).isEqualTo("john@example.com");
assertThat(request.telephoneResponsable()).isEqualTo("+221771234567");
assertThat(request.modePaiementPrefere()).isEqualTo("WAVE_MONEY");
assertThat(request.numeroPaiementMobile()).isEqualTo("+221771234567");
assertThat(request.historiquePaiements()).isEqualTo("Paiements réguliers");
assertThat(request.notes()).isEqualTo("Notes importantes");
assertThat(request.alertesActivees()).isTrue();
assertThat(request.notificationsEmail()).isTrue();
assertThat(request.notificationsSMS()).isTrue();
}
@Test
void testBuilder_MinimalFields() {
UUID organisationId = UUID.randomUUID();
UUID formulaireId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now();
LocalDate dateFin = LocalDate.now().plusMonths(12);
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST9999")
.organisationId(organisationId)
.formulaireId(formulaireId)
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.ANNUEL)
.dateDebut(dateDebut)
.dateFin(dateFin)
.montant(new BigDecimal("5000.00"))
.devise("XOF")
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("ABO-2026-TEST9999");
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.formulaireId()).isEqualTo(formulaireId);
assertThat(request.statut()).isEqualTo(StatutAbonnement.ACTIF);
assertThat(request.typeAbonnement()).isEqualTo(TypePeriodeAbonnement.ANNUEL);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.montant()).isEqualByComparingTo(new BigDecimal("5000.00"));
assertThat(request.devise()).isEqualTo("XOF");
}
@Test
void testValidation_MissingRequiredFields() {
CreateAbonnementRequest request = CreateAbonnementRequest.builder().build();
Set<ConstraintViolation<CreateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroReference"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("organisationId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("formulaireId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("statut"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeAbonnement"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateDebut"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montant"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_InvalidNumeroReference() {
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("INVALID")
.organisationId(UUID.randomUUID())
.formulaireId(UUID.randomUUID())
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(LocalDate.now())
.dateFin(LocalDate.now().plusMonths(12))
.montant(new BigDecimal("1000.00"))
.devise("XOF")
.build();
Set<ConstraintViolation<CreateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroReference"));
}
@Test
void testValidation_InvalidDevise() {
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(UUID.randomUUID())
.formulaireId(UUID.randomUUID())
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(LocalDate.now())
.dateFin(LocalDate.now().plusMonths(12))
.montant(new BigDecimal("1000.00"))
.devise("INVALID")
.build();
Set<ConstraintViolation<CreateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_MontantZero() {
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(UUID.randomUUID())
.formulaireId(UUID.randomUUID())
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(LocalDate.now())
.dateFin(LocalDate.now().plusMonths(12))
.montant(BigDecimal.ZERO)
.devise("XOF")
.build();
Set<ConstraintViolation<CreateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montant"));
}
@Test
void testValidation_ValidFields() {
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(UUID.randomUUID())
.formulaireId(UUID.randomUUID())
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(LocalDate.now())
.dateFin(LocalDate.now().plusMonths(12))
.montant(new BigDecimal("1000.00"))
.devise("XOF")
.build();
Set<ConstraintViolation<CreateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID organisationId = UUID.randomUUID();
UUID formulaireId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now();
LocalDate dateFin = LocalDate.now().plusMonths(12);
CreateAbonnementRequest request1 = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(organisationId)
.formulaireId(formulaireId)
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(dateDebut)
.dateFin(dateFin)
.montant(new BigDecimal("1000.00"))
.devise("XOF")
.build();
CreateAbonnementRequest request2 = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(organisationId)
.formulaireId(formulaireId)
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(dateDebut)
.dateFin(dateFin)
.montant(new BigDecimal("1000.00"))
.devise("XOF")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateAbonnementRequest request = CreateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(UUID.randomUUID())
.formulaireId(UUID.randomUUID())
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(LocalDate.now())
.dateFin(LocalDate.now().plusMonths(12))
.montant(new BigDecimal("1000.00"))
.devise("XOF")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateAbonnementRequest");
assertThat(toString).contains("ABO-2026-TEST1234");
assertThat(toString).contains("ACTIF");
}
}

View File

@@ -0,0 +1,219 @@
package dev.lions.unionflow.server.api.dto.abonnement.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateAbonnementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID organisationId = UUID.randomUUID();
UUID formulaireId = UUID.randomUUID();
UUID responsableId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now();
LocalDate dateFin = LocalDate.now().plusMonths(12);
LocalDate dateProchainePeriode = LocalDate.now().plusMonths(1);
LocalDate dateFinEssai = LocalDate.now().plusDays(30);
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(organisationId)
.nomOrganisation("Test Org")
.formulaireId(formulaireId)
.codeFormule("PREMIUM")
.nomFormule("Premium Formula")
.typeFormule(TypeFormule.PREMIUM)
.statut(StatutAbonnement.ACTIF)
.typeAbonnement(TypePeriodeAbonnement.MENSUEL)
.dateDebut(dateDebut)
.dateFin(dateFin)
.dateProchainePeriode(dateProchainePeriode)
.montant(new BigDecimal("10000.00"))
.devise("XOF")
.remise(new BigDecimal("10.00"))
.montantFinal(new BigDecimal("9000.00"))
.renouvellementAutomatique(true)
.periodeEssaiUtilisee(true)
.dateFinEssai(dateFinEssai)
.maxMembres(100)
.nombreMembresActuels(50)
.espaceStockageGB(new BigDecimal("100.00"))
.espaceStockageUtilise(new BigDecimal("25.50"))
.supportTechnique(true)
.niveauSupport("PREMIUM")
.fonctionnalitesAvancees(true)
.apiAccess(true)
.rapportsPersonnalises(true)
.integrationsTierces(true)
.responsableId(responsableId)
.nomResponsable("John Doe")
.emailResponsable("john@example.com")
.telephoneResponsable("+221771234567")
.modePaiementPrefere("WAVE_MONEY")
.numeroPaiementMobile("+221771234567")
.historiquePaiements("Paiements réguliers")
.notes("Notes importantes")
.alertesActivees(true)
.notificationsEmail(true)
.notificationsSMS(true)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("ABO-2026-TEST1234");
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.nomOrganisation()).isEqualTo("Test Org");
assertThat(request.formulaireId()).isEqualTo(formulaireId);
assertThat(request.codeFormule()).isEqualTo("PREMIUM");
assertThat(request.nomFormule()).isEqualTo("Premium Formula");
assertThat(request.typeFormule()).isEqualTo(TypeFormule.PREMIUM);
assertThat(request.statut()).isEqualTo(StatutAbonnement.ACTIF);
assertThat(request.typeAbonnement()).isEqualTo(TypePeriodeAbonnement.MENSUEL);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.dateFin()).isEqualTo(dateFin);
assertThat(request.dateProchainePeriode()).isEqualTo(dateProchainePeriode);
assertThat(request.montant()).isEqualByComparingTo(new BigDecimal("10000.00"));
assertThat(request.devise()).isEqualTo("XOF");
assertThat(request.remise()).isEqualByComparingTo(new BigDecimal("10.00"));
assertThat(request.montantFinal()).isEqualByComparingTo(new BigDecimal("9000.00"));
assertThat(request.renouvellementAutomatique()).isTrue();
assertThat(request.periodeEssaiUtilisee()).isTrue();
assertThat(request.dateFinEssai()).isEqualTo(dateFinEssai);
assertThat(request.maxMembres()).isEqualTo(100);
assertThat(request.nombreMembresActuels()).isEqualTo(50);
assertThat(request.espaceStockageGB()).isEqualByComparingTo(new BigDecimal("100.00"));
assertThat(request.espaceStockageUtilise()).isEqualByComparingTo(new BigDecimal("25.50"));
assertThat(request.supportTechnique()).isTrue();
assertThat(request.niveauSupport()).isEqualTo("PREMIUM");
assertThat(request.fonctionnalitesAvancees()).isTrue();
assertThat(request.apiAccess()).isTrue();
assertThat(request.rapportsPersonnalises()).isTrue();
assertThat(request.integrationsTierces()).isTrue();
assertThat(request.responsableId()).isEqualTo(responsableId);
assertThat(request.nomResponsable()).isEqualTo("John Doe");
assertThat(request.emailResponsable()).isEqualTo("john@example.com");
assertThat(request.telephoneResponsable()).isEqualTo("+221771234567");
assertThat(request.modePaiementPrefere()).isEqualTo("WAVE_MONEY");
assertThat(request.numeroPaiementMobile()).isEqualTo("+221771234567");
assertThat(request.historiquePaiements()).isEqualTo("Paiements réguliers");
assertThat(request.notes()).isEqualTo("Notes importantes");
assertThat(request.alertesActivees()).isTrue();
assertThat(request.notificationsEmail()).isTrue();
assertThat(request.notificationsSMS()).isTrue();
}
@Test
void testBuilder_MinimalFields() {
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.statut(StatutAbonnement.SUSPENDU)
.build();
assertThat(request).isNotNull();
assertThat(request.statut()).isEqualTo(StatutAbonnement.SUSPENDU);
}
@Test
void testValidation_InvalidNumeroReference() {
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.numeroReference("INVALID")
.build();
Set<ConstraintViolation<UpdateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroReference"));
}
@Test
void testValidation_InvalidDevise() {
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.devise("INVALID")
.build();
Set<ConstraintViolation<UpdateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_MontantZero() {
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.montant(BigDecimal.ZERO)
.build();
Set<ConstraintViolation<UpdateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montant"));
}
@Test
void testValidation_ValidFields() {
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.statut(StatutAbonnement.ACTIF)
.montant(new BigDecimal("1000.00"))
.devise("XOF")
.build();
Set<ConstraintViolation<UpdateAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID organisationId = UUID.randomUUID();
UpdateAbonnementRequest request1 = UpdateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(organisationId)
.statut(StatutAbonnement.ACTIF)
.build();
UpdateAbonnementRequest request2 = UpdateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.organisationId(organisationId)
.statut(StatutAbonnement.ACTIF)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateAbonnementRequest request = UpdateAbonnementRequest.builder()
.numeroReference("ABO-2026-TEST1234")
.statut(StatutAbonnement.ACTIF)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateAbonnementRequest");
assertThat(toString).contains("ABO-2026-TEST1234");
assertThat(toString).contains("ACTIF");
}
}

View File

@@ -210,4 +210,184 @@ class AbonnementResponseTest {
assertThat(response.getStatutLibelle()).isEqualTo("INCONNU");
}
}
@Nested
@DisplayName("getMembresRestants")
class GetMembresRestants {
@Test
@DisplayName("retourne 0 quand maxMembres null")
void testMaxMembresNull() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(null)
.nombreMembresActuels(5)
.build();
assertThat(response.getMembresRestants()).isEqualTo(0);
}
@Test
@DisplayName("retourne maxMembres quand nombreMembresActuels null")
void testNombreMembresActuelsNull() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(null)
.build();
assertThat(response.getMembresRestants()).isEqualTo(10);
}
@Test
@DisplayName("retourne différence quand actuels < max")
void testMembresRestantsNormal() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(7)
.build();
assertThat(response.getMembresRestants()).isEqualTo(3);
}
@Test
@DisplayName("retourne 0 quand actuels >= max")
void testQuotaDepasse() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(12)
.build();
assertThat(response.getMembresRestants()).isEqualTo(0);
}
}
@Nested
@DisplayName("isQuotaAtteint")
class IsQuotaAtteint {
@Test
@DisplayName("retourne false quand maxMembres null")
void testMaxMembresNull() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(null)
.nombreMembresActuels(100)
.build();
assertThat(response.isQuotaAtteint()).isFalse();
}
@Test
@DisplayName("retourne false quand actuels < max")
void testSousQuota() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(7)
.build();
assertThat(response.isQuotaAtteint()).isFalse();
}
@Test
@DisplayName("retourne true quand actuels = max")
void testQuotaAtteintExact() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(10)
.build();
assertThat(response.isQuotaAtteint()).isTrue();
}
@Test
@DisplayName("retourne true quand actuels > max")
void testQuotaDepasse() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(15)
.build();
assertThat(response.isQuotaAtteint()).isTrue();
}
@Test
@DisplayName("retourne false quand nombreMembresActuels null (défaut 0)")
void testNombreMembresActuelsNull() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(null)
.build();
assertThat(response.isQuotaAtteint()).isFalse();
}
}
@Nested
@DisplayName("getPourcentageUtilisation")
class GetPourcentageUtilisation {
@Test
@DisplayName("retourne 0 quand maxMembres null")
void testMaxMembresNull() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(null)
.nombreMembresActuels(5)
.build();
assertThat(response.getPourcentageUtilisation()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand maxMembres = 0")
void testMaxMembresZero() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(0)
.nombreMembresActuels(5)
.build();
assertThat(response.getPourcentageUtilisation()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand nombreMembresActuels null (défaut 0)")
void testNombreMembresActuelsNull() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(null)
.build();
assertThat(response.getPourcentageUtilisation()).isEqualTo(0);
}
@Test
@DisplayName("calcule pourcentage correct")
void testCalculPourcentage() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(7)
.build();
assertThat(response.getPourcentageUtilisation()).isEqualTo(70);
}
@Test
@DisplayName("retourne 100 quand actuels = max")
void testPourcentageCent() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(10)
.build();
assertThat(response.getPourcentageUtilisation()).isEqualTo(100);
}
@Test
@DisplayName("retourne > 100 quand actuels > max")
void testPourcentageDepasse() {
AbonnementResponse response = AbonnementResponse.builder()
.maxMembres(10)
.nombreMembresActuels(15)
.build();
assertThat(response.getPourcentageUtilisation()).isEqualTo(150);
}
}
}

View File

@@ -0,0 +1,131 @@
package dev.lions.unionflow.server.api.dto.admin.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDateTime;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateAuditLogRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDateTime dateHeure = LocalDateTime.now();
CreateAuditLogRequest request = CreateAuditLogRequest.builder()
.typeAction("CREATE")
.severite("INFO")
.utilisateur("john.doe@example.com")
.role("ROLE_ADMIN")
.module("MEMBRES")
.description("Création d'un nouveau membre")
.details("Membre créé avec succès")
.ipAddress("192.168.1.100")
.userAgent("Mozilla/5.0")
.sessionId("session-123")
.dateHeure(dateHeure)
.donneesAvant("{}")
.donneesApres("{\"nom\":\"Doe\",\"prenom\":\"John\"}")
.entiteId("uuid-123")
.entiteType("MEMBRE")
.build();
assertThat(request).isNotNull();
assertThat(request.typeAction()).isEqualTo("CREATE");
assertThat(request.severite()).isEqualTo("INFO");
assertThat(request.utilisateur()).isEqualTo("john.doe@example.com");
assertThat(request.role()).isEqualTo("ROLE_ADMIN");
assertThat(request.module()).isEqualTo("MEMBRES");
assertThat(request.description()).isEqualTo("Création d'un nouveau membre");
assertThat(request.details()).isEqualTo("Membre créé avec succès");
assertThat(request.ipAddress()).isEqualTo("192.168.1.100");
assertThat(request.userAgent()).isEqualTo("Mozilla/5.0");
assertThat(request.sessionId()).isEqualTo("session-123");
assertThat(request.dateHeure()).isEqualTo(dateHeure);
assertThat(request.donneesAvant()).isEqualTo("{}");
assertThat(request.donneesApres()).isEqualTo("{\"nom\":\"Doe\",\"prenom\":\"John\"}");
assertThat(request.entiteId()).isEqualTo("uuid-123");
assertThat(request.entiteType()).isEqualTo("MEMBRE");
}
@Test
void testBuilder_MinimalFields() {
CreateAuditLogRequest request = CreateAuditLogRequest.builder()
.typeAction("READ")
.utilisateur("user@example.com")
.module("DASHBOARD")
.build();
assertThat(request).isNotNull();
assertThat(request.typeAction()).isEqualTo("READ");
assertThat(request.utilisateur()).isEqualTo("user@example.com");
assertThat(request.module()).isEqualTo("DASHBOARD");
}
@Test
void testValidation_ValidFields() {
CreateAuditLogRequest request = CreateAuditLogRequest.builder()
.typeAction("UPDATE")
.severite("WARNING")
.utilisateur("admin@example.com")
.module("SETTINGS")
.description("Modification configuration")
.build();
Set<ConstraintViolation<CreateAuditLogRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
LocalDateTime dateHeure = LocalDateTime.now();
CreateAuditLogRequest request1 = CreateAuditLogRequest.builder()
.typeAction("CREATE")
.utilisateur("user@example.com")
.module("TEST")
.dateHeure(dateHeure)
.build();
CreateAuditLogRequest request2 = CreateAuditLogRequest.builder()
.typeAction("CREATE")
.utilisateur("user@example.com")
.module("TEST")
.dateHeure(dateHeure)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateAuditLogRequest request = CreateAuditLogRequest.builder()
.typeAction("DELETE")
.utilisateur("admin@example.com")
.module("MEMBRES")
.description("Suppression membre")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateAuditLogRequest");
assertThat(toString).contains("DELETE");
assertThat(toString).contains("MEMBRES");
}
}

View File

@@ -0,0 +1,57 @@
package dev.lions.unionflow.server.api.dto.admin.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;
class AuditLogResponseTest {
@Test
void testGettersSetters_AllFields() {
LocalDateTime dateHeure = LocalDateTime.now();
AuditLogResponse response = new AuditLogResponse();
response.setTypeAction("CREATE");
response.setSeverite("INFO");
response.setUtilisateur("john.doe");
response.setRole("ADMIN");
response.setModule("MEMBRES");
response.setDescription("Création d'un nouveau membre");
response.setDetails("Détails complets de l'opération");
response.setIpAddress("192.168.1.100");
response.setUserAgent("Mozilla/5.0");
response.setSessionId("session-123");
response.setDateHeure(dateHeure);
response.setDonneesAvant(null);
response.setDonneesApres("{\"nom\":\"Doe\"}");
response.setEntiteId("123e4567-e89b-12d3-a456-426614174000");
response.setEntiteType("MEMBRE");
assertThat(response.getTypeAction()).isEqualTo("CREATE");
assertThat(response.getSeverite()).isEqualTo("INFO");
assertThat(response.getUtilisateur()).isEqualTo("john.doe");
assertThat(response.getRole()).isEqualTo("ADMIN");
assertThat(response.getModule()).isEqualTo("MEMBRES");
assertThat(response.getDescription()).isEqualTo("Création d'un nouveau membre");
assertThat(response.getDetails()).isEqualTo("Détails complets de l'opération");
assertThat(response.getIpAddress()).isEqualTo("192.168.1.100");
assertThat(response.getUserAgent()).isEqualTo("Mozilla/5.0");
assertThat(response.getSessionId()).isEqualTo("session-123");
assertThat(response.getDateHeure()).isEqualTo(dateHeure);
assertThat(response.getDonneesAvant()).isNull();
assertThat(response.getDonneesApres()).isEqualTo("{\"nom\":\"Doe\"}");
assertThat(response.getEntiteId()).isEqualTo("123e4567-e89b-12d3-a456-426614174000");
assertThat(response.getEntiteType()).isEqualTo("MEMBRE");
}
@Test
void testDefaultConstructor() {
AuditLogResponse response = new AuditLogResponse();
assertThat(response).isNotNull();
assertThat(response.getTypeAction()).isNull();
assertThat(response.getSeverite()).isNull();
assertThat(response.getUtilisateur()).isNull();
}
}

View File

@@ -0,0 +1,269 @@
package dev.lions.unionflow.server.api.dto.adresse.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateAdresseRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID organisationId = UUID.randomUUID();
CreateAdresseRequest request = new CreateAdresseRequest(
"DOMICILE",
"123 Rue de la Liberté",
"Appartement 5B",
"12345",
"Dakar",
"Dakar",
"Sénégal",
new BigDecimal("14.716677"),
new BigDecimal("-17.467686"),
true,
"Domicile principal",
"Notes importantes",
organisationId,
null,
null
);
assertThat(request).isNotNull();
assertThat(request.typeAdresse()).isEqualTo("DOMICILE");
assertThat(request.adresse()).isEqualTo("123 Rue de la Liberté");
assertThat(request.complementAdresse()).isEqualTo("Appartement 5B");
assertThat(request.codePostal()).isEqualTo("12345");
assertThat(request.ville()).isEqualTo("Dakar");
assertThat(request.region()).isEqualTo("Dakar");
assertThat(request.pays()).isEqualTo("Sénégal");
assertThat(request.latitude()).isEqualByComparingTo(new BigDecimal("14.716677"));
assertThat(request.longitude()).isEqualByComparingTo(new BigDecimal("-17.467686"));
assertThat(request.principale()).isTrue();
assertThat(request.libelle()).isEqualTo("Domicile principal");
assertThat(request.notes()).isEqualTo("Notes importantes");
assertThat(request.organisationId()).isEqualTo(organisationId);
}
@Test
void testBuilder_MinimalFields() {
CreateAdresseRequest request = new CreateAdresseRequest(
"BUREAU",
"456 Avenue du Commerce",
null,
null,
"Thiès",
null,
"Sénégal",
null,
null,
false,
null,
null,
null,
null,
null
);
assertThat(request).isNotNull();
assertThat(request.typeAdresse()).isEqualTo("BUREAU");
assertThat(request.adresse()).isEqualTo("456 Avenue du Commerce");
assertThat(request.ville()).isEqualTo("Thiès");
assertThat(request.pays()).isEqualTo("Sénégal");
assertThat(request.principale()).isFalse();
}
@Test
void testValidation_MissingRequiredFields() {
CreateAdresseRequest request = new CreateAdresseRequest(
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<CreateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeAdresse"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("adresse"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ville"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("pays"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("principale"));
}
@Test
void testValidation_InvalidLatitude() {
CreateAdresseRequest request = new CreateAdresseRequest(
"DOMICILE",
"123 Rue Test",
null,
null,
"Dakar",
null,
"Sénégal",
new BigDecimal("100.0"),
new BigDecimal("0.0"),
true,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<CreateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("latitude"));
}
@Test
void testValidation_InvalidLongitude() {
CreateAdresseRequest request = new CreateAdresseRequest(
"DOMICILE",
"123 Rue Test",
null,
null,
"Dakar",
null,
"Sénégal",
new BigDecimal("0.0"),
new BigDecimal("200.0"),
true,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<CreateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("longitude"));
}
@Test
void testValidation_ValidFields() {
CreateAdresseRequest request = new CreateAdresseRequest(
"DOMICILE",
"123 Rue Test",
null,
null,
"Dakar",
null,
"Sénégal",
new BigDecimal("14.716677"),
new BigDecimal("-17.467686"),
true,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<CreateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID orgId = UUID.randomUUID();
CreateAdresseRequest request1 = new CreateAdresseRequest(
"DOMICILE",
"123 Rue Test",
null,
null,
"Dakar",
null,
"Sénégal",
null,
null,
true,
null,
null,
orgId,
null,
null
);
CreateAdresseRequest request2 = new CreateAdresseRequest(
"DOMICILE",
"123 Rue Test",
null,
null,
"Dakar",
null,
"Sénégal",
null,
null,
true,
null,
null,
orgId,
null,
null
);
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateAdresseRequest request = new CreateAdresseRequest(
"DOMICILE",
"123 Rue Test",
null,
null,
"Dakar",
null,
"Sénégal",
null,
null,
true,
null,
null,
null,
null,
null
);
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateAdresseRequest");
assertThat(toString).contains("DOMICILE");
assertThat(toString).contains("Dakar");
}
}

View File

@@ -0,0 +1,232 @@
package dev.lions.unionflow.server.api.dto.adresse.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateAdresseRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID organisationId = UUID.randomUUID();
UpdateAdresseRequest request = new UpdateAdresseRequest(
"BUREAU",
"456 Avenue Mise à jour",
"Suite 10",
"54321",
"Thiès",
"Thiès",
"Sénégal",
new BigDecimal("14.800000"),
new BigDecimal("-16.900000"),
false,
"Bureau secondaire",
"Notes mises à jour",
organisationId,
null,
null
);
assertThat(request).isNotNull();
assertThat(request.typeAdresse()).isEqualTo("BUREAU");
assertThat(request.adresse()).isEqualTo("456 Avenue Mise à jour");
assertThat(request.complementAdresse()).isEqualTo("Suite 10");
assertThat(request.codePostal()).isEqualTo("54321");
assertThat(request.ville()).isEqualTo("Thiès");
assertThat(request.region()).isEqualTo("Thiès");
assertThat(request.pays()).isEqualTo("Sénégal");
assertThat(request.latitude()).isEqualByComparingTo(new BigDecimal("14.800000"));
assertThat(request.longitude()).isEqualByComparingTo(new BigDecimal("-16.900000"));
assertThat(request.principale()).isFalse();
assertThat(request.libelle()).isEqualTo("Bureau secondaire");
assertThat(request.notes()).isEqualTo("Notes mises à jour");
assertThat(request.organisationId()).isEqualTo(organisationId);
}
@Test
void testBuilder_MinimalFields() {
UpdateAdresseRequest request = new UpdateAdresseRequest(
null,
"Nouvelle adresse",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
assertThat(request).isNotNull();
assertThat(request.adresse()).isEqualTo("Nouvelle adresse");
}
@Test
void testValidation_InvalidLatitude() {
UpdateAdresseRequest request = new UpdateAdresseRequest(
null,
null,
null,
null,
null,
null,
null,
new BigDecimal("100.0"),
null,
null,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<UpdateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("latitude"));
}
@Test
void testValidation_InvalidLongitude() {
UpdateAdresseRequest request = new UpdateAdresseRequest(
null,
null,
null,
null,
null,
null,
null,
null,
new BigDecimal("200.0"),
null,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<UpdateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("longitude"));
}
@Test
void testValidation_ValidFields() {
UpdateAdresseRequest request = new UpdateAdresseRequest(
"DOMICILE",
"123 Rue Updated",
null,
null,
"Dakar",
null,
"Sénégal",
new BigDecimal("14.716677"),
new BigDecimal("-17.467686"),
true,
null,
null,
null,
null,
null
);
Set<ConstraintViolation<UpdateAdresseRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateAdresseRequest request1 = new UpdateAdresseRequest(
"BUREAU",
"Test Address",
null,
null,
"Dakar",
null,
"Sénégal",
null,
null,
false,
null,
null,
null,
null,
null
);
UpdateAdresseRequest request2 = new UpdateAdresseRequest(
"BUREAU",
"Test Address",
null,
null,
"Dakar",
null,
"Sénégal",
null,
null,
false,
null,
null,
null,
null,
null
);
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateAdresseRequest request = new UpdateAdresseRequest(
"BUREAU",
"Test Address",
null,
null,
"Dakar",
null,
"Sénégal",
null,
null,
false,
null,
null,
null,
null,
null
);
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateAdresseRequest");
assertThat(toString).contains("BUREAU");
}
}

View File

@@ -0,0 +1,171 @@
package dev.lions.unionflow.server.api.dto.adresse.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
/**
* Tests unitaires pour AdresseResponse.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-15
*/
@DisplayName("Tests AdresseResponse")
class AdresseResponseTest {
@Nested
@DisplayName("Constructeur et getters/setters")
class ConstructeurEtGettersSetters {
@Test
@DisplayName("Le constructeur par défaut crée une instance")
void testConstructeurParDefaut() {
AdresseResponse response = new AdresseResponse();
assertThat(response).isNotNull();
}
@Test
@DisplayName("Les setters et getters fonctionnent correctement")
void testSettersEtGetters() {
AdresseResponse response = new AdresseResponse();
UUID id = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
UUID membreId = UUID.randomUUID();
UUID evenementId = UUID.randomUUID();
BigDecimal latitude = new BigDecimal("48.8566");
BigDecimal longitude = new BigDecimal("2.3522");
response.setId(id);
response.setTypeAdresse("DOMICILE");
response.setTypeAdresseLibelle("Adresse de domicile");
response.setTypeAdresseIcone("home");
response.setAdresse("123 Rue de la Paix");
response.setComplementAdresse("Appartement 4B");
response.setCodePostal("75001");
response.setVille("Paris");
response.setRegion("Île-de-France");
response.setPays("France");
response.setLatitude(latitude);
response.setLongitude(longitude);
response.setPrincipale(true);
response.setLibelle("Domicile principal");
response.setNotes("Interphone code 1234");
response.setOrganisationId(organisationId);
response.setMembreId(membreId);
response.setEvenementId(evenementId);
response.setAdresseComplete("123 Rue de la Paix, 75001 Paris, France");
assertThat(response.getId()).isEqualTo(id);
assertThat(response.getTypeAdresse()).isEqualTo("DOMICILE");
assertThat(response.getTypeAdresseLibelle()).isEqualTo("Adresse de domicile");
assertThat(response.getTypeAdresseIcone()).isEqualTo("home");
assertThat(response.getAdresse()).isEqualTo("123 Rue de la Paix");
assertThat(response.getComplementAdresse()).isEqualTo("Appartement 4B");
assertThat(response.getCodePostal()).isEqualTo("75001");
assertThat(response.getVille()).isEqualTo("Paris");
assertThat(response.getRegion()).isEqualTo("Île-de-France");
assertThat(response.getPays()).isEqualTo("France");
assertThat(response.getLatitude()).isEqualTo(latitude);
assertThat(response.getLongitude()).isEqualTo(longitude);
assertThat(response.getPrincipale()).isTrue();
assertThat(response.getLibelle()).isEqualTo("Domicile principal");
assertThat(response.getNotes()).isEqualTo("Interphone code 1234");
assertThat(response.getOrganisationId()).isEqualTo(organisationId);
assertThat(response.getMembreId()).isEqualTo(membreId);
assertThat(response.getEvenementId()).isEqualTo(evenementId);
assertThat(response.getAdresseComplete()).isEqualTo("123 Rue de la Paix, 75001 Paris, France");
}
@Test
@DisplayName("Les champs peuvent être null")
void testChampsNull() {
AdresseResponse response = new AdresseResponse();
response.setTypeAdresse(null);
response.setLatitude(null);
response.setLongitude(null);
response.setPrincipale(null);
response.setOrganisationId(null);
response.setMembreId(null);
response.setEvenementId(null);
assertThat(response.getTypeAdresse()).isNull();
assertThat(response.getLatitude()).isNull();
assertThat(response.getLongitude()).isNull();
assertThat(response.getPrincipale()).isNull();
assertThat(response.getOrganisationId()).isNull();
assertThat(response.getMembreId()).isNull();
assertThat(response.getEvenementId()).isNull();
}
}
@Nested
@DisplayName("equals et hashCode")
class EqualsEtHashCode {
@Test
@DisplayName("equals retourne true pour même id")
void testEqualsMemeId() {
UUID id = UUID.randomUUID();
AdresseResponse r1 = new AdresseResponse();
r1.setId(id);
r1.setAdresse("Adresse 1");
AdresseResponse r2 = new AdresseResponse();
r2.setId(id);
r2.setAdresse("Adresse 2");
assertThat(r1).isEqualTo(r2);
}
@Test
@DisplayName("equals retourne false pour ids différents")
void testEqualsIdsDifferents() {
AdresseResponse r1 = new AdresseResponse();
r1.setId(UUID.randomUUID());
AdresseResponse r2 = new AdresseResponse();
r2.setId(UUID.randomUUID());
assertThat(r1).isNotEqualTo(r2);
}
@Test
@DisplayName("hashCode est basé sur l'id")
void testHashCode() {
UUID id = UUID.randomUUID();
AdresseResponse r1 = new AdresseResponse();
r1.setId(id);
AdresseResponse r2 = new AdresseResponse();
r2.setId(id);
assertThat(r1.hashCode()).isEqualTo(r2.hashCode());
}
}
@Nested
@DisplayName("toString")
class ToString {
@Test
@DisplayName("toString retourne une représentation non-null")
void testToString() {
AdresseResponse response = new AdresseResponse();
response.setId(UUID.randomUUID());
response.setAdresse("123 Rue Test");
response.setVille("Paris");
String result = response.toString();
assertThat(result).isNotNull();
assertThat(result).contains("AdresseResponse");
}
}
}

View File

@@ -190,7 +190,15 @@ class KPITrendResponseTest {
class HasAnomalies {
@Test
@DisplayName("retourne false quand pointsDonnees null ou aucun point anomalie")
@DisplayName("retourne false quand pointsDonnees null")
void testNull() {
KPITrendResponse k = minimalKpi();
k.setPointsDonnees(null);
assertThat(k.hasAnomalies()).isFalse();
}
@Test
@DisplayName("retourne false quand aucun point anomalie")
void testFalse() {
KPITrendResponse k = minimalKpi();
assertThat(k.hasAnomalies()).isFalse();

View File

@@ -122,6 +122,11 @@ class PagedResponseTest {
response3.setTotal(100L);
response3.setSize(20);
assertFalse(response3.hasNext());
// Page non-null mais totalPages null → hasNext = false
PagedResponse<String> response4 = new PagedResponse<>();
response4.setPage(2);
assertFalse(response4.hasNext());
}
@Test

View File

@@ -0,0 +1,186 @@
package dev.lions.unionflow.server.api.dto.communication.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* Tests unitaires pour CreateConversationRequest.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-13
*/
@DisplayName("Tests CreateConversationRequest")
class CreateConversationRequestTest {
private static Validator validator;
@BeforeAll
static void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
@DisplayName("Le builder doit créer un CreateConversationRequest valide")
void testBuilderValid() {
UUID participant1 = UUID.randomUUID();
UUID participant2 = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
CreateConversationRequest request =
CreateConversationRequest.builder()
.name("Test Conversation")
.description("Test description")
.type(ConversationType.GROUP)
.participantIds(List.of(participant1, participant2))
.organisationId(orgId)
.build();
assertThat(request.name()).isEqualTo("Test Conversation");
assertThat(request.description()).isEqualTo("Test description");
assertThat(request.type()).isEqualTo(ConversationType.GROUP);
assertThat(request.participantIds()).containsExactly(participant1, participant2);
assertThat(request.organisationId()).isEqualTo(orgId);
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
@DisplayName("La validation doit échouer si le nom est null")
void testValidationNameNull() {
CreateConversationRequest request =
CreateConversationRequest.builder()
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of(UUID.randomUUID()))
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("vide");
}
@Test
@DisplayName("La validation doit échouer si le nom est vide")
void testValidationNameBlank() {
CreateConversationRequest request =
CreateConversationRequest.builder()
.name(" ")
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of(UUID.randomUUID()))
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
}
@Test
@DisplayName("La validation doit échouer si le nom dépasse 255 caractères")
void testValidationNameTooLong() {
String longName = "a".repeat(256);
CreateConversationRequest request =
CreateConversationRequest.builder()
.name(longName)
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of(UUID.randomUUID()))
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("taille");
}
@Test
@DisplayName("La validation doit échouer si la description dépasse 1000 caractères")
void testValidationDescriptionTooLong() {
String longDesc = "a".repeat(1001);
CreateConversationRequest request =
CreateConversationRequest.builder()
.name("Test")
.description(longDesc)
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of(UUID.randomUUID()))
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("taille");
}
@Test
@DisplayName("La validation doit échouer si le type est null")
void testValidationTypeNull() {
CreateConversationRequest request =
CreateConversationRequest.builder()
.name("Test")
.participantIds(List.of(UUID.randomUUID()))
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("nul");
}
@Test
@DisplayName("La validation doit échouer si participantIds est vide")
void testValidationParticipantsEmpty() {
CreateConversationRequest request =
CreateConversationRequest.builder()
.name("Test")
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of())
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("vide");
}
@Test
@DisplayName("La validation doit échouer si participantIds est null")
void testValidationParticipantsNull() {
CreateConversationRequest request =
CreateConversationRequest.builder()
.name("Test")
.type(ConversationType.INDIVIDUAL)
.build();
Set<ConstraintViolation<CreateConversationRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
}
@Test
@DisplayName("Deux instances avec les mêmes valeurs doivent être égales")
void testEquality() {
UUID participant = UUID.randomUUID();
CreateConversationRequest request1 =
CreateConversationRequest.builder()
.name("Test")
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of(participant))
.build();
CreateConversationRequest request2 =
CreateConversationRequest.builder()
.name("Test")
.type(ConversationType.INDIVIDUAL)
.participantIds(List.of(participant))
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
}

View File

@@ -0,0 +1,171 @@
package dev.lions.unionflow.server.api.dto.communication.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
import dev.lions.unionflow.server.api.enums.communication.MessageType;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* Tests unitaires pour SendMessageRequest.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-13
*/
@DisplayName("Tests SendMessageRequest")
class SendMessageRequestTest {
private static Validator validator;
@BeforeAll
static void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
@DisplayName("Le builder doit créer un SendMessageRequest valide")
void testBuilderValid() {
UUID conversationId = UUID.randomUUID();
UUID recipient1 = UUID.randomUUID();
UUID recipient2 = UUID.randomUUID();
SendMessageRequest request =
SendMessageRequest.builder()
.conversationId(conversationId)
.content("Test message content")
.type(MessageType.INDIVIDUAL)
.priority(MessagePriority.NORMAL)
.recipientIds(List.of(recipient1, recipient2))
.recipientRoles(List.of("ADMIN", "USER"))
.attachments(List.of("file1.pdf", "file2.png"))
.build();
assertThat(request.conversationId()).isEqualTo(conversationId);
assertThat(request.content()).isEqualTo("Test message content");
assertThat(request.type()).isEqualTo(MessageType.INDIVIDUAL);
assertThat(request.priority()).isEqualTo(MessagePriority.NORMAL);
assertThat(request.recipientIds()).containsExactly(recipient1, recipient2);
assertThat(request.recipientRoles()).containsExactly("ADMIN", "USER");
assertThat(request.attachments()).containsExactly("file1.pdf", "file2.png");
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
@DisplayName("La validation doit échouer si conversationId est null")
void testValidationConversationIdNull() {
SendMessageRequest request =
SendMessageRequest.builder().content("Test message").build();
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("nul");
}
@Test
@DisplayName("La validation doit échouer si le content est null")
void testValidationContentNull() {
SendMessageRequest request =
SendMessageRequest.builder().conversationId(UUID.randomUUID()).build();
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("vide");
}
@Test
@DisplayName("La validation doit échouer si le content est vide")
void testValidationContentBlank() {
SendMessageRequest request =
SendMessageRequest.builder()
.conversationId(UUID.randomUUID())
.content(" ")
.build();
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
}
@Test
@DisplayName("La validation doit échouer si le content dépasse 10000 caractères")
void testValidationContentTooLong() {
String longContent = "a".repeat(10001);
SendMessageRequest request =
SendMessageRequest.builder()
.conversationId(UUID.randomUUID())
.content(longContent)
.build();
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).hasSize(1);
assertThat(violations.iterator().next().getMessage()).contains("taille");
}
@Test
@DisplayName("Le type et priority peuvent être null (champs optionnels)")
void testOptionalFields() {
SendMessageRequest request =
SendMessageRequest.builder()
.conversationId(UUID.randomUUID())
.content("Test message")
.build();
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
@DisplayName("Les listes peuvent être nulles (champs optionnels)")
void testOptionalLists() {
SendMessageRequest request =
SendMessageRequest.builder()
.conversationId(UUID.randomUUID())
.content("Test message")
.recipientIds(null)
.recipientRoles(null)
.attachments(null)
.build();
assertThat(request.recipientIds()).isNull();
assertThat(request.recipientRoles()).isNull();
assertThat(request.attachments()).isNull();
Set<ConstraintViolation<SendMessageRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
@DisplayName("Deux instances avec les mêmes valeurs doivent être égales")
void testEquality() {
UUID conversationId = UUID.randomUUID();
SendMessageRequest request1 =
SendMessageRequest.builder()
.conversationId(conversationId)
.content("Test message")
.type(MessageType.SYSTEM)
.build();
SendMessageRequest request2 =
SendMessageRequest.builder()
.conversationId(conversationId)
.content("Test message")
.type(MessageType.SYSTEM)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
}

View File

@@ -0,0 +1,113 @@
package dev.lions.unionflow.server.api.dto.communication.response;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* Tests unitaires pour ConversationResponse.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-13
*/
@DisplayName("Tests ConversationResponse")
class ConversationResponseTest {
@Test
@DisplayName("Le builder doit créer un ConversationResponse avec tous les champs")
void testBuilder() {
UUID id = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
UUID participant1 = UUID.randomUUID();
UUID participant2 = UUID.randomUUID();
LocalDateTime createdAt = LocalDateTime.now();
LocalDateTime updatedAt = LocalDateTime.now();
MessageResponse lastMessage = MessageResponse.builder().build();
ConversationResponse response =
ConversationResponse.builder()
.id(id)
.name("Conversation Test")
.description("Description test")
.type(ConversationType.GROUP)
.participantIds(List.of(participant1, participant2))
.organisationId(orgId)
.lastMessage(lastMessage)
.unreadCount(5)
.isMuted(true)
.isPinned(false)
.isArchived(false)
.createdAt(createdAt)
.updatedAt(updatedAt)
.avatarUrl("https://example.com/avatar.jpg")
.build();
assertThat(response.id()).isEqualTo(id);
assertThat(response.name()).isEqualTo("Conversation Test");
assertThat(response.description()).isEqualTo("Description test");
assertThat(response.type()).isEqualTo(ConversationType.GROUP);
assertThat(response.participantIds()).containsExactly(participant1, participant2);
assertThat(response.organisationId()).isEqualTo(orgId);
assertThat(response.lastMessage()).isEqualTo(lastMessage);
assertThat(response.unreadCount()).isEqualTo(5);
assertThat(response.isMuted()).isTrue();
assertThat(response.isPinned()).isFalse();
assertThat(response.isArchived()).isFalse();
assertThat(response.createdAt()).isEqualTo(createdAt);
assertThat(response.updatedAt()).isEqualTo(updatedAt);
assertThat(response.avatarUrl()).isEqualTo("https://example.com/avatar.jpg");
}
@Test
@DisplayName("Le builder doit accepter des valeurs nulles")
void testBuilderWithNulls() {
ConversationResponse response = ConversationResponse.builder().build();
assertThat(response.id()).isNull();
assertThat(response.name()).isNull();
assertThat(response.description()).isNull();
assertThat(response.type()).isNull();
assertThat(response.participantIds()).isNull();
assertThat(response.organisationId()).isNull();
assertThat(response.lastMessage()).isNull();
assertThat(response.unreadCount()).isEqualTo(0);
assertThat(response.isMuted()).isFalse();
assertThat(response.isPinned()).isFalse();
assertThat(response.isArchived()).isFalse();
assertThat(response.createdAt()).isNull();
assertThat(response.updatedAt()).isNull();
assertThat(response.avatarUrl()).isNull();
}
@Test
@DisplayName("Deux instances avec les mêmes valeurs doivent être égales")
void testEquality() {
UUID id = UUID.randomUUID();
LocalDateTime now = LocalDateTime.now();
ConversationResponse response1 =
ConversationResponse.builder()
.id(id)
.name("Test")
.type(ConversationType.INDIVIDUAL)
.createdAt(now)
.build();
ConversationResponse response2 =
ConversationResponse.builder()
.id(id)
.name("Test")
.type(ConversationType.INDIVIDUAL)
.createdAt(now)
.build();
assertThat(response1).isEqualTo(response2);
assertThat(response1.hashCode()).isEqualTo(response2.hashCode());
}
}

View File

@@ -0,0 +1,131 @@
package dev.lions.unionflow.server.api.dto.communication.response;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
import dev.lions.unionflow.server.api.enums.communication.MessageStatus;
import dev.lions.unionflow.server.api.enums.communication.MessageType;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* Tests unitaires pour MessageResponse.
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-13
*/
@DisplayName("Tests MessageResponse")
class MessageResponseTest {
@Test
@DisplayName("Le builder doit créer un MessageResponse avec tous les champs")
void testBuilder() {
UUID id = UUID.randomUUID();
UUID conversationId = UUID.randomUUID();
UUID senderId = UUID.randomUUID();
UUID recipient1 = UUID.randomUUID();
UUID recipient2 = UUID.randomUUID();
UUID orgId = UUID.randomUUID();
LocalDateTime createdAt = LocalDateTime.now();
LocalDateTime readAt = LocalDateTime.now().plusMinutes(5);
LocalDateTime editedAt = LocalDateTime.now().plusMinutes(10);
MessageResponse response =
MessageResponse.builder()
.id(id)
.conversationId(conversationId)
.senderId(senderId)
.senderName("John Doe")
.senderAvatar("https://example.com/avatar.jpg")
.content("Message content")
.type(MessageType.INDIVIDUAL)
.status(MessageStatus.READ)
.priority(MessagePriority.HIGH)
.recipientIds(List.of(recipient1, recipient2))
.recipientRoles(List.of("ADMIN", "USER"))
.organisationId(orgId)
.createdAt(createdAt)
.readAt(readAt)
.attachments(List.of("file1.pdf", "file2.png"))
.isEdited(true)
.editedAt(editedAt)
.isDeleted(false)
.build();
assertThat(response.id()).isEqualTo(id);
assertThat(response.conversationId()).isEqualTo(conversationId);
assertThat(response.senderId()).isEqualTo(senderId);
assertThat(response.senderName()).isEqualTo("John Doe");
assertThat(response.senderAvatar()).isEqualTo("https://example.com/avatar.jpg");
assertThat(response.content()).isEqualTo("Message content");
assertThat(response.type()).isEqualTo(MessageType.INDIVIDUAL);
assertThat(response.status()).isEqualTo(MessageStatus.READ);
assertThat(response.priority()).isEqualTo(MessagePriority.HIGH);
assertThat(response.recipientIds()).containsExactly(recipient1, recipient2);
assertThat(response.recipientRoles()).containsExactly("ADMIN", "USER");
assertThat(response.organisationId()).isEqualTo(orgId);
assertThat(response.createdAt()).isEqualTo(createdAt);
assertThat(response.readAt()).isEqualTo(readAt);
assertThat(response.attachments()).containsExactly("file1.pdf", "file2.png");
assertThat(response.isEdited()).isTrue();
assertThat(response.editedAt()).isEqualTo(editedAt);
assertThat(response.isDeleted()).isFalse();
}
@Test
@DisplayName("Le builder doit accepter des valeurs nulles")
void testBuilderWithNulls() {
MessageResponse response = MessageResponse.builder().build();
assertThat(response.id()).isNull();
assertThat(response.conversationId()).isNull();
assertThat(response.senderId()).isNull();
assertThat(response.senderName()).isNull();
assertThat(response.senderAvatar()).isNull();
assertThat(response.content()).isNull();
assertThat(response.type()).isNull();
assertThat(response.status()).isNull();
assertThat(response.priority()).isNull();
assertThat(response.recipientIds()).isNull();
assertThat(response.recipientRoles()).isNull();
assertThat(response.organisationId()).isNull();
assertThat(response.createdAt()).isNull();
assertThat(response.readAt()).isNull();
assertThat(response.attachments()).isNull();
assertThat(response.isEdited()).isFalse();
assertThat(response.editedAt()).isNull();
assertThat(response.isDeleted()).isFalse();
}
@Test
@DisplayName("Deux instances avec les mêmes valeurs doivent être égales")
void testEquality() {
UUID id = UUID.randomUUID();
LocalDateTime now = LocalDateTime.now();
MessageResponse response1 =
MessageResponse.builder()
.id(id)
.content("Test message")
.type(MessageType.SYSTEM)
.status(MessageStatus.SENT)
.createdAt(now)
.build();
MessageResponse response2 =
MessageResponse.builder()
.id(id)
.content("Test message")
.type(MessageType.SYSTEM)
.status(MessageStatus.SENT)
.createdAt(now)
.build();
assertThat(response1).isEqualTo(response2);
assertThat(response1.hashCode()).isEqualTo(response2.hashCode());
}
}

View File

@@ -0,0 +1,159 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateCompteComptableRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder()
.numeroCompte("401000")
.libelle("Fournisseurs")
.typeCompte(TypeCompteComptable.PASSIF)
.classeComptable(4)
.soldeInitial(BigDecimal.valueOf(1000.00))
.soldeActuel(BigDecimal.valueOf(1500.00))
.compteCollectif(true)
.compteAnalytique(false)
.description("Compte fournisseurs principal")
.build();
assertThat(request).isNotNull();
assertThat(request.numeroCompte()).isEqualTo("401000");
assertThat(request.libelle()).isEqualTo("Fournisseurs");
assertThat(request.typeCompte()).isEqualTo(TypeCompteComptable.PASSIF);
assertThat(request.classeComptable()).isEqualTo(4);
assertThat(request.soldeInitial()).isEqualByComparingTo(BigDecimal.valueOf(1000.00));
assertThat(request.soldeActuel()).isEqualByComparingTo(BigDecimal.valueOf(1500.00));
assertThat(request.compteCollectif()).isTrue();
assertThat(request.compteAnalytique()).isFalse();
assertThat(request.description()).isEqualTo("Compte fournisseurs principal");
}
@Test
void testBuilder_MinimalFields() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder()
.numeroCompte("512000")
.libelle("Banque")
.typeCompte(TypeCompteComptable.TRESORERIE)
.classeComptable(5)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroCompte()).isEqualTo("512000");
assertThat(request.libelle()).isEqualTo("Banque");
assertThat(request.typeCompte()).isEqualTo(TypeCompteComptable.TRESORERIE);
assertThat(request.classeComptable()).isEqualTo(5);
}
@Test
void testValidation_MissingRequiredFields() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder().build();
Set<ConstraintViolation<CreateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroCompte"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("libelle"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeCompte"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("classeComptable"));
}
@Test
void testValidation_ClasseComptableTooSmall() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder()
.numeroCompte("001000")
.libelle("Test")
.typeCompte(TypeCompteComptable.ACTIF)
.classeComptable(0)
.build();
Set<ConstraintViolation<CreateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("classeComptable"));
}
@Test
void testValidation_ClasseComptableTooLarge() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder()
.numeroCompte("801000")
.libelle("Test")
.typeCompte(TypeCompteComptable.AUTRE)
.classeComptable(8)
.build();
Set<ConstraintViolation<CreateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("classeComptable"));
}
@Test
void testValidation_ValidFields() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder()
.numeroCompte("601000")
.libelle("Achats de marchandises")
.typeCompte(TypeCompteComptable.CHARGES)
.classeComptable(6)
.build();
Set<ConstraintViolation<CreateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
CreateCompteComptableRequest request1 = CreateCompteComptableRequest.builder()
.numeroCompte("411000")
.libelle("Clients")
.typeCompte(TypeCompteComptable.ACTIF)
.classeComptable(4)
.build();
CreateCompteComptableRequest request2 = CreateCompteComptableRequest.builder()
.numeroCompte("411000")
.libelle("Clients")
.typeCompte(TypeCompteComptable.ACTIF)
.classeComptable(4)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateCompteComptableRequest request = CreateCompteComptableRequest.builder()
.numeroCompte("701000")
.libelle("Ventes de produits")
.typeCompte(TypeCompteComptable.PRODUITS)
.classeComptable(7)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateCompteComptableRequest");
assertThat(toString).contains("701000");
}
}

View File

@@ -0,0 +1,193 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateEcritureComptableRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID journalId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
UUID paiementId = UUID.randomUUID();
LocalDate dateEcriture = LocalDate.of(2025, 3, 15);
CreateLigneEcritureRequest ligne = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(1000.00))
.montantCredit(BigDecimal.ZERO)
.libelle("Ligne 1")
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-001")
.dateEcriture(dateEcriture)
.libelle("Écriture de test")
.reference("REF-001")
.lettrage("A")
.pointe(true)
.montantDebit(BigDecimal.valueOf(1000.00))
.montantCredit(BigDecimal.valueOf(1000.00))
.commentaire("Commentaire test")
.journalId(journalId)
.organisationId(organisationId)
.paiementId(paiementId)
.lignes(List.of(ligne))
.build();
assertThat(request).isNotNull();
assertThat(request.numeroPiece()).isEqualTo("EC-2025-001");
assertThat(request.dateEcriture()).isEqualTo(dateEcriture);
assertThat(request.libelle()).isEqualTo("Écriture de test");
assertThat(request.reference()).isEqualTo("REF-001");
assertThat(request.lettrage()).isEqualTo("A");
assertThat(request.pointe()).isTrue();
assertThat(request.montantDebit()).isEqualByComparingTo(BigDecimal.valueOf(1000.00));
assertThat(request.montantCredit()).isEqualByComparingTo(BigDecimal.valueOf(1000.00));
assertThat(request.commentaire()).isEqualTo("Commentaire test");
assertThat(request.journalId()).isEqualTo(journalId);
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.paiementId()).isEqualTo(paiementId);
assertThat(request.lignes()).hasSize(1);
}
@Test
void testBuilder_MinimalFields() {
UUID journalId = UUID.randomUUID();
LocalDate dateEcriture = LocalDate.of(2025, 3, 15);
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-002")
.dateEcriture(dateEcriture)
.libelle("Écriture minimale")
.journalId(journalId)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroPiece()).isEqualTo("EC-2025-002");
assertThat(request.dateEcriture()).isEqualTo(dateEcriture);
assertThat(request.libelle()).isEqualTo("Écriture minimale");
assertThat(request.journalId()).isEqualTo(journalId);
}
@Test
void testValidation_MissingRequiredFields() {
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder().build();
Set<ConstraintViolation<CreateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroPiece"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateEcriture"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("libelle"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("journalId"));
}
@Test
void testValidation_NegativeMontantDebit() {
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-003")
.dateEcriture(LocalDate.now())
.libelle("Écriture test")
.journalId(UUID.randomUUID())
.montantDebit(BigDecimal.valueOf(-100.00))
.build();
Set<ConstraintViolation<CreateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDebit"));
}
@Test
void testValidation_NegativeMontantCredit() {
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-004")
.dateEcriture(LocalDate.now())
.libelle("Écriture test")
.journalId(UUID.randomUUID())
.montantCredit(BigDecimal.valueOf(-100.00))
.build();
Set<ConstraintViolation<CreateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantCredit"));
}
@Test
void testValidation_ValidFields() {
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-005")
.dateEcriture(LocalDate.of(2025, 3, 15))
.libelle("Écriture valide")
.journalId(UUID.randomUUID())
.montantDebit(BigDecimal.valueOf(1000.00))
.montantCredit(BigDecimal.valueOf(1000.00))
.build();
Set<ConstraintViolation<CreateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID journalId = UUID.randomUUID();
LocalDate dateEcriture = LocalDate.of(2025, 3, 15);
CreateEcritureComptableRequest request1 = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-006")
.dateEcriture(dateEcriture)
.libelle("Écriture test")
.journalId(journalId)
.build();
CreateEcritureComptableRequest request2 = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-006")
.dateEcriture(dateEcriture)
.libelle("Écriture test")
.journalId(journalId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateEcritureComptableRequest request = CreateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-007")
.dateEcriture(LocalDate.of(2025, 3, 15))
.libelle("Écriture toString")
.journalId(UUID.randomUUID())
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateEcritureComptableRequest");
assertThat(toString).contains("EC-2025-007");
}
}

View File

@@ -0,0 +1,136 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateJournalComptableRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateDebut = LocalDate.of(2025, 1, 1);
LocalDate dateFin = LocalDate.of(2025, 12, 31);
CreateJournalComptableRequest request = CreateJournalComptableRequest.builder()
.code("ACH")
.libelle("Journal des achats")
.typeJournal(TypeJournalComptable.ACHATS)
.dateDebut(dateDebut)
.dateFin(dateFin)
.statut("ACTIF")
.description("Journal pour les achats de marchandises")
.build();
assertThat(request).isNotNull();
assertThat(request.code()).isEqualTo("ACH");
assertThat(request.libelle()).isEqualTo("Journal des achats");
assertThat(request.typeJournal()).isEqualTo(TypeJournalComptable.ACHATS);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.dateFin()).isEqualTo(dateFin);
assertThat(request.statut()).isEqualTo("ACTIF");
assertThat(request.description()).isEqualTo("Journal pour les achats de marchandises");
}
@Test
void testBuilder_MinimalFields() {
CreateJournalComptableRequest request = CreateJournalComptableRequest.builder()
.code("BNQ")
.libelle("Journal banque")
.typeJournal(TypeJournalComptable.BANQUE)
.build();
assertThat(request).isNotNull();
assertThat(request.code()).isEqualTo("BNQ");
assertThat(request.libelle()).isEqualTo("Journal banque");
assertThat(request.typeJournal()).isEqualTo(TypeJournalComptable.BANQUE);
}
@Test
void testValidation_MissingRequiredFields() {
CreateJournalComptableRequest request = CreateJournalComptableRequest.builder().build();
Set<ConstraintViolation<CreateJournalComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("libelle"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeJournal"));
}
@Test
void testValidation_ValidFields() {
CreateJournalComptableRequest request = CreateJournalComptableRequest.builder()
.code("VNTE")
.libelle("Journal des ventes")
.typeJournal(TypeJournalComptable.VENTES)
.build();
Set<ConstraintViolation<CreateJournalComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_AllJournalTypes() {
for (TypeJournalComptable type : TypeJournalComptable.values()) {
CreateJournalComptableRequest request = CreateJournalComptableRequest.builder()
.code(type.name())
.libelle("Journal " + type.getLibelle())
.typeJournal(type)
.build();
Set<ConstraintViolation<CreateJournalComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
}
@Test
void testEquals() {
CreateJournalComptableRequest request1 = CreateJournalComptableRequest.builder()
.code("CAI")
.libelle("Journal caisse")
.typeJournal(TypeJournalComptable.CAISSE)
.build();
CreateJournalComptableRequest request2 = CreateJournalComptableRequest.builder()
.code("CAI")
.libelle("Journal caisse")
.typeJournal(TypeJournalComptable.CAISSE)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateJournalComptableRequest request = CreateJournalComptableRequest.builder()
.code("OD")
.libelle("Opérations diverses")
.typeJournal(TypeJournalComptable.OD)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateJournalComptableRequest");
assertThat(toString).contains("OD");
}
}

View File

@@ -0,0 +1,190 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateLigneEcritureRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID ecritureId = UUID.randomUUID();
UUID compteComptableId = UUID.randomUUID();
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(1000.00))
.montantCredit(BigDecimal.ZERO)
.libelle("Ligne d'écriture test")
.reference("REF-LIGNE-001")
.ecritureId(ecritureId)
.compteComptableId(compteComptableId)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroLigne()).isEqualTo(1);
assertThat(request.montantDebit()).isEqualByComparingTo(BigDecimal.valueOf(1000.00));
assertThat(request.montantCredit()).isEqualByComparingTo(BigDecimal.ZERO);
assertThat(request.libelle()).isEqualTo("Ligne d'écriture test");
assertThat(request.reference()).isEqualTo("REF-LIGNE-001");
assertThat(request.ecritureId()).isEqualTo(ecritureId);
assertThat(request.compteComptableId()).isEqualTo(compteComptableId);
}
@Test
void testBuilder_MinimalFields() {
UUID ecritureId = UUID.randomUUID();
UUID compteComptableId = UUID.randomUUID();
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.ecritureId(ecritureId)
.compteComptableId(compteComptableId)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroLigne()).isEqualTo(1);
assertThat(request.ecritureId()).isEqualTo(ecritureId);
assertThat(request.compteComptableId()).isEqualTo(compteComptableId);
}
@Test
void testValidation_MissingRequiredFields() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder().build();
Set<ConstraintViolation<CreateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroLigne"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ecritureId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("compteComptableId"));
}
@Test
void testValidation_NumeroLigneZero() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(0)
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroLigne"));
}
@Test
void testValidation_NumeroLigneNegative() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(-1)
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroLigne"));
}
@Test
void testValidation_NegativeMontantDebit() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(-100.00))
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDebit"));
}
@Test
void testValidation_NegativeMontantCredit() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantCredit(BigDecimal.valueOf(-100.00))
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantCredit"));
}
@Test
void testValidation_ValidFields() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(500.00))
.montantCredit(BigDecimal.ZERO)
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID ecritureId = UUID.randomUUID();
UUID compteComptableId = UUID.randomUUID();
CreateLigneEcritureRequest request1 = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(1000.00))
.ecritureId(ecritureId)
.compteComptableId(compteComptableId)
.build();
CreateLigneEcritureRequest request2 = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(1000.00))
.ecritureId(ecritureId)
.compteComptableId(compteComptableId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateLigneEcritureRequest request = CreateLigneEcritureRequest.builder()
.numeroLigne(1)
.libelle("Test ligne")
.ecritureId(UUID.randomUUID())
.compteComptableId(UUID.randomUUID())
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateLigneEcritureRequest");
assertThat(toString).contains("Test ligne");
}
}

View File

@@ -0,0 +1,143 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateCompteComptableRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder()
.numeroCompte("401000")
.libelle("Fournisseurs mis à jour")
.typeCompte(TypeCompteComptable.PASSIF)
.classeComptable(4)
.soldeInitial(BigDecimal.valueOf(2000.00))
.soldeActuel(BigDecimal.valueOf(2500.00))
.compteCollectif(false)
.compteAnalytique(true)
.description("Compte fournisseurs modifié")
.build();
assertThat(request).isNotNull();
assertThat(request.numeroCompte()).isEqualTo("401000");
assertThat(request.libelle()).isEqualTo("Fournisseurs mis à jour");
assertThat(request.typeCompte()).isEqualTo(TypeCompteComptable.PASSIF);
assertThat(request.classeComptable()).isEqualTo(4);
assertThat(request.soldeInitial()).isEqualByComparingTo(BigDecimal.valueOf(2000.00));
assertThat(request.soldeActuel()).isEqualByComparingTo(BigDecimal.valueOf(2500.00));
assertThat(request.compteCollectif()).isFalse();
assertThat(request.compteAnalytique()).isTrue();
assertThat(request.description()).isEqualTo("Compte fournisseurs modifié");
}
@Test
void testBuilder_MinimalFields() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder()
.libelle("Banque modifiée")
.build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isEqualTo("Banque modifiée");
}
@Test
void testValidation_ClasseComptableTooSmall() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder()
.classeComptable(0)
.build();
Set<ConstraintViolation<UpdateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("classeComptable"));
}
@Test
void testValidation_ClasseComptableTooLarge() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder()
.classeComptable(8)
.build();
Set<ConstraintViolation<UpdateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("classeComptable"));
}
@Test
void testValidation_ValidFields() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder()
.numeroCompte("512000")
.libelle("Banque mise à jour")
.typeCompte(TypeCompteComptable.TRESORERIE)
.classeComptable(5)
.build();
Set<ConstraintViolation<UpdateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_EmptyRequest() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder().build();
Set<ConstraintViolation<UpdateCompteComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateCompteComptableRequest request1 = UpdateCompteComptableRequest.builder()
.numeroCompte("411000")
.libelle("Clients modifiés")
.typeCompte(TypeCompteComptable.ACTIF)
.classeComptable(4)
.build();
UpdateCompteComptableRequest request2 = UpdateCompteComptableRequest.builder()
.numeroCompte("411000")
.libelle("Clients modifiés")
.typeCompte(TypeCompteComptable.ACTIF)
.classeComptable(4)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateCompteComptableRequest request = UpdateCompteComptableRequest.builder()
.numeroCompte("701000")
.libelle("Ventes modifiées")
.typeCompte(TypeCompteComptable.PRODUITS)
.classeComptable(7)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateCompteComptableRequest");
assertThat(toString).contains("701000");
}
}

View File

@@ -0,0 +1,166 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateEcritureComptableRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID journalId = UUID.randomUUID();
UUID paiementId = UUID.randomUUID();
LocalDate dateEcriture = LocalDate.of(2025, 3, 16);
UpdateLigneEcritureRequest ligne = UpdateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(2000.00))
.montantCredit(BigDecimal.ZERO)
.libelle("Ligne modifiée")
.compteComptableId(UUID.randomUUID())
.build();
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-008")
.dateEcriture(dateEcriture)
.libelle("Écriture modifiée")
.reference("REF-002")
.lettrage("B")
.pointe(false)
.montantDebit(BigDecimal.valueOf(2000.00))
.montantCredit(BigDecimal.valueOf(2000.00))
.commentaire("Commentaire modifié")
.journalId(journalId)
.paiementId(paiementId)
.lignes(List.of(ligne))
.build();
assertThat(request).isNotNull();
assertThat(request.numeroPiece()).isEqualTo("EC-2025-008");
assertThat(request.dateEcriture()).isEqualTo(dateEcriture);
assertThat(request.libelle()).isEqualTo("Écriture modifiée");
assertThat(request.reference()).isEqualTo("REF-002");
assertThat(request.lettrage()).isEqualTo("B");
assertThat(request.pointe()).isFalse();
assertThat(request.montantDebit()).isEqualByComparingTo(BigDecimal.valueOf(2000.00));
assertThat(request.montantCredit()).isEqualByComparingTo(BigDecimal.valueOf(2000.00));
assertThat(request.commentaire()).isEqualTo("Commentaire modifié");
assertThat(request.journalId()).isEqualTo(journalId);
assertThat(request.paiementId()).isEqualTo(paiementId);
assertThat(request.lignes()).hasSize(1);
}
@Test
void testBuilder_MinimalFields() {
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder()
.libelle("Libellé modifié")
.build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isEqualTo("Libellé modifié");
}
@Test
void testValidation_NegativeMontantDebit() {
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder()
.montantDebit(BigDecimal.valueOf(-100.00))
.build();
Set<ConstraintViolation<UpdateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDebit"));
}
@Test
void testValidation_NegativeMontantCredit() {
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder()
.montantCredit(BigDecimal.valueOf(-100.00))
.build();
Set<ConstraintViolation<UpdateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantCredit"));
}
@Test
void testValidation_ValidFields() {
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-009")
.dateEcriture(LocalDate.of(2025, 3, 16))
.libelle("Écriture valide")
.montantDebit(BigDecimal.valueOf(1500.00))
.montantCredit(BigDecimal.valueOf(1500.00))
.build();
Set<ConstraintViolation<UpdateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_EmptyRequest() {
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder().build();
Set<ConstraintViolation<UpdateEcritureComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID journalId = UUID.randomUUID();
LocalDate dateEcriture = LocalDate.of(2025, 3, 16);
UpdateEcritureComptableRequest request1 = UpdateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-010")
.dateEcriture(dateEcriture)
.libelle("Écriture test")
.journalId(journalId)
.build();
UpdateEcritureComptableRequest request2 = UpdateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-010")
.dateEcriture(dateEcriture)
.libelle("Écriture test")
.journalId(journalId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateEcritureComptableRequest request = UpdateEcritureComptableRequest.builder()
.numeroPiece("EC-2025-011")
.dateEcriture(LocalDate.of(2025, 3, 16))
.libelle("Écriture toString")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateEcritureComptableRequest");
assertThat(toString).contains("EC-2025-011");
}
}

View File

@@ -0,0 +1,125 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateJournalComptableRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateDebut = LocalDate.of(2025, 1, 1);
LocalDate dateFin = LocalDate.of(2025, 12, 31);
UpdateJournalComptableRequest request = UpdateJournalComptableRequest.builder()
.libelle("Journal des achats modifié")
.typeJournal(TypeJournalComptable.ACHATS)
.dateDebut(dateDebut)
.dateFin(dateFin)
.statut("INACTIF")
.description("Description modifiée")
.build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isEqualTo("Journal des achats modifié");
assertThat(request.typeJournal()).isEqualTo(TypeJournalComptable.ACHATS);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.dateFin()).isEqualTo(dateFin);
assertThat(request.statut()).isEqualTo("INACTIF");
assertThat(request.description()).isEqualTo("Description modifiée");
}
@Test
void testBuilder_MinimalFields() {
UpdateJournalComptableRequest request = UpdateJournalComptableRequest.builder()
.libelle("Libellé modifié")
.build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isEqualTo("Libellé modifié");
}
@Test
void testValidation_EmptyRequest() {
UpdateJournalComptableRequest request = UpdateJournalComptableRequest.builder().build();
Set<ConstraintViolation<UpdateJournalComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_ValidFields() {
UpdateJournalComptableRequest request = UpdateJournalComptableRequest.builder()
.libelle("Journal des ventes modifié")
.typeJournal(TypeJournalComptable.VENTES)
.statut("ACTIF")
.build();
Set<ConstraintViolation<UpdateJournalComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_AllJournalTypes() {
for (TypeJournalComptable type : TypeJournalComptable.values()) {
UpdateJournalComptableRequest request = UpdateJournalComptableRequest.builder()
.libelle("Journal " + type.getLibelle() + " modifié")
.typeJournal(type)
.build();
Set<ConstraintViolation<UpdateJournalComptableRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
}
@Test
void testEquals() {
UpdateJournalComptableRequest request1 = UpdateJournalComptableRequest.builder()
.libelle("Journal caisse modifié")
.typeJournal(TypeJournalComptable.CAISSE)
.statut("ACTIF")
.build();
UpdateJournalComptableRequest request2 = UpdateJournalComptableRequest.builder()
.libelle("Journal caisse modifié")
.typeJournal(TypeJournalComptable.CAISSE)
.statut("ACTIF")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateJournalComptableRequest request = UpdateJournalComptableRequest.builder()
.libelle("Opérations diverses modifié")
.typeJournal(TypeJournalComptable.OD)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateJournalComptableRequest");
assertThat(toString).contains("Opérations diverses modifié");
}
}

View File

@@ -0,0 +1,162 @@
package dev.lions.unionflow.server.api.dto.comptabilite.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateLigneEcritureRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID compteComptableId = UUID.randomUUID();
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.numeroLigne(2)
.montantDebit(BigDecimal.valueOf(2000.00))
.montantCredit(BigDecimal.ZERO)
.libelle("Ligne d'écriture modifiée")
.reference("REF-LIGNE-002")
.compteComptableId(compteComptableId)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroLigne()).isEqualTo(2);
assertThat(request.montantDebit()).isEqualByComparingTo(BigDecimal.valueOf(2000.00));
assertThat(request.montantCredit()).isEqualByComparingTo(BigDecimal.ZERO);
assertThat(request.libelle()).isEqualTo("Ligne d'écriture modifiée");
assertThat(request.reference()).isEqualTo("REF-LIGNE-002");
assertThat(request.compteComptableId()).isEqualTo(compteComptableId);
}
@Test
void testBuilder_MinimalFields() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.libelle("Libellé modifié")
.build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isEqualTo("Libellé modifié");
}
@Test
void testValidation_NumeroLigneZero() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.numeroLigne(0)
.build();
Set<ConstraintViolation<UpdateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroLigne"));
}
@Test
void testValidation_NumeroLigneNegative() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.numeroLigne(-1)
.build();
Set<ConstraintViolation<UpdateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroLigne"));
}
@Test
void testValidation_NegativeMontantDebit() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.montantDebit(BigDecimal.valueOf(-100.00))
.build();
Set<ConstraintViolation<UpdateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDebit"));
}
@Test
void testValidation_NegativeMontantCredit() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.montantCredit(BigDecimal.valueOf(-100.00))
.build();
Set<ConstraintViolation<UpdateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantCredit"));
}
@Test
void testValidation_ValidFields() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.numeroLigne(3)
.montantDebit(BigDecimal.valueOf(500.00))
.montantCredit(BigDecimal.ZERO)
.compteComptableId(UUID.randomUUID())
.build();
Set<ConstraintViolation<UpdateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_EmptyRequest() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder().build();
Set<ConstraintViolation<UpdateLigneEcritureRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID compteComptableId = UUID.randomUUID();
UpdateLigneEcritureRequest request1 = UpdateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(1000.00))
.compteComptableId(compteComptableId)
.build();
UpdateLigneEcritureRequest request2 = UpdateLigneEcritureRequest.builder()
.numeroLigne(1)
.montantDebit(BigDecimal.valueOf(1000.00))
.compteComptableId(compteComptableId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateLigneEcritureRequest request = UpdateLigneEcritureRequest.builder()
.numeroLigne(1)
.libelle("Test ligne modifiée")
.compteComptableId(UUID.randomUUID())
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateLigneEcritureRequest");
assertThat(toString).contains("Test ligne modifiée");
}
}

View File

@@ -0,0 +1,109 @@
package dev.lions.unionflow.server.api.dto.config.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateConfigurationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
Map<String, Object> metadonnees = Map.of("unit", "XOF", "min", 1000, "max", 1000000);
CreateConfigurationRequest request = CreateConfigurationRequest.builder()
.cle("seuil.transaction.max")
.valeur("1000000")
.type("NUMERIC")
.categorie("LCB_FT")
.description("Seuil maximum pour les transactions")
.modifiable(true)
.visible(true)
.metadonnees(metadonnees)
.build();
assertThat(request).isNotNull();
assertThat(request.cle()).isEqualTo("seuil.transaction.max");
assertThat(request.valeur()).isEqualTo("1000000");
assertThat(request.type()).isEqualTo("NUMERIC");
assertThat(request.categorie()).isEqualTo("LCB_FT");
assertThat(request.description()).isEqualTo("Seuil maximum pour les transactions");
assertThat(request.modifiable()).isTrue();
assertThat(request.visible()).isTrue();
assertThat(request.metadonnees()).isEqualTo(metadonnees);
}
@Test
void testBuilder_MinimalFields() {
CreateConfigurationRequest request = CreateConfigurationRequest.builder()
.cle("simple.config")
.valeur("value")
.build();
assertThat(request).isNotNull();
assertThat(request.cle()).isEqualTo("simple.config");
assertThat(request.valeur()).isEqualTo("value");
}
@Test
void testValidation_ValidFields() {
CreateConfigurationRequest request = CreateConfigurationRequest.builder()
.cle("test.config")
.valeur("test_value")
.type("STRING")
.categorie("GENERAL")
.modifiable(true)
.visible(true)
.build();
Set<ConstraintViolation<CreateConfigurationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
CreateConfigurationRequest request1 = CreateConfigurationRequest.builder()
.cle("config.key")
.valeur("value")
.type("STRING")
.build();
CreateConfigurationRequest request2 = CreateConfigurationRequest.builder()
.cle("config.key")
.valeur("value")
.type("STRING")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateConfigurationRequest request = CreateConfigurationRequest.builder()
.cle("test.key")
.valeur("test_value")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateConfigurationRequest");
assertThat(toString).contains("test.key");
}
}

View File

@@ -0,0 +1,102 @@
package dev.lions.unionflow.server.api.dto.config.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateConfigurationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
Map<String, Object> metadonnees = Map.of("lastUpdated", "2026-03-15");
UpdateConfigurationRequest request = UpdateConfigurationRequest.builder()
.cle("updated.key")
.valeur("updated_value")
.type("STRING")
.categorie("SYSTEM")
.description("Updated description")
.modifiable(false)
.visible(false)
.metadonnees(metadonnees)
.build();
assertThat(request).isNotNull();
assertThat(request.cle()).isEqualTo("updated.key");
assertThat(request.valeur()).isEqualTo("updated_value");
assertThat(request.type()).isEqualTo("STRING");
assertThat(request.categorie()).isEqualTo("SYSTEM");
assertThat(request.description()).isEqualTo("Updated description");
assertThat(request.modifiable()).isFalse();
assertThat(request.visible()).isFalse();
assertThat(request.metadonnees()).isEqualTo(metadonnees);
}
@Test
void testBuilder_MinimalFields() {
UpdateConfigurationRequest request = UpdateConfigurationRequest.builder()
.valeur("new_value")
.build();
assertThat(request).isNotNull();
assertThat(request.valeur()).isEqualTo("new_value");
}
@Test
void testValidation_ValidFields() {
UpdateConfigurationRequest request = UpdateConfigurationRequest.builder()
.cle("test.key")
.valeur("test_value")
.modifiable(true)
.build();
Set<ConstraintViolation<UpdateConfigurationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateConfigurationRequest request1 = UpdateConfigurationRequest.builder()
.cle("key")
.valeur("value")
.build();
UpdateConfigurationRequest request2 = UpdateConfigurationRequest.builder()
.cle("key")
.valeur("value")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateConfigurationRequest request = UpdateConfigurationRequest.builder()
.cle("test.key")
.valeur("test_value")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateConfigurationRequest");
assertThat(toString).contains("test.key");
}
}

View File

@@ -0,0 +1,339 @@
package dev.lions.unionflow.server.api.dto.cotisation.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateCotisationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
LocalDate dateEcheance = LocalDate.now().plusDays(30);
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(membreId)
.organisationId(organisationId)
.typeCotisation("MENSUELLE")
.libelle("Cotisation Janvier 2025")
.description("Cotisation mensuelle pour le mois de janvier")
.montantDu(new BigDecimal("25000.00"))
.codeDevise("XOF")
.dateEcheance(dateEcheance)
.periode("Janvier 2025")
.annee(2025)
.mois(1)
.recurrente(true)
.observations("Paiement à effectuer avant la fin du mois")
.build();
assertThat(request).isNotNull();
assertThat(request.membreId()).isEqualTo(membreId);
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.typeCotisation()).isEqualTo("MENSUELLE");
assertThat(request.libelle()).isEqualTo("Cotisation Janvier 2025");
assertThat(request.description()).contains("janvier");
assertThat(request.montantDu()).isEqualByComparingTo(new BigDecimal("25000.00"));
assertThat(request.codeDevise()).isEqualTo("XOF");
assertThat(request.dateEcheance()).isEqualTo(dateEcheance);
assertThat(request.periode()).isEqualTo("Janvier 2025");
assertThat(request.annee()).isEqualTo(2025);
assertThat(request.mois()).isEqualTo(1);
assertThat(request.recurrente()).isTrue();
assertThat(request.observations()).contains("Paiement");
}
@Test
void testBuilder_MinimalFields() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
LocalDate dateEcheance = LocalDate.now().plusMonths(1);
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(membreId)
.organisationId(organisationId)
.typeCotisation("ANNUELLE")
.libelle("Cotisation Simple")
.montantDu(new BigDecimal("50000.00"))
.dateEcheance(dateEcheance)
.build();
assertThat(request).isNotNull();
assertThat(request.membreId()).isEqualTo(membreId);
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.typeCotisation()).isEqualTo("ANNUELLE");
assertThat(request.libelle()).isEqualTo("Cotisation Simple");
assertThat(request.montantDu()).isEqualByComparingTo(new BigDecimal("50000.00"));
assertThat(request.dateEcheance()).isEqualTo(dateEcheance);
assertThat(request.description()).isNull();
assertThat(request.codeDevise()).isNull();
assertThat(request.periode()).isNull();
assertThat(request.annee()).isNull();
assertThat(request.mois()).isNull();
assertThat(request.recurrente()).isNull();
assertThat(request.observations()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreateCotisationRequest request = CreateCotisationRequest.builder().build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("membreId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("organisationId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeCotisation"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("libelle"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDu"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateEcheance"));
}
@Test
void testValidation_EmptyTypeCotisation() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("")
.libelle("Test")
.montantDu(new BigDecimal("10000.00"))
.dateEcheance(LocalDate.now().plusDays(10))
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeCotisation"));
}
@Test
void testValidation_EmptyLibelle() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("")
.montantDu(new BigDecimal("10000.00"))
.dateEcheance(LocalDate.now().plusDays(10))
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("libelle"));
}
@Test
void testValidation_MontantZero() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(BigDecimal.ZERO)
.dateEcheance(LocalDate.now().plusDays(10))
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDu"));
}
@Test
void testValidation_MontantNegatif() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(new BigDecimal("-1000.00"))
.dateEcheance(LocalDate.now().plusDays(10))
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDu"));
}
@Test
void testValidation_CodeDeviseTooLong() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(new BigDecimal("10000.00"))
.codeDevise("XOFF")
.dateEcheance(LocalDate.now().plusDays(10))
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
}
@Test
void testValidation_CodeDeviseTooShort() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(new BigDecimal("10000.00"))
.codeDevise("XO")
.dateEcheance(LocalDate.now().plusDays(10))
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
}
@Test
void testValidation_AnneeTooOld() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(new BigDecimal("10000.00"))
.dateEcheance(LocalDate.now().plusDays(10))
.annee(2019)
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("annee"));
}
@Test
void testValidation_AnneeTooFuture() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(new BigDecimal("10000.00"))
.dateEcheance(LocalDate.now().plusDays(10))
.annee(2101)
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("annee"));
}
@Test
void testValidation_MoisInvalide() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("MENSUELLE")
.libelle("Test")
.montantDu(new BigDecimal("10000.00"))
.dateEcheance(LocalDate.now().plusDays(10))
.mois(13)
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("mois"));
}
@Test
void testValidation_ValidFields() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("TRIMESTRIELLE")
.libelle("Cotisation Valide")
.description("Description valide")
.montantDu(new BigDecimal("75000.00"))
.codeDevise("XOF")
.dateEcheance(LocalDate.now().plusMonths(3))
.periode("T1 2025")
.annee(2025)
.mois(3)
.recurrente(false)
.observations("Aucune observation")
.build();
Set<ConstraintViolation<CreateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
LocalDate dateEcheance = LocalDate.now().plusDays(15);
CreateCotisationRequest request1 = CreateCotisationRequest.builder()
.membreId(membreId)
.organisationId(organisationId)
.typeCotisation("MENSUELLE")
.libelle("Même Cotisation")
.montantDu(new BigDecimal("20000.00"))
.dateEcheance(dateEcheance)
.build();
CreateCotisationRequest request2 = CreateCotisationRequest.builder()
.membreId(membreId)
.organisationId(organisationId)
.typeCotisation("MENSUELLE")
.libelle("Même Cotisation")
.montantDu(new BigDecimal("20000.00"))
.dateEcheance(dateEcheance)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateCotisationRequest request = CreateCotisationRequest.builder()
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.typeCotisation("ANNUELLE")
.libelle("ToString Test Cotisation")
.montantDu(new BigDecimal("100000.00"))
.dateEcheance(LocalDate.now().plusYears(1))
.annee(2026)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateCotisationRequest");
assertThat(toString).contains("ToString Test Cotisation");
assertThat(toString).contains("ANNUELLE");
assertThat(toString).contains("100000.00");
}
}

View File

@@ -0,0 +1,231 @@
package dev.lions.unionflow.server.api.dto.cotisation.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateCotisationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateEcheance = LocalDate.now().plusDays(45);
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.libelle("Cotisation Mise à Jour")
.description("Description mise à jour de la cotisation")
.montantDu(new BigDecimal("30000.00"))
.dateEcheance(dateEcheance)
.observations("Observations modifiées")
.statut("EN_ATTENTE")
.annee(2026)
.mois(6)
.recurrente(false)
.build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isEqualTo("Cotisation Mise à Jour");
assertThat(request.description()).contains("mise à jour");
assertThat(request.montantDu()).isEqualByComparingTo(new BigDecimal("30000.00"));
assertThat(request.dateEcheance()).isEqualTo(dateEcheance);
assertThat(request.observations()).contains("modifiées");
assertThat(request.statut()).isEqualTo("EN_ATTENTE");
assertThat(request.annee()).isEqualTo(2026);
assertThat(request.mois()).isEqualTo(6);
assertThat(request.recurrente()).isFalse();
}
@Test
void testBuilder_MinimalFields() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder().build();
assertThat(request).isNotNull();
assertThat(request.libelle()).isNull();
assertThat(request.description()).isNull();
assertThat(request.montantDu()).isNull();
assertThat(request.dateEcheance()).isNull();
assertThat(request.observations()).isNull();
assertThat(request.statut()).isNull();
assertThat(request.annee()).isNull();
assertThat(request.mois()).isNull();
assertThat(request.recurrente()).isNull();
}
@Test
void testValidation_LibelleTooLong() {
String longLibelle = "A".repeat(101);
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.libelle(longLibelle)
.build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("libelle"));
}
@Test
void testValidation_DescriptionTooLong() {
String longDescription = "B".repeat(501);
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.description(longDescription)
.build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("description"));
}
@Test
void testValidation_MontantZero() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.montantDu(BigDecimal.ZERO)
.build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDu"));
}
@Test
void testValidation_MontantNegatif() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.montantDu(new BigDecimal("-500.00"))
.build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantDu"));
}
@Test
void testValidation_ObservationsTooLong() {
String longObservations = "C".repeat(1001);
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.observations(longObservations)
.build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("observations"));
}
@Test
void testValidation_AnneeTooOld() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder().annee(2018).build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("annee"));
}
@Test
void testValidation_AnneeTooFuture() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder().annee(2105).build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("annee"));
}
@Test
void testValidation_MoisZero() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder().mois(0).build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("mois"));
}
@Test
void testValidation_MoisTooHigh() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder().mois(15).build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("mois"));
}
@Test
void testValidation_ValidFields() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.libelle("Libellé Valide")
.description("Description valide et complète")
.montantDu(new BigDecimal("45000.00"))
.dateEcheance(LocalDate.now().plusMonths(2))
.observations("Observations valides")
.statut("PAYE")
.annee(2025)
.mois(8)
.recurrente(true)
.build();
Set<ConstraintViolation<UpdateCotisationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
LocalDate dateEcheance = LocalDate.now().plusDays(20);
UpdateCotisationRequest request1 = UpdateCotisationRequest.builder()
.libelle("Même Libellé")
.montantDu(new BigDecimal("15000.00"))
.dateEcheance(dateEcheance)
.statut("EN_COURS")
.build();
UpdateCotisationRequest request2 = UpdateCotisationRequest.builder()
.libelle("Même Libellé")
.montantDu(new BigDecimal("15000.00"))
.dateEcheance(dateEcheance)
.statut("EN_COURS")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateCotisationRequest request = UpdateCotisationRequest.builder()
.libelle("ToString Cotisation")
.montantDu(new BigDecimal("55000.00"))
.statut("VALIDE")
.annee(2027)
.mois(12)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateCotisationRequest");
assertThat(toString).contains("ToString Cotisation");
assertThat(toString).contains("55000.00");
assertThat(toString).contains("VALIDE");
}
}

View File

@@ -132,6 +132,102 @@ class CotisationResponseTest {
}
}
@Nested
@DisplayName("Méthodes de formatage des montants")
class MethodesFormatageMontants {
@Test
@DisplayName("getMontantDuFormatte retourne 0 FCFA quand montantDu null")
void testMontantDuNull() {
CotisationResponse r = CotisationResponse.builder().build();
assertThat(r.getMontantDuFormatte()).isEqualTo("0 FCFA");
}
@Test
@DisplayName("getMontantDuFormatte formate avec devise par défaut FCFA")
void testMontantDuSansDevise() {
CotisationResponse r = CotisationResponse.builder().montantDu(BigDecimal.valueOf(5000)).build();
assertThat(r.getMontantDuFormatte()).isEqualTo("5,000 FCFA");
}
@Test
@DisplayName("getMontantDuFormatte formate avec codeDevise fourni")
void testMontantDuAvecDevise() {
CotisationResponse r = CotisationResponse.builder().montantDu(BigDecimal.valueOf(5000)).codeDevise("XOF").build();
assertThat(r.getMontantDuFormatte()).isEqualTo("5,000 XOF");
}
@Test
@DisplayName("getMontantPayeFormatte retourne 0 FCFA quand montantPaye null")
void testMontantPayeNull() {
CotisationResponse r = CotisationResponse.builder().build();
assertThat(r.getMontantPayeFormatte()).isEqualTo("0 FCFA");
}
@Test
@DisplayName("getMontantPayeFormatte formate avec devise par défaut FCFA")
void testMontantPayeSansDevise() {
CotisationResponse r = CotisationResponse.builder().montantPaye(BigDecimal.valueOf(2000)).build();
assertThat(r.getMontantPayeFormatte()).isEqualTo("2,000 FCFA");
}
@Test
@DisplayName("getMontantPayeFormatte formate avec codeDevise fourni")
void testMontantPayeAvecDevise() {
CotisationResponse r = CotisationResponse.builder().montantPaye(BigDecimal.valueOf(2000)).codeDevise("EUR").build();
assertThat(r.getMontantPayeFormatte()).isEqualTo("2,000 EUR");
}
@Test
@DisplayName("getMontantRestantFormatte retourne 0 FCFA quand montantRestant null")
void testMontantRestantNull() {
CotisationResponse r = CotisationResponse.builder().build();
assertThat(r.getMontantRestantFormatte()).isEqualTo("0 FCFA");
}
@Test
@DisplayName("getMontantRestantFormatte formate avec devise par défaut FCFA")
void testMontantRestantSansDevise() {
CotisationResponse r = CotisationResponse.builder().montantRestant(BigDecimal.valueOf(3000)).build();
assertThat(r.getMontantRestantFormatte()).isEqualTo("3,000 FCFA");
}
@Test
@DisplayName("getMontantRestantFormatte formate avec codeDevise fourni")
void testMontantRestantAvecDevise() {
CotisationResponse r = CotisationResponse.builder().montantRestant(BigDecimal.valueOf(3000)).codeDevise("XOF").build();
assertThat(r.getMontantRestantFormatte()).isEqualTo("3,000 XOF");
}
@Test
@DisplayName("isMontantRestantPositif retourne false quand montantRestant null")
void testMontantRestantPositifNull() {
CotisationResponse r = CotisationResponse.builder().build();
assertThat(r.isMontantRestantPositif()).isFalse();
}
@Test
@DisplayName("isMontantRestantPositif retourne false quand montantRestant = 0")
void testMontantRestantPositifZero() {
CotisationResponse r = CotisationResponse.builder().montantRestant(BigDecimal.ZERO).build();
assertThat(r.isMontantRestantPositif()).isFalse();
}
@Test
@DisplayName("isMontantRestantPositif retourne false quand montantRestant négatif")
void testMontantRestantPositifNegatif() {
CotisationResponse r = CotisationResponse.builder().montantRestant(BigDecimal.valueOf(-100)).build();
assertThat(r.isMontantRestantPositif()).isFalse();
}
@Test
@DisplayName("isMontantRestantPositif retourne true quand montantRestant > 0")
void testMontantRestantPositifVrai() {
CotisationResponse r = CotisationResponse.builder().montantRestant(BigDecimal.valueOf(500)).build();
assertThat(r.isMontantRestantPositif()).isTrue();
}
}
@Nested
@DisplayName("Builder complet")
class BuilderComplet {

View File

@@ -0,0 +1,282 @@
package dev.lions.unionflow.server.api.dto.cotisation.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
/**
* Tests unitaires pour CotisationSummaryResponse (record).
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-15
*/
@DisplayName("Tests CotisationSummaryResponse")
class CotisationSummaryResponseTest {
@Nested
@DisplayName("Constructeur et accesseurs")
class ConstructeurEtAccesseurs {
@Test
@DisplayName("Le constructeur crée une instance avec tous les champs")
void testConstructeurComplet() {
UUID id = UUID.randomUUID();
String numeroReference = "COT-2026-001";
String nomMembre = "Jean Dupont";
BigDecimal montantDu = new BigDecimal("50000.00");
BigDecimal montantPaye = new BigDecimal("30000.00");
String statut = "EN_COURS";
String statutLibelle = "Paiement en cours";
LocalDate dateEcheance = LocalDate.of(2026, 12, 31);
Integer annee = 2026;
Boolean actif = true;
CotisationSummaryResponse response = new CotisationSummaryResponse(
id,
numeroReference,
nomMembre,
montantDu,
montantPaye,
statut,
statutLibelle,
dateEcheance,
annee,
actif
);
assertThat(response).isNotNull();
assertThat(response.id()).isEqualTo(id);
assertThat(response.numeroReference()).isEqualTo("COT-2026-001");
assertThat(response.nomMembre()).isEqualTo("Jean Dupont");
assertThat(response.montantDu()).isEqualTo(new BigDecimal("50000.00"));
assertThat(response.montantPaye()).isEqualTo(new BigDecimal("30000.00"));
assertThat(response.statut()).isEqualTo("EN_COURS");
assertThat(response.statutLibelle()).isEqualTo("Paiement en cours");
assertThat(response.dateEcheance()).isEqualTo(LocalDate.of(2026, 12, 31));
assertThat(response.annee()).isEqualTo(2026);
assertThat(response.actif()).isTrue();
}
@Test
@DisplayName("Le constructeur accepte des valeurs null")
void testConstructeurAvecNull() {
CotisationSummaryResponse response = new CotisationSummaryResponse(
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
assertThat(response).isNotNull();
assertThat(response.id()).isNull();
assertThat(response.numeroReference()).isNull();
assertThat(response.nomMembre()).isNull();
assertThat(response.montantDu()).isNull();
assertThat(response.montantPaye()).isNull();
assertThat(response.statut()).isNull();
assertThat(response.statutLibelle()).isNull();
assertThat(response.dateEcheance()).isNull();
assertThat(response.annee()).isNull();
assertThat(response.actif()).isNull();
}
}
@Nested
@DisplayName("equals et hashCode")
class EqualsEtHashCode {
@Test
@DisplayName("equals retourne true pour mêmes valeurs")
void testEqualsMemeValeurs() {
UUID id = UUID.randomUUID();
LocalDate date = LocalDate.of(2026, 12, 31);
BigDecimal montantDu = new BigDecimal("50000.00");
BigDecimal montantPaye = new BigDecimal("30000.00");
CotisationSummaryResponse r1 = new CotisationSummaryResponse(
id, "COT-001", "Jean", montantDu, montantPaye,
"PAYE", "Payé", date, 2026, true
);
CotisationSummaryResponse r2 = new CotisationSummaryResponse(
id, "COT-001", "Jean", montantDu, montantPaye,
"PAYE", "Payé", date, 2026, true
);
assertThat(r1).isEqualTo(r2);
}
@Test
@DisplayName("equals retourne false pour valeurs différentes")
void testEqualsValeursDifferentes() {
UUID id1 = UUID.randomUUID();
UUID id2 = UUID.randomUUID();
LocalDate date = LocalDate.of(2026, 12, 31);
BigDecimal montant = new BigDecimal("50000.00");
CotisationSummaryResponse r1 = new CotisationSummaryResponse(
id1, "COT-001", "Jean", montant, montant,
"PAYE", "Payé", date, 2026, true
);
CotisationSummaryResponse r2 = new CotisationSummaryResponse(
id2, "COT-002", "Marie", montant, montant,
"EN_COURS", "En cours", date, 2026, true
);
assertThat(r1).isNotEqualTo(r2);
}
@Test
@DisplayName("hashCode est cohérent avec equals")
void testHashCodeCoherentAvecEquals() {
UUID id = UUID.randomUUID();
LocalDate date = LocalDate.of(2026, 12, 31);
BigDecimal montantDu = new BigDecimal("50000.00");
BigDecimal montantPaye = new BigDecimal("30000.00");
CotisationSummaryResponse r1 = new CotisationSummaryResponse(
id, "COT-001", "Jean", montantDu, montantPaye,
"PAYE", "Payé", date, 2026, true
);
CotisationSummaryResponse r2 = new CotisationSummaryResponse(
id, "COT-001", "Jean", montantDu, montantPaye,
"PAYE", "Payé", date, 2026, true
);
assertThat(r1).isEqualTo(r2);
assertThat(r1.hashCode()).isEqualTo(r2.hashCode());
}
}
@Nested
@DisplayName("toString")
class ToString {
@Test
@DisplayName("toString retourne une représentation lisible")
void testToString() {
UUID id = UUID.randomUUID();
CotisationSummaryResponse response = new CotisationSummaryResponse(
id,
"COT-2026-001",
"Jean Dupont",
new BigDecimal("50000.00"),
new BigDecimal("30000.00"),
"EN_COURS",
"Paiement en cours",
LocalDate.of(2026, 12, 31),
2026,
true
);
String result = response.toString();
assertThat(result).isNotNull();
assertThat(result).contains("CotisationSummaryResponse");
assertThat(result).contains("COT-2026-001");
assertThat(result).contains("Jean Dupont");
}
}
@Nested
@DisplayName("Scénarios métier")
class ScenariosMetier {
@Test
@DisplayName("Cotisation entièrement payée")
void testCotisationPayee() {
BigDecimal montant = new BigDecimal("50000.00");
CotisationSummaryResponse response = new CotisationSummaryResponse(
UUID.randomUUID(),
"COT-2026-001",
"Jean Dupont",
montant,
montant,
"PAYE",
"Payé",
LocalDate.of(2026, 12, 31),
2026,
true
);
assertThat(response.montantDu()).isEqualTo(response.montantPaye());
assertThat(response.statut()).isEqualTo("PAYE");
}
@Test
@DisplayName("Cotisation partiellement payée")
void testCotisationPartielle() {
CotisationSummaryResponse response = new CotisationSummaryResponse(
UUID.randomUUID(),
"COT-2026-002",
"Marie Martin",
new BigDecimal("50000.00"),
new BigDecimal("25000.00"),
"EN_COURS",
"Paiement en cours",
LocalDate.of(2026, 12, 31),
2026,
true
);
assertThat(response.montantPaye()).isLessThan(response.montantDu());
assertThat(response.statut()).isEqualTo("EN_COURS");
}
@Test
@DisplayName("Cotisation non payée")
void testCotisationNonPayee() {
CotisationSummaryResponse response = new CotisationSummaryResponse(
UUID.randomUUID(),
"COT-2026-003",
"Pierre Durand",
new BigDecimal("50000.00"),
BigDecimal.ZERO,
"IMPAYE",
"Impayé",
LocalDate.of(2026, 12, 31),
2026,
true
);
assertThat(response.montantPaye()).isEqualByComparingTo(BigDecimal.ZERO);
assertThat(response.statut()).isEqualTo("IMPAYE");
}
@Test
@DisplayName("Cotisation échue")
void testCotisationEchue() {
LocalDate datePassee = LocalDate.now().minusDays(30);
CotisationSummaryResponse response = new CotisationSummaryResponse(
UUID.randomUUID(),
"COT-2026-004",
"Sophie Bernard",
new BigDecimal("50000.00"),
BigDecimal.ZERO,
"RETARD",
"En retard",
datePassee,
2026,
true
);
assertThat(response.dateEcheance()).isBefore(LocalDate.now());
assertThat(response.statut()).isEqualTo("RETARD");
}
}
}

View File

@@ -167,6 +167,15 @@ class UpcomingEventResponseTest {
assertThat(dto.getIsFull()).isFalse();
}
@Test
@DisplayName("retourne false quand maxParticipants défini mais currentParticipants null")
void testMaxDefinitCurrentNull() {
UpcomingEventResponse dto = UpcomingEventResponse.builder()
.maxParticipants(10)
.build();
assertThat(dto.getIsFull()).isFalse();
}
@Test
@DisplayName("retourne true quand current >= max")
void testFull() {
@@ -341,6 +350,15 @@ class UpcomingEventResponseTest {
assertThat(dto.getAvailableSpots()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand maxParticipants défini mais currentParticipants null")
void testMaxDefinitCurrentNull() {
UpcomingEventResponse dto = UpcomingEventResponse.builder()
.maxParticipants(10)
.build();
assertThat(dto.getAvailableSpots()).isEqualTo(0);
}
@Test
@DisplayName("retourne max - current")
void testCalcul() {
@@ -369,6 +387,15 @@ class UpcomingEventResponseTest {
assertThat(dto.getParticipationSummary()).isEqualTo("0/0 participants");
}
@Test
@DisplayName("retourne 0/0 quand maxParticipants défini mais currentParticipants null")
void testMaxDefinitCurrentNull() {
UpcomingEventResponse dto = UpcomingEventResponse.builder()
.maxParticipants(20)
.build();
assertThat(dto.getParticipationSummary()).isEqualTo("0/0 participants");
}
@Test
@DisplayName("retourne current/max participants")
void testSummary() {

View File

@@ -0,0 +1,173 @@
package dev.lions.unionflow.server.api.dto.document.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.document.TypeDocument;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateDocumentRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("document_2025.pdf")
.nomOriginal("Document Original.pdf")
.cheminStockage("/storage/documents/2025/")
.typeMime("application/pdf")
.tailleOctets(1024000L)
.typeDocument(TypeDocument.CONTRAT)
.hashMd5("5d41402abc4b2a76b9719d911017c592")
.hashSha256("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
.description("Contrat de prestation")
.build();
assertThat(request).isNotNull();
assertThat(request.nomFichier()).isEqualTo("document_2025.pdf");
assertThat(request.nomOriginal()).isEqualTo("Document Original.pdf");
assertThat(request.cheminStockage()).isEqualTo("/storage/documents/2025/");
assertThat(request.typeMime()).isEqualTo("application/pdf");
assertThat(request.tailleOctets()).isEqualTo(1024000L);
assertThat(request.typeDocument()).isEqualTo(TypeDocument.CONTRAT);
assertThat(request.hashMd5()).isEqualTo("5d41402abc4b2a76b9719d911017c592");
assertThat(request.hashSha256())
.isEqualTo("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
assertThat(request.description()).isEqualTo("Contrat de prestation");
}
@Test
void testBuilder_MinimalFields() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("simple.pdf")
.cheminStockage("/storage/")
.tailleOctets(1024L)
.build();
assertThat(request).isNotNull();
assertThat(request.nomFichier()).isEqualTo("simple.pdf");
assertThat(request.cheminStockage()).isEqualTo("/storage/");
assertThat(request.tailleOctets()).isEqualTo(1024L);
assertThat(request.nomOriginal()).isNull();
assertThat(request.typeMime()).isNull();
assertThat(request.typeDocument()).isNull();
assertThat(request.hashMd5()).isNull();
assertThat(request.hashSha256()).isNull();
assertThat(request.description()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreateDocumentRequest request = CreateDocumentRequest.builder().build();
Set<ConstraintViolation<CreateDocumentRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nomFichier"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("cheminStockage"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("tailleOctets"));
}
@Test
void testValidation_EmptyNomFichier() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("")
.cheminStockage("/storage/")
.tailleOctets(1024L)
.build();
Set<ConstraintViolation<CreateDocumentRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nomFichier"));
}
@Test
void testValidation_EmptyCheminStockage() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("file.pdf")
.cheminStockage("")
.tailleOctets(1024L)
.build();
Set<ConstraintViolation<CreateDocumentRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("cheminStockage"));
}
@Test
void testValidation_NegativeTaille() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("file.pdf")
.cheminStockage("/storage/")
.tailleOctets(-100L)
.build();
Set<ConstraintViolation<CreateDocumentRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("tailleOctets"));
}
@Test
void testValidation_ValidFields() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("valid.pdf")
.cheminStockage("/storage/docs/")
.tailleOctets(2048L)
.typeDocument(TypeDocument.FACTURE)
.build();
Set<ConstraintViolation<CreateDocumentRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
CreateDocumentRequest request1 = CreateDocumentRequest.builder()
.nomFichier("doc.pdf")
.cheminStockage("/storage/")
.tailleOctets(1024L)
.build();
CreateDocumentRequest request2 = CreateDocumentRequest.builder()
.nomFichier("doc.pdf")
.cheminStockage("/storage/")
.tailleOctets(1024L)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateDocumentRequest request = CreateDocumentRequest.builder()
.nomFichier("test.pdf")
.cheminStockage("/storage/test/")
.tailleOctets(512L)
.typeDocument(TypeDocument.RAPPORT)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateDocumentRequest");
assertThat(toString).contains("test.pdf");
assertThat(toString).contains("RAPPORT");
}
}

View File

@@ -0,0 +1,168 @@
package dev.lions.unionflow.server.api.dto.document.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreatePieceJointeRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID documentId = UUID.randomUUID();
UUID entiteId = UUID.randomUUID();
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder()
.ordre(1)
.libelle("Pièce principale")
.commentaire("Document requis pour validation")
.documentId(documentId)
.typeEntiteRattachee("MEMBRE")
.entiteRattacheeId(entiteId)
.build();
assertThat(request).isNotNull();
assertThat(request.ordre()).isEqualTo(1);
assertThat(request.libelle()).isEqualTo("Pièce principale");
assertThat(request.commentaire()).isEqualTo("Document requis pour validation");
assertThat(request.documentId()).isEqualTo(documentId);
assertThat(request.typeEntiteRattachee()).isEqualTo("MEMBRE");
assertThat(request.entiteRattacheeId()).isEqualTo(entiteId);
}
@Test
void testBuilder_MinimalFields() {
UUID documentId = UUID.randomUUID();
UUID entiteId = UUID.randomUUID();
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder()
.ordre(1)
.documentId(documentId)
.typeEntiteRattachee("ORGANISATION")
.entiteRattacheeId(entiteId)
.build();
assertThat(request).isNotNull();
assertThat(request.ordre()).isEqualTo(1);
assertThat(request.documentId()).isEqualTo(documentId);
assertThat(request.typeEntiteRattachee()).isEqualTo("ORGANISATION");
assertThat(request.entiteRattacheeId()).isEqualTo(entiteId);
assertThat(request.libelle()).isNull();
assertThat(request.commentaire()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder().build();
Set<ConstraintViolation<CreatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ordre"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("documentId"));
assertThat(violations)
.anyMatch(v -> v.getPropertyPath().toString().equals("typeEntiteRattachee"));
assertThat(violations)
.anyMatch(v -> v.getPropertyPath().toString().equals("entiteRattacheeId"));
}
@Test
void testValidation_OrdreZero() {
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder()
.ordre(0)
.documentId(UUID.randomUUID())
.typeEntiteRattachee("MEMBRE")
.entiteRattacheeId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ordre"));
}
@Test
void testValidation_OrdreNegatif() {
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder()
.ordre(-5)
.documentId(UUID.randomUUID())
.typeEntiteRattachee("MEMBRE")
.entiteRattacheeId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ordre"));
}
@Test
void testValidation_ValidFields() {
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder()
.ordre(2)
.libelle("Pièce valide")
.documentId(UUID.randomUUID())
.typeEntiteRattachee("EVENEMENT")
.entiteRattacheeId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID documentId = UUID.randomUUID();
UUID entiteId = UUID.randomUUID();
CreatePieceJointeRequest request1 = CreatePieceJointeRequest.builder()
.ordre(1)
.documentId(documentId)
.typeEntiteRattachee("MEMBRE")
.entiteRattacheeId(entiteId)
.build();
CreatePieceJointeRequest request2 = CreatePieceJointeRequest.builder()
.ordre(1)
.documentId(documentId)
.typeEntiteRattachee("MEMBRE")
.entiteRattacheeId(entiteId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreatePieceJointeRequest request = CreatePieceJointeRequest.builder()
.ordre(3)
.libelle("Test Pièce")
.documentId(UUID.randomUUID())
.typeEntiteRattachee("CONTRAT")
.entiteRattacheeId(UUID.randomUUID())
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreatePieceJointeRequest");
assertThat(toString).contains("Test Pièce");
assertThat(toString).contains("CONTRAT");
}
}

View File

@@ -0,0 +1,95 @@
package dev.lions.unionflow.server.api.dto.document.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.document.TypeDocument;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateDocumentRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UpdateDocumentRequest request = UpdateDocumentRequest.builder()
.nomFichier("updated_document.pdf")
.nomOriginal("Updated Original.pdf")
.typeDocument(TypeDocument.RECU)
.description("Description mise à jour")
.build();
assertThat(request).isNotNull();
assertThat(request.nomFichier()).isEqualTo("updated_document.pdf");
assertThat(request.nomOriginal()).isEqualTo("Updated Original.pdf");
assertThat(request.typeDocument()).isEqualTo(TypeDocument.RECU);
assertThat(request.description()).isEqualTo("Description mise à jour");
}
@Test
void testBuilder_MinimalFields() {
UpdateDocumentRequest request = UpdateDocumentRequest.builder().build();
assertThat(request).isNotNull();
assertThat(request.nomFichier()).isNull();
assertThat(request.nomOriginal()).isNull();
assertThat(request.typeDocument()).isNull();
assertThat(request.description()).isNull();
}
@Test
void testValidation_ValidFields() {
UpdateDocumentRequest request = UpdateDocumentRequest.builder()
.nomFichier("valid_update.pdf")
.typeDocument(TypeDocument.AUTRE)
.description("Valid description")
.build();
Set<ConstraintViolation<UpdateDocumentRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateDocumentRequest request1 = UpdateDocumentRequest.builder()
.nomFichier("same.pdf")
.typeDocument(TypeDocument.PHOTO)
.build();
UpdateDocumentRequest request2 = UpdateDocumentRequest.builder()
.nomFichier("same.pdf")
.typeDocument(TypeDocument.PHOTO)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateDocumentRequest request = UpdateDocumentRequest.builder()
.nomFichier("toString_test.pdf")
.typeDocument(TypeDocument.IDENTITE)
.description("Test toString")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateDocumentRequest");
assertThat(toString).contains("toString_test.pdf");
assertThat(toString).contains("IDENTITE");
}
}

View File

@@ -0,0 +1,110 @@
package dev.lions.unionflow.server.api.dto.document.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdatePieceJointeRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UpdatePieceJointeRequest request = UpdatePieceJointeRequest.builder()
.ordre(5)
.libelle("Libellé mis à jour")
.commentaire("Nouveau commentaire")
.build();
assertThat(request).isNotNull();
assertThat(request.ordre()).isEqualTo(5);
assertThat(request.libelle()).isEqualTo("Libellé mis à jour");
assertThat(request.commentaire()).isEqualTo("Nouveau commentaire");
}
@Test
void testBuilder_MinimalFields() {
UpdatePieceJointeRequest request = UpdatePieceJointeRequest.builder().build();
assertThat(request).isNotNull();
assertThat(request.ordre()).isNull();
assertThat(request.libelle()).isNull();
assertThat(request.commentaire()).isNull();
}
@Test
void testValidation_OrdreZero() {
UpdatePieceJointeRequest request = UpdatePieceJointeRequest.builder().ordre(0).build();
Set<ConstraintViolation<UpdatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ordre"));
}
@Test
void testValidation_OrdreNegatif() {
UpdatePieceJointeRequest request = UpdatePieceJointeRequest.builder().ordre(-10).build();
Set<ConstraintViolation<UpdatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ordre"));
}
@Test
void testValidation_ValidFields() {
UpdatePieceJointeRequest request = UpdatePieceJointeRequest.builder()
.ordre(3)
.libelle("Valid label")
.commentaire("Valid comment")
.build();
Set<ConstraintViolation<UpdatePieceJointeRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdatePieceJointeRequest request1 = UpdatePieceJointeRequest.builder()
.ordre(2)
.libelle("Same label")
.build();
UpdatePieceJointeRequest request2 = UpdatePieceJointeRequest.builder()
.ordre(2)
.libelle("Same label")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdatePieceJointeRequest request = UpdatePieceJointeRequest.builder()
.ordre(7)
.libelle("Test toString")
.commentaire("Comment test")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdatePieceJointeRequest");
assertThat(toString).contains("Test toString");
}
}

View File

@@ -0,0 +1,282 @@
package dev.lions.unionflow.server.api.dto.evenement.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateEvenementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID associationId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now().plusDays(10);
LocalDate dateFin = LocalDate.now().plusDays(12);
LocalDate dateLimite = LocalDate.now().plusDays(5);
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Assemblée Générale 2025")
.description("Réunion annuelle de tous les membres")
.typeEvenement(TypeEvenementMetier.ASSEMBLEE_GENERALE)
.statut(StatutEvenement.PLANIFIE)
.priorite(PrioriteEvenement.HAUTE)
.dateDebut(dateDebut)
.dateFin(dateFin)
.heureDebut(LocalTime.of(9, 0))
.heureFin(LocalTime.of(17, 0))
.lieu("Salle des Congrès")
.adresse("123 Avenue de la République")
.ville("Dakar")
.region("Dakar")
.latitude(new BigDecimal("14.6937"))
.longitude(new BigDecimal("-17.4441"))
.associationId(associationId)
.organisateur("Comité d'Organisation")
.emailOrganisateur("contact@unionflow.org")
.telephoneOrganisateur("+221 33 123 45 67")
.capaciteMax(500)
.budget(new BigDecimal("5000000.00"))
.coutReel(new BigDecimal("4500000.00"))
.codeDevise("XOF")
.inscriptionObligatoire(true)
.dateLimiteInscription(dateLimite)
.evenementPublic(false)
.recurrent(false)
.frequenceRecurrence(null)
.instructions("Apporter votre carte de membre")
.materielNecessaire("Aucun")
.conditionsMeteo("Intérieur")
.imageUrl("https://example.com/image.jpg")
.couleurTheme("#FF5733")
.build();
assertThat(request).isNotNull();
assertThat(request.titre()).isEqualTo("Assemblée Générale 2025");
assertThat(request.description()).contains("Réunion annuelle");
assertThat(request.typeEvenement()).isEqualTo(TypeEvenementMetier.ASSEMBLEE_GENERALE);
assertThat(request.statut()).isEqualTo(StatutEvenement.PLANIFIE);
assertThat(request.priorite()).isEqualTo(PrioriteEvenement.HAUTE);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.dateFin()).isEqualTo(dateFin);
assertThat(request.heureDebut()).isEqualTo(LocalTime.of(9, 0));
assertThat(request.heureFin()).isEqualTo(LocalTime.of(17, 0));
assertThat(request.lieu()).isEqualTo("Salle des Congrès");
assertThat(request.ville()).isEqualTo("Dakar");
assertThat(request.capaciteMax()).isEqualTo(500);
assertThat(request.budget()).isEqualByComparingTo(new BigDecimal("5000000.00"));
assertThat(request.codeDevise()).isEqualTo("XOF");
assertThat(request.inscriptionObligatoire()).isTrue();
assertThat(request.couleurTheme()).isEqualTo("#FF5733");
}
@Test
void testBuilder_MinimalFields() {
UUID associationId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now().plusDays(1);
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Événement Simple")
.typeEvenement(TypeEvenementMetier.FORMATION)
.statut(StatutEvenement.CONFIRME)
.dateDebut(dateDebut)
.lieu("Salle A")
.associationId(associationId)
.build();
assertThat(request).isNotNull();
assertThat(request.titre()).isEqualTo("Événement Simple");
assertThat(request.typeEvenement()).isEqualTo(TypeEvenementMetier.FORMATION);
assertThat(request.statut()).isEqualTo(StatutEvenement.CONFIRME);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.lieu()).isEqualTo("Salle A");
assertThat(request.associationId()).isEqualTo(associationId);
}
@Test
void testValidation_MissingRequiredFields() {
CreateEvenementRequest request = CreateEvenementRequest.builder().build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("titre"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeEvenement"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("statut"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateDebut"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("lieu"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("associationId"));
}
@Test
void testValidation_TitreTooShort() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("AB")
.typeEvenement(TypeEvenementMetier.CONFERENCE)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(LocalDate.now().plusDays(1))
.lieu("Lieu")
.associationId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("titre"));
}
@Test
void testValidation_EmailInvalide() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Événement Test")
.typeEvenement(TypeEvenementMetier.ATELIER)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(LocalDate.now().plusDays(1))
.lieu("Lieu")
.associationId(UUID.randomUUID())
.emailOrganisateur("invalid-email")
.build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("emailOrganisateur"));
}
@Test
void testValidation_LatitudeInvalide() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Événement Test")
.typeEvenement(TypeEvenementMetier.CEREMONIE)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(LocalDate.now().plusDays(1))
.lieu("Lieu")
.associationId(UUID.randomUUID())
.latitude(new BigDecimal("95.0"))
.build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("latitude"));
}
@Test
void testValidation_LongitudeInvalide() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Événement Test")
.typeEvenement(TypeEvenementMetier.ACTION_CARITATIVE)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(LocalDate.now().plusDays(1))
.lieu("Lieu")
.associationId(UUID.randomUUID())
.longitude(new BigDecimal("-185.0"))
.build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("longitude"));
}
@Test
void testValidation_CouleurThemeInvalide() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Événement Test")
.typeEvenement(TypeEvenementMetier.AUTRE)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(LocalDate.now().plusDays(1))
.lieu("Lieu")
.associationId(UUID.randomUUID())
.couleurTheme("invalid")
.build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("couleurTheme"));
}
@Test
void testValidation_ValidFields() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Événement Valide")
.typeEvenement(TypeEvenementMetier.REUNION_BUREAU)
.statut(StatutEvenement.CONFIRME)
.dateDebut(LocalDate.now().plusDays(5))
.lieu("Bureau Central")
.associationId(UUID.randomUUID())
.emailOrganisateur("valid@example.com")
.telephoneOrganisateur("+221 77 123 45 67")
.build();
Set<ConstraintViolation<CreateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID associationId = UUID.randomUUID();
LocalDate dateDebut = LocalDate.now().plusDays(1);
CreateEvenementRequest request1 = CreateEvenementRequest.builder()
.titre("Même Événement")
.typeEvenement(TypeEvenementMetier.FORMATION)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(dateDebut)
.lieu("Lieu")
.associationId(associationId)
.build();
CreateEvenementRequest request2 = CreateEvenementRequest.builder()
.titre("Même Événement")
.typeEvenement(TypeEvenementMetier.FORMATION)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(dateDebut)
.lieu("Lieu")
.associationId(associationId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateEvenementRequest request = CreateEvenementRequest.builder()
.titre("Test ToString")
.typeEvenement(TypeEvenementMetier.ACTIVITE_SOCIALE)
.statut(StatutEvenement.PLANIFIE)
.dateDebut(LocalDate.now().plusDays(1))
.lieu("Test Lieu")
.associationId(UUID.randomUUID())
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateEvenementRequest");
assertThat(toString).contains("Test ToString");
assertThat(toString).contains("ACTIVITE_SOCIALE");
}
}

View File

@@ -0,0 +1,205 @@
package dev.lions.unionflow.server.api.dto.evenement.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateEvenementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateDebut = LocalDate.now().plusDays(15);
LocalDate dateFin = LocalDate.now().plusDays(17);
LocalDate dateLimite = LocalDate.now().plusDays(10);
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.titre("Événement Mis à Jour")
.description("Description modifiée")
.typeEvenement(TypeEvenementMetier.CONFERENCE)
.statut(StatutEvenement.CONFIRME)
.priorite(PrioriteEvenement.NORMALE)
.dateDebut(dateDebut)
.dateFin(dateFin)
.heureDebut(LocalTime.of(10, 0))
.heureFin(LocalTime.of(18, 0))
.lieu("Nouveau Lieu")
.adresse("Nouvelle Adresse")
.ville("Saint-Louis")
.region("Saint-Louis")
.latitude(new BigDecimal("16.0333"))
.longitude(new BigDecimal("-16.5000"))
.organisateur("Nouveau Organisateur")
.emailOrganisateur("nouveau@example.com")
.telephoneOrganisateur("+221 77 987 65 43")
.capaciteMax(800)
.budget(new BigDecimal("8000000.00"))
.coutReel(new BigDecimal("7500000.00"))
.codeDevise("XOF")
.inscriptionObligatoire(false)
.dateLimiteInscription(dateLimite)
.evenementPublic(true)
.recurrent(true)
.frequenceRecurrence("MENSUEL")
.instructions("Nouvelles instructions")
.materielNecessaire("Ordinateur portable")
.conditionsMeteo("Extérieur")
.imageUrl("https://example.com/new-image.jpg")
.couleurTheme("#3498DB")
.build();
assertThat(request).isNotNull();
assertThat(request.titre()).isEqualTo("Événement Mis à Jour");
assertThat(request.description()).isEqualTo("Description modifiée");
assertThat(request.typeEvenement()).isEqualTo(TypeEvenementMetier.CONFERENCE);
assertThat(request.statut()).isEqualTo(StatutEvenement.CONFIRME);
assertThat(request.priorite()).isEqualTo(PrioriteEvenement.NORMALE);
assertThat(request.dateDebut()).isEqualTo(dateDebut);
assertThat(request.dateFin()).isEqualTo(dateFin);
assertThat(request.lieu()).isEqualTo("Nouveau Lieu");
assertThat(request.ville()).isEqualTo("Saint-Louis");
assertThat(request.capaciteMax()).isEqualTo(800);
assertThat(request.budget()).isEqualByComparingTo(new BigDecimal("8000000.00"));
assertThat(request.evenementPublic()).isTrue();
assertThat(request.recurrent()).isTrue();
assertThat(request.couleurTheme()).isEqualTo("#3498DB");
}
@Test
void testBuilder_MinimalFields() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.titre("Titre Simple")
.lieu("Lieu Simple")
.build();
assertThat(request).isNotNull();
assertThat(request.titre()).isEqualTo("Titre Simple");
assertThat(request.lieu()).isEqualTo("Lieu Simple");
assertThat(request.description()).isNull();
assertThat(request.typeEvenement()).isNull();
assertThat(request.statut()).isNull();
}
@Test
void testValidation_EmptyLieu() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder().lieu("").build();
Set<ConstraintViolation<UpdateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("lieu"));
}
@Test
void testValidation_EmailInvalide() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.lieu("Lieu Test")
.emailOrganisateur("not-an-email")
.build();
Set<ConstraintViolation<UpdateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("emailOrganisateur"));
}
@Test
void testValidation_LatitudeInvalide() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.lieu("Lieu Test")
.latitude(new BigDecimal("100.0"))
.build();
Set<ConstraintViolation<UpdateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("latitude"));
}
@Test
void testValidation_CouleurThemeInvalide() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.lieu("Lieu Test")
.couleurTheme("NotAColor")
.build();
Set<ConstraintViolation<UpdateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("couleurTheme"));
}
@Test
void testValidation_ValidFields() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.titre("Événement Valide")
.lieu("Lieu Valide")
.typeEvenement(TypeEvenementMetier.ATELIER)
.statut(StatutEvenement.EN_COURS)
.emailOrganisateur("valide@test.com")
.telephoneOrganisateur("+221 33 111 22 33")
.latitude(new BigDecimal("14.5"))
.longitude(new BigDecimal("-17.5"))
.couleurTheme("#AABBCC")
.build();
Set<ConstraintViolation<UpdateEvenementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateEvenementRequest request1 = UpdateEvenementRequest.builder()
.titre("Même Titre")
.lieu("Même Lieu")
.statut(StatutEvenement.REPORTE)
.build();
UpdateEvenementRequest request2 = UpdateEvenementRequest.builder()
.titre("Même Titre")
.lieu("Même Lieu")
.statut(StatutEvenement.REPORTE)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateEvenementRequest request = UpdateEvenementRequest.builder()
.titre("ToString Test")
.lieu("Test Lieu")
.typeEvenement(TypeEvenementMetier.CEREMONIE)
.statut(StatutEvenement.TERMINE)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateEvenementRequest");
assertThat(toString).contains("ToString Test");
assertThat(toString).contains("CEREMONIE");
assertThat(toString).contains("TERMINE");
}
}

View File

@@ -98,6 +98,44 @@ class EvenementResponseTest {
.build();
assertThat(r.getAdresseComplete()).isEqualTo("Lyon");
}
@Test
@DisplayName("adresse seule sans virgule (premier champ)")
void testAdresseSeule() {
EvenementResponse r = EvenementResponse.builder()
.adresse("1 rue Test")
.build();
assertThat(r.getAdresseComplete()).isEqualTo("1 rue Test");
}
@Test
@DisplayName("ville avec espaces uniquement est ignorée")
void testVilleEspaces() {
EvenementResponse r = EvenementResponse.builder()
.lieu("Salle")
.ville(" ")
.build();
assertThat(r.getAdresseComplete()).isEqualTo("Salle");
}
@Test
@DisplayName("region avec espaces uniquement est ignorée")
void testRegionEspaces() {
EvenementResponse r = EvenementResponse.builder()
.lieu("Salle")
.region(" ")
.build();
assertThat(r.getAdresseComplete()).isEqualTo("Salle");
}
@Test
@DisplayName("region seule sans virgule (premier champ)")
void testRegionSeule() {
EvenementResponse r = EvenementResponse.builder()
.region("Île-de-France")
.build();
assertThat(r.getAdresseComplete()).isEqualTo("Île-de-France");
}
}
@Nested
@@ -305,4 +343,408 @@ class EvenementResponseTest {
assertThat(r.estBudgetDepasse()).isFalse();
}
}
@Nested
@DisplayName("getPlacesDisponibles")
class GetPlacesDisponibles {
@Test
@DisplayName("retourne 0 quand capaciteMax null")
void testCapaciteNull() {
EvenementResponse r = base();
r.setCapaciteMax(null);
r.setParticipantsInscrits(50);
assertThat(r.getPlacesDisponibles()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand participantsInscrits null")
void testInscritsNull() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(null);
assertThat(r.getPlacesDisponibles()).isEqualTo(0);
}
@Test
@DisplayName("retourne différence capaciteMax - participantsInscrits")
void testCalcul() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(70);
assertThat(r.getPlacesDisponibles()).isEqualTo(30);
}
@Test
@DisplayName("retourne 0 quand participantsInscrits >= capaciteMax")
void testComplet() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(110);
assertThat(r.getPlacesDisponibles()).isEqualTo(0);
}
}
@Nested
@DisplayName("getTauxRemplissage")
class GetTauxRemplissage {
@Test
@DisplayName("retourne 0 quand capaciteMax null")
void testCapaciteNull() {
EvenementResponse r = base();
r.setCapaciteMax(null);
r.setParticipantsInscrits(50);
assertThat(r.getTauxRemplissage()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand capaciteMax = 0")
void testCapaciteZero() {
EvenementResponse r = base();
r.setCapaciteMax(0);
r.setParticipantsInscrits(0);
assertThat(r.getTauxRemplissage()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand participantsInscrits null")
void testInscritsNull() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(null);
assertThat(r.getTauxRemplissage()).isEqualTo(0);
}
@Test
@DisplayName("calcule pourcentage remplissage")
void testCalcul() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(75);
assertThat(r.getTauxRemplissage()).isEqualTo(75);
}
@Test
@DisplayName("retourne 100 quand capaciteMax = participantsInscrits")
void testComplet() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(100);
assertThat(r.getTauxRemplissage()).isEqualTo(100);
}
@Test
@DisplayName("retourne > 100 quand participantsInscrits > capaciteMax")
void testSurReservation() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(120);
assertThat(r.getTauxRemplissage()).isEqualTo(120);
}
}
@Nested
@DisplayName("Branches manquantes")
class BranchesManquantes {
@Test
@DisplayName("getPrioriteLibelle retourne libellé quand priorite non null")
void testPrioriteNonNull() {
EvenementResponse r = base();
r.setPriorite(PrioriteEvenement.HAUTE);
assertThat(r.getPrioriteLibelle()).isEqualTo(PrioriteEvenement.HAUTE.getLibelle());
}
@Test
@DisplayName("estEvenementMultiJours false quand dateFin null")
void testDateFinNull() {
EvenementResponse r = base();
r.setDateFin(null);
assertThat(r.estEvenementMultiJours()).isFalse();
}
@Test
@DisplayName("estEvenementMultiJours false quand dateDebut = dateFin")
void testMemeJour() {
EvenementResponse r = base();
LocalDate date = LocalDate.now();
r.setDateDebut(date);
r.setDateFin(date);
assertThat(r.estEvenementMultiJours()).isFalse();
}
@Test
@DisplayName("estComplet false quand capaciteMax null")
void testCompletCapaciteNull() {
EvenementResponse r = base();
r.setCapaciteMax(null);
r.setParticipantsInscrits(100);
assertThat(r.estComplet()).isFalse();
}
@Test
@DisplayName("estComplet false quand participantsInscrits null")
void testCompletInscritsNull() {
EvenementResponse r = base();
r.setCapaciteMax(100);
r.setParticipantsInscrits(null);
assertThat(r.estComplet()).isFalse();
}
}
@Nested
@DisplayName("getTypeEvenementIcon")
class GetTypeEvenementIcon {
@Test
@DisplayName("retourne icône par défaut quand type null")
void testNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-calendar");
}
@Test
@DisplayName("ASSEMBLEE_GENERALE → pi pi-building")
void testAssembleeGenerale() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.ASSEMBLEE_GENERALE).build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-building");
}
@Test
@DisplayName("FORMATION → pi pi-book")
void testFormation() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.FORMATION).build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-book");
}
@Test
@DisplayName("REUNION_BUREAU → pi pi-users")
void testReunionBureau() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.REUNION_BUREAU).build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-users");
}
@Test
@DisplayName("CONFERENCE → pi pi-microphone")
void testConference() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.CONFERENCE).build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-microphone");
}
@Test
@DisplayName("ATELIER → pi pi-wrench")
void testAtelier() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.ATELIER).build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-wrench");
}
@Test
@DisplayName("CEREMONIE → pi pi-flag")
void testCeremonie() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.CEREMONIE).build();
assertThat(r.getTypeEvenementIcon()).isEqualTo("pi pi-flag");
}
@Test
@DisplayName("ACTIVITE_SOCIALE, ACTION_CARITATIVE, AUTRE → pi pi-calendar")
void testAutres() {
assertThat(EvenementResponse.builder().typeEvenement(TypeEvenementMetier.ACTIVITE_SOCIALE).build().getTypeEvenementIcon()).isEqualTo("pi pi-calendar");
assertThat(EvenementResponse.builder().typeEvenement(TypeEvenementMetier.ACTION_CARITATIVE).build().getTypeEvenementIcon()).isEqualTo("pi pi-calendar");
assertThat(EvenementResponse.builder().typeEvenement(TypeEvenementMetier.AUTRE).build().getTypeEvenementIcon()).isEqualTo("pi pi-calendar");
}
}
@Nested
@DisplayName("getTypeEvenementSeverity")
class GetTypeEvenementSeverity {
@Test
@DisplayName("retourne secondary quand type null")
void testNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getTypeEvenementSeverity()).isEqualTo("secondary");
}
@Test
@DisplayName("ASSEMBLEE_GENERALE → warning")
void testAssembleeGenerale() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.ASSEMBLEE_GENERALE).build();
assertThat(r.getTypeEvenementSeverity()).isEqualTo("warning");
}
@Test
@DisplayName("FORMATION → info")
void testFormation() {
EvenementResponse r = EvenementResponse.builder().typeEvenement(TypeEvenementMetier.FORMATION).build();
assertThat(r.getTypeEvenementSeverity()).isEqualTo("info");
}
@Test
@DisplayName("autres types → secondary")
void testAutres() {
for (TypeEvenementMetier t : new TypeEvenementMetier[]{
TypeEvenementMetier.ACTIVITE_SOCIALE, TypeEvenementMetier.ACTION_CARITATIVE,
TypeEvenementMetier.REUNION_BUREAU, TypeEvenementMetier.CONFERENCE,
TypeEvenementMetier.ATELIER, TypeEvenementMetier.CEREMONIE, TypeEvenementMetier.AUTRE}) {
assertThat(EvenementResponse.builder().typeEvenement(t).build().getTypeEvenementSeverity())
.as("Type: %s", t).isEqualTo("secondary");
}
}
}
@Nested
@DisplayName("getStatutSeverity")
class GetStatutSeverity {
@Test
@DisplayName("retourne secondary quand statut null")
void testNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getStatutSeverity()).isEqualTo("secondary");
}
@Test
@DisplayName("PLANIFIE → info")
void testPlanifie() {
assertThat(EvenementResponse.builder().statut(StatutEvenement.PLANIFIE).build().getStatutSeverity()).isEqualTo("info");
}
@Test
@DisplayName("EN_COURS → success")
void testEnCours() {
assertThat(EvenementResponse.builder().statut(StatutEvenement.EN_COURS).build().getStatutSeverity()).isEqualTo("success");
}
@Test
@DisplayName("TERMINE et CONFIRME → secondary")
void testTermineConfirme() {
assertThat(EvenementResponse.builder().statut(StatutEvenement.TERMINE).build().getStatutSeverity()).isEqualTo("secondary");
assertThat(EvenementResponse.builder().statut(StatutEvenement.CONFIRME).build().getStatutSeverity()).isEqualTo("secondary");
}
@Test
@DisplayName("ANNULE → danger")
void testAnnule() {
assertThat(EvenementResponse.builder().statut(StatutEvenement.ANNULE).build().getStatutSeverity()).isEqualTo("danger");
}
@Test
@DisplayName("REPORTE → warning")
void testReporte() {
assertThat(EvenementResponse.builder().statut(StatutEvenement.REPORTE).build().getStatutSeverity()).isEqualTo("warning");
}
}
@Nested
@DisplayName("getStatutIcon")
class GetStatutIcon {
@Test
@DisplayName("retourne pi pi-question quand statut null")
void testNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getStatutIcon()).isEqualTo("pi pi-question");
}
@Test
@DisplayName("tous les statuts retournent la bonne icône")
void testTousStatuts() {
assertThat(EvenementResponse.builder().statut(StatutEvenement.PLANIFIE).build().getStatutIcon()).isEqualTo("pi pi-clock");
assertThat(EvenementResponse.builder().statut(StatutEvenement.CONFIRME).build().getStatutIcon()).isEqualTo("pi pi-check-circle");
assertThat(EvenementResponse.builder().statut(StatutEvenement.EN_COURS).build().getStatutIcon()).isEqualTo("pi pi-play");
assertThat(EvenementResponse.builder().statut(StatutEvenement.TERMINE).build().getStatutIcon()).isEqualTo("pi pi-check");
assertThat(EvenementResponse.builder().statut(StatutEvenement.ANNULE).build().getStatutIcon()).isEqualTo("pi pi-times");
assertThat(EvenementResponse.builder().statut(StatutEvenement.REPORTE).build().getStatutIcon()).isEqualTo("pi pi-refresh");
}
}
@Nested
@DisplayName("getPrioriteSeverity")
class GetPrioriteSeverity {
@Test
@DisplayName("retourne secondary quand priorite null")
void testNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getPrioriteSeverity()).isEqualTo("secondary");
}
@Test
@DisplayName("toutes les priorités retournent la bonne sévérité")
void testToutesPriorites() {
assertThat(EvenementResponse.builder().priorite(PrioriteEvenement.CRITIQUE).build().getPrioriteSeverity()).isEqualTo("danger");
assertThat(EvenementResponse.builder().priorite(PrioriteEvenement.HAUTE).build().getPrioriteSeverity()).isEqualTo("warning");
assertThat(EvenementResponse.builder().priorite(PrioriteEvenement.NORMALE).build().getPrioriteSeverity()).isEqualTo("info");
assertThat(EvenementResponse.builder().priorite(PrioriteEvenement.BASSE).build().getPrioriteSeverity()).isEqualTo("secondary");
}
}
@Nested
@DisplayName("getDateDebutFormatee, getHeureDebutFormatee, getHeureFinFormatee, getBudgetFormate")
class MethodesFormatage {
@Test
@DisplayName("getDateDebutFormatee retourne — quand null")
void testDateDebutNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getDateDebutFormatee()).isEqualTo("");
}
@Test
@DisplayName("getDateDebutFormatee formate en dd/MM/yyyy")
void testDateDebut() {
EvenementResponse r = EvenementResponse.builder().dateDebut(java.time.LocalDate.of(2026, 4, 7)).build();
assertThat(r.getDateDebutFormatee()).isEqualTo("07/04/2026");
}
@Test
@DisplayName("getHeureDebutFormatee retourne — quand null")
void testHeureDebutNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getHeureDebutFormatee()).isEqualTo("");
}
@Test
@DisplayName("getHeureDebutFormatee formate en HH:mm")
void testHeureDebut() {
EvenementResponse r = EvenementResponse.builder().heureDebut(java.time.LocalTime.of(9, 30)).build();
assertThat(r.getHeureDebutFormatee()).isEqualTo("09:30");
}
@Test
@DisplayName("getHeureFinFormatee retourne — quand null")
void testHeureFinNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getHeureFinFormatee()).isEqualTo("");
}
@Test
@DisplayName("getHeureFinFormatee formate en HH:mm")
void testHeureFin() {
EvenementResponse r = EvenementResponse.builder().heureFin(java.time.LocalTime.of(18, 0)).build();
assertThat(r.getHeureFinFormatee()).isEqualTo("18:00");
}
@Test
@DisplayName("getBudgetFormate retourne — quand budget null")
void testBudgetNull() {
EvenementResponse r = EvenementResponse.builder().build();
assertThat(r.getBudgetFormate()).isEqualTo("");
}
@Test
@DisplayName("getBudgetFormate formate avec devise par défaut FCFA")
void testBudgetSansDevise() {
EvenementResponse r = EvenementResponse.builder().budget(java.math.BigDecimal.valueOf(50000)).build();
assertThat(r.getBudgetFormate()).isEqualTo("50,000 FCFA");
}
@Test
@DisplayName("getBudgetFormate formate avec codeDevise fourni")
void testBudgetAvecDevise() {
EvenementResponse r = EvenementResponse.builder().budget(java.math.BigDecimal.valueOf(50000)).codeDevise("EUR").build();
assertThat(r.getBudgetFormate()).isEqualTo("50,000 EUR");
}
}
}

View File

@@ -0,0 +1,131 @@
package dev.lions.unionflow.server.api.dto.favoris.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateFavoriRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID utilisateurId = UUID.randomUUID();
CreateFavoriRequest request = CreateFavoriRequest.builder()
.utilisateurId(utilisateurId)
.typeFavori("PAGE")
.titre("Dashboard Principal")
.description("Tableau de bord principal avec statistiques")
.url("/dashboard")
.icon("pi-chart-bar")
.couleur("#3B82F6")
.categorie("ANALYTICS")
.ordre(1)
.nbVisites(25)
.derniereVisite("2026-03-15T10:30:00")
.estPlusUtilise(true)
.build();
assertThat(request).isNotNull();
assertThat(request.utilisateurId()).isEqualTo(utilisateurId);
assertThat(request.typeFavori()).isEqualTo("PAGE");
assertThat(request.titre()).isEqualTo("Dashboard Principal");
assertThat(request.description()).isEqualTo("Tableau de bord principal avec statistiques");
assertThat(request.url()).isEqualTo("/dashboard");
assertThat(request.icon()).isEqualTo("pi-chart-bar");
assertThat(request.couleur()).isEqualTo("#3B82F6");
assertThat(request.categorie()).isEqualTo("ANALYTICS");
assertThat(request.ordre()).isEqualTo(1);
assertThat(request.nbVisites()).isEqualTo(25);
assertThat(request.derniereVisite()).isEqualTo("2026-03-15T10:30:00");
assertThat(request.estPlusUtilise()).isTrue();
}
@Test
void testBuilder_MinimalFields() {
UUID utilisateurId = UUID.randomUUID();
CreateFavoriRequest request = CreateFavoriRequest.builder()
.utilisateurId(utilisateurId)
.typeFavori("LINK")
.titre("Lien rapide")
.url("/quick-link")
.build();
assertThat(request).isNotNull();
assertThat(request.utilisateurId()).isEqualTo(utilisateurId);
assertThat(request.typeFavori()).isEqualTo("LINK");
assertThat(request.titre()).isEqualTo("Lien rapide");
assertThat(request.url()).isEqualTo("/quick-link");
}
@Test
void testValidation_ValidFields() {
CreateFavoriRequest request = CreateFavoriRequest.builder()
.utilisateurId(UUID.randomUUID())
.typeFavori("MODULE")
.titre("Module Membres")
.url("/membres")
.icon("pi-users")
.categorie("MODULES")
.build();
Set<ConstraintViolation<CreateFavoriRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID utilisateurId = UUID.randomUUID();
CreateFavoriRequest request1 = CreateFavoriRequest.builder()
.utilisateurId(utilisateurId)
.typeFavori("PAGE")
.titre("Test Page")
.url("/test")
.build();
CreateFavoriRequest request2 = CreateFavoriRequest.builder()
.utilisateurId(utilisateurId)
.typeFavori("PAGE")
.titre("Test Page")
.url("/test")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateFavoriRequest request = CreateFavoriRequest.builder()
.utilisateurId(UUID.randomUUID())
.typeFavori("PAGE")
.titre("Favorite Page")
.url("/favorite")
.icon("pi-star")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateFavoriRequest");
assertThat(toString).contains("Favorite Page");
assertThat(toString).contains("PAGE");
}
}

View File

@@ -0,0 +1,185 @@
package dev.lions.unionflow.server.api.dto.finance.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateAdhesionRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
LocalDate dateDemande = LocalDate.now();
CreateAdhesionRequest request = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-001")
.membreId(membreId)
.organisationId(organisationId)
.dateDemande(dateDemande)
.fraisAdhesion(new BigDecimal("50000.00"))
.codeDevise("XOF")
.observations("Demande d'adhésion standard")
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("ADH-2026-001");
assertThat(request.membreId()).isEqualTo(membreId);
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.dateDemande()).isEqualTo(dateDemande);
assertThat(request.fraisAdhesion()).isEqualByComparingTo(new BigDecimal("50000.00"));
assertThat(request.codeDevise()).isEqualTo("XOF");
assertThat(request.observations()).isEqualTo("Demande d'adhésion standard");
}
@Test
void testBuilder_MinimalFields() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
CreateAdhesionRequest request = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-002")
.membreId(membreId)
.organisationId(organisationId)
.dateDemande(LocalDate.now())
.fraisAdhesion(new BigDecimal("25000.00"))
.codeDevise("XOF")
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("ADH-2026-002");
assertThat(request.membreId()).isEqualTo(membreId);
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.fraisAdhesion()).isEqualByComparingTo(new BigDecimal("25000.00"));
assertThat(request.codeDevise()).isEqualTo("XOF");
}
@Test
void testValidation_MissingRequiredFields() {
CreateAdhesionRequest request = CreateAdhesionRequest.builder().build();
Set<ConstraintViolation<CreateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroReference"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("membreId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("organisationId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateDemande"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("fraisAdhesion"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
}
@Test
void testValidation_InvalidDevise() {
CreateAdhesionRequest request = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-003")
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.dateDemande(LocalDate.now())
.fraisAdhesion(new BigDecimal("50000.00"))
.codeDevise("INVALID")
.build();
Set<ConstraintViolation<CreateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
}
@Test
void testValidation_FraisAdhesionZero() {
CreateAdhesionRequest request = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-004")
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.dateDemande(LocalDate.now())
.fraisAdhesion(BigDecimal.ZERO)
.codeDevise("XOF")
.build();
Set<ConstraintViolation<CreateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("fraisAdhesion"));
}
@Test
void testValidation_ValidFields() {
CreateAdhesionRequest request = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-005")
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.dateDemande(LocalDate.now())
.fraisAdhesion(new BigDecimal("50000.00"))
.codeDevise("XOF")
.observations("Observation valide")
.build();
Set<ConstraintViolation<CreateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
LocalDate dateDemande = LocalDate.now();
CreateAdhesionRequest request1 = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-006")
.membreId(membreId)
.organisationId(organisationId)
.dateDemande(dateDemande)
.fraisAdhesion(new BigDecimal("50000.00"))
.codeDevise("XOF")
.build();
CreateAdhesionRequest request2 = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-006")
.membreId(membreId)
.organisationId(organisationId)
.dateDemande(dateDemande)
.fraisAdhesion(new BigDecimal("50000.00"))
.codeDevise("XOF")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateAdhesionRequest request = CreateAdhesionRequest.builder()
.numeroReference("ADH-2026-007")
.membreId(UUID.randomUUID())
.organisationId(UUID.randomUUID())
.dateDemande(LocalDate.now())
.fraisAdhesion(new BigDecimal("50000.00"))
.codeDevise("XOF")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateAdhesionRequest");
assertThat(toString).contains("ADH-2026-007");
}
}

View File

@@ -0,0 +1,147 @@
package dev.lions.unionflow.server.api.dto.finance.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateAdhesionRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateApprobation = LocalDate.now();
LocalDateTime datePaiement = LocalDateTime.now();
LocalDate dateValidation = LocalDate.now();
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.montantPaye(new BigDecimal("50000.00"))
.statut("APPROUVEE")
.dateApprobation(dateApprobation)
.datePaiement(datePaiement)
.methodePaiement("WAVE_MONEY")
.referencePaiement("REF-PAY-001")
.motifRejet(null)
.observations("Adhésion approuvée")
.approuvePar("Admin Principal")
.dateValidation(dateValidation)
.build();
assertThat(request).isNotNull();
assertThat(request.montantPaye()).isEqualByComparingTo(new BigDecimal("50000.00"));
assertThat(request.statut()).isEqualTo("APPROUVEE");
assertThat(request.dateApprobation()).isEqualTo(dateApprobation);
assertThat(request.datePaiement()).isEqualTo(datePaiement);
assertThat(request.methodePaiement()).isEqualTo("WAVE_MONEY");
assertThat(request.referencePaiement()).isEqualTo("REF-PAY-001");
assertThat(request.observations()).isEqualTo("Adhésion approuvée");
assertThat(request.approuvePar()).isEqualTo("Admin Principal");
assertThat(request.dateValidation()).isEqualTo(dateValidation);
}
@Test
void testBuilder_MinimalFields() {
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.statut("EN_ATTENTE")
.build();
assertThat(request).isNotNull();
assertThat(request.statut()).isEqualTo("EN_ATTENTE");
}
@Test
void testValidation_InvalidStatut() {
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.statut("INVALID_STATUS")
.build();
Set<ConstraintViolation<UpdateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("statut"));
}
@Test
void testValidation_InvalidMethodePaiement() {
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.methodePaiement("INVALID_METHOD")
.build();
Set<ConstraintViolation<UpdateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("methodePaiement"));
}
@Test
void testValidation_MontantPayeNegatif() {
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.montantPaye(new BigDecimal("-100.00"))
.build();
Set<ConstraintViolation<UpdateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montantPaye"));
}
@Test
void testValidation_ValidFields() {
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.montantPaye(new BigDecimal("50000.00"))
.statut("PAYEE")
.methodePaiement("VIREMENT")
.referencePaiement("REF-001")
.observations("Paiement effectué")
.build();
Set<ConstraintViolation<UpdateAdhesionRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateAdhesionRequest request1 = UpdateAdhesionRequest.builder()
.statut("APPROUVEE")
.montantPaye(new BigDecimal("50000.00"))
.build();
UpdateAdhesionRequest request2 = UpdateAdhesionRequest.builder()
.statut("APPROUVEE")
.montantPaye(new BigDecimal("50000.00"))
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateAdhesionRequest request = UpdateAdhesionRequest.builder()
.statut("PAYEE")
.montantPaye(new BigDecimal("50000.00"))
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateAdhesionRequest");
assertThat(toString).contains("PAYEE");
}
}

View File

@@ -0,0 +1,281 @@
package dev.lions.unionflow.server.api.dto.formuleabonnement.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateFormuleAbonnementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateDebut = LocalDate.now();
LocalDate dateFin = LocalDate.now().plusYears(1);
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Formule Premium")
.code("PREMIUM_PLUS")
.description("Formule premium avec tous les avantages")
.type(TypeFormule.PREMIUM)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("50000.00"))
.prixAnnuel(new BigDecimal("500000.00"))
.devise("XOF")
.maxMembres(500)
.maxAdministrateurs(10)
.espaceStockageGB(new BigDecimal("500.00"))
.supportTechnique(true)
.niveauSupport("PREMIUM")
.fonctionnalitesAvancees(true)
.apiAccess(true)
.rapportsPersonnalises(true)
.integrationsTierces(true)
.sauvegardeAutomatique(true)
.multiLangues(true)
.personnalisationInterface(true)
.formationIncluse(true)
.heuresFormation(10)
.populaire(true)
.recommandee(true)
.periodeEssaiJours(30)
.dateDebutValidite(dateDebut)
.dateFinValidite(dateFin)
.ordreAffichage(1)
.couleur("#FF5733")
.icone("pi-star")
.notes("Formule recommandée")
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Formule Premium");
assertThat(request.code()).isEqualTo("PREMIUM_PLUS");
assertThat(request.description()).isEqualTo("Formule premium avec tous les avantages");
assertThat(request.type()).isEqualTo(TypeFormule.PREMIUM);
assertThat(request.statut()).isEqualTo(StatutFormule.ACTIVE);
assertThat(request.prixMensuel()).isEqualByComparingTo(new BigDecimal("50000.00"));
assertThat(request.prixAnnuel()).isEqualByComparingTo(new BigDecimal("500000.00"));
assertThat(request.devise()).isEqualTo("XOF");
assertThat(request.maxMembres()).isEqualTo(500);
assertThat(request.maxAdministrateurs()).isEqualTo(10);
assertThat(request.espaceStockageGB()).isEqualByComparingTo(new BigDecimal("500.00"));
assertThat(request.supportTechnique()).isTrue();
assertThat(request.niveauSupport()).isEqualTo("PREMIUM");
assertThat(request.fonctionnalitesAvancees()).isTrue();
assertThat(request.apiAccess()).isTrue();
assertThat(request.rapportsPersonnalises()).isTrue();
assertThat(request.integrationsTierces()).isTrue();
assertThat(request.sauvegardeAutomatique()).isTrue();
assertThat(request.multiLangues()).isTrue();
assertThat(request.personnalisationInterface()).isTrue();
assertThat(request.formationIncluse()).isTrue();
assertThat(request.heuresFormation()).isEqualTo(10);
assertThat(request.populaire()).isTrue();
assertThat(request.recommandee()).isTrue();
assertThat(request.periodeEssaiJours()).isEqualTo(30);
assertThat(request.dateDebutValidite()).isEqualTo(dateDebut);
assertThat(request.dateFinValidite()).isEqualTo(dateFin);
assertThat(request.ordreAffichage()).isEqualTo(1);
assertThat(request.couleur()).isEqualTo("#FF5733");
assertThat(request.icone()).isEqualTo("pi-star");
assertThat(request.notes()).isEqualTo("Formule recommandée");
}
@Test
void testBuilder_MinimalFields() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Basic")
.code("BASIC")
.type(TypeFormule.BASIC)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("10000.00"))
.devise("XOF")
.maxMembres(50)
.maxAdministrateurs(2)
.espaceStockageGB(new BigDecimal("10.00"))
.supportTechnique(false)
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Basic");
assertThat(request.code()).isEqualTo("BASIC");
assertThat(request.type()).isEqualTo(TypeFormule.BASIC);
assertThat(request.statut()).isEqualTo(StatutFormule.ACTIVE);
assertThat(request.prixMensuel()).isEqualByComparingTo(new BigDecimal("10000.00"));
assertThat(request.devise()).isEqualTo("XOF");
}
@Test
void testValidation_MissingRequiredFields() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder().build();
Set<ConstraintViolation<CreateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("type"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("statut"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prixMensuel"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("maxMembres"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("maxAdministrateurs"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("espaceStockageGB"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("supportTechnique"));
}
@Test
void testValidation_InvalidCode() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Test")
.code("invalid-code")
.type(TypeFormule.BASIC)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("10000.00"))
.devise("XOF")
.maxMembres(50)
.maxAdministrateurs(2)
.espaceStockageGB(new BigDecimal("10.00"))
.supportTechnique(false)
.build();
Set<ConstraintViolation<CreateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_InvalidDevise() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Test")
.code("TEST")
.type(TypeFormule.BASIC)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("10000.00"))
.devise("INVALID")
.maxMembres(50)
.maxAdministrateurs(2)
.espaceStockageGB(new BigDecimal("10.00"))
.supportTechnique(false)
.build();
Set<ConstraintViolation<CreateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_PrixMensuelZero() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Test")
.code("TEST")
.type(TypeFormule.BASIC)
.statut(StatutFormule.ACTIVE)
.prixMensuel(BigDecimal.ZERO)
.devise("XOF")
.maxMembres(50)
.maxAdministrateurs(2)
.espaceStockageGB(new BigDecimal("10.00"))
.supportTechnique(false)
.build();
Set<ConstraintViolation<CreateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prixMensuel"));
}
@Test
void testValidation_ValidFields() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.type(TypeFormule.PREMIUM)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("50000.00"))
.devise("XOF")
.maxMembres(500)
.maxAdministrateurs(10)
.espaceStockageGB(new BigDecimal("500.00"))
.supportTechnique(true)
.niveauSupport("PREMIUM")
.build();
Set<ConstraintViolation<CreateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
CreateFormuleAbonnementRequest request1 = CreateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.type(TypeFormule.PREMIUM)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("50000.00"))
.devise("XOF")
.maxMembres(500)
.maxAdministrateurs(10)
.espaceStockageGB(new BigDecimal("500.00"))
.supportTechnique(true)
.build();
CreateFormuleAbonnementRequest request2 = CreateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.type(TypeFormule.PREMIUM)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("50000.00"))
.devise("XOF")
.maxMembres(500)
.maxAdministrateurs(10)
.espaceStockageGB(new BigDecimal("500.00"))
.supportTechnique(true)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateFormuleAbonnementRequest request = CreateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.type(TypeFormule.PREMIUM)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("50000.00"))
.devise("XOF")
.maxMembres(500)
.maxAdministrateurs(10)
.espaceStockageGB(new BigDecimal("500.00"))
.supportTechnique(true)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateFormuleAbonnementRequest");
assertThat(toString).contains("Premium");
assertThat(toString).contains("PREMIUM");
}
}

View File

@@ -0,0 +1,176 @@
package dev.lions.unionflow.server.api.dto.formuleabonnement.request;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateFormuleAbonnementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateDebut = LocalDate.now();
LocalDate dateFin = LocalDate.now().plusYears(1);
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.nom("Formule Premium Updated")
.code("PREMIUM_UPDATED")
.description("Description mise à jour")
.type(TypeFormule.PREMIUM)
.statut(StatutFormule.ACTIVE)
.prixMensuel(new BigDecimal("55000.00"))
.prixAnnuel(new BigDecimal("550000.00"))
.devise("XOF")
.maxMembres(600)
.maxAdministrateurs(12)
.espaceStockageGB(new BigDecimal("600.00"))
.supportTechnique(true)
.niveauSupport("PREMIUM")
.fonctionnalitesAvancees(true)
.apiAccess(true)
.rapportsPersonnalises(true)
.integrationsTierces(true)
.sauvegardeAutomatique(true)
.multiLangues(true)
.personnalisationInterface(true)
.formationIncluse(true)
.heuresFormation(15)
.populaire(true)
.recommandee(true)
.periodeEssaiJours(45)
.dateDebutValidite(dateDebut)
.dateFinValidite(dateFin)
.ordreAffichage(2)
.couleur("#00FF00")
.icone("pi-crown")
.notes("Notes mises à jour")
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Formule Premium Updated");
assertThat(request.code()).isEqualTo("PREMIUM_UPDATED");
assertThat(request.description()).isEqualTo("Description mise à jour");
assertThat(request.type()).isEqualTo(TypeFormule.PREMIUM);
assertThat(request.statut()).isEqualTo(StatutFormule.ACTIVE);
assertThat(request.prixMensuel()).isEqualByComparingTo(new BigDecimal("55000.00"));
assertThat(request.prixAnnuel()).isEqualByComparingTo(new BigDecimal("550000.00"));
assertThat(request.devise()).isEqualTo("XOF");
assertThat(request.maxMembres()).isEqualTo(600);
assertThat(request.maxAdministrateurs()).isEqualTo(12);
assertThat(request.espaceStockageGB()).isEqualByComparingTo(new BigDecimal("600.00"));
assertThat(request.supportTechnique()).isTrue();
assertThat(request.niveauSupport()).isEqualTo("PREMIUM");
assertThat(request.couleur()).isEqualTo("#00FF00");
assertThat(request.icone()).isEqualTo("pi-crown");
}
@Test
void testBuilder_MinimalFields() {
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.statut(StatutFormule.INACTIVE)
.build();
assertThat(request).isNotNull();
assertThat(request.statut()).isEqualTo(StatutFormule.INACTIVE);
}
@Test
void testValidation_InvalidCode() {
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.code("invalid-code")
.build();
Set<ConstraintViolation<UpdateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_InvalidDevise() {
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.devise("INVALID")
.build();
Set<ConstraintViolation<UpdateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_PrixMensuelZero() {
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.prixMensuel(BigDecimal.ZERO)
.build();
Set<ConstraintViolation<UpdateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prixMensuel"));
}
@Test
void testValidation_ValidFields() {
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.nom("Premium Updated")
.code("PREMIUM_UPD")
.prixMensuel(new BigDecimal("55000.00"))
.devise("XOF")
.build();
Set<ConstraintViolation<UpdateFormuleAbonnementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateFormuleAbonnementRequest request1 = UpdateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.statut(StatutFormule.ACTIVE)
.build();
UpdateFormuleAbonnementRequest request2 = UpdateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.statut(StatutFormule.ACTIVE)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateFormuleAbonnementRequest request = UpdateFormuleAbonnementRequest.builder()
.nom("Premium")
.code("PREMIUM")
.statut(StatutFormule.ACTIVE)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateFormuleAbonnementRequest");
assertThat(toString).contains("Premium");
}
}

View File

@@ -66,6 +66,64 @@ class FormuleAbonnementResponseTest {
.build();
assertThat(r.isValide()).isTrue();
}
@Test
@DisplayName("true quand ACTIVE et dateDebutValidite null")
void testDateDebutNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.statut(StatutFormule.ACTIVE)
.dateDebutValidite(null)
.dateFinValidite(LocalDate.now().plusDays(1))
.build();
assertThat(r.isValide()).isTrue();
}
@Test
@DisplayName("true quand ACTIVE et dateFinValidite null")
void testDateFinNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.statut(StatutFormule.ACTIVE)
.dateDebutValidite(LocalDate.now().minusDays(1))
.dateFinValidite(null)
.build();
assertThat(r.isValide()).isTrue();
}
}
@Nested
@DisplayName("getEconomieAnnuelle")
class GetEconomieAnnuelle {
@Test
@DisplayName("retourne ZERO quand prixMensuel null")
void testPrixMensuelNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.prixMensuel(null)
.prixAnnuel(BigDecimal.valueOf(100))
.build();
assertThat(r.getEconomieAnnuelle()).isEqualByComparingTo(BigDecimal.ZERO);
}
@Test
@DisplayName("retourne ZERO quand prixAnnuel null")
void testPrixAnnuelNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.prixMensuel(BigDecimal.valueOf(10))
.prixAnnuel(null)
.build();
assertThat(r.getEconomieAnnuelle()).isEqualByComparingTo(BigDecimal.ZERO);
}
@Test
@DisplayName("calcule économie quand les deux prix sont non-null")
void testCalculEconomie() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.prixMensuel(BigDecimal.valueOf(10))
.prixAnnuel(BigDecimal.valueOf(100))
.build();
// 10*12 - 100 = 120 - 100 = 20
assertThat(r.getEconomieAnnuelle()).isEqualByComparingTo(BigDecimal.valueOf(20));
}
}
@Nested
@@ -79,6 +137,13 @@ class FormuleAbonnementResponseTest {
assertThat(r.getPourcentageEconomieAnnuelle()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand prixAnnuel null")
void testPrixAnnuelNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder().prixMensuel(BigDecimal.TEN).build();
assertThat(r.getPourcentageEconomieAnnuelle()).isEqualTo(0);
}
@Test
@DisplayName("retourne 0 quand coutMensuelAnnuel <= 0")
void testCoutMensuelZero() {
@@ -177,8 +242,8 @@ class FormuleAbonnementResponseTest {
}
@Test
@DisplayName("score > 0 quand au moins un true")
void testAuMoinsUnTrue() {
@DisplayName("score > 0 quand supportTechnique true")
void testSupportTechnique() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(true)
.sauvegardeAutomatique(false)
@@ -193,8 +258,88 @@ class FormuleAbonnementResponseTest {
}
@Test
@DisplayName("personnalisationInterface et multiLangues true augmentent le score")
void testPersonnalisationEtMultiLangues() {
@DisplayName("score > 0 quand sauvegardeAutomatique true")
void testSauvegardeAutomatique() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(false)
.sauvegardeAutomatique(true)
.fonctionnalitesAvancees(false)
.apiAccess(false)
.rapportsPersonnalises(false)
.integrationsTierces(false)
.multiLangues(false)
.personnalisationInterface(false)
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score > 0 quand fonctionnalitesAvancees true")
void testFonctionnalitesAvancees() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(false)
.sauvegardeAutomatique(false)
.fonctionnalitesAvancees(true)
.apiAccess(false)
.rapportsPersonnalises(false)
.integrationsTierces(false)
.multiLangues(false)
.personnalisationInterface(false)
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score > 0 quand apiAccess true")
void testApiAccess() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(false)
.sauvegardeAutomatique(false)
.fonctionnalitesAvancees(false)
.apiAccess(true)
.rapportsPersonnalises(false)
.integrationsTierces(false)
.multiLangues(false)
.personnalisationInterface(false)
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score > 0 quand rapportsPersonnalises true")
void testRapportsPersonnalises() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(false)
.sauvegardeAutomatique(false)
.fonctionnalitesAvancees(false)
.apiAccess(false)
.rapportsPersonnalises(true)
.integrationsTierces(false)
.multiLangues(false)
.personnalisationInterface(false)
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score > 0 quand integrationsTierces true")
void testIntegrationsTierces() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(false)
.sauvegardeAutomatique(false)
.fonctionnalitesAvancees(false)
.apiAccess(false)
.rapportsPersonnalises(false)
.integrationsTierces(true)
.multiLangues(false)
.personnalisationInterface(false)
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score > 0 quand multiLangues et personnalisationInterface true")
void testMultiLanguesEtPersonnalisation() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(false)
.sauvegardeAutomatique(false)
@@ -207,6 +352,102 @@ class FormuleAbonnementResponseTest {
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score = 100 quand toutes les fonctionnalités true")
void testToutesTrue() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(true)
.sauvegardeAutomatique(true)
.fonctionnalitesAvancees(true)
.apiAccess(true)
.rapportsPersonnalises(true)
.integrationsTierces(true)
.multiLangues(true)
.personnalisationInterface(true)
.build();
assertThat(r.getScoreFonctionnalites()).isEqualTo(100);
}
@Test
@DisplayName("score calculé quand premier champ non null, reste null")
void testSupportTechniqueNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.supportTechnique(true)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score calculé quand deuxième champ non null, reste null")
void testSauvegardeNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.sauvegardeAutomatique(false)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isEqualTo(0);
}
@Test
@DisplayName("score calculé quand troisième champ non null, reste null")
void testFonctionnalitesAvanceesNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.fonctionnalitesAvancees(true)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score calculé quand quatrième champ non null, reste null")
void testApiAccessNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.apiAccess(false)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isEqualTo(0);
}
@Test
@DisplayName("score calculé quand cinquième champ non null, reste null")
void testRapportsNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.rapportsPersonnalises(true)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score calculé quand sixième champ non null, reste null")
void testIntegrationsNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.integrationsTierces(false)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isEqualTo(0);
}
@Test
@DisplayName("score calculé quand septième champ non null, reste null")
void testMultiLanguesNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.multiLangues(true)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isGreaterThan(0);
}
@Test
@DisplayName("score calculé quand huitième champ non null, reste null")
void testPersonnalisationNonNullRestNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.personnalisationInterface(false)
// Les autres champs restent null
.build();
assertThat(r.getScoreFonctionnalites()).isEqualTo(0);
}
}
@Nested
@@ -286,6 +527,22 @@ class FormuleAbonnementResponseTest {
assertThat(r.hasPeriodeEssai()).isTrue();
}
@Test
@DisplayName("hasPeriodeEssai false quand periodeEssaiJours null")
void testHasPeriodeEssaiNull() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder().periodeEssaiJours(null).build();
assertThat(r.hasPeriodeEssai()).isFalse();
}
@Test
@DisplayName("hasPeriodeEssai false quand periodeEssaiJours <= 0")
void testHasPeriodeEssaiZeroOuNegatif() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder().periodeEssaiJours(0).build();
assertThat(r.hasPeriodeEssai()).isFalse();
r.setPeriodeEssaiJours(-1);
assertThat(r.hasPeriodeEssai()).isFalse();
}
@Test
@DisplayName("hasFormation true quand formationIncluse et heuresFormation > 0")
void testHasFormation() {
@@ -327,5 +584,15 @@ class FormuleAbonnementResponseTest {
r.setRecommandee(true);
assertThat(r.isMiseEnAvant()).isTrue();
}
@Test
@DisplayName("isMiseEnAvant false quand ni populaire ni recommandee")
void testPasMiseEnAvant() {
FormuleAbonnementResponse r = FormuleAbonnementResponse.builder()
.populaire(false)
.recommandee(false)
.build();
assertThat(r.isMiseEnAvant()).isFalse();
}
}
}

View File

@@ -0,0 +1,93 @@
package dev.lions.unionflow.server.api.dto.membre;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.time.LocalDate;
import org.junit.jupiter.api.Test;
class CompteAdherentResponseTest {
@Test
void testRecord_AllFields() {
LocalDate dateAdhesion = LocalDate.of(2024, 1, 15);
LocalDate dateCalcul = LocalDate.now();
CompteAdherentResponse response = new CompteAdherentResponse(
"MUF-2026-001",
"John Doe",
"Mutuelle du Futur",
dateAdhesion,
"ACTIF",
new BigDecimal("50000.00"),
new BigDecimal("100000.00"),
new BigDecimal("10000.00"),
new BigDecimal("140000.00"),
new BigDecimal("0.00"),
new BigDecimal("300000.00"),
12,
12,
0,
100,
2,
dateCalcul
);
assertThat(response.numeroMembre()).isEqualTo("MUF-2026-001");
assertThat(response.nomComplet()).isEqualTo("John Doe");
assertThat(response.organisationNom()).isEqualTo("Mutuelle du Futur");
assertThat(response.dateAdhesion()).isEqualTo(dateAdhesion);
assertThat(response.statutCompte()).isEqualTo("ACTIF");
assertThat(response.soldeCotisations()).isEqualByComparingTo(new BigDecimal("50000.00"));
assertThat(response.soldeEpargne()).isEqualByComparingTo(new BigDecimal("100000.00"));
assertThat(response.soldeBloque()).isEqualByComparingTo(new BigDecimal("10000.00"));
assertThat(response.soldeTotalDisponible()).isEqualByComparingTo(new BigDecimal("140000.00"));
assertThat(response.encoursCreditTotal()).isEqualByComparingTo(new BigDecimal("0.00"));
assertThat(response.capaciteEmprunt()).isEqualByComparingTo(new BigDecimal("300000.00"));
assertThat(response.nombreCotisationsPayees()).isEqualTo(12);
assertThat(response.nombreCotisationsTotal()).isEqualTo(12);
assertThat(response.nombreCotisationsEnRetard()).isEqualTo(0);
assertThat(response.tauxEngagement()).isEqualTo(100);
assertThat(response.nombreComptesEpargne()).isEqualTo(2);
assertThat(response.dateCalcul()).isEqualTo(dateCalcul);
}
@Test
void testRecord_Equals() {
LocalDate date1 = LocalDate.of(2024, 1, 1);
LocalDate date2 = LocalDate.now();
CompteAdherentResponse response1 = new CompteAdherentResponse(
"MUF-001", "John Doe", "Mutuelle", date1, "ACTIF",
new BigDecimal("1000"), new BigDecimal("2000"), BigDecimal.ZERO,
new BigDecimal("3000"), BigDecimal.ZERO, new BigDecimal("6000"),
10, 10, 0, 100, 1, date2
);
CompteAdherentResponse response2 = new CompteAdherentResponse(
"MUF-001", "John Doe", "Mutuelle", date1, "ACTIF",
new BigDecimal("1000"), new BigDecimal("2000"), BigDecimal.ZERO,
new BigDecimal("3000"), BigDecimal.ZERO, new BigDecimal("6000"),
10, 10, 0, 100, 1, date2
);
assertThat(response1).isEqualTo(response2);
assertThat(response1.hashCode()).isEqualTo(response2.hashCode());
}
@Test
void testRecord_ToString() {
CompteAdherentResponse response = new CompteAdherentResponse(
"MUF-001", "John Doe", "Mutuelle", LocalDate.now(), "ACTIF",
new BigDecimal("1000"), new BigDecimal("2000"), BigDecimal.ZERO,
new BigDecimal("3000"), BigDecimal.ZERO, new BigDecimal("6000"),
10, 10, 0, 100, 1, LocalDate.now()
);
String toString = response.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CompteAdherentResponse");
assertThat(toString).contains("MUF-001");
}
}

View File

@@ -178,6 +178,76 @@ class MembreSearchCriteriaTest {
MembreSearchCriteria c = MembreSearchCriteria.builder().responsable(true).build();
assertThat(c.hasAnyCriteria()).isTrue();
}
@Test
@DisplayName("false quand nom vide après trim")
void testNomVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().nom(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand prenom vide après trim")
void testPrenomVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().prenom(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand email vide après trim")
void testEmailVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().email(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand telephone vide après trim")
void testTelephoneVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().telephone(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand statut vide après trim")
void testStatutVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().statut(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand region vide après trim")
void testRegionVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().region(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand ville vide après trim")
void testVilleVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().ville(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand profession vide après trim")
void testProfessionVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().profession(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand nationalite vide après trim")
void testNationaliteVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().nationalite(" ").build();
assertThat(c.hasAnyCriteria()).isFalse();
}
@Test
@DisplayName("false quand roles vide")
void testRolesVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().roles(List.of()).build();
assertThat(c.hasAnyCriteria()).isFalse();
}
}
@Nested
@@ -230,6 +300,38 @@ class MembreSearchCriteriaTest {
.build();
assertThat(c.isValid()).isTrue();
}
@Test
@DisplayName("true quand seulement dateAdhesionMin défini")
void testSeulementDateAdhesionMin() {
MembreSearchCriteria c = MembreSearchCriteria.builder()
.dateAdhesionMin(LocalDate.of(2020, 1, 1))
.build();
assertThat(c.isValid()).isTrue();
}
@Test
@DisplayName("true quand seulement dateAdhesionMax défini")
void testSeulementDateAdhesionMax() {
MembreSearchCriteria c = MembreSearchCriteria.builder()
.dateAdhesionMax(LocalDate.of(2025, 12, 31))
.build();
assertThat(c.isValid()).isTrue();
}
@Test
@DisplayName("true quand seulement ageMin défini")
void testSeulementAgeMin() {
MembreSearchCriteria c = MembreSearchCriteria.builder().ageMin(18).build();
assertThat(c.isValid()).isTrue();
}
@Test
@DisplayName("true quand seulement ageMax défini")
void testSeulementAgeMax() {
MembreSearchCriteria c = MembreSearchCriteria.builder().ageMax(65).build();
assertThat(c.isValid()).isTrue();
}
}
@Nested
@@ -363,5 +465,35 @@ class MembreSearchCriteriaTest {
MembreSearchCriteria c = MembreSearchCriteria.builder().membreBureau(false).build();
assertThat(c.getDescription()).doesNotContain("Membre bureau");
}
@Test
@DisplayName("contient email")
void testAvecEmail() {
MembreSearchCriteria c = MembreSearchCriteria.builder().email("test@example.com").build();
assertThat(c.getDescription()).contains("test@example.com");
}
@Test
@DisplayName("organisationIds vide pas affiché")
void testOrganisationIdsVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder()
.organisationIds(List.of())
.build();
assertThat(c.getDescription()).doesNotContain("Organisations");
}
@Test
@DisplayName("roles vide pas affiché")
void testRolesVide() {
MembreSearchCriteria c = MembreSearchCriteria.builder().roles(List.of()).build();
assertThat(c.getDescription()).doesNotContain("Rôles");
}
@Test
@DisplayName("responsable false pas affiché")
void testResponsableFalse() {
MembreSearchCriteria c = MembreSearchCriteria.builder().responsable(false).build();
assertThat(c.getDescription()).doesNotContain("Responsable");
}
}
}

View File

@@ -23,7 +23,7 @@ class MembreSearchResultDTOTest {
private static MembreSummaryResponse unMembre() {
return new MembreSummaryResponse(
UUID.randomUUID(), null, "Prenom", "Nom", null, null, null, null, null, null, true, List.of(), null, null);
UUID.randomUUID(), null, "Prenom", "Nom", null, null, null, null, null, null, true, List.of(), null, null, null);
}
@Nested

View File

@@ -0,0 +1,266 @@
package dev.lions.unionflow.server.api.dto.membre;
import static org.assertj.core.api.Assertions.assertThat;
import dev.lions.unionflow.server.api.dto.membre.response.MembreSummaryResponse;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@DisplayName("Tests MembreSummaryResponse — méthodes calculées")
class MembreSummaryResponseTest {
private static MembreSummaryResponse make(String statut, List<String> roles) {
return new MembreSummaryResponse(
UUID.randomUUID(), "UF-001", "Jean", "Dupont", "jean@test.com",
"0100000000", "Dev", statut, statut + "_libelle", statut + "_severity",
"ACTIF".equals(statut), roles, null, null, null);
}
// ── nomComplet ─────────────────────────────────────────────────────────
@Nested
@DisplayName("nomComplet()")
class NomComplet {
@Test
@DisplayName("prenom + nom concaténés")
void nominal() {
MembreSummaryResponse r = make("ACTIF", List.of());
assertThat(r.nomComplet()).isEqualTo("Jean Dupont");
}
@Test
@DisplayName("prenom null → uniquement le nom")
void prenomNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, "Dupont", null,
null, null, null, null, null, false, List.of(), null, null, null);
assertThat(r.nomComplet()).isEqualTo("Dupont");
}
@Test
@DisplayName("nom null → uniquement le prenom")
void nomNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, "Jean", null, null,
null, null, null, null, null, false, List.of(), null, null, null);
assertThat(r.nomComplet()).isEqualTo("Jean");
}
@Test
@DisplayName("prenom et nom null → chaîne vide")
void tousNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, null, null,
null, null, null, null, null, false, List.of(), null, null, null);
assertThat(r.nomComplet()).isEmpty();
}
}
// ── Alias statut ───────────────────────────────────────────────────────
@Nested
@DisplayName("aliases statut*()")
class AliasStatut {
@Test
@DisplayName("statut() retourne statutCompte")
void statut() {
MembreSummaryResponse r = make("ACTIF", List.of());
assertThat(r.statut()).isEqualTo(r.statutCompte());
}
@Test
@DisplayName("statutLibelle() retourne statutCompteLibelle")
void statutLibelle() {
MembreSummaryResponse r = make("ACTIF", List.of());
assertThat(r.statutLibelle()).isEqualTo(r.statutCompteLibelle());
}
@Test
@DisplayName("statutSeverity() retourne statutCompteSeverity")
void statutSeverity() {
MembreSummaryResponse r = make("ACTIF", List.of());
assertThat(r.statutSeverity()).isEqualTo(r.statutCompteSeverity());
}
}
// ── statutIcon ─────────────────────────────────────────────────────────
@Nested
@DisplayName("statutIcon()")
class StatutIcon {
@Test void actif() { assertThat(make("ACTIF", List.of()).statutIcon()).isEqualTo("pi pi-check-circle"); }
@Test void inactif() { assertThat(make("INACTIF", List.of()).statutIcon()).isEqualTo("pi pi-pause-circle"); }
@Test void suspendu() { assertThat(make("SUSPENDU", List.of()).statutIcon()).isEqualTo("pi pi-ban"); }
@Test void radie() { assertThat(make("RADIE", List.of()).statutIcon()).isEqualTo("pi pi-times-circle"); }
@Test
@DisplayName("statut inconnu → pi pi-question-circle")
void inconnu() {
assertThat(make("AUTRE", List.of()).statutIcon()).isEqualTo("pi pi-question-circle");
}
@Test
@DisplayName("statut null → pi pi-question-circle")
void statutNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, null, null,
null, null, null, null, null, false, List.of(), null, null, null);
assertThat(r.statutIcon()).isEqualTo("pi pi-question-circle");
}
}
// ── typeMembre ─────────────────────────────────────────────────────────
@Nested
@DisplayName("typeMembre()")
class TypeMembre {
@Test void president() { assertThat(make("ACTIF", List.of("PRESIDENT")).typeMembre()).isEqualTo("Président"); }
@Test void vicePresident() { assertThat(make("ACTIF", List.of("VICE_PRESIDENT")).typeMembre()).isEqualTo("Vice-Président"); }
@Test void secretaire() { assertThat(make("ACTIF", List.of("SECRETAIRE")).typeMembre()).isEqualTo("Secrétaire"); }
@Test void tresorier() { assertThat(make("ACTIF", List.of("TRESORIER")).typeMembre()).isEqualTo("Trésorier"); }
@Test void adminOrg() { assertThat(make("ACTIF", List.of("ADMIN_ORGANISATION")).typeMembre()).isEqualTo("Administrateur"); }
@Test void moderateur() { assertThat(make("ACTIF", List.of("MODERATEUR")).typeMembre()).isEqualTo("Modérateur"); }
@Test void membreActif() { assertThat(make("ACTIF", List.of("MEMBRE_ACTIF")).typeMembre()).isEqualTo("Membre"); }
@Test void rolesVide() { assertThat(make("ACTIF", List.of()).typeMembre()).isEqualTo("Membre"); }
@Test void rolesNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, null, null,
null, null, null, null, null, false, null, null, null, null);
assertThat(r.typeMembre()).isEqualTo("Membre");
}
}
// ── typeSeverity ───────────────────────────────────────────────────────
@Nested
@DisplayName("typeSeverity()")
class TypeSeverity {
@Test void president() { assertThat(make("ACTIF", List.of("PRESIDENT")).typeSeverity()).isEqualTo("primary"); }
@Test void vicePresident() { assertThat(make("ACTIF", List.of("VICE_PRESIDENT")).typeSeverity()).isEqualTo("primary"); }
@Test void secretaire() { assertThat(make("ACTIF", List.of("SECRETAIRE")).typeSeverity()).isEqualTo("info"); }
@Test void tresorier() { assertThat(make("ACTIF", List.of("TRESORIER")).typeSeverity()).isEqualTo("warning"); }
@Test void adminOrg() { assertThat(make("ACTIF", List.of("ADMIN_ORGANISATION")).typeSeverity()).isEqualTo("danger"); }
@Test void moderateur() { assertThat(make("ACTIF", List.of("MODERATEUR")).typeSeverity()).isEqualTo("warning"); }
@Test void roleDefault() { assertThat(make("ACTIF", List.of("MEMBRE_ACTIF")).typeSeverity()).isEqualTo("secondary"); }
@Test void rolesVide() { assertThat(make("ACTIF", List.of()).typeSeverity()).isEqualTo("secondary"); }
@Test void rolesNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, null, null,
null, null, null, null, null, false, null, null, null, null);
assertThat(r.typeSeverity()).isEqualTo("secondary");
}
}
// ── typeIcon ───────────────────────────────────────────────────────────
@Nested
@DisplayName("typeIcon()")
class TypeIcon {
@Test void president() { assertThat(make("ACTIF", List.of("PRESIDENT")).typeIcon()).isEqualTo("pi pi-star"); }
@Test void vicePresident() { assertThat(make("ACTIF", List.of("VICE_PRESIDENT")).typeIcon()).isEqualTo("pi pi-star"); }
@Test void secretaire() { assertThat(make("ACTIF", List.of("SECRETAIRE")).typeIcon()).isEqualTo("pi pi-file-edit"); }
@Test void tresorier() { assertThat(make("ACTIF", List.of("TRESORIER")).typeIcon()).isEqualTo("pi pi-wallet"); }
@Test void adminOrg() { assertThat(make("ACTIF", List.of("ADMIN_ORGANISATION")).typeIcon()).isEqualTo("pi pi-shield"); }
@Test void moderateur() { assertThat(make("ACTIF", List.of("MODERATEUR")).typeIcon()).isEqualTo("pi pi-wrench"); }
@Test void roleDefault() { assertThat(make("ACTIF", List.of("MEMBRE_ACTIF")).typeIcon()).isEqualTo("pi pi-user"); }
@Test void rolesVide() { assertThat(make("ACTIF", List.of()).typeIcon()).isEqualTo("pi pi-user"); }
@Test void rolesNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, null, null,
null, null, null, null, null, false, null, null, null, null);
assertThat(r.typeIcon()).isEqualTo("pi pi-user");
}
}
// ── dateAdhesion ───────────────────────────────────────────────────────
@Nested
@DisplayName("dateAdhesion()")
class DateAdhesion {
@Test
@DisplayName("dateAdhesion est accessible via le composant record")
void accesseur() {
LocalDate date = LocalDate.of(2024, 3, 15);
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, "Jean", "Dupont", null,
null, null, "ACTIF", null, null, true, List.of(), null, null, date);
assertThat(r.dateAdhesion()).isEqualTo(date);
}
@Test
@DisplayName("dateAdhesion null par défaut")
void nullParDefaut() {
assertThat(make("ACTIF", List.of()).dateAdhesion()).isNull();
}
}
// ── Getters JavaBean ───────────────────────────────────────────────────
@Nested
@DisplayName("getters JavaBean (compatibilité JSF EL)")
class GettersJavaBean {
@Test
@DisplayName("getId/getNumeroMembre/getPrenom/getNom/getEmail/getTelephone/getProfession")
void champsSimples() {
LocalDate date = LocalDate.of(2024, 1, 1);
UUID orgId = UUID.randomUUID();
UUID id = UUID.randomUUID();
MembreSummaryResponse r = new MembreSummaryResponse(
id, "UF-001", "Jean", "Dupont", "jean@test.com",
"0100000000", "Dev", "ACTIF", "Actif", "success",
true, List.of("MEMBRE_ACTIF"), orgId, "Org Test", date);
assertThat(r.getId()).isEqualTo(id);
assertThat(r.getNumeroMembre()).isEqualTo("UF-001");
assertThat(r.getPrenom()).isEqualTo("Jean");
assertThat(r.getNom()).isEqualTo("Dupont");
assertThat(r.getEmail()).isEqualTo("jean@test.com");
assertThat(r.getTelephone()).isEqualTo("0100000000");
assertThat(r.getProfession()).isEqualTo("Dev");
assertThat(r.getStatutCompte()).isEqualTo("ACTIF");
assertThat(r.getStatutCompteLibelle()).isEqualTo("Actif");
assertThat(r.getStatutCompteSeverity()).isEqualTo("success");
assertThat(r.getActif()).isTrue();
assertThat(r.isActif()).isTrue();
assertThat(r.getRoles()).containsExactly("MEMBRE_ACTIF");
assertThat(r.getOrganisationId()).isEqualTo(orgId);
assertThat(r.getOrganisationNom()).isEqualTo("Org Test");
assertThat(r.getDateAdhesion()).isEqualTo(date);
}
@Test
@DisplayName("isActif false quand actif null")
void isActifNull() {
MembreSummaryResponse r = new MembreSummaryResponse(
UUID.randomUUID(), null, null, null, null,
null, null, null, null, null, null, null, null, null, null);
assertThat(r.isActif()).isFalse();
assertThat(r.getActif()).isNull();
}
@Test
@DisplayName("getters calculés délèguent aux méthodes calculées")
void gettersCalcules() {
MembreSummaryResponse r = make("ACTIF", List.of("PRESIDENT"));
assertThat(r.getNomComplet()).isEqualTo(r.nomComplet());
assertThat(r.getStatut()).isEqualTo(r.statut());
assertThat(r.getStatutLibelle()).isEqualTo(r.statutLibelle());
assertThat(r.getStatutSeverity()).isEqualTo(r.statutSeverity());
assertThat(r.getStatutIcon()).isEqualTo(r.statutIcon());
assertThat(r.getTypeMembre()).isEqualTo(r.typeMembre());
assertThat(r.getTypeSeverity()).isEqualTo(r.typeSeverity());
assertThat(r.getTypeIcon()).isEqualTo(r.typeIcon());
}
}
}

View File

@@ -0,0 +1,231 @@
package dev.lions.unionflow.server.api.dto.membre.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateMembreRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateNaissance = LocalDate.of(1985, 5, 20);
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Amadou")
.nom("Diallo")
.email("amadou.diallo@example.com")
.telephone("+221 77 123 45 67")
.telephoneWave("+221771234567")
.dateNaissance(dateNaissance)
.profession("Ingénieur Informatique")
.photoUrl("https://example.com/photos/amadou.jpg")
.statutMatrimonial("MARIE")
.nationalite("Sénégalaise")
.typeIdentite("CNI")
.numeroIdentite("1234567890123")
.build();
assertThat(request).isNotNull();
assertThat(request.prenom()).isEqualTo("Amadou");
assertThat(request.nom()).isEqualTo("Diallo");
assertThat(request.email()).isEqualTo("amadou.diallo@example.com");
assertThat(request.telephone()).isEqualTo("+221 77 123 45 67");
assertThat(request.telephoneWave()).isEqualTo("+221771234567");
assertThat(request.dateNaissance()).isEqualTo(dateNaissance);
assertThat(request.profession()).isEqualTo("Ingénieur Informatique");
assertThat(request.photoUrl()).contains("amadou.jpg");
assertThat(request.statutMatrimonial()).isEqualTo("MARIE");
assertThat(request.nationalite()).isEqualTo("Sénégalaise");
assertThat(request.typeIdentite()).isEqualTo("CNI");
assertThat(request.numeroIdentite()).isEqualTo("1234567890123");
}
@Test
void testBuilder_MinimalFields() {
LocalDate dateNaissance = LocalDate.of(1990, 1, 1);
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Fatou")
.nom("Sow")
.email("fatou.sow@example.com")
.dateNaissance(dateNaissance)
.build();
assertThat(request).isNotNull();
assertThat(request.prenom()).isEqualTo("Fatou");
assertThat(request.nom()).isEqualTo("Sow");
assertThat(request.email()).isEqualTo("fatou.sow@example.com");
assertThat(request.dateNaissance()).isEqualTo(dateNaissance);
assertThat(request.telephone()).isNull();
assertThat(request.telephoneWave()).isNull();
assertThat(request.profession()).isNull();
assertThat(request.photoUrl()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreateMembreRequest request = CreateMembreRequest.builder().build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prenom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateNaissance"));
}
@Test
void testValidation_EmptyPrenom() {
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("")
.nom("Test")
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prenom"));
}
@Test
void testValidation_EmptyNom() {
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Test")
.nom("")
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
}
@Test
void testValidation_EmailInvalide() {
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Test")
.nom("User")
.email("not-a-valid-email")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
}
@Test
void testValidation_PrenomTooLong() {
String longPrenom = "A".repeat(101);
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom(longPrenom)
.nom("Test")
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prenom"));
}
@Test
void testValidation_TelephoneWaveTooLong() {
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Test")
.nom("User")
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.telephoneWave("+221771234567890123456") // 22 chars > max 20
.build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("telephoneWave"));
}
@Test
void testValidation_ValidFields() {
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Moussa")
.nom("Ba")
.email("moussa.ba@example.com")
.telephone("+221 33 987 65 43")
.telephoneWave("+221339876543")
.dateNaissance(LocalDate.of(1988, 3, 15))
.profession("Médecin")
.nationalite("Sénégalaise")
.typeIdentite("PASSEPORT")
.numeroIdentite("SN123456789")
.build();
Set<ConstraintViolation<CreateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
LocalDate dateNaissance = LocalDate.of(1995, 7, 10);
CreateMembreRequest request1 = CreateMembreRequest.builder()
.prenom("Aissatou")
.nom("Ndiaye")
.email("aissatou@example.com")
.dateNaissance(dateNaissance)
.build();
CreateMembreRequest request2 = CreateMembreRequest.builder()
.prenom("Aissatou")
.nom("Ndiaye")
.email("aissatou@example.com")
.dateNaissance(dateNaissance)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateMembreRequest request = CreateMembreRequest.builder()
.prenom("Ibrahima")
.nom("Sarr")
.email("ibrahima.sarr@example.com")
.dateNaissance(LocalDate.of(1992, 11, 5))
.profession("Avocat")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateMembreRequest");
assertThat(toString).contains("Ibrahima");
assertThat(toString).contains("Sarr");
assertThat(toString).contains("ibrahima.sarr@example.com");
assertThat(toString).contains("Avocat");
}
}

View File

@@ -0,0 +1,220 @@
package dev.lions.unionflow.server.api.dto.membre.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateMembreRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateNaissance = LocalDate.of(1987, 8, 25);
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Cheikh")
.nom("Fall")
.email("cheikh.fall@updated.com")
.telephone("+221 77 999 88 77")
.telephoneWave("+221779998877")
.dateNaissance(dateNaissance)
.profession("Entrepreneur")
.photoUrl("https://example.com/photos/cheikh_updated.jpg")
.statutMatrimonial("CELIBATAIRE")
.nationalite("Sénégalaise")
.typeIdentite("CNI")
.numeroIdentite("9876543210987")
.actif(true)
.build();
assertThat(request).isNotNull();
assertThat(request.prenom()).isEqualTo("Cheikh");
assertThat(request.nom()).isEqualTo("Fall");
assertThat(request.email()).isEqualTo("cheikh.fall@updated.com");
assertThat(request.telephone()).isEqualTo("+221 77 999 88 77");
assertThat(request.telephoneWave()).isEqualTo("+221779998877");
assertThat(request.dateNaissance()).isEqualTo(dateNaissance);
assertThat(request.profession()).isEqualTo("Entrepreneur");
assertThat(request.photoUrl()).contains("cheikh_updated.jpg");
assertThat(request.statutMatrimonial()).isEqualTo("CELIBATAIRE");
assertThat(request.nationalite()).isEqualTo("Sénégalaise");
assertThat(request.typeIdentite()).isEqualTo("CNI");
assertThat(request.numeroIdentite()).isEqualTo("9876543210987");
assertThat(request.actif()).isTrue();
}
@Test
void testBuilder_MinimalFields() {
LocalDate dateNaissance = LocalDate.of(1993, 2, 14);
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Mariama")
.nom("Diop")
.email("mariama.diop@example.com")
.dateNaissance(dateNaissance)
.build();
assertThat(request).isNotNull();
assertThat(request.prenom()).isEqualTo("Mariama");
assertThat(request.nom()).isEqualTo("Diop");
assertThat(request.email()).isEqualTo("mariama.diop@example.com");
assertThat(request.dateNaissance()).isEqualTo(dateNaissance);
assertThat(request.actif()).isNull();
assertThat(request.profession()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
UpdateMembreRequest request = UpdateMembreRequest.builder().build();
Set<ConstraintViolation<UpdateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prenom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dateNaissance"));
}
@Test
void testValidation_EmptyPrenom() {
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("")
.nom("Test")
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<UpdateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("prenom"));
}
@Test
void testValidation_EmptyNom() {
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Test")
.nom("")
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<UpdateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
}
@Test
void testValidation_EmailInvalide() {
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Test")
.nom("User")
.email("invalid-email-format")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<UpdateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
}
@Test
void testValidation_NomTooLong() {
String longNom = "B".repeat(101);
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Test")
.nom(longNom)
.email("test@example.com")
.dateNaissance(LocalDate.of(1990, 1, 1))
.build();
Set<ConstraintViolation<UpdateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
}
@Test
void testValidation_ValidFields() {
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Omar")
.nom("Sy")
.email("omar.sy@example.com")
.telephone("+221 33 444 55 66")
.telephoneWave("+221334445566")
.dateNaissance(LocalDate.of(1985, 12, 20))
.profession("Artiste")
.statutMatrimonial("MARIE")
.nationalite("Française")
.typeIdentite("PASSEPORT")
.numeroIdentite("FR987654321")
.actif(false)
.build();
Set<ConstraintViolation<UpdateMembreRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
LocalDate dateNaissance = LocalDate.of(1991, 4, 18);
UpdateMembreRequest request1 = UpdateMembreRequest.builder()
.prenom("Khadija")
.nom("Thiam")
.email("khadija@example.com")
.dateNaissance(dateNaissance)
.actif(true)
.build();
UpdateMembreRequest request2 = UpdateMembreRequest.builder()
.prenom("Khadija")
.nom("Thiam")
.email("khadija@example.com")
.dateNaissance(dateNaissance)
.actif(true)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateMembreRequest request = UpdateMembreRequest.builder()
.prenom("Mamadou")
.nom("Cisse")
.email("mamadou.cisse@example.com")
.dateNaissance(LocalDate.of(1989, 9, 30))
.profession("Professeur")
.actif(true)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateMembreRequest");
assertThat(toString).contains("Mamadou");
assertThat(toString).contains("Cisse");
assertThat(toString).contains("mamadou.cisse@example.com");
assertThat(toString).contains("Professeur");
}
}

View File

@@ -319,6 +319,38 @@ class ActionNotificationDTOTest {
action.setPermissionsRequises(null);
assertThat(action.utilisateurAutorise(new String[] {}, new String[] {})).isTrue();
}
@Test
@DisplayName("false quand rolesAutorises requis mais rolesUtilisateur vide")
void testRolesRequisUtilisateurVide() {
ActionNotificationDTO action = new ActionNotificationDTO("a", "L", "confirm");
action.setRolesAutorises(new String[] { "ADMIN" });
assertThat(action.utilisateurAutorise(new String[] {}, new String[] {})).isFalse();
}
@Test
@DisplayName("false quand permissionsRequises requises mais permissionsUtilisateur vides")
void testPermissionsRequisesUtilisateurVides() {
ActionNotificationDTO action = new ActionNotificationDTO("a", "L", "confirm");
action.setPermissionsRequises(new String[] { "write" });
assertThat(action.utilisateurAutorise(new String[] {}, new String[] {})).isFalse();
}
@Test
@DisplayName("true quand rolesAutorises tableau vide (length == 0)")
void testRolesTableauVide() {
ActionNotificationDTO action = new ActionNotificationDTO("a", "L", "confirm");
action.setRolesAutorises(new String[] {});
assertThat(action.utilisateurAutorise(new String[] {}, new String[] {})).isTrue();
}
@Test
@DisplayName("true quand permissionsRequises tableau vide (length == 0)")
void testPermissionsTableauVide() {
ActionNotificationDTO action = new ActionNotificationDTO("a", "L", "confirm");
action.setPermissionsRequises(new String[] {});
assertThat(action.utilisateurAutorise(new String[] {}, new String[] {})).isTrue();
}
}
@Nested
@@ -379,4 +411,103 @@ class ActionNotificationDTOTest {
assertThat(a.getTypeAction()).isEqualTo("route");
}
}
@Nested
@DisplayName("Getters et Setters")
class GettersEtSetters {
@Test
@DisplayName("tous les getters et setters fonctionnent correctement")
void testTousLesGettersSetters() {
ActionNotificationDTO dto = new ActionNotificationDTO();
// Test id
dto.setId("act-123");
assertThat(dto.getId()).isEqualTo("act-123");
// Test libelle
dto.setLibelle("Cliquer ici");
assertThat(dto.getLibelle()).isEqualTo("Cliquer ici");
// Test typeAction
dto.setTypeAction("custom");
assertThat(dto.getTypeAction()).isEqualTo("custom");
// Test url
dto.setUrl("https://example.com");
assertThat(dto.getUrl()).isEqualTo("https://example.com");
// Test estActivee
dto.setEstActivee(false);
assertThat(dto.getEstActivee()).isFalse();
// Test rolesAutorises
String[] roles = new String[] {"ADMIN", "MODERATOR"};
dto.setRolesAutorises(roles);
assertThat(dto.getRolesAutorises()).isEqualTo(roles);
// Test permissionsRequises
String[] permissions = new String[] {"read", "write"};
dto.setPermissionsRequises(permissions);
assertThat(dto.getPermissionsRequises()).isEqualTo(permissions);
// Test maxExecutions
dto.setMaxExecutions(5);
assertThat(dto.getMaxExecutions()).isEqualTo(5);
// Test peutEtreRepetee
dto.setPeutEtreRepetee(true);
assertThat(dto.getPeutEtreRepetee()).isTrue();
// Test description
dto.setDescription("Description détaillée de l'action");
assertThat(dto.getDescription()).isEqualTo("Description détaillée de l'action");
// Test parametres
Map<String, String> params = Map.of("key1", "val1", "key2", "val2");
dto.setParametres(params);
assertThat(dto.getParametres()).isEqualTo(params);
// Test fermeNotification
dto.setFermeNotification(false);
assertThat(dto.getFermeNotification()).isFalse();
// Test necessiteConfirmation
dto.setNecessiteConfirmation(true);
assertThat(dto.getNecessiteConfirmation()).isTrue();
// Test messageConfirmation
dto.setMessageConfirmation("Êtes-vous sûr ?");
assertThat(dto.getMessageConfirmation()).isEqualTo("Êtes-vous sûr ?");
// Test ordre
dto.setOrdre(5);
assertThat(dto.getOrdre()).isEqualTo(5);
// Test conditionAffichage
dto.setConditionAffichage("user.role === 'ADMIN'");
assertThat(dto.getConditionAffichage()).isEqualTo("user.role === 'ADMIN'");
// Test delaiExpirationMinutes
dto.setDelaiExpirationMinutes(120);
assertThat(dto.getDelaiExpirationMinutes()).isEqualTo(120);
// Test styleBouton
dto.setStyleBouton("outline");
assertThat(dto.getStyleBouton()).isEqualTo("outline");
// Test tailleBouton
dto.setTailleBouton("large");
assertThat(dto.getTailleBouton()).isEqualTo("large");
// Test positionBouton
dto.setPositionBouton("center");
assertThat(dto.getPositionBouton()).isEqualTo("center");
// Test donneesPersonnalisees
Map<String, Object> donneesPerso = Map.of("custom", "value", "count", 42);
dto.setDonneesPersonnalisees(donneesPerso);
assertThat(dto.getDonneesPersonnalisees()).isEqualTo(donneesPerso);
}
}
}

View File

@@ -0,0 +1,97 @@
package dev.lions.unionflow.server.api.dto.notification;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class PreferenceCanalNotificationDTOTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testConstructorAndGettersSetters() {
PreferenceCanalNotificationDTO dto = new PreferenceCanalNotificationDTO();
dto.setActive(true);
dto.setImportance(3);
dto.setSonPersonnalise("custom_sound.mp3");
dto.setPatternVibration(new long[]{100, 200, 100});
dto.setCouleurLED("#FF0000");
dto.setSonActive(true);
dto.setVibrationActive(false);
dto.setLedActive(true);
dto.setPeutEtreDesactive(true);
assertThat(dto.getActive()).isTrue();
assertThat(dto.getImportance()).isEqualTo(3);
assertThat(dto.getSonPersonnalise()).isEqualTo("custom_sound.mp3");
assertThat(dto.getPatternVibration()).containsExactly(100L, 200L, 100L);
assertThat(dto.getCouleurLED()).isEqualTo("#FF0000");
assertThat(dto.getSonActive()).isTrue();
assertThat(dto.getVibrationActive()).isFalse();
assertThat(dto.getLedActive()).isTrue();
assertThat(dto.getPeutEtreDesactive()).isTrue();
}
@Test
void testValidation_ImportanceTooLow() {
PreferenceCanalNotificationDTO dto = new PreferenceCanalNotificationDTO();
dto.setImportance(0);
Set<ConstraintViolation<PreferenceCanalNotificationDTO>> violations = validator.validate(dto);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("importance"));
}
@Test
void testValidation_ImportanceTooHigh() {
PreferenceCanalNotificationDTO dto = new PreferenceCanalNotificationDTO();
dto.setImportance(6);
Set<ConstraintViolation<PreferenceCanalNotificationDTO>> violations = validator.validate(dto);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("importance"));
}
@Test
void testValidation_ValidImportance() {
PreferenceCanalNotificationDTO dto = new PreferenceCanalNotificationDTO();
dto.setImportance(1);
Set<ConstraintViolation<PreferenceCanalNotificationDTO>> violations1 = validator.validate(dto);
assertThat(violations1).isEmpty();
dto.setImportance(5);
Set<ConstraintViolation<PreferenceCanalNotificationDTO>> violations2 = validator.validate(dto);
assertThat(violations2).isEmpty();
}
@Test
void testAllFieldsNull() {
PreferenceCanalNotificationDTO dto = new PreferenceCanalNotificationDTO();
assertThat(dto.getActive()).isNull();
assertThat(dto.getImportance()).isNull();
assertThat(dto.getSonPersonnalise()).isNull();
assertThat(dto.getPatternVibration()).isNull();
assertThat(dto.getCouleurLED()).isNull();
assertThat(dto.getSonActive()).isNull();
assertThat(dto.getVibrationActive()).isNull();
assertThat(dto.getLedActive()).isNull();
assertThat(dto.getPeutEtreDesactive()).isNull();
}
}

View File

@@ -0,0 +1,124 @@
package dev.lions.unionflow.server.api.dto.notification;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class PreferenceTypeNotificationDTOTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testConstructorAndGettersSetters() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
dto.setActive(true);
dto.setPriorite(4);
dto.setSonPersonnalise("alert.mp3");
dto.setPatternVibration(new long[]{50, 100, 50});
dto.setCouleurLED("#00FF00");
dto.setDureeAffichageSecondes(60);
dto.setDoitVibrer(true);
dto.setDoitEmettreSon(true);
dto.setDoitAllumerLED(false);
dto.setIgnoreModeSilencieux(true);
assertThat(dto.getActive()).isTrue();
assertThat(dto.getPriorite()).isEqualTo(4);
assertThat(dto.getSonPersonnalise()).isEqualTo("alert.mp3");
assertThat(dto.getPatternVibration()).containsExactly(50L, 100L, 50L);
assertThat(dto.getCouleurLED()).isEqualTo("#00FF00");
assertThat(dto.getDureeAffichageSecondes()).isEqualTo(60);
assertThat(dto.getDoitVibrer()).isTrue();
assertThat(dto.getDoitEmettreSon()).isTrue();
assertThat(dto.getDoitAllumerLED()).isFalse();
assertThat(dto.getIgnoreModeSilencieux()).isTrue();
}
@Test
void testValidation_PrioriteTooLow() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
dto.setPriorite(0);
Set<ConstraintViolation<PreferenceTypeNotificationDTO>> violations = validator.validate(dto);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("priorite"));
}
@Test
void testValidation_PrioriteTooHigh() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
dto.setPriorite(6);
Set<ConstraintViolation<PreferenceTypeNotificationDTO>> violations = validator.validate(dto);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("priorite"));
}
@Test
void testValidation_DureeAffichageTooLow() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
dto.setDureeAffichageSecondes(0);
Set<ConstraintViolation<PreferenceTypeNotificationDTO>> violations = validator.validate(dto);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dureeAffichageSecondes"));
}
@Test
void testValidation_DureeAffichageTooHigh() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
dto.setDureeAffichageSecondes(301);
Set<ConstraintViolation<PreferenceTypeNotificationDTO>> violations = validator.validate(dto);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("dureeAffichageSecondes"));
}
@Test
void testValidation_ValidFields() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
dto.setPriorite(1);
dto.setDureeAffichageSecondes(1);
Set<ConstraintViolation<PreferenceTypeNotificationDTO>> violations1 = validator.validate(dto);
assertThat(violations1).isEmpty();
dto.setPriorite(5);
dto.setDureeAffichageSecondes(300);
Set<ConstraintViolation<PreferenceTypeNotificationDTO>> violations2 = validator.validate(dto);
assertThat(violations2).isEmpty();
}
@Test
void testAllFieldsNull() {
PreferenceTypeNotificationDTO dto = new PreferenceTypeNotificationDTO();
assertThat(dto.getActive()).isNull();
assertThat(dto.getPriorite()).isNull();
assertThat(dto.getSonPersonnalise()).isNull();
assertThat(dto.getPatternVibration()).isNull();
assertThat(dto.getCouleurLED()).isNull();
assertThat(dto.getDureeAffichageSecondes()).isNull();
assertThat(dto.getDoitVibrer()).isNull();
assertThat(dto.getDoitEmettreSon()).isNull();
assertThat(dto.getDoitAllumerLED()).isNull();
assertThat(dto.getIgnoreModeSilencieux()).isNull();
}
}

View File

@@ -97,6 +97,16 @@ class PreferencesNotificationDTOTest {
dto.setTypesActives(Set.of(TypeNotification.IN_APP));
assertThat(dto.isTypeActive(TypeNotification.EMAIL)).isFalse();
}
@Test
@DisplayName("retourne type.isActiveeParDefaut() quand typesDesactivees non null (mais vide) et typesActives null")
void testTypesDesactiveesVideTypesActivesNull() {
PreferencesNotificationDTO dto = new PreferencesNotificationDTO();
dto.setTypesActives(null);
dto.setTypesDesactivees(Set.of());
TypeNotification type = TypeNotification.EMAIL;
assertThat(dto.isTypeActive(type)).isEqualTo(type.isActiveeParDefaut());
}
}
@Nested
@@ -143,6 +153,15 @@ class PreferencesNotificationDTOTest {
dto.setCanauxActifs(Set.of(CanalNotification.REMINDER_CHANNEL));
assertThat(dto.isCanalActif(CanalNotification.DEFAULT_CHANNEL)).isFalse();
}
@Test
@DisplayName("retourne true quand canauxDesactives non null (mais vide) et canauxActifs null")
void testCanauxDesactivesVideCanauxActifsNull() {
PreferencesNotificationDTO dto = new PreferencesNotificationDTO();
dto.setCanauxActifs(null);
dto.setCanauxDesactives(Set.of());
assertThat(dto.isCanalActif(CanalNotification.DEFAULT_CHANNEL)).isTrue();
}
}
@Nested
@@ -213,6 +232,15 @@ class PreferencesNotificationDTOTest {
dto.setHeureFinSilencieux(LocalTime.of(7, 0));
assertThat(dto.isEnModeSilencieux(LocalTime.of(10, 0))).isFalse();
}
@Test
@DisplayName("méthode publique sans paramètre appelle version avec LocalTime.now()")
void testPublicNoArg() {
PreferencesNotificationDTO dto = new PreferencesNotificationDTO();
dto.setModeSilencieux(false);
// Devrait retourner false car modeSilencieux est false
assertThat(dto.isEnModeSilencieux()).isFalse();
}
}
@Nested
@@ -286,4 +314,206 @@ class PreferencesNotificationDTOTest {
assertThat(s).contains("true");
}
}
@Nested
@DisplayName("Getters et Setters")
class GettersEtSetters {
@Test
@DisplayName("tous les getters et setters fonctionnent correctement")
void testTousLesGettersSetters() {
PreferencesNotificationDTO dto = new PreferencesNotificationDTO();
// Test id
dto.setId("pref-123");
assertThat(dto.getId()).isEqualTo("pref-123");
// Test utilisateurId
dto.setUtilisateurId("user-789");
assertThat(dto.getUtilisateurId()).isEqualTo("user-789");
// Test organisationId
dto.setOrganisationId("org-456");
assertThat(dto.getOrganisationId()).isEqualTo("org-456");
// Test pushActivees
dto.setPushActivees(false);
assertThat(dto.getPushActivees()).isFalse();
// Test emailActivees
dto.setEmailActivees(false);
assertThat(dto.getEmailActivees()).isFalse();
// Test smsActivees
dto.setSmsActivees(true);
assertThat(dto.getSmsActivees()).isTrue();
// Test inAppActivees
dto.setInAppActivees(false);
assertThat(dto.getInAppActivees()).isFalse();
// Test typesActives
Set<TypeNotification> types = Set.of(TypeNotification.EMAIL);
dto.setTypesActives(types);
assertThat(dto.getTypesActives()).isEqualTo(types);
// Test typesDesactivees
Set<TypeNotification> typesDesac = Set.of(TypeNotification.IN_APP);
dto.setTypesDesactivees(typesDesac);
assertThat(dto.getTypesDesactivees()).isEqualTo(typesDesac);
// Test canauxActifs
Set<CanalNotification> canaux = Set.of(CanalNotification.DEFAULT_CHANNEL);
dto.setCanauxActifs(canaux);
assertThat(dto.getCanauxActifs()).isEqualTo(canaux);
// Test canauxDesactives
Set<CanalNotification> canauxDesac = Set.of(CanalNotification.REMINDER_CHANNEL);
dto.setCanauxDesactives(canauxDesac);
assertThat(dto.getCanauxDesactives()).isEqualTo(canauxDesac);
// Test heureDebutSilencieux
dto.setHeureDebutSilencieux(LocalTime.of(22, 30));
assertThat(dto.getHeureDebutSilencieux()).isEqualTo(LocalTime.of(22, 30));
// Test heureFinSilencieux
dto.setHeureFinSilencieux(LocalTime.of(7, 0));
assertThat(dto.getHeureFinSilencieux()).isEqualTo(LocalTime.of(7, 0));
// Test joursSilencieux
Set<Integer> jours = Set.of(1, 2, 3, 4, 5);
dto.setJoursSilencieux(jours);
assertThat(dto.getJoursSilencieux()).isEqualTo(jours);
// Test urgentesIgnorentSilencieux
dto.setUrgentesIgnorentSilencieux(false);
assertThat(dto.getUrgentesIgnorentSilencieux()).isFalse();
// Test frequenceRegroupementMinutes
dto.setFrequenceRegroupementMinutes(15);
assertThat(dto.getFrequenceRegroupementMinutes()).isEqualTo(15);
// Test maxNotificationsSimultanees
dto.setMaxNotificationsSimultanees(20);
assertThat(dto.getMaxNotificationsSimultanees()).isEqualTo(20);
// Test dureeAffichageSecondes
dto.setDureeAffichageSecondes(5);
assertThat(dto.getDureeAffichageSecondes()).isEqualTo(5);
// Test langue
dto.setLangue("en");
assertThat(dto.getLangue()).isEqualTo("en");
// Test vibrationActivee
dto.setVibrationActivee(false);
assertThat(dto.getVibrationActivee()).isFalse();
// Test sonActive
dto.setSonActive(false);
assertThat(dto.getSonActive()).isFalse();
// Test ledActivee
dto.setLedActivee(false);
assertThat(dto.getLedActivee()).isFalse();
// Test sonPersonnalise
dto.setSonPersonnalise("custom_sound.mp3");
assertThat(dto.getSonPersonnalise()).isEqualTo("custom_sound.mp3");
// Test patternVibrationPersonnalise
long[] pattern = new long[]{100L, 200L, 300L};
dto.setPatternVibrationPersonnalise(pattern);
assertThat(dto.getPatternVibrationPersonnalise()).isEqualTo(pattern);
// Test couleurLEDPersonnalisee
dto.setCouleurLEDPersonnalisee("#FF5733");
assertThat(dto.getCouleurLEDPersonnalisee()).isEqualTo("#FF5733");
// Test apercuEcranVerrouillage
dto.setApercuEcranVerrouillage(false);
assertThat(dto.getApercuEcranVerrouillage()).isFalse();
// Test affichageHistorique
dto.setAffichageHistorique(false);
assertThat(dto.getAffichageHistorique()).isFalse();
// Test dureeConservationJours
dto.setDureeConservationJours(60);
assertThat(dto.getDureeConservationJours()).isEqualTo(60);
// Test marquageLectureAutomatique
dto.setMarquageLectureAutomatique(true);
assertThat(dto.getMarquageLectureAutomatique()).isTrue();
// Test delaiMarquageLectureSecondes
dto.setDelaiMarquageLectureSecondes(30);
assertThat(dto.getDelaiMarquageLectureSecondes()).isEqualTo(30);
// Test archivageAutomatique
dto.setArchivageAutomatique(false);
assertThat(dto.getArchivageAutomatique()).isFalse();
// Test delaiArchivageHeures
dto.setDelaiArchivageHeures(72);
assertThat(dto.getDelaiArchivageHeures()).isEqualTo(72);
// Test preferencesParType
java.util.Map<TypeNotification, PreferenceTypeNotificationDTO> prefsType = new java.util.HashMap<>();
prefsType.put(TypeNotification.EMAIL, new PreferenceTypeNotificationDTO());
dto.setPreferencesParType(prefsType);
assertThat(dto.getPreferencesParType()).isEqualTo(prefsType);
// Test preferencesParCanal
java.util.Map<CanalNotification, PreferenceCanalNotificationDTO> prefsCanal = new java.util.HashMap<>();
prefsCanal.put(CanalNotification.DEFAULT_CHANNEL, new PreferenceCanalNotificationDTO());
dto.setPreferencesParCanal(prefsCanal);
assertThat(dto.getPreferencesParCanal()).isEqualTo(prefsCanal);
// Test motsClesFiltre
Set<String> motsCles = Set.of("urgent", "important");
dto.setMotsClesFiltre(motsCles);
assertThat(dto.getMotsClesFiltre()).isEqualTo(motsCles);
// Test expediteursBloques
Set<String> bloques = Set.of("exp-block-1", "exp-block-2");
dto.setExpediteursBloques(bloques);
assertThat(dto.getExpediteursBloques()).isEqualTo(bloques);
// Test expediteursPrioritaires
Set<String> prioritaires = Set.of("exp-prio-1", "exp-prio-2");
dto.setExpediteursPrioritaires(prioritaires);
assertThat(dto.getExpediteursPrioritaires()).isEqualTo(prioritaires);
// Test notificationsTestActivees
dto.setNotificationsTestActivees(true);
assertThat(dto.getNotificationsTestActivees()).isTrue();
// Test niveauLog
dto.setNiveauLog("DEBUG");
assertThat(dto.getNiveauLog()).isEqualTo("DEBUG");
// Test tokenFCM
dto.setTokenFCM("fcm-token-12345");
assertThat(dto.getTokenFCM()).isEqualTo("fcm-token-12345");
// Test plateforme
dto.setPlateforme("android");
assertThat(dto.getPlateforme()).isEqualTo("android");
// Test versionApp
dto.setVersionApp("1.2.3");
assertThat(dto.getVersionApp()).isEqualTo("1.2.3");
// Test fuseauHoraire
dto.setFuseauHoraire("Europe/Paris");
assertThat(dto.getFuseauHoraire()).isEqualTo("Europe/Paris");
// Test metadonnees
java.util.Map<String, Object> metadata = new java.util.HashMap<>();
metadata.put("custom_key", "custom_value");
dto.setMetadonnees(metadata);
assertThat(dto.getMetadonnees()).isEqualTo(metadata);
}
}
}

View File

@@ -0,0 +1,130 @@
package dev.lions.unionflow.server.api.dto.notification.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDateTime;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateNotificationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID membreId = UUID.randomUUID();
UUID organisationId = UUID.randomUUID();
UUID templateId = UUID.randomUUID();
LocalDateTime dateEnvoi = LocalDateTime.now().plusDays(1);
CreateNotificationRequest request = CreateNotificationRequest.builder()
.typeNotification("EMAIL")
.priorite("HAUTE")
.sujet("Notification importante")
.corps("Corps du message")
.dateEnvoiPrevue(dateEnvoi)
.donneesAdditionnelles("{\"key\":\"value\"}")
.membreId(membreId)
.organisationId(organisationId)
.templateId(templateId)
.build();
assertThat(request).isNotNull();
assertThat(request.typeNotification()).isEqualTo("EMAIL");
assertThat(request.priorite()).isEqualTo("HAUTE");
assertThat(request.sujet()).isEqualTo("Notification importante");
assertThat(request.corps()).isEqualTo("Corps du message");
assertThat(request.dateEnvoiPrevue()).isEqualTo(dateEnvoi);
assertThat(request.donneesAdditionnelles()).isEqualTo("{\"key\":\"value\"}");
assertThat(request.membreId()).isEqualTo(membreId);
assertThat(request.organisationId()).isEqualTo(organisationId);
assertThat(request.templateId()).isEqualTo(templateId);
}
@Test
void testBuilder_MinimalFields() {
CreateNotificationRequest request = CreateNotificationRequest.builder()
.typeNotification("SMS")
.build();
assertThat(request).isNotNull();
assertThat(request.typeNotification()).isEqualTo("SMS");
assertThat(request.priorite()).isNull();
assertThat(request.sujet()).isNull();
assertThat(request.corps()).isNull();
assertThat(request.dateEnvoiPrevue()).isNull();
assertThat(request.donneesAdditionnelles()).isNull();
assertThat(request.membreId()).isNull();
assertThat(request.organisationId()).isNull();
assertThat(request.templateId()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreateNotificationRequest request = CreateNotificationRequest.builder().build();
Set<ConstraintViolation<CreateNotificationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("typeNotification"));
}
@Test
void testValidation_ValidFields() {
CreateNotificationRequest request = CreateNotificationRequest.builder()
.typeNotification("PUSH")
.priorite("NORMALE")
.sujet("Sujet")
.corps("Corps")
.build();
Set<ConstraintViolation<CreateNotificationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID membreId = UUID.randomUUID();
CreateNotificationRequest request1 = CreateNotificationRequest.builder()
.typeNotification("EMAIL")
.membreId(membreId)
.build();
CreateNotificationRequest request2 = CreateNotificationRequest.builder()
.typeNotification("EMAIL")
.membreId(membreId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateNotificationRequest request = CreateNotificationRequest.builder()
.typeNotification("EMAIL")
.sujet("Test")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateNotificationRequest");
assertThat(toString).contains("EMAIL");
assertThat(toString).contains("Test");
}
}

View File

@@ -0,0 +1,145 @@
package dev.lions.unionflow.server.api.dto.notification.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateTemplateNotificationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder()
.code("WELCOME_EMAIL")
.sujet("Bienvenue sur UnionFlow")
.corpsTexte("Bonjour {{prenom}},\nBienvenue!")
.corpsHtml("<h1>Bienvenue {{prenom}}</h1>")
.variablesDisponibles("prenom,nom,email")
.canauxSupportes("EMAIL,SMS")
.langue("fr")
.description("Template de bienvenue")
.build();
assertThat(request).isNotNull();
assertThat(request.code()).isEqualTo("WELCOME_EMAIL");
assertThat(request.sujet()).isEqualTo("Bienvenue sur UnionFlow");
assertThat(request.corpsTexte()).contains("Bonjour");
assertThat(request.corpsHtml()).contains("<h1>");
assertThat(request.variablesDisponibles()).isEqualTo("prenom,nom,email");
assertThat(request.canauxSupportes()).isEqualTo("EMAIL,SMS");
assertThat(request.langue()).isEqualTo("fr");
assertThat(request.description()).isEqualTo("Template de bienvenue");
}
@Test
void testBuilder_MinimalFields() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder()
.code("SIMPLE_NOTIF")
.build();
assertThat(request).isNotNull();
assertThat(request.code()).isEqualTo("SIMPLE_NOTIF");
assertThat(request.sujet()).isNull();
assertThat(request.corpsTexte()).isNull();
assertThat(request.corpsHtml()).isNull();
assertThat(request.variablesDisponibles()).isNull();
assertThat(request.canauxSupportes()).isNull();
assertThat(request.langue()).isNull();
assertThat(request.description()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder().build();
Set<ConstraintViolation<CreateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_EmptyCode() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder()
.code("")
.build();
Set<ConstraintViolation<CreateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_BlankCode() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder()
.code(" ")
.build();
Set<ConstraintViolation<CreateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_ValidFields() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder()
.code("VALID_CODE")
.sujet("Sujet")
.corpsTexte("Corps")
.build();
Set<ConstraintViolation<CreateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
CreateTemplateNotificationRequest request1 = CreateTemplateNotificationRequest.builder()
.code("CODE1")
.sujet("Sujet")
.build();
CreateTemplateNotificationRequest request2 = CreateTemplateNotificationRequest.builder()
.code("CODE1")
.sujet("Sujet")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateTemplateNotificationRequest request = CreateTemplateNotificationRequest.builder()
.code("TEST_CODE")
.sujet("Test Subject")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateTemplateNotificationRequest");
assertThat(toString).contains("TEST_CODE");
assertThat(toString).contains("Test Subject");
}
}

View File

@@ -0,0 +1,96 @@
package dev.lions.unionflow.server.api.dto.notification.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.time.LocalDateTime;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateNotificationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDateTime dateLecture = LocalDateTime.now();
UpdateNotificationRequest request = UpdateNotificationRequest.builder()
.statut("LU")
.dateLecture(dateLecture)
.nombreTentatives(3)
.messageErreur("Erreur temporaire")
.build();
assertThat(request).isNotNull();
assertThat(request.statut()).isEqualTo("LU");
assertThat(request.dateLecture()).isEqualTo(dateLecture);
assertThat(request.nombreTentatives()).isEqualTo(3);
assertThat(request.messageErreur()).isEqualTo("Erreur temporaire");
}
@Test
void testBuilder_MinimalFields() {
UpdateNotificationRequest request = UpdateNotificationRequest.builder().build();
assertThat(request).isNotNull();
assertThat(request.statut()).isNull();
assertThat(request.dateLecture()).isNull();
assertThat(request.nombreTentatives()).isNull();
assertThat(request.messageErreur()).isNull();
}
@Test
void testValidation_ValidFields() {
UpdateNotificationRequest request = UpdateNotificationRequest.builder()
.statut("ENVOYE")
.nombreTentatives(1)
.build();
Set<ConstraintViolation<UpdateNotificationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
LocalDateTime dateLecture = LocalDateTime.now();
UpdateNotificationRequest request1 = UpdateNotificationRequest.builder()
.statut("LU")
.dateLecture(dateLecture)
.build();
UpdateNotificationRequest request2 = UpdateNotificationRequest.builder()
.statut("LU")
.dateLecture(dateLecture)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateNotificationRequest request = UpdateNotificationRequest.builder()
.statut("ENVOYE")
.nombreTentatives(2)
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateNotificationRequest");
assertThat(toString).contains("ENVOYE");
}
}

View File

@@ -0,0 +1,144 @@
package dev.lions.unionflow.server.api.dto.notification.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateTemplateNotificationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder()
.code("UPDATED_CODE")
.sujet("Nouveau sujet")
.corpsTexte("Nouveau corps texte")
.corpsHtml("<p>Nouveau corps HTML</p>")
.variablesDisponibles("var1,var2")
.canauxSupportes("EMAIL,PUSH")
.langue("en")
.description("Description mise à jour")
.build();
assertThat(request).isNotNull();
assertThat(request.code()).isEqualTo("UPDATED_CODE");
assertThat(request.sujet()).isEqualTo("Nouveau sujet");
assertThat(request.corpsTexte()).isEqualTo("Nouveau corps texte");
assertThat(request.corpsHtml()).isEqualTo("<p>Nouveau corps HTML</p>");
assertThat(request.variablesDisponibles()).isEqualTo("var1,var2");
assertThat(request.canauxSupportes()).isEqualTo("EMAIL,PUSH");
assertThat(request.langue()).isEqualTo("en");
assertThat(request.description()).isEqualTo("Description mise à jour");
}
@Test
void testBuilder_MinimalFields() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder()
.code("MIN_CODE")
.build();
assertThat(request).isNotNull();
assertThat(request.code()).isEqualTo("MIN_CODE");
assertThat(request.sujet()).isNull();
assertThat(request.corpsTexte()).isNull();
assertThat(request.corpsHtml()).isNull();
assertThat(request.variablesDisponibles()).isNull();
assertThat(request.canauxSupportes()).isNull();
assertThat(request.langue()).isNull();
assertThat(request.description()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder().build();
Set<ConstraintViolation<UpdateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_EmptyCode() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder()
.code("")
.build();
Set<ConstraintViolation<UpdateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_BlankCode() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder()
.code(" ")
.build();
Set<ConstraintViolation<UpdateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("code"));
}
@Test
void testValidation_ValidFields() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder()
.code("VALID_UPDATE")
.sujet("Nouveau sujet")
.build();
Set<ConstraintViolation<UpdateTemplateNotificationRequest>> violations =
validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UpdateTemplateNotificationRequest request1 = UpdateTemplateNotificationRequest.builder()
.code("SAME_CODE")
.sujet("Sujet")
.build();
UpdateTemplateNotificationRequest request2 = UpdateTemplateNotificationRequest.builder()
.code("SAME_CODE")
.sujet("Sujet")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateTemplateNotificationRequest request = UpdateTemplateNotificationRequest.builder()
.code("TO_STRING_CODE")
.description("Description test")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateTemplateNotificationRequest");
assertThat(toString).contains("TO_STRING_CODE");
assertThat(toString).contains("Description test");
}
}

View File

@@ -0,0 +1,293 @@
package dev.lions.unionflow.server.api.dto.organisation.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreateOrganisationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateFondation = LocalDate.of(2020, 1, 15);
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Union des Entrepreneurs du Sénégal")
.nomCourt("UES")
.description("Association regroupant les entrepreneurs sénégalais")
.email("contact@ues.sn")
.telephone("+221 33 123 45 67")
.telephoneSecondaire("+221 77 987 65 43")
.emailSecondaire("info@ues.sn")
.siteWeb("https://www.ues.sn")
.logo("https://www.ues.sn/logo.png")
.reseauxSociaux("{\"facebook\":\"UES.Senegal\",\"twitter\":\"@UES_SN\"}")
.typeOrganisation("ASSOCIATION")
.statut("ACTIF")
.dateFondation(dateFondation)
.numeroEnregistrement("SN-ASSOC-2020-001")
.devise("XOF")
.budgetAnnuel(new BigDecimal("50000000.00"))
.cotisationObligatoire(true)
.montantCotisationAnnuelle(new BigDecimal("25000.00"))
.objectifs("Promouvoir l'entrepreneuriat au Sénégal")
.activitesPrincipales("Formation, networking, advocacy")
.certifications("ISO 9001")
.partenaires("Ministère du Commerce, Banque Mondiale")
.notes("Organisation de référence dans le secteur")
.latitude(new BigDecimal("14.6937"))
.longitude(new BigDecimal("-17.4441"))
.adresse("123 Rue des Entreprises, Plateau")
.ville("Dakar")
.region("Dakar")
.pays("Sénégal")
.codePostal("BP 3456")
.organisationPublique(true)
.accepteNouveauxMembres(false)
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Union des Entrepreneurs du Sénégal");
assertThat(request.nomCourt()).isEqualTo("UES");
assertThat(request.description()).contains("entrepreneurs sénégalais");
assertThat(request.email()).isEqualTo("contact@ues.sn");
assertThat(request.telephone()).isEqualTo("+221 33 123 45 67");
assertThat(request.telephoneSecondaire()).isEqualTo("+221 77 987 65 43");
assertThat(request.emailSecondaire()).isEqualTo("info@ues.sn");
assertThat(request.siteWeb()).isEqualTo("https://www.ues.sn");
assertThat(request.logo()).contains("logo.png");
assertThat(request.typeOrganisation()).isEqualTo("ASSOCIATION");
assertThat(request.statut()).isEqualTo("ACTIF");
assertThat(request.dateFondation()).isEqualTo(dateFondation);
assertThat(request.numeroEnregistrement()).isEqualTo("SN-ASSOC-2020-001");
assertThat(request.devise()).isEqualTo("XOF");
assertThat(request.budgetAnnuel()).isEqualByComparingTo(new BigDecimal("50000000.00"));
assertThat(request.cotisationObligatoire()).isTrue();
assertThat(request.montantCotisationAnnuelle()).isEqualByComparingTo(new BigDecimal("25000.00"));
assertThat(request.objectifs()).contains("entrepreneuriat");
assertThat(request.certifications()).isEqualTo("ISO 9001");
assertThat(request.latitude()).isEqualByComparingTo(new BigDecimal("14.6937"));
assertThat(request.longitude()).isEqualByComparingTo(new BigDecimal("-17.4441"));
assertThat(request.adresse()).isEqualTo("123 Rue des Entreprises, Plateau");
assertThat(request.ville()).isEqualTo("Dakar");
assertThat(request.region()).isEqualTo("Dakar");
assertThat(request.pays()).isEqualTo("Sénégal");
assertThat(request.codePostal()).isEqualTo("BP 3456");
assertThat(request.organisationPublique()).isTrue();
assertThat(request.accepteNouveauxMembres()).isFalse();
}
@Test
void testBuilder_MinimalFields() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Organisation Simple")
.email("simple@org.sn")
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Organisation Simple");
assertThat(request.email()).isEqualTo("simple@org.sn");
assertThat(request.nomCourt()).isNull();
assertThat(request.description()).isNull();
assertThat(request.telephone()).isNull();
assertThat(request.siteWeb()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder().build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
}
@Test
void testValidation_EmptyNom() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("")
.email("test@org.sn")
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
}
@Test
void testValidation_EmailInvalide() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Organisation Test")
.email("not-an-email")
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
}
@Test
void testValidation_EmailSecondaireInvalide() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Organisation Test")
.email("valid@test.sn")
.emailSecondaire("invalid-email")
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations)
.anyMatch(v -> v.getPropertyPath().toString().equals("emailSecondaire"));
}
@Test
void testValidation_NomTooLong() {
String longNom = "A".repeat(256);
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom(longNom)
.email("test@org.sn")
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
}
@Test
void testValidation_DeviseTooLong() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Organisation Test")
.email("test@org.sn")
.devise("XOFF")
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_ValidFields() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Organisation Valide")
.nomCourt("OV")
.email("contact@valide.org")
.emailSecondaire("info@valide.org")
.telephone("+221 33 111 22 33")
.devise("XOF")
.cotisationObligatoire(false)
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testBuilder_AdresseFields() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("ONG Dakar Centre")
.email("contact@ongdc.sn")
.adresse("Rue 10, Médina")
.ville("Dakar")
.region("Dakar")
.pays("Sénégal")
.codePostal("BP 1234")
.organisationPublique(false)
.accepteNouveauxMembres(true)
.build();
assertThat(request.adresse()).isEqualTo("Rue 10, Médina");
assertThat(request.ville()).isEqualTo("Dakar");
assertThat(request.region()).isEqualTo("Dakar");
assertThat(request.pays()).isEqualTo("Sénégal");
assertThat(request.codePostal()).isEqualTo("BP 1234");
assertThat(request.organisationPublique()).isFalse();
assertThat(request.accepteNouveauxMembres()).isTrue();
}
@Test
void testBuilder_AdresseFieldsNull_WhenNotProvided() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Org Minimal")
.email("min@org.sn")
.build();
assertThat(request.adresse()).isNull();
assertThat(request.ville()).isNull();
assertThat(request.region()).isNull();
assertThat(request.pays()).isNull();
assertThat(request.codePostal()).isNull();
assertThat(request.organisationPublique()).isNull();
assertThat(request.accepteNouveauxMembres()).isNull();
}
@Test
void testValidation_CodePostalTooLong() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Organisation Test")
.email("test@org.sn")
.codePostal("A".repeat(21))
.build();
Set<ConstraintViolation<CreateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codePostal"));
}
@Test
void testEquals() {
CreateOrganisationRequest request1 = CreateOrganisationRequest.builder()
.nom("Même Organisation")
.email("same@org.sn")
.build();
CreateOrganisationRequest request2 = CreateOrganisationRequest.builder()
.nom("Même Organisation")
.email("same@org.sn")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreateOrganisationRequest request = CreateOrganisationRequest.builder()
.nom("Test ToString Organisation")
.email("tostring@test.sn")
.nomCourt("TTO")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreateOrganisationRequest");
assertThat(toString).contains("Test ToString Organisation");
assertThat(toString).contains("tostring@test.sn");
assertThat(toString).contains("TTO");
}
}

View File

@@ -0,0 +1,258 @@
package dev.lions.unionflow.server.api.dto.organisation.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UpdateOrganisationRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
LocalDate dateFondation = LocalDate.of(2018, 6, 10);
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Organisation Mise à Jour")
.nomCourt("OMJ")
.description("Description mise à jour de l'organisation")
.email("updated@org.sn")
.telephone("+221 33 999 88 77")
.telephoneSecondaire("+221 77 666 55 44")
.emailSecondaire("secondary@org.sn")
.siteWeb("https://www.updated.org")
.logo("https://www.updated.org/new-logo.png")
.reseauxSociaux("{\"linkedin\":\"updated-org\"}")
.typeOrganisation("ONG")
.statut("EN_REVISION")
.dateFondation(dateFondation)
.numeroEnregistrement("SN-ONG-2018-045")
.devise("EUR")
.budgetAnnuel(new BigDecimal("75000000.00"))
.cotisationObligatoire(false)
.montantCotisationAnnuelle(new BigDecimal("50000.00"))
.objectifs("Nouveaux objectifs stratégiques")
.activitesPrincipales("Nouvelles activités")
.certifications("ISO 14001")
.partenaires("Nouveaux partenaires internationaux")
.notes("Notes mises à jour")
.latitude(new BigDecimal("12.5"))
.longitude(new BigDecimal("-15.5"))
.adresse("Avenue Cheikh Anta Diop, Fann")
.ville("Dakar")
.region("Dakar")
.pays("Sénégal")
.codePostal("BP 5000")
.organisationPublique(false)
.accepteNouveauxMembres(true)
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Organisation Mise à Jour");
assertThat(request.nomCourt()).isEqualTo("OMJ");
assertThat(request.description()).contains("mise à jour");
assertThat(request.email()).isEqualTo("updated@org.sn");
assertThat(request.telephone()).isEqualTo("+221 33 999 88 77");
assertThat(request.emailSecondaire()).isEqualTo("secondary@org.sn");
assertThat(request.siteWeb()).contains("updated.org");
assertThat(request.typeOrganisation()).isEqualTo("ONG");
assertThat(request.statut()).isEqualTo("EN_REVISION");
assertThat(request.dateFondation()).isEqualTo(dateFondation);
assertThat(request.devise()).isEqualTo("EUR");
assertThat(request.budgetAnnuel()).isEqualByComparingTo(new BigDecimal("75000000.00"));
assertThat(request.cotisationObligatoire()).isFalse();
assertThat(request.certifications()).isEqualTo("ISO 14001");
assertThat(request.adresse()).isEqualTo("Avenue Cheikh Anta Diop, Fann");
assertThat(request.ville()).isEqualTo("Dakar");
assertThat(request.region()).isEqualTo("Dakar");
assertThat(request.pays()).isEqualTo("Sénégal");
assertThat(request.codePostal()).isEqualTo("BP 5000");
assertThat(request.organisationPublique()).isFalse();
assertThat(request.accepteNouveauxMembres()).isTrue();
}
@Test
void testBuilder_MinimalFields() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Simple Update")
.email("simple@update.org")
.build();
assertThat(request).isNotNull();
assertThat(request.nom()).isEqualTo("Simple Update");
assertThat(request.email()).isEqualTo("simple@update.org");
assertThat(request.nomCourt()).isNull();
assertThat(request.description()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder().build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
}
@Test
void testValidation_EmptyNom() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("")
.email("test@org.sn")
.build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("nom"));
}
@Test
void testValidation_EmailInvalide() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Test Org")
.email("invalid-email-format")
.build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("email"));
}
@Test
void testValidation_EmailSecondaireInvalide() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Test Org")
.email("valid@org.sn")
.emailSecondaire("bad-email")
.build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations)
.anyMatch(v -> v.getPropertyPath().toString().equals("emailSecondaire"));
}
@Test
void testValidation_DeviseTooLong() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Test Org")
.email("test@org.sn")
.devise("XOFF")
.build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("devise"));
}
@Test
void testValidation_ValidFields() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Organisation Valide")
.email("valid@organisation.sn")
.emailSecondaire("info@organisation.sn")
.telephone("+221 33 222 33 44")
.devise("USD")
.cotisationObligatoire(true)
.montantCotisationAnnuelle(new BigDecimal("10000.00"))
.build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testBuilder_AdresseFields() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Association Abidjan Nord")
.email("contact@abn.ci")
.adresse("Quartier Deux Plateaux, Rue des Jardins")
.ville("Abidjan")
.region("Lagunes")
.pays("Côte d'Ivoire")
.codePostal("01 BP 1234")
.organisationPublique(true)
.accepteNouveauxMembres(true)
.build();
assertThat(request.adresse()).isEqualTo("Quartier Deux Plateaux, Rue des Jardins");
assertThat(request.ville()).isEqualTo("Abidjan");
assertThat(request.region()).isEqualTo("Lagunes");
assertThat(request.pays()).isEqualTo("Côte d'Ivoire");
assertThat(request.codePostal()).isEqualTo("01 BP 1234");
assertThat(request.organisationPublique()).isTrue();
assertThat(request.accepteNouveauxMembres()).isTrue();
}
@Test
void testValidation_VilleTooLong() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("Test Org")
.email("test@org.ci")
.ville("A".repeat(101))
.build();
Set<ConstraintViolation<UpdateOrganisationRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("ville"));
}
@Test
void testEquals() {
UpdateOrganisationRequest request1 = UpdateOrganisationRequest.builder()
.nom("Identique")
.email("same@test.org")
.statut("ACTIF")
.build();
UpdateOrganisationRequest request2 = UpdateOrganisationRequest.builder()
.nom("Identique")
.email("same@test.org")
.statut("ACTIF")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
UpdateOrganisationRequest request = UpdateOrganisationRequest.builder()
.nom("ToString Test Org")
.email("toString@test.org")
.nomCourt("TTO")
.statut("INACTIF")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("UpdateOrganisationRequest");
assertThat(toString).contains("ToString Test Org");
assertThat(toString).contains("toString@test.org");
assertThat(toString).contains("TTO");
assertThat(toString).contains("INACTIF");
}
}

View File

@@ -0,0 +1,80 @@
package dev.lions.unionflow.server.api.dto.organisation.response;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.UUID;
import org.junit.jupiter.api.Test;
class OrganisationSummaryResponseTest {
@Test
void testRecord_AllFields() {
UUID id = UUID.randomUUID();
OrganisationSummaryResponse response = new OrganisationSummaryResponse(
id,
"Mutuelle du Futur",
"MDF",
"MUTUELLE",
"Mutuelle",
"ACTIF",
"Actif",
"success",
150,
true
);
assertThat(response.id()).isEqualTo(id);
assertThat(response.nom()).isEqualTo("Mutuelle du Futur");
assertThat(response.nomCourt()).isEqualTo("MDF");
assertThat(response.typeOrganisation()).isEqualTo("MUTUELLE");
assertThat(response.typeOrganisationLibelle()).isEqualTo("Mutuelle");
assertThat(response.statut()).isEqualTo("ACTIF");
assertThat(response.statutLibelle()).isEqualTo("Actif");
assertThat(response.statutSeverity()).isEqualTo("success");
assertThat(response.nombreMembres()).isEqualTo(150);
assertThat(response.actif()).isTrue();
}
@Test
void testRecord_Equals() {
UUID id = UUID.randomUUID();
OrganisationSummaryResponse response1 = new OrganisationSummaryResponse(
id, "Org", "ORG", "TYPE", "Type", "ACTIF", "Actif", "success", 100, true
);
OrganisationSummaryResponse response2 = new OrganisationSummaryResponse(
id, "Org", "ORG", "TYPE", "Type", "ACTIF", "Actif", "success", 100, true
);
assertThat(response1).isEqualTo(response2);
assertThat(response1.hashCode()).isEqualTo(response2.hashCode());
}
@Test
void testRecord_ToString() {
OrganisationSummaryResponse response = new OrganisationSummaryResponse(
UUID.randomUUID(), "Org", "ORG", "TYPE", "Type",
"ACTIF", "Actif", "success", 100, true
);
String toString = response.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("OrganisationSummaryResponse");
assertThat(toString).contains("Org");
}
@Test
void testRecord_WithNullValues() {
OrganisationSummaryResponse response = new OrganisationSummaryResponse(
UUID.randomUUID(), "Org", null, "TYPE", "Type",
"ACTIF", "Actif", "success", null, false
);
assertThat(response.nomCourt()).isNull();
assertThat(response.nombreMembres()).isNull();
assertThat(response.actif()).isFalse();
}
}

View File

@@ -64,6 +64,29 @@ class WaveBalanceDTOTest {
dto.setSoldeDisponible(BigDecimal.valueOf(200));
assertThat(dto.getSoldeTotal()).isEqualByComparingTo(BigDecimal.valueOf(220));
}
@Test
@DisplayName("ne calcule pas soldeTotal si soldeDisponible null")
void testCalculSoldeTotalAvecDisponibleNull() {
WaveBalanceDTO dto = new WaveBalanceDTO();
BigDecimal soldeInitial = dto.getSoldeTotal(); // null au départ
dto.setSoldeDisponible(null);
dto.setSoldeEnAttente(BigDecimal.valueOf(50));
// soldeTotal ne devrait pas être calculé car soldeDisponible est null
assertThat(dto.getSoldeTotal()).isEqualTo(soldeInitial);
}
@Test
@DisplayName("ne calcule pas soldeTotal si soldeEnAttente null après calcul initial")
void testCalculSoldeTotalAvecEnAttenteNull() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setSoldeDisponible(BigDecimal.valueOf(100));
// À ce stade soldeTotal = 100 + 0 = 100 (car soldeEnAttente initialisé à ZERO)
BigDecimal soldeAvantNull = dto.getSoldeTotal();
dto.setSoldeEnAttente(null);
// soldeTotal ne devrait pas être recalculé, garde sa valeur précédente
assertThat(dto.getSoldeTotal()).isEqualTo(soldeAvantNull);
}
}
@Nested
@@ -137,6 +160,16 @@ class WaveBalanceDTOTest {
assertThat(dto.getSoldeDisponibleAujourdhui()).isEqualByComparingTo(BigDecimal.valueOf(500));
}
@Test
@DisplayName("retourne soldeDisponible null quand soldeDisponible null")
void testSoldeDisponibleNull() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setSoldeDisponible(null);
dto.setLimiteQuotidienne(BigDecimal.valueOf(1000));
dto.setMontantUtiliseAujourdhui(BigDecimal.valueOf(100));
assertThat(dto.getSoldeDisponibleAujourdhui()).isNull();
}
@Test
@DisplayName("retourne le minimum entre solde et limite restante")
void testMinimum() {
@@ -196,4 +229,91 @@ class WaveBalanceDTOTest {
assertThat(s).contains("500");
}
}
@Nested
@DisplayName("Getters et Setters complémentaires")
class GettersSettersComplementaires {
@Test
@DisplayName("setSoldeTotal / getSoldeTotal")
void testSoldeTotal() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setSoldeTotal(BigDecimal.valueOf(1500));
assertThat(dto.getSoldeTotal()).isEqualByComparingTo(BigDecimal.valueOf(1500));
}
@Test
@DisplayName("setDevise / getDevise")
void testDevise() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setDevise("USD");
assertThat(dto.getDevise()).isEqualTo("USD");
}
@Test
@DisplayName("setNumeroWallet / getNumeroWallet")
void testNumeroWallet() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setNumeroWallet("+221771234567");
assertThat(dto.getNumeroWallet()).isEqualTo("+221771234567");
}
@Test
@DisplayName("setNomBusiness / getNomBusiness")
void testNomBusiness() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setNomBusiness("UnionFlow Business");
assertThat(dto.getNomBusiness()).isEqualTo("UnionFlow Business");
}
@Test
@DisplayName("setDateDerniereMiseAJour / getDateDerniereMiseAJour")
void testDateDerniereMiseAJour() {
WaveBalanceDTO dto = new WaveBalanceDTO();
LocalDateTime now = LocalDateTime.now();
dto.setDateDerniereMiseAJour(now);
assertThat(dto.getDateDerniereMiseAJour()).isEqualTo(now);
}
@Test
@DisplayName("setDateDerniereSynchronisation / getDateDerniereSynchronisation")
void testDateDerniereSynchronisation() {
WaveBalanceDTO dto = new WaveBalanceDTO();
LocalDateTime dateSync = LocalDateTime.of(2025, 1, 15, 10, 30);
dto.setDateDerniereSynchronisation(dateSync);
assertThat(dto.getDateDerniereSynchronisation()).isEqualTo(dateSync);
}
@Test
@DisplayName("setLimiteQuotidienne / getLimiteQuotidienne")
void testLimiteQuotidienne() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setLimiteQuotidienne(BigDecimal.valueOf(50000));
assertThat(dto.getLimiteQuotidienne()).isEqualByComparingTo(BigDecimal.valueOf(50000));
}
@Test
@DisplayName("setLimiteMensuelle / getLimiteMensuelle")
void testLimiteMensuelle() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setLimiteMensuelle(BigDecimal.valueOf(500000));
assertThat(dto.getLimiteMensuelle()).isEqualByComparingTo(BigDecimal.valueOf(500000));
}
@Test
@DisplayName("setDerniereErreur / getDerniereErreur")
void testDerniereErreur() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setDerniereErreur("Erreur de synchronisation avec Wave API");
assertThat(dto.getDerniereErreur()).isEqualTo("Erreur de synchronisation avec Wave API");
}
@Test
@DisplayName("setCodeDerniereErreur / getCodeDerniereErreur")
void testCodeDerniereErreur() {
WaveBalanceDTO dto = new WaveBalanceDTO();
dto.setCodeDerniereErreur("ERR_WAVE_500");
assertThat(dto.getCodeDerniereErreur()).isEqualTo("ERR_WAVE_500");
}
}
}

View File

@@ -212,4 +212,129 @@ class WaveWebhookDTOTest {
assertThat(s).contains("sess-1");
}
}
@Nested
@DisplayName("Getters et Setters")
class GettersEtSetters {
@Test
@DisplayName("tous les getters et setters fonctionnent correctement")
void testTousLesGettersSetters() {
WaveWebhookDTO dto = new WaveWebhookDTO();
// Test webhookId
dto.setWebhookId("webhook-test-123");
assertThat(dto.getWebhookId()).isEqualTo("webhook-test-123");
// Test statutTraitement
dto.setStatutTraitement(StatutTraitement.EN_COURS);
assertThat(dto.getStatutTraitement()).isEqualTo(StatutTraitement.EN_COURS);
// Test payloadJson
dto.setPayloadJson("{\"test\": \"value\"}");
assertThat(dto.getPayloadJson()).isEqualTo("{\"test\": \"value\"}");
// Test headersHttp
dto.setHeadersHttp("Content-Type: application/json");
assertThat(dto.getHeadersHttp()).isEqualTo("Content-Type: application/json");
// Test signatureWave
dto.setSignatureWave("signature-abc123");
assertThat(dto.getSignatureWave()).isEqualTo("signature-abc123");
// Test dateReception
LocalDateTime dateReception = LocalDateTime.of(2026, 3, 13, 10, 30);
dto.setDateReception(dateReception);
assertThat(dto.getDateReception()).isEqualTo(dateReception);
// Test dateTraitement
LocalDateTime dateTraitement = LocalDateTime.of(2026, 3, 13, 11, 0);
dto.setDateTraitement(dateTraitement);
assertThat(dto.getDateTraitement()).isEqualTo(dateTraitement);
// Test sessionCheckoutId
dto.setSessionCheckoutId("checkout-session-456");
assertThat(dto.getSessionCheckoutId()).isEqualTo("checkout-session-456");
// Test transactionWaveId
dto.setTransactionWaveId("wave-txn-789");
assertThat(dto.getTransactionWaveId()).isEqualTo("wave-txn-789");
// Test montantTransaction
BigDecimal montant = new BigDecimal("1500.50");
dto.setMontantTransaction(montant);
assertThat(dto.getMontantTransaction()).isEqualTo(montant);
// Test deviseTransaction
dto.setDeviseTransaction("XOF");
assertThat(dto.getDeviseTransaction()).isEqualTo("XOF");
// Test statutTransactionWave
dto.setStatutTransactionWave("COMPLETED");
assertThat(dto.getStatutTransactionWave()).isEqualTo("COMPLETED");
// Test organisationId
UUID orgId = UUID.randomUUID();
dto.setOrganisationId(orgId);
assertThat(dto.getOrganisationId()).isEqualTo(orgId);
// Test membreId
UUID membreId = UUID.randomUUID();
dto.setMembreId(membreId);
assertThat(dto.getMembreId()).isEqualTo(membreId);
// Test referenceUnionFlow
dto.setReferenceUnionFlow("REF-UF-2026-001");
assertThat(dto.getReferenceUnionFlow()).isEqualTo("REF-UF-2026-001");
// Test typePaiementUnionFlow
dto.setTypePaiementUnionFlow("COTISATION");
assertThat(dto.getTypePaiementUnionFlow()).isEqualTo("COTISATION");
// Test adresseIpSource
dto.setAdresseIpSource("192.168.1.100");
assertThat(dto.getAdresseIpSource()).isEqualTo("192.168.1.100");
// Test userAgentSource
dto.setUserAgentSource("Mozilla/5.0");
assertThat(dto.getUserAgentSource()).isEqualTo("Mozilla/5.0");
// Test nombreTentativesTraitement
dto.setNombreTentativesTraitement(3);
assertThat(dto.getNombreTentativesTraitement()).isEqualTo(3);
// Test messageErreurTraitement
dto.setMessageErreurTraitement("Erreur de connexion");
assertThat(dto.getMessageErreurTraitement()).isEqualTo("Erreur de connexion");
// Test codeErreurTraitement
dto.setCodeErreurTraitement("ERR_TIMEOUT");
assertThat(dto.getCodeErreurTraitement()).isEqualTo("ERR_TIMEOUT");
// Test stackTraceErreur
dto.setStackTraceErreur("java.lang.Exception: Test\n\tat Class.method(...)");
assertThat(dto.getStackTraceErreur()).isEqualTo("java.lang.Exception: Test\n\tat Class.method(...)");
// Test traitementAutomatique
dto.setTraitementAutomatique(false);
assertThat(dto.getTraitementAutomatique()).isFalse();
// Test interventionManuelleRequise
dto.setInterventionManuelleRequise(true);
assertThat(dto.getInterventionManuelleRequise()).isTrue();
// Test notesTraitementManuel
dto.setNotesTraitementManuel("Traité manuellement après erreur");
assertThat(dto.getNotesTraitementManuel()).isEqualTo("Traité manuellement après erreur");
// Test utilisateurTraitementManuel
dto.setUtilisateurTraitementManuel("admin@unionflow.com");
assertThat(dto.getUtilisateurTraitementManuel()).isEqualTo("admin@unionflow.com");
// Test dateTraitementManuel
LocalDateTime dateManuel = LocalDateTime.of(2026, 3, 13, 15, 0);
dto.setDateTraitementManuel(dateManuel);
assertThat(dto.getDateTraitementManuel()).isEqualTo(dateManuel);
}
}
}

View File

@@ -0,0 +1,221 @@
package dev.lions.unionflow.server.api.dto.paiement.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.math.BigDecimal;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CreatePaiementRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID membreId = UUID.randomUUID();
BigDecimal montant = new BigDecimal("5000.00");
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000001")
.montant(montant)
.codeDevise("XOF")
.methodePaiement("WAVE")
.commentaire("Paiement pour cotisation mensuelle")
.membreId(membreId)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("PAY-2025-000001");
assertThat(request.montant()).isEqualByComparingTo(montant);
assertThat(request.codeDevise()).isEqualTo("XOF");
assertThat(request.methodePaiement()).isEqualTo("WAVE");
assertThat(request.commentaire()).isEqualTo("Paiement pour cotisation mensuelle");
assertThat(request.membreId()).isEqualTo(membreId);
}
@Test
void testBuilder_MinimalFields() {
UUID membreId = UUID.randomUUID();
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000002")
.montant(new BigDecimal("1000.00"))
.codeDevise("EUR")
.methodePaiement("ESPECES")
.membreId(membreId)
.build();
assertThat(request).isNotNull();
assertThat(request.numeroReference()).isEqualTo("PAY-2025-000002");
assertThat(request.montant()).isEqualByComparingTo(new BigDecimal("1000.00"));
assertThat(request.codeDevise()).isEqualTo("EUR");
assertThat(request.methodePaiement()).isEqualTo("ESPECES");
assertThat(request.membreId()).isEqualTo(membreId);
assertThat(request.commentaire()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
CreatePaiementRequest request = CreatePaiementRequest.builder().build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroReference"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montant"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("methodePaiement"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("membreId"));
}
@Test
void testValidation_BlankNumeroReference() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference(" ")
.montant(new BigDecimal("1000.00"))
.codeDevise("XOF")
.methodePaiement("WAVE")
.membreId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("numeroReference"));
}
@Test
void testValidation_MontantNegatif() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000003")
.montant(new BigDecimal("-100.00"))
.codeDevise("XOF")
.methodePaiement("WAVE")
.membreId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("montant"));
}
@Test
void testValidation_CodeDeviseInvalide() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000004")
.montant(new BigDecimal("1000.00"))
.codeDevise("INVALID")
.methodePaiement("WAVE")
.membreId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
}
@Test
void testValidation_CodeDeviseTooShort() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000005")
.montant(new BigDecimal("1000.00"))
.codeDevise("XO")
.methodePaiement("WAVE")
.membreId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("codeDevise"));
}
@Test
void testValidation_BlankMethodePaiement() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000006")
.montant(new BigDecimal("1000.00"))
.codeDevise("XOF")
.methodePaiement(" ")
.membreId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("methodePaiement"));
}
@Test
void testValidation_ValidFields() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000007")
.montant(new BigDecimal("5000.00"))
.codeDevise("XOF")
.methodePaiement("WAVE")
.commentaire("Paiement mensuel")
.membreId(UUID.randomUUID())
.build();
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID membreId = UUID.randomUUID();
CreatePaiementRequest request1 = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000008")
.montant(new BigDecimal("1000.00"))
.codeDevise("XOF")
.methodePaiement("WAVE")
.membreId(membreId)
.build();
CreatePaiementRequest request2 = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000008")
.montant(new BigDecimal("1000.00"))
.codeDevise("XOF")
.methodePaiement("WAVE")
.membreId(membreId)
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
CreatePaiementRequest request = CreatePaiementRequest.builder()
.numeroReference("PAY-2025-000009")
.montant(new BigDecimal("1000.00"))
.codeDevise("XOF")
.methodePaiement("WAVE")
.membreId(UUID.randomUUID())
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("CreatePaiementRequest");
assertThat(toString).contains("PAY-2025-000009");
assertThat(toString).contains("XOF");
assertThat(toString).contains("WAVE");
}
}

View File

@@ -0,0 +1,230 @@
package dev.lions.unionflow.server.api.dto.paiement.request;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class DeclarerPaiementManuelRequestTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
void testBuilder_AllFields() {
UUID cotisationId = UUID.randomUUID();
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(cotisationId)
.methodePaiement("ESPECES")
.reference("REF-2025-001")
.commentaire("Paiement reçu en espèces")
.origineFonds("Salaire mensuel")
.justificationLcbFt("Bulletin de salaire fourni")
.build();
assertThat(request).isNotNull();
assertThat(request.cotisationId()).isEqualTo(cotisationId);
assertThat(request.methodePaiement()).isEqualTo("ESPECES");
assertThat(request.reference()).isEqualTo("REF-2025-001");
assertThat(request.commentaire()).isEqualTo("Paiement reçu en espèces");
assertThat(request.origineFonds()).isEqualTo("Salaire mensuel");
assertThat(request.justificationLcbFt()).isEqualTo("Bulletin de salaire fourni");
}
@Test
void testBuilder_MinimalFields() {
UUID cotisationId = UUID.randomUUID();
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(cotisationId)
.methodePaiement("VIREMENT")
.build();
assertThat(request).isNotNull();
assertThat(request.cotisationId()).isEqualTo(cotisationId);
assertThat(request.methodePaiement()).isEqualTo("VIREMENT");
assertThat(request.reference()).isNull();
assertThat(request.commentaire()).isNull();
assertThat(request.origineFonds()).isNull();
assertThat(request.justificationLcbFt()).isNull();
}
@Test
void testValidation_MissingRequiredFields() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder().build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("cotisationId"));
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("methodePaiement"));
}
@Test
void testValidation_BlankMethodePaiement() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement(" ")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("methodePaiement"));
}
@Test
void testValidation_InvalidMethodePaiement() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("PAYPAL")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("methodePaiement")
&& v.getMessage().contains("Valeurs autorisées : ESPECES, VIREMENT, CHEQUE, AUTRE"));
}
@Test
void testValidation_ReferenceTooLong() {
String longReference = "A".repeat(101);
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("ESPECES")
.reference(longReference)
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("reference"));
}
@Test
void testValidation_CommentaireTooLong() {
String longCommentaire = "A".repeat(501);
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("ESPECES")
.commentaire(longCommentaire)
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isNotEmpty();
assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("commentaire"));
}
@Test
void testValidation_ValidMethodePaiement_ESPECES() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("ESPECES")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_ValidMethodePaiement_VIREMENT() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("VIREMENT")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_ValidMethodePaiement_CHEQUE() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("CHEQUE")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_ValidMethodePaiement_AUTRE() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("AUTRE")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testValidation_ValidFields() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("ESPECES")
.reference("REF-2025-001")
.commentaire("Paiement mensuel")
.origineFonds("Salaire")
.justificationLcbFt("Bulletin de paie")
.build();
Set<ConstraintViolation<DeclarerPaiementManuelRequest>> violations = validator.validate(request);
assertThat(violations).isEmpty();
}
@Test
void testEquals() {
UUID cotisationId = UUID.randomUUID();
DeclarerPaiementManuelRequest request1 = DeclarerPaiementManuelRequest.builder()
.cotisationId(cotisationId)
.methodePaiement("ESPECES")
.reference("REF-001")
.build();
DeclarerPaiementManuelRequest request2 = DeclarerPaiementManuelRequest.builder()
.cotisationId(cotisationId)
.methodePaiement("ESPECES")
.reference("REF-001")
.build();
assertThat(request1).isEqualTo(request2);
assertThat(request1.hashCode()).isEqualTo(request2.hashCode());
}
@Test
void testToString() {
DeclarerPaiementManuelRequest request = DeclarerPaiementManuelRequest.builder()
.cotisationId(UUID.randomUUID())
.methodePaiement("ESPECES")
.reference("REF-001")
.build();
String toString = request.toString();
assertThat(toString).isNotNull();
assertThat(toString).contains("DeclarerPaiementManuelRequest");
assertThat(toString).contains("ESPECES");
}
}

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