package dev.lions.unionflow.server.resource; import dev.lions.unionflow.server.common.ErrorResponse; import dev.lions.unionflow.server.api.dto.wave.CompteWaveDTO; import dev.lions.unionflow.server.api.dto.wave.TransactionWaveDTO; import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave; import dev.lions.unionflow.server.service.WaveService; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.validation.Valid; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.UUID; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.jboss.logging.Logger; /** * Resource REST pour l'intégration Wave Mobile Money * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @Path("/api/wave") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE", "USER" }) @Tag(name = "Wave Mobile Money", description = "Gestion des comptes et transactions Wave Mobile Money") public class WaveResource { private static final Logger LOG = Logger.getLogger(WaveResource.class); @Inject WaveService waveService; // ======================================== // COMPTES WAVE // ======================================== @POST @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE" }) @Path("/comptes") @Operation(summary = "Créer un compte Wave", description = "Crée un nouveau compte Wave pour un membre ou une organisation") @APIResponses({ @APIResponse(responseCode = "201", description = "Compte Wave créé avec succès"), @APIResponse(responseCode = "400", description = "Données invalides") }) public Response creerCompteWave(@Valid CompteWaveDTO compteWaveDTO) { try { CompteWaveDTO result = waveService.creerCompteWave(compteWaveDTO); return Response.status(Response.Status.CREATED).entity(result).build(); } catch (IllegalArgumentException e) { return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError(e.getMessage())) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la création du compte Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la création du compte Wave: " + e.getMessage())) .build(); } } @PUT @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE" }) @Path("/comptes/{id}") @Operation(summary = "Mettre à jour un compte Wave", description = "Met à jour les informations d'un compte Wave existant") @APIResponses({ @APIResponse(responseCode = "200", description = "Compte Wave mis à jour"), @APIResponse(responseCode = "404", description = "Compte Wave non trouvé"), @APIResponse(responseCode = "400", description = "Données invalides") }) public Response mettreAJourCompteWave( @Parameter(description = "UUID du compte Wave", required = true) @PathParam("id") UUID id, @Valid CompteWaveDTO compteWaveDTO) { try { CompteWaveDTO result = waveService.mettreAJourCompteWave(id, compteWaveDTO); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(ErrorResponse.ofError("Compte Wave non trouvé")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la mise à jour du compte Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la mise à jour du compte Wave: " + e.getMessage())) .build(); } } @POST @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE" }) @Path("/comptes/{id}/verifier") @Operation(summary = "Vérifier un compte Wave", description = "Vérifie la validité d'un compte Wave") @APIResponses({ @APIResponse(responseCode = "200", description = "Compte Wave vérifié"), @APIResponse(responseCode = "404", description = "Compte Wave non trouvé"), @APIResponse(responseCode = "400", description = "Erreur de vérification") }) public Response verifierCompteWave( @Parameter(description = "UUID du compte Wave", required = true) @PathParam("id") UUID id) { try { CompteWaveDTO result = waveService.verifierCompteWave(id); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(ErrorResponse.ofError("Compte Wave non trouvé")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la vérification du compte Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la vérification du compte Wave: " + e.getMessage())) .build(); } } @GET @Path("/comptes/{id}") @Operation(summary = "Trouver un compte Wave par ID", description = "Recherche un compte Wave par son identifiant unique") @APIResponses({ @APIResponse(responseCode = "200", description = "Compte Wave trouvé"), @APIResponse(responseCode = "404", description = "Compte Wave non trouvé") }) public Response trouverCompteWaveParId( @Parameter(description = "UUID du compte Wave", required = true) @PathParam("id") UUID id) { try { CompteWaveDTO result = waveService.trouverCompteWaveParId(id); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(ErrorResponse.ofError("Compte Wave non trouvé")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la recherche du compte Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la recherche du compte Wave: " + e.getMessage())) .build(); } } @GET @Path("/comptes/telephone/{numeroTelephone}") @Operation(summary = "Trouver un compte Wave par téléphone", description = "Recherche un compte Wave par numéro de téléphone") @APIResponses({ @APIResponse(responseCode = "200", description = "Compte Wave trouvé"), @APIResponse(responseCode = "404", description = "Compte Wave non trouvé pour ce numéro") }) public Response trouverCompteWaveParTelephone( @Parameter(description = "Numéro de téléphone associé au compte Wave", required = true) @PathParam("numeroTelephone") String numeroTelephone) { try { CompteWaveDTO result = waveService.trouverCompteWaveParTelephone(numeroTelephone); if (result == null) { return Response.status(Response.Status.NOT_FOUND) .entity(ErrorResponse.ofError("Compte Wave non trouvé")) .build(); } return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la recherche du compte Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la recherche du compte Wave: " + e.getMessage())) .build(); } } @GET @Path("/comptes/organisation/{organisationId}") @Operation(summary = "Lister les comptes Wave d'une organisation", description = "Retourne tous les comptes Wave associés à une organisation") @APIResponses({ @APIResponse(responseCode = "200", description = "Liste des comptes Wave"), @APIResponse(responseCode = "400", description = "Erreur lors de la récupération") }) public Response listerComptesWaveParOrganisation( @Parameter(description = "UUID de l'organisation", required = true) @PathParam("organisationId") UUID organisationId) { try { List result = waveService.listerComptesWaveParOrganisation(organisationId); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la liste des comptes Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la liste des comptes Wave: " + e.getMessage())) .build(); } } // ======================================== // TRANSACTIONS WAVE // ======================================== @POST @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE" }) @Path("/transactions") @Operation(summary = "Créer une transaction Wave", description = "Initie une nouvelle transaction de paiement Wave") @APIResponses({ @APIResponse(responseCode = "201", description = "Transaction Wave créée"), @APIResponse(responseCode = "400", description = "Données invalides ou erreur de traitement") }) public Response creerTransactionWave(@Valid TransactionWaveDTO transactionWaveDTO) { try { TransactionWaveDTO result = waveService.creerTransactionWave(transactionWaveDTO); return Response.status(Response.Status.CREATED).entity(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la création de la transaction Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la création de la transaction Wave: " + e.getMessage())) .build(); } } @PUT @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE" }) @Path("/transactions/{waveTransactionId}/statut") @Operation(summary = "Mettre à jour le statut d'une transaction", description = "Met à jour le statut d'une transaction Wave (ex: COMPLETED, FAILED)") @APIResponses({ @APIResponse(responseCode = "200", description = "Statut mis à jour"), @APIResponse(responseCode = "404", description = "Transaction non trouvée"), @APIResponse(responseCode = "400", description = "Erreur de mise à jour") }) public Response mettreAJourStatutTransaction( @Parameter(description = "Identifiant Wave de la transaction", required = true) @PathParam("waveTransactionId") String waveTransactionId, StatutTransactionWave statut) { try { TransactionWaveDTO result = waveService.mettreAJourStatutTransaction(waveTransactionId, statut); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(ErrorResponse.ofError("Transaction Wave non trouvée")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la mise à jour du statut de la transaction Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la mise à jour du statut de la transaction Wave: " + e.getMessage())) .build(); } } @GET @Path("/transactions/{waveTransactionId}") @Operation(summary = "Trouver une transaction Wave", description = "Recherche une transaction Wave par son identifiant Wave") @APIResponses({ @APIResponse(responseCode = "200", description = "Transaction trouvée"), @APIResponse(responseCode = "404", description = "Transaction non trouvée") }) public Response trouverTransactionWaveParId( @Parameter(description = "Identifiant Wave de la transaction", required = true) @PathParam("waveTransactionId") String waveTransactionId) { try { TransactionWaveDTO result = waveService.trouverTransactionWaveParId(waveTransactionId); return Response.ok(result).build(); } catch (jakarta.ws.rs.NotFoundException e) { return Response.status(Response.Status.NOT_FOUND) .entity(ErrorResponse.ofError("Transaction Wave non trouvée")) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur lors de la recherche de la transaction Wave"); return Response.status(Response.Status.BAD_REQUEST) .entity(ErrorResponse.ofError("Erreur lors de la recherche de la transaction Wave: " + e.getMessage())) .build(); } } }