Files
unionflow-server-api/README.md
dahoud 32823206db Initial commit: unionflow-server-api
Code source complet à la racine du repository.

Signed-off-by: lions dev Team
2026-03-15 16:23:37 +00:00

13 KiB

UnionFlow Server API - DTOs et Contrats

Java Maven License

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 transaction
  • BudgetResponse - Budget avec lignes budgétaires
  • AdhesionResponse - Adhésion membre

Membres

  • MembreResponse - Détails membre complets
  • MembreSummaryResponse - Résumé membre (liste)
  • CreateMembreRequest - Création membre
  • UpdateMembreRequest - Modification membre

Cotisations

  • CotisationResponse - Cotisation avec détails
  • CreateCotisationRequest - Enregistrement cotisation
  • CotisationStatisticsResponse - Statistiques cotisations

Notifications

  • NotificationResponse - Notification utilisateur
  • MarkAsReadRequest - 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 @ValidAmount avec min/max
  • Enums BudgetPeriod, BudgetCategory
  • TransactionApprovalResponse avec 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


🤝 Contribution

  1. Créer une branche feature
  2. Ajouter DTOs/Validators avec tests
  3. Documenter avec Javadoc
  4. 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