Constructeur passé de 10 à 12 arguments avec l'ajout de ville et pays. Tests mis à jour + nouveau test testSettersVillePays.
UnionFlow Server API - DTOs et Contrats
Module API partagé UnionFlow - DTOs, Request/Response, Validation, Enums.
📋 Vue d'ensemble
Ce module contient les contrats d'API partagés entre :
- Backend Quarkus (unionflow-server-impl-quarkus)
- Frontend Web (unionflow-client-quarkus-primefaces-freya)
- Mobile Flutter (unionflow-mobile-apps) - via génération TypeScript/JSON
Avantages
✅ Type-safety : Contrats Java typés ✅ Validation centralisée : Contraintes Jakarta Bean Validation ✅ DRY : Zéro duplication entre projets ✅ Versioning : Maven semantic versioning ✅ Documentation : Javadoc complète
🏗️ Structure
src/main/java/dev/lions/unionflow/server/api/
├── dto/ # Data Transfer Objects
│ ├── base/ # DTOs de base
│ │ ├── BaseRequest.java
│ │ └── BaseResponse.java
│ ├── dashboard/ # Dashboard
│ │ ├── DashboardStatsResponse.java
│ │ ├── MembreDashboardSyntheseResponse.java
│ │ └── UpcomingEventResponse.java
│ ├── membre/ # Membres
│ │ ├── request/
│ │ │ └── CreateMembreRequest.java
│ │ └── response/
│ │ ├── MembreResponse.java
│ └── MembreSummaryResponse.java
│ ├── finance/ # Finance Workflow
│ │ ├── request/
│ │ │ ├── ApproveTransactionRequest.java
│ │ │ └── RejectTransactionRequest.java
│ │ └── response/
│ │ ├── AdhesionResponse.java
│ │ ├── TransactionApprovalResponse.java
│ │ └── BudgetResponse.java
│ ├── cotisation/ # Cotisations
│ ├── evenement/ # Événements
│ ├── solidarite/ # Demandes d'aide
│ └── notification/ # Notifications
├── enums/ # Énumérations
│ ├── membre/
│ │ ├── StatutMembre.java
│ │ └── TypeMembre.java
│ ├── finance/
│ │ ├── StatutApprobation.java
│ │ ├── TypeTransaction.java
│ │ └── BudgetPeriod.java
│ ├── paiement/
│ │ ├── StatutPaiement.java
│ │ └── ModePaiement.java
│ └── notification/
│ └── TypeNotification.java
├── validation/ # Validateurs custom
│ ├── annotations/ # Annotations validation
│ │ ├── @ValidEmail
│ │ ├── @ValidPhoneNumber
│ │ └── @ValidAmount
│ ├── validators/ # Implémentations
│ │ ├── EmailValidator.java
│ │ └── AmountValidator.java
│ └── ValidationConstants.java # Constantes (regex, limites)
└── exception/ # Exceptions API
├── ApiException.java
├── ValidationException.java
└── ErrorResponse.java
📦 Installation
Maven Dependency
Ajouter à votre pom.xml :
<dependency>
<groupId>dev.lions.unionflow</groupId>
<artifactId>unionflow-server-api</artifactId>
<version>2.0.0</version>
</dependency>
Repository Gitea (Maven Registry)
Configurer ~/.m2/settings.xml :
<settings>
<servers>
<server>
<id>gitea-lionsdev</id>
<username>${env.GITEA_USERNAME}</username>
<password>${env.GITEA_TOKEN}</password>
</server>
</servers>
<repositories>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</repository>
</repositories>
</settings>
Variables d'environnement
export GITEA_USERNAME=lionsdev
export GITEA_TOKEN=your-gitea-token
🎯 Utilisation
1. DTOs Request/Response
Exemple : Créer un membre
Request DTO :
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreateMembreRequest {
@NotBlank(message = "Le nom est requis")
@Size(min = 2, max = 100)
private String nom;
@NotBlank(message = "Le prénom est requis")
@Size(min = 2, max = 100)
private String prenom;
@ValidEmail
private String email;
@ValidPhoneNumber
private String telephone;
@NotNull
private UUID organisationId;
private TypeMembre typeMembre = TypeMembre.MEMBRE;
}
Response DTO :
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MembreResponse extends BaseResponse {
private UUID id;
private String nom;
private String prenom;
private String email;
private String telephone;
private StatutMembre statut;
private TypeMembre type;
private String numeroMembre;
private LocalDate dateAdhesion;
private UUID organisationId;
private String organisationNom;
}
Usage Backend :
@POST
@Path("/membres")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createMembre(@Valid CreateMembreRequest request) {
MembreResponse response = membreService.create(request);
return Response.status(201).entity(response).build();
}
Usage Frontend (REST Client) :
@Path("/api/v1/membres")
@RegisterRestClient(configKey = "unionflow-backend")
public interface MembreRestClient {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
MembreResponse createMembre(@Valid CreateMembreRequest request);
}
2. Validation
Annotations standard (Jakarta Bean Validation)
@NotNull // Non null
@NotBlank // Non vide (String)
@Size(min, max) // Taille min/max
@Min(value) // Valeur minimale (nombres)
@Max(value) // Valeur maximale (nombres)
@Email // Format email
@Pattern(regex) // Regex custom
@Positive // > 0
@PositiveOrZero // >= 0
Annotations custom UnionFlow
@ValidEmail // Email avec domaines autorisés
@ValidPhoneNumber // Téléphone international (+225, +33, etc.)
@ValidAmount // Montant positif, max 2 décimales
@ValidNumeroMembre // Format: ORG-YYYY-NNNN
@ValidPeriodeCotisation // Format: YYYY-MM
Exemple d'utilisation :
public class PaiementRequest {
@ValidAmount(min = 100.0, max = 10_000_000.0)
private BigDecimal montant;
@ValidPhoneNumber
private String telephonePaiement;
@NotNull
@Pattern(regexp = "^\\d{4}-\\d{2}$")
private String periode; // Ex: "2026-03"
}
Validators custom - Implémentation
Annotation :
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AmountValidator.class)
public @interface ValidAmount {
String message() default "Montant invalide";
double min() default 0.0;
double max() default Double.MAX_VALUE;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Validator :
public class AmountValidator implements ConstraintValidator<ValidAmount, BigDecimal> {
private double min;
private double max;
@Override
public void initialize(ValidAmount annotation) {
this.min = annotation.min();
this.max = annotation.max();
}
@Override
public boolean isValid(BigDecimal value, ConstraintValidatorContext context) {
if (value == null) return true; // Use @NotNull separately
double amount = value.doubleValue();
// Check positive
if (amount <= 0) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Le montant doit être positif")
.addConstraintViolation();
return false;
}
// Check range
if (amount < min || amount > max) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(
String.format("Le montant doit être entre %.2f et %.2f", min, max)
).addConstraintViolation();
return false;
}
// Check max 2 decimals
if (value.scale() > 2) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Maximum 2 décimales autorisées")
.addConstraintViolation();
return false;
}
return true;
}
}
3. Enums
Exemple : StatutApprobation
public enum StatutApprobation {
PENDING("En attente"),
APPROVED("Approuvée"),
REJECTED("Rejetée"),
CANCELLED("Annulée");
private final String libelle;
StatutApprobation(String libelle) {
this.libelle = libelle;
}
public String getLibelle() {
return libelle;
}
public static StatutApprobation fromString(String str) {
return Arrays.stream(values())
.filter(s -> s.name().equalsIgnoreCase(str))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Statut invalide: " + str));
}
}
Usage :
StatutApprobation statut = StatutApprobation.APPROVED;
System.out.println(statut.getLibelle()); // "Approuvée"
StatutApprobation parsed = StatutApprobation.fromString("PENDING");
4. BaseResponse - Héritage commun
Tous les Response DTOs étendent BaseResponse :
@Data
@NoArgsConstructor
public abstract class BaseResponse implements Serializable {
private static final long serialVersionUID = 1L;
// Audit fields (si nécessaire côté client)
private LocalDateTime dateCreation;
private LocalDateTime dateModification;
private Boolean actif;
}
Avantages :
- Champs audit automatiques
- Serializable pour cache/sessions
- Type-safe avec génériques
🧪 Tests
Tests de validation
Fichier : src/test/java/dev/lions/unionflow/server/api/validation/AmountValidatorTest.java
@Test
void shouldRejectNegativeAmount() {
CreatePaiementRequest request = new CreatePaiementRequest();
request.setMontant(BigDecimal.valueOf(-100));
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertFalse(violations.isEmpty());
assertTrue(violations.stream()
.anyMatch(v -> v.getMessage().contains("positif")));
}
@Test
void shouldRejectTooManyDecimals() {
CreatePaiementRequest request = new CreatePaiementRequest();
request.setMontant(BigDecimal.valueOf(100.123));
Set<ConstraintViolation<CreatePaiementRequest>> violations = validator.validate(request);
assertFalse(violations.isEmpty());
assertTrue(violations.stream()
.anyMatch(v -> v.getMessage().contains("2 décimales")));
}
Lancer les tests
mvn test
📊 DTOs par Feature
Dashboard
DashboardStatsResponse- Stats organisation (membres, cotisations, events)MembreDashboardSyntheseResponse- Synthèse membre (solde, cotisations)UpcomingEventResponse- Événements à venir
Finance Workflow
TransactionApprovalResponse- Approbation de transactionBudgetResponse- Budget avec lignes budgétairesAdhesionResponse- Adhésion membre
Membres
MembreResponse- Détails membre completsMembreSummaryResponse- Résumé membre (liste)CreateMembreRequest- Création membreUpdateMembreRequest- Modification membre
Cotisations
CotisationResponse- Cotisation avec détailsCreateCotisationRequest- Enregistrement cotisationCotisationStatisticsResponse- Statistiques cotisations
Notifications
NotificationResponse- Notification utilisateurMarkAsReadRequest- Marquer comme lue
🔄 Publication Maven (Développeurs seulement)
Publier une nouvelle version
# 1. Mettre à jour la version dans pom.xml
<version>2.1.0</version>
# 2. Compiler et publier
mvn clean deploy
# Les artifacts sont publiés sur:
# https://git.lions.dev/api/packages/lionsdev/maven
Versioning Semantic
- Major (2.0.0) : Breaking changes
- Minor (2.1.0) : Nouvelles features (backward compatible)
- Patch (2.0.1) : Bugfixes
📝 Changelog
v2.0.0 (2026-03-14)
✅ Nouveau :
- DTOs Finance Workflow complets
- Validation
@ValidAmountavec min/max - Enums
BudgetPeriod,BudgetCategory TransactionApprovalResponseavec tous les champs
✅ Améliorations :
- BaseResponse avec audit fields
- ValidationConstants centralisées
- Javadoc complète pour tous les DTOs
v1.0.0 (2026-01-04)
- Version initiale
- 20+ DTOs principaux
- 10+ validators custom
📚 Documentation
Javadoc
# Générer Javadoc
mvn javadoc:javadoc
# Ouvrir
open target/site/apidocs/index.html
Ressources
- Jakarta Bean Validation: https://jakarta.ee/specifications/bean-validation/
- Maven Repository: https://git.lions.dev/lionsdev/unionflow-server-api
🤝 Contribution
- Créer une branche feature
- Ajouter DTOs/Validators avec tests
- Documenter avec Javadoc
- Pull Request avec description
📄 Licence
Propriétaire - © 2026 Lions Club Côte d'Ivoire
Version : 2.0.0 Dernière mise à jour : 2026-03-14 Auteur : Équipe UnionFlow