package com.astalange.web.controller; import com.astalange.core.entity.PreInscription; import com.astalange.core.entity.TokenPreInscription; import com.astalange.core.entity.Saison; import com.astalange.core.repository.PreInscriptionRepository; import com.astalange.core.repository.TokenPreInscriptionRepository; import com.astalange.core.repository.SaisonRepository; import com.astalange.core.repository.CategorieRepository; import com.astalange.core.entity.Categorie; import com.astalange.core.service.CaptchaValidationService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.beans.factory.annotation.Value; import java.time.LocalDateTime; import java.time.LocalDate; import java.util.UUID; import java.util.List; import java.math.BigDecimal; @Controller @RequestMapping("/inscription-public") public class PublicInscriptionController { private final CaptchaValidationService captchaValidationService; private final TokenPreInscriptionRepository tokenRepository; private final PreInscriptionRepository preInscriptionRepository; private final SaisonRepository saisonRepository; private final CategorieRepository categorieRepository; public PublicInscriptionController(CaptchaValidationService captchaValidationService, TokenPreInscriptionRepository tokenRepository, PreInscriptionRepository preInscriptionRepository, SaisonRepository saisonRepository, CategorieRepository categorieRepository) { this.captchaValidationService = captchaValidationService; this.tokenRepository = tokenRepository; this.preInscriptionRepository = preInscriptionRepository; this.saisonRepository = saisonRepository; this.categorieRepository = categorieRepository; } @Value("${captcha.sitekey:1x00000000000000000000AA}") private String captchaSiteKey; @GetMapping("/demarrer") public String showDemarrer(Model model) { model.addAttribute("captchaSiteKey", captchaSiteKey); Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null); if (activeSaison == null || !activeSaison.getInscriptionsOuvertes()) { model.addAttribute("inscriptionsFermees", true); } return "public/demarrer"; } @PostMapping("/demarrer") public String processDemarrer(@RequestParam("cf-turnstile-response") String captchaResponse, RedirectAttributes redirectAttributes) { Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null); if (activeSaison == null || !activeSaison.getInscriptionsOuvertes()) { redirectAttributes.addFlashAttribute("error", "Les inscriptions ne sont pas ouvertes pour le moment, veuillez contacter un responsable du club."); return "redirect:/inscription-public/demarrer"; } // En vrai, captchaResponse dépend du fournisseur. Cloudflare Turnstile = // cf-turnstile-response if (!captchaValidationService.validateCaptcha(captchaResponse)) { redirectAttributes.addFlashAttribute("error", "Validation CAPTCHA échouée. Veuillez réessayer."); return "redirect:/inscription-public/demarrer"; } TokenPreInscription token = new TokenPreInscription(); token.setValeurUuid(UUID.randomUUID().toString()); token.setDateExpiration(LocalDateTime.now().plusMinutes(15)); tokenRepository.save(token); return "redirect:/inscription-public/formulaire?token=" + token.getValeurUuid(); } @GetMapping("/formulaire") public String showFormulaire(@RequestParam("token") String tokenUuid, Model model, RedirectAttributes redirectAttributes) { Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null); if (activeSaison == null || !activeSaison.getInscriptionsOuvertes()) { redirectAttributes.addFlashAttribute("error", "Les inscriptions ne sont pas ouvertes pour le moment, veuillez contacter un responsable du club."); return "redirect:/inscription-public/demarrer"; } TokenPreInscription token = tokenRepository.findByValeurUuid(tokenUuid).orElse(null); if (token == null || !token.isValide()) { return "public/lien-expire"; } model.addAttribute("preInscription", new PreInscription()); model.addAttribute("tokenUuid", tokenUuid); return "public/formulaire"; } @PostMapping("/formulaire") public String processFormulaire(@RequestParam("token") String tokenUuid, @ModelAttribute("preInscription") PreInscription preInscription, RedirectAttributes redirectAttributes) { TokenPreInscription token = tokenRepository.findByValeurUuid(tokenUuid).orElse(null); if (token == null || !token.isValide()) { return "public/lien-expire"; } Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null); if (activeSaison == null || !activeSaison.getInscriptionsOuvertes()) { redirectAttributes.addFlashAttribute("error", "Les inscriptions ne sont pas ouvertes pour le moment, veuillez contacter un responsable du club."); return "redirect:/inscription-public/demarrer"; } // Sauvegarde de la pré-inscription preInscription.setSaison(activeSaison); preInscription.setStatutTraite(false); preInscriptionRepository.save(preInscription); // Invalidation du token token.setEstUtilise(true); tokenRepository.save(token); if ("NOUVELLE".equals(preInscription.getTypeDemande())) { String tarifStr = "210 €"; // Default if (preInscription.getDateNaissance() != null) { int annee = preInscription.getDateNaissance().getYear(); List categories = categorieRepository.findBySaisonAndAnnee(activeSaison, annee); if (!categories.isEmpty()) { Categorie cat = categories.get(0); if (cat.getTarifBase() != null) { BigDecimal prixMaillot = BigDecimal.ZERO; if (cat.isU11OrBelow()) { prixMaillot = cat.getEquipementPrixByNom("Maillot"); } BigDecimal tarifTotal = cat.getTarifBase().add(prixMaillot); tarifStr = tarifTotal.intValue() + " €"; } } } redirectAttributes.addFlashAttribute("prenom", preInscription.getPrenom()); redirectAttributes.addFlashAttribute("tarif", tarifStr); redirectAttributes.addFlashAttribute("documents", java.util.Arrays.asList( "Photo d’identité", "Carte d’identité ou passeport de l'adhérent", "Livret de famille (si pas de pièce d’identité)", "Adresse e-mail de l'adhérent (représentant légal en cas de mineur)", "Pour les adhérents nés à l'étranger : Passeport + justificatif de domicile (du représentant légal en cas de mineur)" )); redirectAttributes.addFlashAttribute("isNouvelle", true); } return "redirect:/inscription-public/succes"; } @GetMapping("/api/tarif") @ResponseBody public String getTarif(@RequestParam(value = "dateNaissance", required = false) String dateNaissanceStr) { if (dateNaissanceStr == null || dateNaissanceStr.isEmpty()) { return "210 €"; } try { LocalDate dateNaissance = LocalDate.parse(dateNaissanceStr); int annee = dateNaissance.getYear(); Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null); if (activeSaison == null) return "210 €"; List categories = categorieRepository.findBySaisonAndAnnee(activeSaison, annee); if (categories.isEmpty()) return "210 €"; Categorie cat = categories.get(0); if (cat.getTarifBase() != null) { BigDecimal prixMaillot = BigDecimal.ZERO; if (cat.isU11OrBelow()) { prixMaillot = cat.getEquipementPrixByNom("Maillot"); } BigDecimal tarifTotal = cat.getTarifBase().add(prixMaillot); return tarifTotal.intValue() + " €"; } } catch (Exception e) { // Return default on error } return "210 €"; } @GetMapping("/succes") public String showSucces() { return "public/succes"; } }