package com.astalange.web.controller; import com.astalange.core.entity.Licence; import com.astalange.core.entity.ModePaiement; import com.astalange.core.entity.Paiement; import com.astalange.core.entity.AuditLogPaiement; import com.astalange.core.repository.AuditLogPaiementRepository; import com.astalange.core.repository.LicenceRepository; import com.astalange.core.repository.ModePaiementRepository; import com.astalange.core.repository.PaiementRepository; import com.astalange.core.service.PaiementEmailService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import java.security.Principal; import java.math.BigDecimal; import java.time.LocalDate; @Controller public class PaiementController { private static final Logger log = LoggerFactory.getLogger(PaiementController.class); private final LicenceRepository licenceRepository; private final ModePaiementRepository modePaiementRepository; private final PaiementRepository paiementRepository; private final AuditLogPaiementRepository auditLogPaiementRepository; private final PaiementEmailService paiementEmailService; public PaiementController(LicenceRepository licenceRepository, ModePaiementRepository modePaiementRepository, PaiementRepository paiementRepository, AuditLogPaiementRepository auditLogPaiementRepository, PaiementEmailService paiementEmailService) { this.licenceRepository = licenceRepository; this.modePaiementRepository = modePaiementRepository; this.paiementRepository = paiementRepository; this.auditLogPaiementRepository = auditLogPaiementRepository; this.paiementEmailService = paiementEmailService; } @PostMapping("/licences/{id}/paiements") public String addPaiement( @PathVariable Long id, @RequestParam Long adherentId, @RequestParam BigDecimal montant, @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate datePaiement, @RequestParam Long modePaiementId, @RequestParam(required = false) String numeroCheque, @RequestParam(required = false, defaultValue = "true") Boolean remis, @RequestParam(required = false) String commentaire, Principal principal) { Licence licence = licenceRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Licence ID")); ModePaiement mode = modePaiementRepository.findById(modePaiementId) .orElseThrow(() -> new IllegalArgumentException("Invalid ModePaiement ID")); log.info(">>> [PaiementController] Demande de création de paiement reçue pour Licence ID: {}, Adhérent ID: {}, Montant: {} €, Remis: {}", id, adherentId, montant, remis); // Validation basique pour ne pas payer plus que le reste à payer if (montant.compareTo(licence.getResteAPayer()) > 0) { montant = licence.getResteAPayer(); } if (montant.compareTo(BigDecimal.ZERO) > 0) { Paiement paiement = new Paiement(); paiement.setLicence(licence); paiement.setModePaiement(mode); paiement.setMontant(montant); paiement.setDatePaiement(datePaiement); paiement.setNumeroCheque(numeroCheque); paiement.setCommentaire(commentaire); paiement.setRemis(Boolean.TRUE.equals(remis)); if (principal != null) { paiement.setGestionnaire(principal.getName()); } paiementRepository.save(paiement); licence.addPaiement(paiement); AuditLogPaiement auditLog = new AuditLogPaiement(); auditLog.setAction("CREATE"); auditLog.setUtilisateur(principal != null ? principal.getName() : "Système"); auditLog.setPaiementId(paiement.getId()); auditLog.setMontant(montant); auditLog.setAdherentNomComplet(licence.getAdherent().getNom() + " " + licence.getAdherent().getPrenom()); auditLog.setDetails("Création d'un paiement de " + montant + "€ via " + mode.getNom() + " (Remis: " + (Boolean.TRUE.equals(remis) ? "Oui" : "Non") + ") pour la licence " + (licence.getNumeroLicence() != null ? licence.getNumeroLicence() : "sans numéro")); auditLogPaiementRepository.save(auditLog); try { log.info("Appel de sendPaiementConfirmation depuis addPaiement pour le paiement ID: {}", paiement.getId()); paiementEmailService.sendPaiementConfirmation(paiement); } catch (Exception e) { log.error("Erreur lors de l'appel à sendPaiementConfirmation: ", e); } } return "redirect:/adherents/" + adherentId + "/edit"; } @PostMapping("/paiements/{id}/update") public String updatePaiement( @PathVariable Long id, @RequestParam BigDecimal montant, @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate datePaiement, @RequestParam Long modePaiementId, @RequestParam(required = false) String numeroCheque, @RequestParam(required = false, defaultValue = "true") Boolean remis, @RequestParam(required = false) String commentaire, @RequestParam(required = false) String redirect, Principal principal) { Paiement paiement = paiementRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Paiement ID")); ModePaiement mode = modePaiementRepository.findById(modePaiementId) .orElseThrow(() -> new IllegalArgumentException("Invalid ModePaiement ID")); BigDecimal ancienMontant = paiement.getMontant(); String ancienMode = paiement.getModePaiement().getNom(); Licence licence = paiement.getLicence(); // Validation basique pour ne pas dépasser le montant total de la licence BigDecimal currentContribution = Boolean.TRUE.equals(paiement.getRemis()) ? paiement.getMontant() : BigDecimal.ZERO; BigDecimal maxAmount = licence.getResteAPayer().add(currentContribution); if (montant.compareTo(maxAmount) > 0) { montant = maxAmount; } if (montant.compareTo(BigDecimal.ZERO) > 0) { paiement.setModePaiement(mode); paiement.setMontant(montant); paiement.setDatePaiement(datePaiement); paiement.setNumeroCheque(numeroCheque); paiement.setCommentaire(commentaire); paiement.setRemis(Boolean.TRUE.equals(remis)); if (principal != null) { paiement.setGestionnaire(principal.getName()); } paiementRepository.save(paiement); AuditLogPaiement auditLog = new AuditLogPaiement(); auditLog.setAction("UPDATE"); auditLog.setUtilisateur(principal != null ? principal.getName() : "Système"); auditLog.setPaiementId(paiement.getId()); auditLog.setMontant(montant); auditLog.setAdherentNomComplet(licence.getAdherent().getNom() + " " + licence.getAdherent().getPrenom()); auditLog.setDetails("Modification du paiement: montant " + ancienMontant + "€ -> " + montant + "€, mode " + ancienMode + " -> " + mode.getNom() + ", remis -> " + (Boolean.TRUE.equals(remis) ? "Oui" : "Non")); auditLogPaiementRepository.save(auditLog); } if (redirect != null && !redirect.isEmpty()) { return "redirect:" + redirect; } return "redirect:/adherents/" + licence.getAdherent().getId() + "/edit"; } @PostMapping("/paiements/{id}/delete") public String deletePaiement( @PathVariable Long id, @RequestParam(required = false) String redirect, Principal principal) { Paiement paiement = paiementRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Paiement ID")); Long adherentId = paiement.getLicence().getAdherent().getId(); AuditLogPaiement auditLog = new AuditLogPaiement(); auditLog.setAction("DELETE"); auditLog.setUtilisateur(principal != null ? principal.getName() : "Système"); auditLog.setPaiementId(paiement.getId()); auditLog.setMontant(paiement.getMontant()); auditLog.setAdherentNomComplet(paiement.getLicence().getAdherent().getNom() + " " + paiement.getLicence().getAdherent().getPrenom()); auditLog.setDetails("Suppression du paiement de " + paiement.getMontant() + "€ via " + paiement.getModePaiement().getNom()); auditLogPaiementRepository.save(auditLog); paiementRepository.delete(paiement); if (redirect != null && !redirect.isEmpty()) { return "redirect:" + redirect; } return "redirect:/adherents/" + adherentId + "/edit"; } @PostMapping("/paiements/{id}/resend-email") public String resendPaiementEmail( @PathVariable Long id, @RequestParam(required = false) String redirect) { log.info(">>> [PaiementController] Demande de renvoi d'e-mail reçue pour le paiement ID: {}", id); Paiement paiement = paiementRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Paiement ID")); try { log.info("Appel de sendPaiementConfirmation depuis resendPaiementEmail pour le paiement ID: {}", id); paiementEmailService.sendPaiementConfirmation(paiement); } catch (Exception e) { log.error("Erreur lors du renvoi de l'e-mail pour le paiement ID {}: ", id, e); } if (redirect != null && !redirect.isEmpty()) { return "redirect:" + redirect; } return "redirect:/adherents/" + paiement.getLicence().getAdherent().getId() + "/edit"; } }