package com.astalange.web.controller; import com.astalange.core.entity.Dotation; import com.astalange.core.repository.DotationRepository; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.http.ResponseEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import java.time.LocalDate; import com.astalange.core.service.DotationService; import com.astalange.core.repository.SaisonRepository; import com.astalange.core.entity.Saison; import com.astalange.core.repository.EquipementRepository; import com.astalange.core.repository.CategorieRepository; import org.springframework.ui.Model; import org.springframework.data.jpa.domain.Specification; import jakarta.persistence.criteria.Predicate; import java.util.ArrayList; @Controller public class DotationController { private final DotationRepository dotationRepository; private final DotationService dotationService; private final SaisonRepository saisonRepository; private final EquipementRepository equipementRepository; private final CategorieRepository categorieRepository; public DotationController(DotationRepository dotationRepository, DotationService dotationService, SaisonRepository saisonRepository, EquipementRepository equipementRepository, CategorieRepository categorieRepository) { this.dotationRepository = dotationRepository; this.dotationService = dotationService; this.saisonRepository = saisonRepository; this.equipementRepository = equipementRepository; this.categorieRepository = categorieRepository; } private Specification buildSpecification(Long equipementId, Long categorieId, Boolean fourni, Saison saisonActive) { return (root, query, cb) -> { if (Long.class != query.getResultType() && long.class != query.getResultType()) { root.fetch("equipement", jakarta.persistence.criteria.JoinType.LEFT); jakarta.persistence.criteria.Fetch licenceFetch = root.fetch("licence", jakarta.persistence.criteria.JoinType.LEFT); licenceFetch.fetch("adherent", jakarta.persistence.criteria.JoinType.LEFT); licenceFetch.fetch("categorie", jakarta.persistence.criteria.JoinType.LEFT); } List predicates = new ArrayList<>(); if (saisonActive != null) { predicates.add(cb.equal(root.get("licence").get("saison"), saisonActive)); } if (equipementId != null) { predicates.add(cb.equal(root.get("equipement").get("id"), equipementId)); } if (categorieId != null) { predicates.add(cb.equal(root.get("licence").get("categorie").get("id"), categorieId)); } if (fourni != null) { predicates.add(cb.equal(root.get("fourni"), fourni)); } return cb.and(predicates.toArray(new Predicate[0])); }; } @GetMapping("/admin/equipements/recherche") public String rechercheEquipements( @RequestParam(required = false) Long equipementId, @RequestParam(required = false) Long categorieId, @RequestParam(required = false) Boolean fourni, Model model) { Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); Specification spec = buildSpecification(equipementId, categorieId, fourni, saisonActive); List dotations = dotationRepository.findAll(spec); model.addAttribute("dotations", dotations); model.addAttribute("equipements", equipementRepository.findAll()); model.addAttribute("categories", categorieRepository.findAll()); model.addAttribute("equipementId", equipementId); model.addAttribute("categorieId", categorieId); model.addAttribute("fourni", fourni); return "parametrage/equipements_recherche"; } @GetMapping("/admin/equipements/recherche/export") public ResponseEntity exportRechercheEquipements( @RequestParam(required = false) Long equipementId, @RequestParam(required = false) Long categorieId, @RequestParam(required = false) Boolean fourni) { Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null); Specification spec = buildSpecification(equipementId, categorieId, fourni, saisonActive); List dotations = dotationRepository.findAll(spec); String csvContent = dotationService.genererCsvSearchEquipement(dotations); byte[] csvBytes = csvContent.getBytes(java.nio.charset.StandardCharsets.UTF_8); HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", "recherche_equipements_" + LocalDate.now() + ".csv"); headers.setContentType(MediaType.parseMediaType("text/csv; charset=UTF-8")); return new ResponseEntity<>(csvBytes, headers, org.springframework.http.HttpStatus.OK); } @GetMapping("/admin/equipements/export-commande") public ResponseEntity exportCommande() { Saison saisonActive = saisonRepository.findByEstActiveTrue() .orElseThrow(() -> new IllegalStateException("Aucune saison active")); String csvContent = dotationService.genererCsvCommandeEquipement(saisonActive); byte[] csvBytes = csvContent.getBytes(java.nio.charset.StandardCharsets.UTF_8); HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", "commande_equipements_" + LocalDate.now() + ".csv"); headers.setContentType(MediaType.parseMediaType("text/csv; charset=UTF-8")); return new ResponseEntity<>(csvBytes, headers, org.springframework.http.HttpStatus.OK); } @PostMapping("/dotations/{id}") public String updateDotation( @PathVariable Long id, @RequestParam Long adherentId, @RequestParam(required = false, defaultValue = "") String taille, @RequestParam(required = false, defaultValue = "") String flocage, @RequestParam(required = false, defaultValue = "") String numero, @RequestParam(required = false) Boolean fourni, @RequestParam(required = false) Boolean choisi) { Dotation dotation = dotationRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Dotation ID: " + id)); dotation.setTaille(taille); dotation.setFlocage(flocage); dotation.setNumero(numero); dotation.setFourni(fourni != null && fourni); if (dotation.getLicence().getCategorie().isEquipementObligatoire(dotation.getEquipement().getId())) { dotation.setChoisi(true); } else { dotation.setChoisi(choisi != null && choisi); } dotationRepository.save(dotation); return "redirect:/adherents/" + adherentId + "/edit"; } @Transactional @PostMapping("/dotations/bulk") public String bulkUpdateDotations( @RequestParam Long adherentId, @RequestParam("dotationIds") List dotationIds, HttpServletRequest request) { for (Long id : dotationIds) { Dotation dotation = dotationRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid Dotation ID: " + id)); String taille = request.getParameter("taille_" + id); String couleur = request.getParameter("couleur_" + id); String numero = request.getParameter("numero_" + id); String flocage = request.getParameter("flocage_" + id); String choisiParam = request.getParameter("choisi_" + id); String fourniParam = request.getParameter("fourni_" + id); if (taille != null) dotation.setTaille(taille); if (couleur != null) dotation.setCouleur(couleur); if (numero != null) dotation.setNumero(numero); if (flocage != null) dotation.setFlocage(flocage); if (dotation.getLicence().getCategorie().isEquipementObligatoire(dotation.getEquipement().getId())) { dotation.setChoisi(true); } else { dotation.setChoisi(choisiParam != null); } dotation.setFourni(fourniParam != null); dotationRepository.save(dotation); } return "redirect:/adherents/" + adherentId + "/edit"; } }