package com.astalange.web.controller; import com.astalange.core.entity.*; import com.astalange.core.repository.*; 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 org.springframework.transaction.annotation.Transactional; import java.util.List; @Controller @Transactional public class LicenceController { private final AdherentRepository adherentRepository; private final CategorieRepository categorieRepository; private final LicenceRepository licenceRepository; private final EquipementRepository equipementRepository; private final DotationRepository dotationRepository; private final SaisonRepository saisonRepository; private final EquipeRepository equipeRepository; private final com.astalange.core.service.CategorieService categorieService; public LicenceController(AdherentRepository adherentRepository, CategorieRepository categorieRepository, LicenceRepository licenceRepository, EquipementRepository equipementRepository, DotationRepository dotationRepository, SaisonRepository saisonRepository, EquipeRepository equipeRepository, com.astalange.core.service.CategorieService categorieService) { this.adherentRepository = adherentRepository; this.categorieRepository = categorieRepository; this.licenceRepository = licenceRepository; this.equipementRepository = equipementRepository; this.dotationRepository = dotationRepository; this.saisonRepository = saisonRepository; this.equipeRepository = equipeRepository; this.categorieService = categorieService; } @PostMapping("/adherents/{id}/licences") public String addLicence( @PathVariable Long id, @RequestParam Long categorieId, @RequestParam String etat, @RequestParam(required = false) String numeroLicence, @RequestParam(required = false) String typeDemande, @RequestParam(required = false) String typeLicence, @RequestParam(required = false) Long equipeId) { Adherent adherent = adherentRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Adherent ID")); List existingLicences = licenceRepository.findByAdherentId(id); if (!existingLicences.isEmpty()) { return "redirect:/adherents/" + id + "/edit"; } Categorie categorie = categorieRepository.findById(categorieId) .orElseThrow(() -> new IllegalArgumentException("Invalid Categorie ID")); Saison saisonActive = saisonRepository.findByEstActiveTrue() .orElseThrow(() -> new IllegalStateException("Aucune saison active trouvée")); Licence licence = new Licence(); licence.setAdherent(adherent); licence.setCategorie(categorie); licence.setSaison(saisonActive); licence.setEtat(etat); licence.setNumeroLicence(numeroLicence); licence.setTypeDemande(typeDemande); licence.setTypeLicence(typeLicence); if (equipeId != null) { Equipe equipe = equipeRepository.findById(equipeId) .orElseThrow(() -> new IllegalArgumentException("Invalid Equipe ID")); licence.setEquipe(equipe); } licence = licenceRepository.save(licence); // Auto-initialize dotations via CategorieService to ensure consistency categorieService.syncDotationsForLicence(licence); return "redirect:/adherents/" + id + "/edit"; } @PostMapping("/adherents/{adherentId}/licences/{licenceId}/update") public String updateLicence( @PathVariable Long adherentId, @PathVariable Long licenceId, @RequestParam Long categorieId, @RequestParam String etat, @RequestParam(required = false) String numeroLicence, @RequestParam(required = false) String typeDemande, @RequestParam(required = false) String typeLicence, @RequestParam(required = false) Long equipeId) { Licence licence = licenceRepository.findById(licenceId) .orElseThrow(() -> new IllegalArgumentException("Invalid Licence ID")); Categorie categorie = categorieRepository.findById(categorieId) .orElseThrow(() -> new IllegalArgumentException("Invalid Categorie ID")); licence.setCategorie(categorie); licence.setEtat(etat); licence.setNumeroLicence(numeroLicence); licence.setTypeDemande(typeDemande); licence.setTypeLicence(typeLicence); if (equipeId != null) { Equipe equipe = equipeRepository.findById(equipeId) .orElseThrow(() -> new IllegalArgumentException("Invalid Equipe ID")); licence.setEquipe(equipe); } else { licence.setEquipe(null); } licence = licenceRepository.save(licence); // Sync dotations when category changes categorieService.syncDotationsForLicence(licence); return "redirect:/adherents/" + adherentId + "/edit"; } @org.springframework.web.bind.annotation.GetMapping("/admin/licences/recherche") public String rechercheLicences( @RequestParam(required = false) String nom, @RequestParam(required = false) String prenom, @RequestParam(required = false) Long categorieId, @RequestParam(required = false) String numeroLicence, @RequestParam(required = false) String email, @RequestParam(required = false) String typeDemande, org.springframework.ui.Model model) { Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); org.springframework.data.jpa.domain.Specification spec = buildLicenceSpecification(nom, prenom, categorieId, numeroLicence, email, typeDemande, saisonActive); List licences = licenceRepository.findAll(spec); model.addAttribute("licences", licences); model.addAttribute("categories", categorieRepository.findAll()); model.addAttribute("nomFilter", nom); model.addAttribute("prenomFilter", prenom); model.addAttribute("categorieId", categorieId); model.addAttribute("numeroLicenceFilter", numeroLicence); model.addAttribute("emailFilter", email); model.addAttribute("typeDemandeFilter", typeDemande); return "parametrage/licences_recherche"; } @org.springframework.web.bind.annotation.GetMapping("/admin/licences/recherche/export") public org.springframework.http.ResponseEntity exportRechercheLicences( @RequestParam(required = false) String nom, @RequestParam(required = false) String prenom, @RequestParam(required = false) Long categorieId, @RequestParam(required = false) String numeroLicence, @RequestParam(required = false) String email, @RequestParam(required = false) String typeDemande) { Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); org.springframework.data.jpa.domain.Specification spec = buildLicenceSpecification(nom, prenom, categorieId, numeroLicence, email, typeDemande, saisonActive); List licences = licenceRepository.findAll(spec); StringBuilder sb = new StringBuilder(); sb.append('\ufeff'); sb.append("Nom;Prénom;Catégorie;N° Licence;Email;Type de Demande;Saison;Etat\n"); for (Licence l : licences) { String n = l.getAdherent() != null && l.getAdherent().getNom() != null ? l.getAdherent().getNom() : ""; String p = l.getAdherent() != null && l.getAdherent().getPrenom() != null ? l.getAdherent().getPrenom() : ""; String c = l.getCategorie() != null ? l.getCategorie().getNom() : ""; String num = l.getNumeroLicence() != null ? l.getNumeroLicence() : ""; String e = l.getAdherent() != null && l.getAdherent().getEmail() != null ? l.getAdherent().getEmail() : ""; String td = l.getTypeDemande() != null ? l.getTypeDemande() : ""; String s = l.getSaison() != null ? l.getSaison().getNom() : ""; String etat = l.getEtat() != null ? l.getEtat() : ""; sb.append(escapeCsv(n)).append(";") .append(escapeCsv(p)).append(";") .append(escapeCsv(c)).append(";") .append(escapeCsv(num)).append(";") .append(escapeCsv(e)).append(";") .append(escapeCsv(td)).append(";") .append(escapeCsv(s)).append(";") .append(escapeCsv(etat)).append("\n"); } byte[] csvBytes = sb.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8); org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders(); headers.setContentDispositionFormData("attachment", "recherche_licences_" + java.time.LocalDate.now() + ".csv"); headers.setContentType(org.springframework.http.MediaType.parseMediaType("text/csv; charset=UTF-8")); return new org.springframework.http.ResponseEntity<>(csvBytes, headers, org.springframework.http.HttpStatus.OK); } private String escapeCsv(String value) { if (value == null) return ""; if (value.contains("\"")) value = value.replace("\"", "\"\""); if (value.contains(";") || value.contains("\n") || value.contains("\"")) return "\"" + value + "\""; return value; } private org.springframework.data.jpa.domain.Specification buildLicenceSpecification( String nom, String prenom, Long categorieId, String numeroLicence, String email, String typeDemande, Saison saisonActive) { return (root, query, cb) -> { List predicates = new java.util.ArrayList<>(); if (Long.class != query.getResultType() && long.class != query.getResultType()) { root.fetch("adherent", jakarta.persistence.criteria.JoinType.LEFT); root.fetch("categorie", jakarta.persistence.criteria.JoinType.LEFT); } if (saisonActive != null) { predicates.add(cb.equal(root.get("saison"), saisonActive)); } if (nom != null && !nom.trim().isEmpty()) { predicates.add(cb.like(cb.lower(root.get("adherent").get("nom")), "%" + nom.trim().toLowerCase() + "%")); } if (prenom != null && !prenom.trim().isEmpty()) { predicates.add(cb.like(cb.lower(root.get("adherent").get("prenom")), "%" + prenom.trim().toLowerCase() + "%")); } if (categorieId != null) { predicates.add(cb.equal(root.get("categorie").get("id"), categorieId)); } if (numeroLicence != null && !numeroLicence.trim().isEmpty()) { predicates.add(cb.like(cb.lower(root.get("numeroLicence")), "%" + numeroLicence.trim().toLowerCase() + "%")); } if (email != null && !email.trim().isEmpty()) { predicates.add(cb.like(cb.lower(root.get("adherent").get("email")), "%" + email.trim().toLowerCase() + "%")); } if (typeDemande != null && !typeDemande.trim().isEmpty()) { predicates.add(cb.equal(root.get("typeDemande"), typeDemande.trim())); } return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0])); }; } }