package fr.eni.enchere.controllers; import com.fasterxml.jackson.databind.JsonNode; import fr.eni.enchere.bll.*; import fr.eni.enchere.bo.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.ObjectError; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; @Controller() @RequestMapping("/article") public class ArticleController { private final String API_URL = "https://apicarto.ign.fr/api/codes-postaux/communes/"; @Autowired private final ArticleService articleService; private final UserService userService; private CategorieService categorieService; private RetraitService retraitService; private EnchereService enchereService; public ArticleController(ArticleService articleService, UserService userService, CategorieService categorieService, RetraitService retraitService, EnchereService enchereService) { this.articleService = articleService; this.userService = userService; this.categorieService = categorieService; this.retraitService = retraitService; this.enchereService = enchereService; } @GetMapping public String viewArticle(Model model) { return "redirect:/enchere"; } //Affichage d'un article @GetMapping("/show") public String showArticle(@RequestParam()int id, Model model, HttpSession session) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!authentication.getName().equals("anonymousUser")) { Article article = articleService.findArticleById(id); UserProfil user = userService.utilisateurById(article.getUtilisateur()); Categorie cate = categorieService.findCategorieById(article.getNumCategorie()); Retrait retrait = retraitService.findByNumArticle(article.getId()); article.setPseudoUtilisateur(user.getPseudo()); List lastEnchere = this.enchereService.enchereByArticle(article.getId()); Optional maxMontantEnchere = lastEnchere.stream() .map(Enchere::getMontantEnchere) .max(Float::compareTo); UserProfil currentUser = userService.utilisateurByName(authentication.getName()); boolean isArticleCurrentUser = false; if (currentUser.getId() == user.getId()) { isArticleCurrentUser = true; } lastEnchere = lastEnchere.stream() .sorted(Comparator.comparing(Enchere::getMontantEnchere).reversed()) .collect(Collectors.toList()); Optional pseudoMaxEnchere = lastEnchere.stream() .max(Comparator.comparing(Enchere::getMontantEnchere)) // Comparaison basée sur le montant d'enchère .map(Enchere::getPseudoUtilisateur); model.addAttribute("encheres", lastEnchere); model.addAttribute("maxEncherePseudo", pseudoMaxEnchere.orElse(null)); model.addAttribute("isArticleCurrentUser", isArticleCurrentUser); model.addAttribute("article", article); model.addAttribute("username", user); model.addAttribute("cate", cate.getLibelle()); model.addAttribute("retrait", retrait); model.addAttribute("enchere", new Enchere()); if (maxMontantEnchere.isPresent()) { model.addAttribute("maxEnchere", maxMontantEnchere.get()); } if (article.getId() != 0) { model.addAttribute("imagePath", "/images/articles/" + article.getId() + ".jpg"); } else { model.addAttribute("imagePath", "/images/articles/no-data.jpg"); } List errors = (List) session.getAttribute("errors"); if (errors != null) { model.addAttribute("errors", errors); session.removeAttribute("errors"); // Supprimer les erreurs de la session après utilisation } return "article"; } else { return "redirect:/login"; } } //Création d'un article @GetMapping("/new") public String newArticleForm(HttpServletRequest request, Model model) { model.addAttribute("categories", categorieService.findAllCategories()); model.addAttribute("article", new Article()); model.addAttribute("retrait", new Retrait()); model.addAttribute("requestURI", request.getRequestURI()); //Récupérer l'utilisateur pour set le retrait à son adresse par defaut Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String username = authentication.getName(); UserProfil userProfile = userService.utilisateurByName(username); model.addAttribute("user", userProfile); return "newArticle"; } @PostMapping("/new") public String newArticle(@ModelAttribute("article") Article article, @RequestParam("rue") String rue, @RequestParam("code_postal") String code_postal, @RequestParam("ville") String ville, @RequestParam("dateDebut") String dateDebut, @RequestParam("dateFin") String dateFin, RedirectAttributes redirectAttributes) { //Récupérer l'utilisateur pour set l'article Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String username = authentication.getName(); UserProfil userProfile = userService.utilisateurByName(username); article.setNoUtilisateur(userProfile.getId()); //Récupérer le lieu de retrait Retrait retrait = new Retrait(); retrait.setRue(rue); retrait.setCode_postale(code_postal); retrait.setVille(ville); //Reste de l'article SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date dDateDebut = null; Date dDateFin = null; try { dDateDebut = format.parse(dateDebut); dDateFin = format.parse(dateFin); } catch (ParseException e) { redirectAttributes.addAttribute("erreur", "La date de début n'est pas valide."); redirectAttributes.addAttribute("erreur", "La date de fin n'est pas valide."); } article.setDateDebutEnch(dDateDebut); article.setDateFinEnch(dDateFin); //Vérification du formulaire //Vérification du nom de l'article String regex = "^[a-zA-Z0-9 ]*$"; if (article.getNom().length() < 3){ redirectAttributes.addAttribute("erreur", "Le nom de l'article doit contenir au moin 3 caractères."); return "redirect:/article/new"; } if (!Pattern.matches(regex, article.getNom())){ redirectAttributes.addAttribute("erreur", "Le nom de l'article ne doit pas contenir de caractère speciaux."); return "redirect:/article/new"; } //Vérification description de l'article if (article.getDesc().length() < 20){ redirectAttributes.addAttribute("erreur", "La description de l'article doit contenir au moin 20 caractères."); return "redirect:/article/new"; } //Vérification de la photo if (article.getPhoto() != null && !article.getPhoto().isEmpty()) { if (article.getPhoto().getSize() > 5 * 1024 * 1024) { redirectAttributes.addAttribute("erreur", "La photo ne doit pas faire plus de 5 Mo."); return "redirect:/article/new"; } if (!article.getPhoto().getOriginalFilename().toLowerCase().endsWith(".jpg")) { redirectAttributes.addAttribute("erreur", "L'image doit avoir une extension .jpg."); return "redirect:/article/new"; } } //Vérification du prix initial if (article.getPrixInitial() > 2000000000 && article.getPrixInitial() < 0){ redirectAttributes.addAttribute("erreur", "Le prix doit être compris entre 0 et 2 000 000 000 crédits."); return "redirect:/article/new"; } //Vérifier les dates LocalDate dateDebutEnch = LocalDate.parse(dateDebut); LocalDate dateActuelle = LocalDate.now(); if (dateDebutEnch.isBefore(dateActuelle)) { redirectAttributes.addAttribute("erreur", "La date de début d'enchère ne peux pas être infèrieur à la date du jour."); return "redirect:/article/new"; } LocalDate dateFinEnch = LocalDate.parse(dateFin); LocalDate datePlusUnJour = LocalDate.now().plusDays(1); if (dateFinEnch.isBefore(datePlusUnJour)) { redirectAttributes.addAttribute("erreur", "La date de début d'enchère ne peux pas être infàrieur à la date du jour + 1."); return "redirect:/article/new"; } //Vérification rue if (!Pattern.matches("^[a-zA-Z0-9 ]+$", retrait.getRue())){ redirectAttributes.addAttribute("erreur", "Le rue n'est pas valide."); return "redirect:/article/new"; } if (retrait.getRue().isEmpty()){ redirectAttributes.addAttribute("erreur", "Entrer une rue."); return "redirect:/article/new"; } //Vérifier code postal et ville if(Pattern.matches("^\\d{5}$", retrait.getCode_postale())){ //Récupérer les villes en fonction du code postal RestTemplate restTemplate = new RestTemplate(); List villeCodePostal = new ArrayList<>(); // Initialisez la liste pour éviter les NullPointerException String apiUrl = API_URL + retrait.getCode_postale(); ResponseEntity response = restTemplate.getForEntity(apiUrl, JsonNode.class); // Désérialiser en JsonNode if (response.getStatusCode().is2xxSuccessful()) { JsonNode responseBody = response.getBody(); if (responseBody.isArray()) { // Vérifiez si le corps de la réponse est un tableau JSON for (JsonNode node : responseBody) { String cityName = node.get("nomCommune").asText(); villeCodePostal.add(cityName); } } else { redirectAttributes.addAttribute("erreur", "Une erreur est survenue !"); return "redirect:/article/new"; } if (!villeCodePostal.contains(userProfile.getVille())) { String showCity = String.join(", ", villeCodePostal); redirectAttributes.addAttribute("erreur", "Essayer : " + showCity); return "redirect:/article/new"; } } else { redirectAttributes.addAttribute("erreur", "La ville n'est pas valide."); return "redirect:/article/new"; } } else { redirectAttributes.addAttribute("erreur", "Le code postal n'est pas valide."); return "redirect:/article/new"; } //Validation du formulaire retrait.setNumArticle(articleService.saveArticle(article)); retraitService.setRetrait(retrait); return "redirect:/enchere"; } //Update d'un article @GetMapping("/edit") public String edit(Model model, @RequestParam()int id) { Article article = this.articleService.findArticleById(id); Retrait retrait = this.retraitService.findByNumArticle(id); model.addAttribute("article", article); model.addAttribute("retrait", retrait); model.addAttribute("categories", this.categorieService.findAllCategories()); return "editArticle"; } @PostMapping("/edit") public String edit(@ModelAttribute("article") Article article, @ModelAttribute("retrait") Retrait retrait, @RequestParam("dateDebut") String dateDebut, @RequestParam("dateFin") String dateFin, RedirectAttributes redirectAttributes) { //Récupérer l'utilisateur pour set l'article Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String username = authentication.getName(); UserProfil userProfile = userService.utilisateurByName(username); article.setNoUtilisateur(userProfile.getId()); //Reste de l'article SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date dDateDebut = null; Date dDateFin = null; try { dDateDebut = format.parse(dateDebut); dDateFin = format.parse(dateFin); } catch (ParseException e) { redirectAttributes.addAttribute("erreur", "La date de début n'est pas valide."); redirectAttributes.addAttribute("erreur", "La date de fin n'est pas valide."); } article.setDateDebutEnch(dDateDebut); article.setDateFinEnch(dDateFin); //Vérification du formulaire //Vérification du nom de l'article String regex = "^[a-zA-Z0-9 ]*$"; if (article.getNom().length() < 3){ redirectAttributes.addAttribute("erreur", "Le nom de l'article doit contenir au moin 3 caractères."); return "redirect:/article/edit?id="+article.getId(); } if (!Pattern.matches(regex, article.getNom())){ redirectAttributes.addAttribute("erreur", "Le nom de l'article ne doit pas contenir de caractère speciaux."); return "redirect:/article/edit?id="+article.getId(); } //Vérification description de l'article if (article.getDesc().length() < 20){ redirectAttributes.addAttribute("erreur", "La description de l'article doit contenir au moin 20 caractères."); return "redirect:/article/edit?id="+article.getId(); } //Vérification de la photo if (article.getPhoto() != null && !article.getPhoto().isEmpty()) { if (article.getPhoto().getSize() > 5 * 1024 * 1024) { redirectAttributes.addAttribute("erreur", "La photo ne doit pas faire plus de 5 Mo."); return "redirect:/article/edit?id="+article.getId(); } if (!article.getPhoto().getOriginalFilename().toLowerCase().endsWith(".jpg")) { redirectAttributes.addAttribute("erreur", "L'image doit avoir une extension .jpg."); return "redirect:/article/edit?id="+article.getId(); } } //Vérification du prix initial if (article.getPrixInitial() > 2000000000 && article.getPrixInitial() < 0){ redirectAttributes.addAttribute("erreur", "Le prix doit être compris entre 0 et 2 000 000 000 crédits."); return "redirect:/article/edit?id="+article.getId(); } //Vérifier les dates LocalDate dateDebutEnch = LocalDate.parse(dateDebut); LocalDate dateActuelle = LocalDate.now(); if (dateDebutEnch.isBefore(dateActuelle)) { redirectAttributes.addAttribute("erreur", "La date de début d'enchère ne peux pas être infèrieur à la date du jour."); return "redirect:/article/edit?id="+article.getId(); } LocalDate dateFinEnch = LocalDate.parse(dateFin); LocalDate datePlusUnJour = LocalDate.now().plusDays(1); if (dateFinEnch.isBefore(datePlusUnJour)) { redirectAttributes.addAttribute("erreur", "La date de début d'enchère ne peux pas être infàrieur à la date du jour + 1."); return "redirect:/article/edit?id="+article.getId(); } //Vérification rue if (!Pattern.matches("^[a-zA-Z0-9 ]+$", retrait.getRue())){ redirectAttributes.addAttribute("erreur", "Le rue n'est pas valide."); return "redirect:/article/edit?id="+article.getId(); } if (retrait.getRue().isEmpty()){ redirectAttributes.addAttribute("erreur", "Entrer une rue."); return "redirect:/article/edit?id="+article.getId(); } //Vérifier code postal et ville if(Pattern.matches("^\\d{5}$", retrait.getCode_postale())){ //Récupérer les villes en fonction du code postal RestTemplate restTemplate = new RestTemplate(); List villeCodePostal = new ArrayList<>(); // Initialisez la liste pour éviter les NullPointerException String apiUrl = API_URL + retrait.getCode_postale(); ResponseEntity response = restTemplate.getForEntity(apiUrl, JsonNode.class); // Désérialiser en JsonNode if (response.getStatusCode().is2xxSuccessful()) { JsonNode responseBody = response.getBody(); if (responseBody.isArray()) { // Vérifiez si le corps de la réponse est un tableau JSON for (JsonNode node : responseBody) { String cityName = node.get("nomCommune").asText(); villeCodePostal.add(cityName); } } else { redirectAttributes.addAttribute("erreur", "Une erreur est survenue !"); return "redirect:/article/edit?id="+article.getId(); } if (!villeCodePostal.contains(userProfile.getVille())) { String showCity = String.join(", ", villeCodePostal); redirectAttributes.addAttribute("erreur", "Essayer : " + showCity); return "redirect:/article/edit?id="+article.getId(); } } else { redirectAttributes.addAttribute("erreur", "La ville n'est pas valide."); return "redirect:/article/edit?id="+article.getId(); } } else { redirectAttributes.addAttribute("erreur", "Le code postal n'est pas valide."); return "redirect:/article/edit?id="+article.getId(); } //Validation du formulaire retrait.setNumArticle(articleService.updateArticle(article)); retraitService.updateRetrait(retrait); return "redirect:/enchere"; } @PostMapping("/delete") public String deleteArticle(@RequestParam("articleId") int articleId) { this.articleService.deleteArticle(articleId); return "redirect:/enchere"; } }