fix(frontend): corrections workflow v3.0 — inscription événements, CreateMembreRequest, AJAX session expiry

Services:
- EvenementService: POST /inscriptions (sans membreId), DELETE /inscriptions, GET /recherche, GET /type/{type}
- MembreService: creer() accepte CreateMembreRequest au lieu de MembreResponse
- Nouveaux services: BackupService, EpargneService, FinanceApprovalService, LogsService, MessageService, OrganisationService, PaiementClientService

Beans:
- MembreInscriptionBean: construit CreateMembreRequest.builder() avec organisationId UUID
- EvenementsBean: inscrireParticipant(id) sans userId (backend infère depuis token)
- DashboardBean: checkAccessAndRedirect() SUPER_ADMIN en premier

Sécurité:
- AuthenticationFilter: gestion AJAX PrimeFaces (partial/ajax → XML partial-response redirect)
- PermissionChecker: vérification rôles côté bean
- k8s/: manifestes secrets SMTP et Wave (placeholders à remplir)

Pages XHTML: dashboards rôles, cotisations, membres, événements, organisations
This commit is contained in:
dahoud
2026-04-07 20:54:20 +00:00
parent 0dc050f422
commit ac0c5a67a1
96 changed files with 7264 additions and 2497 deletions

View File

@@ -125,8 +125,8 @@ public class AuthenticationService {
userInfo.setPrenom("Fatou");
userInfo.setEmail("fatou.traore@association-example.sn");
userInfo.setUsername("admin");
userInfo.setTypeCompte("ADMIN_ENTITE");
userInfo.setRoles(java.util.Arrays.asList("ADMIN_ENTITE"));
userInfo.setTypeCompte("ADMIN_ORGANISATION");
userInfo.setRoles(java.util.Arrays.asList("ADMIN_ORGANISATION"));
// Entité de démonstration
LoginResponse.EntiteInfo entite = new LoginResponse.EntiteInfo();

View File

@@ -0,0 +1,55 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.backup.request.CreateBackupRequest;
import dev.lions.unionflow.server.api.dto.backup.request.RestoreBackupRequest;
import dev.lions.unionflow.server.api.dto.backup.request.UpdateBackupConfigRequest;
import dev.lions.unionflow.server.api.dto.backup.response.BackupConfigResponse;
import dev.lions.unionflow.server.api.dto.backup.response.BackupResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/backups")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface BackupService {
@GET
List<BackupResponse> listerSauvegardes(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/{id}")
BackupResponse obtenirParId(@PathParam("id") UUID id);
@POST
BackupResponse creerSauvegarde(CreateBackupRequest request);
@POST
@Path("/restore")
BackupResponse restaurer(RestoreBackupRequest request);
@DELETE
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);
@GET
@Path("/config")
BackupConfigResponse obtenirConfiguration();
@PUT
@Path("/config")
BackupConfigResponse mettreAJourConfiguration(UpdateBackupConfigRequest request);
@POST
@Path("/restore-point")
BackupResponse creerPointDeRestauration(CreateBackupRequest request);
}

View File

@@ -0,0 +1,51 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.communication.request.CreateConversationRequest;
import dev.lions.unionflow.server.api.dto.communication.response.ConversationResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/conversations")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface ConversationService {
@GET
List<ConversationResponse> listerConversations(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/{id}")
ConversationResponse obtenirParId(@PathParam("id") UUID id);
@POST
ConversationResponse creer(CreateConversationRequest request);
@PUT
@Path("/{id}/archive")
ConversationResponse archiver(
@PathParam("id") UUID id,
@QueryParam("archive") @DefaultValue("true") boolean archive
);
@PUT
@Path("/{id}/mark-read")
void marquerCommeLue(@PathParam("id") UUID id);
@PUT
@Path("/{id}/toggle-mute")
ConversationResponse basculerSilence(@PathParam("id") UUID id);
@PUT
@Path("/{id}/toggle-pin")
ConversationResponse basculerEpinglage(@PathParam("id") UUID id);
}

View File

@@ -1,6 +1,7 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.cotisation.request.CreateCotisationRequest;
import dev.lions.unionflow.server.api.dto.cotisation.request.UpdateCotisationRequest;
import dev.lions.unionflow.server.api.dto.cotisation.response.CotisationResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@@ -112,7 +113,7 @@ public interface CotisationService {
*/
@PUT
@Path("/{id}")
CotisationResponse modifier(@PathParam("id") UUID id, CotisationResponse cotisation);
CotisationResponse modifier(@PathParam("id") UUID id, UpdateCotisationRequest request);
/**
* Supprime une cotisation
@@ -121,11 +122,34 @@ public interface CotisationService {
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);
/**
* Enregistre le paiement d'une cotisation (endpoint dédié backend).
* Corps attendu : { montantPaye, datePaiement, modePaiement, reference }
*/
@PUT
@Path("/{id}/payer")
@Consumes(MediaType.APPLICATION_JSON)
CotisationResponse payer(@PathParam("id") UUID id, Map<String, Object> paiementData);
/**
* Récupère les cotisations du membre connecté (authentification JWT).
*/
@GET
@Path("/mes-cotisations")
List<CotisationResponse> getMesCotisations(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les cotisations en attente du membre connecté.
*/
@GET
@Path("/mes-cotisations/en-attente")
List<CotisationResponse> getMesCotisationsEnAttente();
/**
* Envoie des rappels de cotisations groupés à plusieurs membres (WOU/DRY)
*
* @param membreIds Liste des IDs des membres destinataires
* @return Nombre de rappels envoyés
*/
@POST
@Path("/rappels/groupes")

View File

@@ -22,6 +22,13 @@ import java.util.UUID;
@Produces(MediaType.APPLICATION_JSON)
public interface DocumentService {
/**
* Liste les documents de l'utilisateur connecté
*/
@GET
@Path("/mes-documents")
List<DocumentResponse> mesDocuments();
/**
* Crée un nouveau document
*/

View File

@@ -0,0 +1,71 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.CompteEpargneRequest;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.CompteEpargneResponse;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.TransactionEpargneRequest;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.TransactionEpargneResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/v1/epargne")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface EpargneService {
// --- Comptes ---
@POST
@Path("/comptes")
CompteEpargneResponse ouvrirCompte(CompteEpargneRequest request);
@GET
@Path("/comptes/{id}")
CompteEpargneResponse obtenirCompte(@PathParam("id") String id);
@GET
@Path("/comptes/mes-comptes")
List<CompteEpargneResponse> obtenirMesComptes();
@GET
@Path("/comptes/membre/{membreId}")
List<CompteEpargneResponse> obtenirComptesParMembre(@PathParam("membreId") String membreId);
@GET
@Path("/comptes/organisation/{organisationId}")
List<CompteEpargneResponse> obtenirComptesParOrganisation(
@PathParam("organisationId") String organisationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@PATCH
@Path("/comptes/{id}/statut")
CompteEpargneResponse changerStatut(
@PathParam("id") String id,
@QueryParam("statut") String statut
);
// --- Transactions ---
@POST
@Path("/transactions")
TransactionEpargneResponse executerTransaction(TransactionEpargneRequest request);
@POST
@Path("/transactions/transfert")
TransactionEpargneResponse effectuerTransfert(TransactionEpargneRequest request);
@GET
@Path("/transactions/compte/{compteId}")
List<TransactionEpargneResponse> obtenirTransactions(
@PathParam("compteId") String compteId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
}

View File

@@ -73,38 +73,23 @@ public interface EvenementService {
);
/**
* Recherche d'événements avec filtres
* Recherche d'événements — backend: GET /api/evenements/recherche
*/
@GET
@Path("/search")
PagedResponse<EvenementResponse> rechercher(
@QueryParam("titre") String titre,
@QueryParam("type") String type,
@QueryParam("statut") String statut,
@QueryParam("dateDebut") String dateDebut,
@QueryParam("dateFin") String dateFin,
@Path("/recherche")
List<EvenementResponse> rechercher(
@QueryParam("q") String q,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Liste les événements par statut
* Événements par type — backend: GET /api/evenements/type/{type}
*/
@GET
@Path("/statut/{statut}")
PagedResponse<EvenementResponse> listerParStatut(
@PathParam("statut") String statut,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Liste les événements par association
*/
@GET
@Path("/association/{associationId}")
PagedResponse<EvenementResponse> listerParAssociation(
@PathParam("associationId") UUID associationId,
@Path("/type/{type}")
List<EvenementResponse> listerParType(
@PathParam("type") String type,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@@ -117,19 +102,21 @@ public interface EvenementService {
Map<String, Object> compter();
/**
* Inscrit un participant à un événement
* Inscrit le membre connecté à un événement
* Backend: POST /api/evenements/{id}/inscriptions (membre résolu via SecurityIdentity)
*/
@POST
@Path("/{evenementId}/participants/{membreId}")
void inscrireParticipant(@PathParam("evenementId") UUID evenementId, @PathParam("membreId") UUID membreId);
@Path("/{evenementId}/inscriptions")
void inscrireParticipant(@PathParam("evenementId") UUID evenementId);
/**
* Désinscrit un participant d'un événement
* Désinscrit le membre connecté d'un événement
* Backend: DELETE /api/evenements/{id}/inscriptions (membre résolu via SecurityIdentity)
*/
@DELETE
@Path("/{evenementId}/participants/{membreId}")
void desinscrireParticipant(@PathParam("evenementId") UUID evenementId, @PathParam("membreId") UUID membreId);
@Path("/{evenementId}/inscriptions")
void desinscrireParticipant(@PathParam("evenementId") UUID evenementId);
/**
* Liste les participants d'un événement
*/

View File

@@ -0,0 +1,102 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.finance_workflow.request.ApproveTransactionRequest;
import dev.lions.unionflow.server.api.dto.finance_workflow.request.CreateBudgetRequest;
import dev.lions.unionflow.server.api.dto.finance_workflow.request.RejectTransactionRequest;
import dev.lions.unionflow.server.api.dto.finance_workflow.response.BudgetResponse;
import dev.lions.unionflow.server.api.dto.finance_workflow.response.TransactionApprovalResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/finance")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface FinanceApprovalService {
// --- Approbations ---
@GET
@Path("/approvals/pending")
List<TransactionApprovalResponse> obtenirApprobationsEnAttente(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/approvals/{approvalId}")
TransactionApprovalResponse obtenirApprobation(@PathParam("approvalId") UUID approvalId);
@POST
@Path("/approvals/{approvalId}/approve")
TransactionApprovalResponse approuver(
@PathParam("approvalId") UUID approvalId,
ApproveTransactionRequest request
);
@POST
@Path("/approvals/{approvalId}/reject")
TransactionApprovalResponse rejeter(
@PathParam("approvalId") UUID approvalId,
RejectTransactionRequest request
);
@GET
@Path("/approvals/history")
List<TransactionApprovalResponse> obtenirHistorique(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate,
@QueryParam("status") String status,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/approvals/count/pending")
Map<String, Long> compterEnAttente(@QueryParam("organizationId") UUID organizationId);
// --- Budgets ---
@GET
@Path("/budgets")
List<BudgetResponse> listerBudgets(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/budgets/{budgetId}")
BudgetResponse obtenirBudget(@PathParam("budgetId") UUID budgetId);
@POST
@Path("/budgets")
BudgetResponse creerBudget(CreateBudgetRequest request);
@PUT
@Path("/budgets/{budgetId}")
BudgetResponse modifierBudget(@PathParam("budgetId") UUID budgetId, CreateBudgetRequest request);
@DELETE
@Path("/budgets/{budgetId}")
void supprimerBudget(@PathParam("budgetId") UUID budgetId);
// --- Statistiques workflow ---
@GET
@Path("/stats")
Map<String, Object> obtenirStatistiques(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate
);
}

View File

@@ -0,0 +1,63 @@
package dev.lions.unionflow.client.service;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface LogsService {
@GET
@Path("/logs/search")
List<Map<String, Object>> rechercherLogs(
@QueryParam("level") String level,
@QueryParam("source") String source,
@QueryParam("userId") String userId,
@QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate,
@QueryParam("keyword") String keyword,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("50") int size
);
@GET
@Path("/finance/audit-logs")
List<Map<String, Object>> obtenirLogsAuditFinance(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate,
@QueryParam("operation") String operation,
@QueryParam("entityType") String entityType,
@QueryParam("severity") String severity,
@QueryParam("limit") @DefaultValue("100") int limit
);
@GET
@Path("/finance/audit-logs/anomalies")
List<Map<String, Object>> obtenirAnomalies(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate
);
@POST
@Path("/finance/audit-logs/export")
byte[] exporterLogsAudit(Map<String, Object> request);
@GET
@Path("/monitoring/metrics")
Map<String, Object> obtenirMetriques();
@GET
@Path("/v1/dashboard/health")
Map<String, Object> obtenirSanteSysteme();
}

View File

@@ -1,7 +1,9 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.common.PagedResponse;
import dev.lions.unionflow.server.api.dto.membre.request.CreateMembreRequest;
import dev.lions.unionflow.server.api.dto.membre.response.MembreResponse;
import dev.lions.unionflow.server.api.dto.membre.response.MembreSummaryResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
@@ -17,7 +19,14 @@ import java.util.UUID;
public interface MembreService {
@GET
PagedResponse<MembreResponse> listerTous();
PagedResponse<MembreSummaryResponse> listerTous(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size);
/** Surcharge sans pagination — retourne jusqu'à 1000 membres (usage hors DataTable). */
default PagedResponse<MembreSummaryResponse> listerTous() {
return listerTous(0, 1000);
}
@GET
@Path("/{id}")
@@ -53,8 +62,8 @@ public interface MembreService {
@QueryParam("direction") @DefaultValue("asc") String sortDirection);
@GET
@Path("/association/{associationId}")
List<MembreResponse> listerParAssociation(@PathParam("associationId") UUID associationId);
@Path("/organisation/{organisationId}")
List<MembreResponse> listerParOrganisation(@PathParam("organisationId") UUID organisationId);
@GET
@Path("/actifs")
@@ -65,7 +74,7 @@ public interface MembreService {
List<MembreResponse> listerInactifs();
@POST
MembreResponse creer(MembreResponse membre);
MembreResponse creer(CreateMembreRequest membre);
@PUT
@Path("/{id}")
@@ -137,6 +146,46 @@ public interface MembreService {
@Path("/autocomplete/villes")
List<String> obtenirVilles(@QueryParam("query") String query);
@GET
@Path("/mes-organisations")
List<OrganisationSwitcherDTO> mesOrganisations();
// ── Cycle de vie des adhésions ─────────────────────────────────────────
@GET
@Path("/{membreId}/adhesion")
@SuppressWarnings("unchecked")
java.util.Map<String, Object> getAdhesionStatut(@PathParam("membreId") UUID membreId,
@QueryParam("organisationId") UUID organisationId);
@PUT
@Path("/{membreId}/inviter-organisation")
java.util.Map<String, Object> inviterMembreOrg(@PathParam("membreId") UUID membreId,
@QueryParam("organisationId") UUID organisationId,
@QueryParam("roleOrg") String roleOrg);
@POST
@Path("/accepter-invitation/{token}")
java.util.Map<String, Object> accepterInvitation(@PathParam("token") String token);
@PUT
@Path("/{membreId}/adhesion/activer")
java.util.Map<String, Object> activerAdhesion(@PathParam("membreId") UUID membreId,
@QueryParam("organisationId") UUID organisationId,
java.util.Map<String, String> body);
@PUT
@Path("/{membreId}/adhesion/suspendre")
java.util.Map<String, Object> suspendrAdhesion(@PathParam("membreId") UUID membreId,
@QueryParam("organisationId") UUID organisationId,
java.util.Map<String, String> body);
@PUT
@Path("/{membreId}/adhesion/radier")
java.util.Map<String, Object> radierAdhesion(@PathParam("membreId") UUID membreId,
@QueryParam("organisationId") UUID organisationId,
java.util.Map<String, String> body);
@GET
@Path("/autocomplete/professions")
List<String> obtenirProfessions(@QueryParam("query") String query);
@@ -150,6 +199,52 @@ public interface MembreService {
@QueryParam("format") @DefaultValue("EXCEL") String format);
// Classes DTO internes pour les réponses spécialisées
/**
* DTO pour le sélecteur d'organisation (multi-org switcher).
* Mappé depuis GET /api/membres/mes-organisations.
*/
class OrganisationSwitcherDTO implements java.io.Serializable {
public String organisationId;
public String nom;
public String nomCourt;
public String typeOrganisation;
public String categorieType;
public String modulesActifs;
public String statut;
public String statutMembre;
public String roleOrg;
public String dateAdhesion;
public String getOrganisationId() { return organisationId; }
public void setOrganisationId(String v) { this.organisationId = v; }
public String getNom() { return nom; }
public void setNom(String v) { this.nom = v; }
public String getNomCourt() { return nomCourt; }
public void setNomCourt(String v) { this.nomCourt = v; }
public String getTypeOrganisation() { return typeOrganisation; }
public void setTypeOrganisation(String v) { this.typeOrganisation = v; }
public String getCategorieType() { return categorieType; }
public void setCategorieType(String v) { this.categorieType = v; }
public String getModulesActifs() { return modulesActifs; }
public void setModulesActifs(String v) { this.modulesActifs = v; }
public String getStatut() { return statut; }
public void setStatut(String v) { this.statut = v; }
public String getStatutMembre() { return statutMembre; }
public void setStatutMembre(String v) { this.statutMembre = v; }
public String getRoleOrg() { return roleOrg; }
public void setRoleOrg(String v) { this.roleOrg = v; }
public String getDateAdhesion() { return dateAdhesion; }
public void setDateAdhesion(String v) { this.dateAdhesion = v; }
/** Retourne le libellé court à afficher dans le switcher. */
public String getLibelleCourt() {
if (nomCourt != null && !nomCourt.isBlank()) return nomCourt;
if (nom != null && nom.length() > 25) return nom.substring(0, 22) + "";
return nom;
}
}
class StatistiquesMembreDTO {
public Long totalMembres;
public Long membresActifs;

View File

@@ -0,0 +1,41 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.communication.request.SendMessageRequest;
import dev.lions.unionflow.server.api.dto.communication.response.MessageResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/messages")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface MessageService {
@GET
List<MessageResponse> listerMessages(
@QueryParam("conversationId") UUID conversationId,
@QueryParam("limit") @DefaultValue("50") int limit
);
@POST
MessageResponse envoyer(SendMessageRequest request);
@PUT
@Path("/{id}")
MessageResponse modifier(@PathParam("id") UUID id, Map<String, String> body);
@DELETE
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);
@POST
@Path("/broadcast")
MessageResponse diffuser(SendMessageRequest request);
}

View File

@@ -4,11 +4,13 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
/**
* Service REST client pour les notifications
* Client REST pour l'envoi de notifications groupées.
* Seul endpoint utilisé côté web : POST /api/notifications/groupees.
*
* Pour les opérations de lecture/marquage, utiliser {@link NotificationService}.
*/
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@@ -16,40 +18,13 @@ import java.util.Map;
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface NotificationClientService {
@POST
@Path("/groupe")
List<Map<String, Object>> envoyerNotificationGroupe(
@QueryParam("type") String type,
@QueryParam("titre") String titre,
@QueryParam("message") String message,
List<String> destinatairesIds
);
@GET
@Path("/utilisateur/{utilisateurId}")
List<Map<String, Object>> obtenirNotifications(
@PathParam("utilisateurId") String utilisateurId,
@QueryParam("includeArchivees") @DefaultValue("false") boolean includeArchivees,
@QueryParam("limite") @DefaultValue("50") int limite
);
@PUT
@Path("/{notificationId}/lue")
Map<String, Object> marquerCommeLue(
@PathParam("notificationId") String notificationId,
@QueryParam("utilisateurId") String utilisateurId
);
@GET
@Path("/stats")
Map<String, Long> obtenirStatistiques();
@POST
@Path("/test/{utilisateurId}")
Map<String, Object> envoyerNotificationTest(
@PathParam("utilisateurId") String utilisateurId,
@QueryParam("type") @DefaultValue("SYSTEME") String type
);
}
/**
* Envoie des notifications groupées à plusieurs membres.
* Body attendu : {@code { sujet, corps, membreIds: [UUID], canaux: [String] (optionnel) }}
* Retourne : {@code { notificationsCreees: int }}
*/
@POST
@Path("/groupees")
Map<String, Integer> envoyerNotificationGroupe(Map<String, Object> request);
}

View File

@@ -2,6 +2,7 @@ package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.common.PagedResponse;
import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationResponse;
import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationSummaryResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
@@ -14,10 +15,10 @@ import java.util.UUID;
@Path("/api/organisations")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface AssociationService {
public interface OrganisationService {
@GET
PagedResponse<OrganisationResponse> listerToutes(
PagedResponse<OrganisationSummaryResponse> listerToutes(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("1000") int size);
@@ -27,7 +28,7 @@ public interface AssociationService {
@GET
@Path("/recherche")
PagedResponse<OrganisationResponse> rechercher(
PagedResponse<OrganisationSummaryResponse> rechercher(
@QueryParam("nom") String nom,
@QueryParam("type") String type,
@QueryParam("statut") String statut,
@@ -38,18 +39,18 @@ public interface AssociationService {
@GET
@Path("/type/{type}")
List<OrganisationResponse> listerParType(@PathParam("type") String type);
List<OrganisationSummaryResponse> listerParType(@PathParam("type") String type);
@GET
@Path("/region/{region}")
List<OrganisationResponse> listerParRegion(@PathParam("region") String region);
List<OrganisationSummaryResponse> listerParRegion(@PathParam("region") String region);
@POST
OrganisationResponse creer(OrganisationResponse association);
OrganisationResponse creer(OrganisationResponse organisation);
@PUT
@Path("/{id}")
OrganisationResponse modifier(@PathParam("id") UUID id, OrganisationResponse association);
OrganisationResponse modifier(@PathParam("id") UUID id, OrganisationResponse organisation);
@DELETE
@Path("/{id}")
@@ -71,7 +72,7 @@ public interface AssociationService {
@GET
@Path("/statistiques")
StatistiquesAssociationDTO obtenirStatistiques();
StatistiquesOrganisationDTO obtenirStatistiques();
@GET
@Path("/{id}/membres/count")
@@ -79,10 +80,10 @@ public interface AssociationService {
@GET
@Path("/{id}/performance")
PerformanceAssociationDTO obtenirPerformance(@PathParam("id") UUID id);
PerformanceOrganisationDTO obtenirPerformance(@PathParam("id") UUID id);
// Classes DTO internes
class StatistiquesAssociationDTO {
class StatistiquesOrganisationDTO {
public Long totalAssociations;
public Long associationsActives;
public Long associationsInactives;
@@ -94,7 +95,7 @@ public interface AssociationService {
public java.util.Map<String, Long> repartitionParRegion;
// Constructeurs
public StatistiquesAssociationDTO() {
public StatistiquesOrganisationDTO() {
}
// Getters et setters
@@ -171,8 +172,8 @@ public interface AssociationService {
}
}
class PerformanceAssociationDTO {
public UUID associationId;
class PerformanceOrganisationDTO {
public UUID organisationId;
public String nom;
public Integer scoreGlobal;
public Integer scoreMembres;
@@ -182,16 +183,16 @@ public interface AssociationService {
public java.time.LocalDateTime derniereMiseAJour;
// Constructeurs
public PerformanceAssociationDTO() {
public PerformanceOrganisationDTO() {
}
// Getters et setters
public UUID getAssociationId() {
return associationId;
public UUID getOrganisationId() {
return organisationId;
}
public void setAssociationId(UUID associationId) {
this.associationId = associationId;
public void setOrganisationId(UUID organisationId) {
this.organisationId = organisationId;
}
public String getNom() {

View File

@@ -0,0 +1,39 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.paiement.request.InitierPaiementEnLigneRequest;
import dev.lions.unionflow.server.api.dto.paiement.response.IntentionStatutResponse;
import dev.lions.unionflow.server.api.dto.paiement.response.PaiementGatewayResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.UUID;
/**
* Client REST pour les paiements en ligne (Wave Checkout QR).
*/
@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/paiements")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface PaiementClientService {
/**
* Initie un paiement Wave et retourne le wave_launch_url à encoder en QR code.
* Sur le web, laisser {@code numeroTelephone} null → pas de restriction de payeur.
*/
@POST
@Path("/initier-paiement-en-ligne")
PaiementGatewayResponse initierPaiementEnLigne(InitierPaiementEnLigneRequest request);
/**
* Polling du statut d'une intention Wave.
* Si Wave a confirmé, retourne statut=COMPLETEE et la cotisation est marquée PAYEE.
*
* @param intentionId UUID retourné dans {@code clientReference} de {@link PaiementGatewayResponse}
*/
@GET
@Path("/statut-intention/{intentionId}")
IntentionStatutResponse getStatutIntention(@PathParam("intentionId") UUID intentionId);
}

View File

@@ -24,7 +24,7 @@ import java.util.function.Supplier;
* RetryService retryService;
*
* OrganisationResponse org = retryService.executeWithRetry(
* () -> associationService.creer(nouvelleOrganisation),
* () -> organisationService.creer(nouvelleOrganisation),
* "création d'une organisation"
* );
* }</pre>

View File

@@ -1,6 +1,6 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.server.api.dto.abonnement.response.AbonnementResponse;
import dev.lions.unionflow.server.api.dto.souscription.SouscriptionStatutResponse;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import jakarta.ws.rs.*;
@@ -14,35 +14,29 @@ import java.util.UUID;
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface SouscriptionService {
/** Liste toutes les souscriptions — SUPER_ADMIN. Filtre par org si organisationId non null. */
@GET
List<AbonnementResponse> listerToutes(
@Path("/admin/toutes")
List<SouscriptionStatutResponse> listerToutes(
@QueryParam("organisationId") UUID organisationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
@QueryParam("size") @DefaultValue("1000") int size
);
/** Souscription active d'une organisation spécifique — SUPER_ADMIN. */
@GET
@Path("/{id}")
AbonnementResponse obtenirParId(@PathParam("id") UUID id);
@Path("/admin/organisation/{organisationId}/active")
SouscriptionStatutResponse obtenirActive(@PathParam("organisationId") UUID organisationId);
/** Souscriptions en attente de validation — SUPER_ADMIN. */
@GET
@Path("/organisation/{organisationId}/active")
AbonnementResponse obtenirActive(@PathParam("organisationId") UUID organisationId);
@POST
AbonnementResponse creer(AbonnementResponse souscription);
@PUT
@Path("/{id}")
AbonnementResponse modifier(@PathParam("id") UUID id, AbonnementResponse souscription);
@DELETE
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);
@PUT
@Path("/{id}/renouveler")
AbonnementResponse renouveler(@PathParam("id") UUID id);
@Path("/admin/en-attente")
List<SouscriptionStatutResponse> listerEnAttente();
/** Souscription de l'organisation du membre connecté. */
@GET
@Path("/ma-souscription")
SouscriptionStatutResponse getMaSouscription();
}