Refactor: Move equipment price and mandatory status to Categorie relationship
- Created CategorieEquipement entity to act as a join table between Category and Equipment. - Moved 'obligatoire' and 'prix' (formerly prixContribution) fields from Equipement to the new CategorieEquipement entity. - Added Flyway migrations V14 and V15 to update the database schema and migrate existing data. - Updated Categorie UI to use a select dropdown and price input for managing category-specific equipment configurations. - Replaced 'equipement.obligatoire' and 'equipement.prixContribution' calls with their new category-level equivalents in logic and templates. - Updated pricing calculation in Licence entity to source prices dynamically from the Categorie configuration. - Updated Dotation generation logic to sync with category requirements automatically.
This commit is contained in:
@@ -1,19 +1,31 @@
|
||||
package com.astalange.web.controller;
|
||||
|
||||
import com.astalange.core.entity.Categorie;
|
||||
import com.astalange.core.entity.Saison;
|
||||
import com.astalange.core.repository.CategorieRepository;
|
||||
import com.astalange.core.repository.SaisonRepository;
|
||||
import com.astalange.core.repository.EquipementRepository;
|
||||
import com.astalange.core.service.CategorieService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/categories")
|
||||
public class CategorieController {
|
||||
|
||||
private final CategorieRepository categorieRepository;
|
||||
private final SaisonRepository saisonRepository;
|
||||
private final EquipementRepository equipementRepository;
|
||||
private final CategorieService categorieService;
|
||||
|
||||
public CategorieController(CategorieRepository categorieRepository) {
|
||||
public CategorieController(CategorieRepository categorieRepository, SaisonRepository saisonRepository, EquipementRepository equipementRepository, CategorieService categorieService) {
|
||||
this.categorieRepository = categorieRepository;
|
||||
this.saisonRepository = saisonRepository;
|
||||
this.equipementRepository = equipementRepository;
|
||||
this.categorieService = categorieService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@@ -25,6 +37,8 @@ public class CategorieController {
|
||||
@GetMapping("/new")
|
||||
public String showCreateForm(Model model) {
|
||||
model.addAttribute("categorie", new Categorie());
|
||||
Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null);
|
||||
model.addAttribute("allEquipements", activeSaison != null ? equipementRepository.findBySaison(activeSaison) : List.of());
|
||||
return "parametrage/categories_form";
|
||||
}
|
||||
|
||||
@@ -33,12 +47,37 @@ public class CategorieController {
|
||||
Categorie categorie = categorieRepository.findById(id)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid category ID: " + id));
|
||||
model.addAttribute("categorie", categorie);
|
||||
Saison activeSaison = saisonRepository.findByEstActiveTrue().orElse(null);
|
||||
model.addAttribute("allEquipements", activeSaison != null ? equipementRepository.findBySaison(activeSaison) : List.of());
|
||||
return "parametrage/categories_form";
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public String saveCategorie(@ModelAttribute("categorie") Categorie categorie) {
|
||||
categorieRepository.save(categorie);
|
||||
public String saveCategorie(@ModelAttribute("categorie") Categorie categorie,
|
||||
jakarta.servlet.http.HttpServletRequest request) {
|
||||
|
||||
java.util.Map<Long, com.astalange.core.service.CategorieService.EquipementConfig> configs = new java.util.HashMap<>();
|
||||
|
||||
request.getParameterMap().forEach((key, values) -> {
|
||||
if (key.startsWith("etatEquipement_") && values.length > 0) {
|
||||
String idStr = key.substring("etatEquipement_".length());
|
||||
try {
|
||||
Long eqId = Long.parseLong(idStr);
|
||||
String etat = values[0];
|
||||
if (!"NON_LIE".equals(etat)) {
|
||||
boolean obligatoire = "OBLIGATOIRE".equals(etat);
|
||||
String prixStr = request.getParameter("prixEquipement_" + eqId);
|
||||
java.math.BigDecimal prix = java.math.BigDecimal.ZERO;
|
||||
if (prixStr != null && !prixStr.trim().isEmpty()) {
|
||||
prix = new java.math.BigDecimal(prixStr.trim());
|
||||
}
|
||||
configs.put(eqId, new com.astalange.core.service.CategorieService.EquipementConfig(obligatoire, prix));
|
||||
}
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
});
|
||||
|
||||
categorieService.saveCategorie(categorie, configs);
|
||||
return "redirect:/categories";
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class DotationController {
|
||||
dotation.setNumero(numero);
|
||||
dotation.setFourni(fourni != null && fourni);
|
||||
|
||||
if (dotation.getEquipement().getObligatoire()) {
|
||||
if (dotation.getLicence().getCategorie().isEquipementObligatoire(dotation.getEquipement().getId())) {
|
||||
dotation.setChoisi(true);
|
||||
} else {
|
||||
dotation.setChoisi(choisi != null && choisi);
|
||||
@@ -70,7 +70,7 @@ public class DotationController {
|
||||
if (numero != null) dotation.setNumero(numero);
|
||||
if (flocage != null) dotation.setFlocage(flocage);
|
||||
|
||||
if (dotation.getEquipement().getObligatoire()) {
|
||||
if (dotation.getLicence().getCategorie().isEquipementObligatoire(dotation.getEquipement().getId())) {
|
||||
dotation.setChoisi(true);
|
||||
} else {
|
||||
dotation.setChoisi(choisiParam != null);
|
||||
|
||||
+14
-3
@@ -1,7 +1,9 @@
|
||||
package com.astalange.web.controller;
|
||||
|
||||
import com.astalange.core.entity.Equipement;
|
||||
import com.astalange.core.entity.Saison;
|
||||
import com.astalange.core.repository.EquipementRepository;
|
||||
import com.astalange.core.repository.SaisonRepository;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -11,9 +13,11 @@ import org.springframework.web.bind.annotation.*;
|
||||
public class EquipementController {
|
||||
|
||||
private final EquipementRepository equipementRepository;
|
||||
private final SaisonRepository saisonRepository;
|
||||
|
||||
public EquipementController(EquipementRepository equipementRepository) {
|
||||
public EquipementController(EquipementRepository equipementRepository, SaisonRepository saisonRepository) {
|
||||
this.equipementRepository = equipementRepository;
|
||||
this.saisonRepository = saisonRepository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@@ -38,8 +42,15 @@ public class EquipementController {
|
||||
|
||||
@PostMapping
|
||||
public String saveEquipement(@ModelAttribute("equipement") Equipement equipement) {
|
||||
if (equipement.getObligatoire() == null) {
|
||||
equipement.setObligatoire(false);
|
||||
|
||||
if (equipement.getId() == null) {
|
||||
Saison activeSaison = saisonRepository.findByEstActiveTrue()
|
||||
.orElseThrow(() -> new IllegalStateException("Aucune saison active trouvée"));
|
||||
equipement.setSaison(activeSaison);
|
||||
} else {
|
||||
Equipement existing = equipementRepository.findById(equipement.getId())
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid equipment ID: " + equipement.getId()));
|
||||
equipement.setSaison(existing.getSaison());
|
||||
}
|
||||
equipementRepository.save(equipement);
|
||||
return "redirect:/equipements";
|
||||
|
||||
@@ -6,10 +6,12 @@ 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;
|
||||
@@ -73,18 +75,20 @@ public class LicenceController {
|
||||
|
||||
licence = licenceRepository.save(licence);
|
||||
|
||||
// Auto-initialize dotations for all configured equipments of the active season
|
||||
List<Equipement> equipements = equipementRepository.findBySaison(saisonActive);
|
||||
for (Equipement eq : equipements) {
|
||||
Dotation dotation = new Dotation();
|
||||
dotation.setLicence(licence);
|
||||
dotation.setEquipement(eq);
|
||||
dotation.setTaille("");
|
||||
dotation.setFlocage(adherent.getNom().toUpperCase() + " " + adherent.getPrenom());
|
||||
dotation.setNumero("");
|
||||
dotation.setFourni(false);
|
||||
dotation.setChoisi(eq.getObligatoire());
|
||||
dotationRepository.save(dotation);
|
||||
// Auto-initialize dotations for all configured equipments of the category
|
||||
List<CategorieEquipement> catEquipements = categorie.getCategorieEquipements();
|
||||
if (catEquipements != null) {
|
||||
for (CategorieEquipement ce : catEquipements) {
|
||||
Dotation dotation = new Dotation();
|
||||
dotation.setLicence(licence);
|
||||
dotation.setEquipement(ce.getEquipement());
|
||||
dotation.setTaille("");
|
||||
dotation.setFlocage(adherent.getNom().toUpperCase() + " " + adherent.getPrenom());
|
||||
dotation.setNumero("");
|
||||
dotation.setFourni(false);
|
||||
dotation.setChoisi(Boolean.TRUE.equals(ce.getObligatoire()));
|
||||
dotationRepository.save(dotation);
|
||||
}
|
||||
}
|
||||
|
||||
return "redirect:/adherents/" + id + "/edit";
|
||||
|
||||
Reference in New Issue
Block a user