package com.astalange.web.controller; import com.astalange.core.entity.Adherent; import com.astalange.core.entity.Categorie; import com.astalange.core.entity.Licence; import com.astalange.core.entity.Saison; import com.astalange.core.repository.AdherentRepository; import com.astalange.core.repository.CategorieRepository; import com.astalange.core.repository.SaisonRepository; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import java.util.List; @Controller @RequestMapping("/adherents") public class AdherentController { private final AdherentRepository adherentRepository; private final CategorieRepository categorieRepository; private final com.astalange.core.repository.LicenceRepository licenceRepository; private final com.astalange.core.repository.ModePaiementRepository modePaiementRepository; private final SaisonRepository saisonRepository; private final com.astalange.core.service.CategorieService categorieService; public AdherentController(AdherentRepository adherentRepository, CategorieRepository categorieRepository, com.astalange.core.repository.LicenceRepository licenceRepository, com.astalange.core.repository.ModePaiementRepository modePaiementRepository, SaisonRepository saisonRepository, com.astalange.core.service.CategorieService categorieService) { this.adherentRepository = adherentRepository; this.categorieRepository = categorieRepository; this.licenceRepository = licenceRepository; this.modePaiementRepository = modePaiementRepository; this.saisonRepository = saisonRepository; this.categorieService = categorieService; } @org.springframework.web.bind.annotation.ModelAttribute("equipes") public List populateEquipes() { return List.of(); } @GetMapping public String listAdherents( @org.springframework.web.bind.annotation.RequestParam(required = false) String query, @org.springframework.web.bind.annotation.RequestParam(required = false) String nom, @org.springframework.web.bind.annotation.RequestParam(required = false) String prenom, @org.springframework.web.bind.annotation.RequestParam(required = false) String categorie, @org.springframework.web.bind.annotation.RequestParam(required = false) String licence, @org.springframework.web.bind.annotation.RequestParam(required = false) String email, @org.springframework.web.bind.annotation.RequestParam(required = false) String paiement, @org.springframework.web.bind.annotation.RequestParam(defaultValue = "0") int page, @org.springframework.web.bind.annotation.RequestParam(defaultValue = "20") int size, Model model) { List adherents = adherentRepository.findAllWithLicencesAndCategories(); // 1. Filter by global query if (query != null && !query.trim().isEmpty()) { String q = query.trim().toLowerCase(); adherents = adherents.stream().filter(a -> (a.getNom() != null && a.getNom().toLowerCase().contains(q)) || (a.getPrenom() != null && a.getPrenom().toLowerCase().contains(q)) || (a.getLicenceActuelle() != null && a.getLicenceActuelle().getNumeroLicence() != null && a.getLicenceActuelle().getNumeroLicence().toLowerCase().contains(q)) ).collect(java.util.stream.Collectors.toList()); model.addAttribute("searchQuery", query.trim()); } // 2. Filter by specific column filters if (nom != null && !nom.trim().isEmpty()) { String n = nom.trim().toLowerCase(); adherents = adherents.stream().filter(a -> a.getNom() != null && a.getNom().toLowerCase().contains(n)).collect(java.util.stream.Collectors.toList()); model.addAttribute("nomFilter", nom.trim()); } if (prenom != null && !prenom.trim().isEmpty()) { String p = prenom.trim().toLowerCase(); adherents = adherents.stream().filter(a -> a.getPrenom() != null && a.getPrenom().toLowerCase().contains(p)).collect(java.util.stream.Collectors.toList()); model.addAttribute("prenomFilter", prenom.trim()); } if (categorie != null && !categorie.trim().isEmpty()) { adherents = adherents.stream().filter(a -> a.getLicenceActuelle() != null && a.getLicenceActuelle().getCategorie() != null && a.getLicenceActuelle().getCategorie().getNom().equalsIgnoreCase(categorie.trim()) ).collect(java.util.stream.Collectors.toList()); model.addAttribute("categorieFilter", categorie.trim()); } if (licence != null && !licence.trim().isEmpty()) { String l = licence.trim().toLowerCase(); adherents = adherents.stream().filter(a -> a.getLicenceActuelle() != null && a.getLicenceActuelle().getNumeroLicence() != null && a.getLicenceActuelle().getNumeroLicence().toLowerCase().contains(l) ).collect(java.util.stream.Collectors.toList()); model.addAttribute("licenceFilter", licence.trim()); } if (email != null && !email.trim().isEmpty()) { String e = email.trim().toLowerCase(); adherents = adherents.stream().filter(a -> a.getEmail() != null && a.getEmail().toLowerCase().contains(e)).collect(java.util.stream.Collectors.toList()); model.addAttribute("emailFilter", email.trim()); } if (paiement != null && !paiement.trim().isEmpty()) { adherents = adherents.stream().filter(a -> { String statut = a.getStatutPaiement(); if ("A_JOUR".equalsIgnoreCase(paiement)) { return "À jour".equalsIgnoreCase(statut); } else if ("RESTE".equalsIgnoreCase(paiement)) { return statut != null && statut.startsWith("Reste"); } else if ("AUCUNE".equalsIgnoreCase(paiement)) { return "Aucune licence".equalsIgnoreCase(statut); } return true; }).collect(java.util.stream.Collectors.toList()); model.addAttribute("paiementFilter", paiement.trim()); } // 3. Paginate int totalElements = adherents.size(); int totalPages = (int) Math.ceil((double) totalElements / size); if (page < 0) page = 0; if (page >= totalPages && totalPages > 0) page = totalPages - 1; int start = page * size; int end = Math.min(start + size, totalElements); List pageContent = (start < totalElements) ? adherents.subList(start, end) : List.of(); model.addAttribute("adherents", pageContent); model.addAttribute("currentPage", page); model.addAttribute("totalPages", totalPages); model.addAttribute("totalElements", totalElements); model.addAttribute("pageSize", size); Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); if (saisonActive != null) { model.addAttribute("categories", categorieRepository.findBySaison(saisonActive)); } else { model.addAttribute("categories", categorieRepository.findAll()); } return "adherents/list"; } @GetMapping("/new") public String showCreateForm(Model model) { model.addAttribute("adherent", new Adherent()); return "adherents/form"; } @org.springframework.web.bind.annotation.PostMapping public String saveAdherent( @jakarta.validation.Valid @org.springframework.web.bind.annotation.ModelAttribute("adherent") Adherent adherent, org.springframework.validation.BindingResult result, Model model) { if (result.hasErrors()) { if (adherent.getId() != null) { Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); if (saisonActive != null) { model.addAttribute("categories", categorieRepository.findBySaison(saisonActive)); model.addAttribute("saisonActive", saisonActive); } else { model.addAttribute("categories", categorieRepository.findAll()); } model.addAttribute("licences", licenceRepository.findByAdherentId(adherent.getId())); model.addAttribute("modesPaiement", modePaiementRepository.findAll()); } else { Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); if (saisonActive != null) { model.addAttribute("categories", categorieRepository.findBySaison(saisonActive)); } else { model.addAttribute("categories", categorieRepository.findAll()); } } return "adherents/form"; } if (adherent.getId() != null) { Adherent existing = adherentRepository.findById(adherent.getId()).orElse(null); if (existing != null) { boolean dateChanged = !existing.getDateNaissance().equals(adherent.getDateNaissance()); boolean typeMaillotChanged = !existing.getTypeMaillot().equals(adherent.getTypeMaillot()); if (dateChanged || typeMaillotChanged) { int newBirthYear = adherent.getDateNaissance().getYear(); List licences = licenceRepository.findByAdherentId(adherent.getId()); for (Licence licence : licences) { if (dateChanged) { Saison saison = licence.getSaison(); Categorie newCat = categorieRepository.findBySaison(saison).stream() .filter(c -> newBirthYear >= c.getAnneeMin() && newBirthYear <= c.getAnneeMax()) .findFirst() .orElse(null); if (newCat != null) { licence.setCategorie(newCat); licence = licenceRepository.save(licence); } } // We need to update the entity's state before syncing dotations so it reads the new typeMaillot. // We haven't updated 'existing' yet, so let's temporarily set it on the licence's adherent or wait. // Actually, 'adherent' has the new typeMaillot. licence.getAdherent().setTypeMaillot(adherent.getTypeMaillot()); categorieService.syncDotationsForLicence(licence); } } existing.setNom(adherent.getNom()); existing.setPrenom(adherent.getPrenom()); existing.setDateNaissance(adherent.getDateNaissance()); existing.setLieuNaissanceVille(adherent.getLieuNaissanceVille()); existing.setLieuNaissancePays(adherent.getLieuNaissancePays()); existing.setNationalite(adherent.getNationalite()); existing.setEmail(adherent.getEmail()); existing.setRepresentantLegal(adherent.getRepresentantLegal()); existing.setResidentTalange(adherent.isResidentTalange()); existing.setSexe(adherent.getSexe()); existing.setTypeMaillot(adherent.getTypeMaillot()); adherentRepository.save(existing); } else { adherentRepository.save(adherent); } return "redirect:/adherents"; } else { Adherent saved = adherentRepository.save(adherent); return "redirect:/adherents/" + saved.getId() + "/edit"; } } @GetMapping("/{id}/edit") public String editAdherent(@org.springframework.web.bind.annotation.PathVariable Long id, Model model) { Adherent adherent = adherentRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Adhérent invalide : " + id)); Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); if (saisonActive != null) { model.addAttribute("categories", categorieRepository.findBySaison(saisonActive)); model.addAttribute("saisonActive", saisonActive); } else { model.addAttribute("categories", categorieRepository.findAll()); } model.addAttribute("adherent", adherent); model.addAttribute("licences", licenceRepository.findByAdherentId(id)); model.addAttribute("modesPaiement", modePaiementRepository.findAll()); return "adherents/form"; } @org.springframework.web.bind.annotation.PostMapping("/{id}/delete") public String deleteAdherent(@org.springframework.web.bind.annotation.PathVariable Long id) { Adherent adherent = adherentRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Adhérent invalide : " + id)); adherentRepository.delete(adherent); return "redirect:/adherents"; } }