package dev.lions.unionflow.server.service; import dev.lions.unionflow.server.api.dto.paiement.PaiementDTO; import dev.lions.unionflow.server.api.enums.paiement.StatutPaiement; import dev.lions.unionflow.server.entity.Membre; import dev.lions.unionflow.server.entity.Paiement; import dev.lions.unionflow.server.repository.MembreRepository; import dev.lions.unionflow.server.repository.PaiementRepository; import dev.lions.unionflow.server.service.KeycloakService; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.NotFoundException; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; import org.jboss.logging.Logger; /** * Service métier pour la gestion des paiements * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @ApplicationScoped public class PaiementService { private static final Logger LOG = Logger.getLogger(PaiementService.class); @Inject PaiementRepository paiementRepository; @Inject MembreRepository membreRepository; @Inject KeycloakService keycloakService; /** * Crée un nouveau paiement * * @param paiementDTO DTO du paiement à créer * @return DTO du paiement créé */ @Transactional public PaiementDTO creerPaiement(PaiementDTO paiementDTO) { LOG.infof("Création d'un nouveau paiement: %s", paiementDTO.getNumeroReference()); Paiement paiement = convertToEntity(paiementDTO); paiement.setCreePar(keycloakService.getCurrentUserEmail()); paiementRepository.persist(paiement); LOG.infof("Paiement créé avec succès: ID=%s, Référence=%s", paiement.getId(), paiement.getNumeroReference()); return convertToDTO(paiement); } /** * Met à jour un paiement existant * * @param id ID du paiement * @param paiementDTO DTO avec les modifications * @return DTO du paiement mis à jour */ @Transactional public PaiementDTO mettreAJourPaiement(UUID id, PaiementDTO paiementDTO) { LOG.infof("Mise à jour du paiement ID: %s", id); Paiement paiement = paiementRepository .findPaiementById(id) .orElseThrow(() -> new NotFoundException("Paiement non trouvé avec l'ID: " + id)); if (!paiement.peutEtreModifie()) { throw new IllegalStateException("Le paiement ne peut plus être modifié (statut finalisé)"); } updateFromDTO(paiement, paiementDTO); paiement.setModifiePar(keycloakService.getCurrentUserEmail()); paiementRepository.persist(paiement); LOG.infof("Paiement mis à jour avec succès: ID=%s", id); return convertToDTO(paiement); } /** * Valide un paiement * * @param id ID du paiement * @return DTO du paiement validé */ @Transactional public PaiementDTO validerPaiement(UUID id) { LOG.infof("Validation du paiement ID: %s", id); Paiement paiement = paiementRepository .findPaiementById(id) .orElseThrow(() -> new NotFoundException("Paiement non trouvé avec l'ID: " + id)); if (paiement.isValide()) { LOG.warnf("Le paiement ID=%s est déjà validé", id); return convertToDTO(paiement); } paiement.setStatutPaiement(StatutPaiement.VALIDE); paiement.setDateValidation(LocalDateTime.now()); paiement.setValidateur(keycloakService.getCurrentUserEmail()); paiement.setModifiePar(keycloakService.getCurrentUserEmail()); paiementRepository.persist(paiement); LOG.infof("Paiement validé avec succès: ID=%s", id); return convertToDTO(paiement); } /** * Annule un paiement * * @param id ID du paiement * @return DTO du paiement annulé */ @Transactional public PaiementDTO annulerPaiement(UUID id) { LOG.infof("Annulation du paiement ID: %s", id); Paiement paiement = paiementRepository .findPaiementById(id) .orElseThrow(() -> new NotFoundException("Paiement non trouvé avec l'ID: " + id)); if (!paiement.peutEtreModifie()) { throw new IllegalStateException("Le paiement ne peut plus être annulé (statut finalisé)"); } paiement.setStatutPaiement(StatutPaiement.ANNULE); paiement.setModifiePar(keycloakService.getCurrentUserEmail()); paiementRepository.persist(paiement); LOG.infof("Paiement annulé avec succès: ID=%s", id); return convertToDTO(paiement); } /** * Trouve un paiement par son ID * * @param id ID du paiement * @return DTO du paiement */ public PaiementDTO trouverParId(UUID id) { return paiementRepository .findPaiementById(id) .map(this::convertToDTO) .orElseThrow(() -> new NotFoundException("Paiement non trouvé avec l'ID: " + id)); } /** * Trouve un paiement par son numéro de référence * * @param numeroReference Numéro de référence * @return DTO du paiement */ public PaiementDTO trouverParNumeroReference(String numeroReference) { return paiementRepository .findByNumeroReference(numeroReference) .map(this::convertToDTO) .orElseThrow(() -> new NotFoundException("Paiement non trouvé avec la référence: " + numeroReference)); } /** * Liste tous les paiements d'un membre * * @param membreId ID du membre * @return Liste des paiements */ public List listerParMembre(UUID membreId) { return paiementRepository.findByMembreId(membreId).stream() .map(this::convertToDTO) .collect(Collectors.toList()); } /** * Calcule le montant total des paiements validés dans une période * * @param dateDebut Date de début * @param dateFin Date de fin * @return Montant total */ public BigDecimal calculerMontantTotalValides(LocalDateTime dateDebut, LocalDateTime dateFin) { return paiementRepository.calculerMontantTotalValides(dateDebut, dateFin); } // ======================================== // MÉTHODES PRIVÉES // ======================================== /** Convertit une entité en DTO */ private PaiementDTO convertToDTO(Paiement paiement) { if (paiement == null) { return null; } PaiementDTO dto = new PaiementDTO(); dto.setId(paiement.getId()); dto.setNumeroReference(paiement.getNumeroReference()); dto.setMontant(paiement.getMontant()); dto.setCodeDevise(paiement.getCodeDevise()); dto.setMethodePaiement(paiement.getMethodePaiement()); dto.setStatutPaiement(paiement.getStatutPaiement()); dto.setDatePaiement(paiement.getDatePaiement()); dto.setDateValidation(paiement.getDateValidation()); dto.setValidateur(paiement.getValidateur()); dto.setReferenceExterne(paiement.getReferenceExterne()); dto.setUrlPreuve(paiement.getUrlPreuve()); dto.setCommentaire(paiement.getCommentaire()); dto.setIpAddress(paiement.getIpAddress()); dto.setUserAgent(paiement.getUserAgent()); if (paiement.getMembre() != null) { dto.setMembreId(paiement.getMembre().getId()); } if (paiement.getTransactionWave() != null) { dto.setTransactionWaveId(paiement.getTransactionWave().getId()); } dto.setDateCreation(paiement.getDateCreation()); dto.setDateModification(paiement.getDateModification()); dto.setActif(paiement.getActif()); return dto; } /** Convertit un DTO en entité */ private Paiement convertToEntity(PaiementDTO dto) { if (dto == null) { return null; } Paiement paiement = new Paiement(); paiement.setNumeroReference(dto.getNumeroReference()); paiement.setMontant(dto.getMontant()); paiement.setCodeDevise(dto.getCodeDevise()); paiement.setMethodePaiement(dto.getMethodePaiement()); paiement.setStatutPaiement(dto.getStatutPaiement() != null ? dto.getStatutPaiement() : StatutPaiement.EN_ATTENTE); paiement.setDatePaiement(dto.getDatePaiement()); paiement.setDateValidation(dto.getDateValidation()); paiement.setValidateur(dto.getValidateur()); paiement.setReferenceExterne(dto.getReferenceExterne()); paiement.setUrlPreuve(dto.getUrlPreuve()); paiement.setCommentaire(dto.getCommentaire()); paiement.setIpAddress(dto.getIpAddress()); paiement.setUserAgent(dto.getUserAgent()); // Relation Membre if (dto.getMembreId() != null) { Membre membre = membreRepository .findByIdOptional(dto.getMembreId()) .orElseThrow(() -> new NotFoundException("Membre non trouvé avec l'ID: " + dto.getMembreId())); paiement.setMembre(membre); } // Relation TransactionWave sera gérée par WaveService return paiement; } /** Met à jour une entité à partir d'un DTO */ private void updateFromDTO(Paiement paiement, PaiementDTO dto) { if (dto.getMontant() != null) { paiement.setMontant(dto.getMontant()); } if (dto.getCodeDevise() != null) { paiement.setCodeDevise(dto.getCodeDevise()); } if (dto.getMethodePaiement() != null) { paiement.setMethodePaiement(dto.getMethodePaiement()); } if (dto.getStatutPaiement() != null) { paiement.setStatutPaiement(dto.getStatutPaiement()); } if (dto.getDatePaiement() != null) { paiement.setDatePaiement(dto.getDatePaiement()); } if (dto.getDateValidation() != null) { paiement.setDateValidation(dto.getDateValidation()); } if (dto.getValidateur() != null) { paiement.setValidateur(dto.getValidateur()); } if (dto.getReferenceExterne() != null) { paiement.setReferenceExterne(dto.getReferenceExterne()); } if (dto.getUrlPreuve() != null) { paiement.setUrlPreuve(dto.getUrlPreuve()); } if (dto.getCommentaire() != null) { paiement.setCommentaire(dto.getCommentaire()); } if (dto.getIpAddress() != null) { paiement.setIpAddress(dto.getIpAddress()); } if (dto.getUserAgent() != null) { paiement.setUserAgent(dto.getUserAgent()); } } }