feat: ajouter les exports CSV individuels des equipements commandes pour le flocage (initiales et prenom/numero)

This commit is contained in:
2026-08-09 00:44:51 +02:00
parent cb281aa3e0
commit 6539e33f08
7 changed files with 302 additions and 9 deletions
@@ -42,6 +42,12 @@ public class Dotation {
@Column(name = "date_commande")
private java.time.LocalDateTime dateCommande;
@Column(name = "flocage_exporte", nullable = false)
private Boolean flocageExporte = false;
@Column(name = "date_flocage")
private java.time.LocalDateTime dateFlocage;
// Getters and Setters
public Long getId() { return id; }
@@ -77,6 +83,13 @@ public class Dotation {
public java.time.LocalDateTime getDateCommande() { return dateCommande; }
public void setDateCommande(java.time.LocalDateTime dateCommande) { this.dateCommande = dateCommande; }
public Boolean getFlocageExporte() { return flocageExporte; }
public void setFlocageExporte(Boolean flocageExporte) { this.flocageExporte = flocageExporte; }
public java.time.LocalDateTime getDateFlocage() { return dateFlocage; }
public void setDateFlocage(java.time.LocalDateTime dateFlocage) { this.dateFlocage = dateFlocage; }
public static boolean isSizeMatch(String option, String adherentSize) {
if (option == null || adherentSize == null) return false;
String opt = option.trim();
@@ -12,4 +12,6 @@ import com.astalange.core.entity.Saison;
public interface DotationRepository extends JpaRepository<Dotation, Long>, JpaSpecificationExecutor<Dotation> {
List<Dotation> findByLicence_SaisonAndChoisiTrueAndFourniFalse(Saison saison);
List<Dotation> findByLicence_SaisonAndChoisiTrueAndCommandeeFalse(Saison saison);
List<Dotation> findByLicence_SaisonAndChoisiTrueAndCommandeeTrueAndFlocageExporteFalse(Saison saison);
}
@@ -116,6 +116,106 @@ public class DotationService {
return sb.toString();
}
@Transactional
public String genererCsvFlocageInitiales(Saison saisonActive) {
List<Dotation> dotations = dotationRepository.findByLicence_SaisonAndChoisiTrueAndCommandeeTrueAndFlocageExporteFalse(saisonActive);
LocalDateTime now = LocalDateTime.now();
String dateExportFormatted = now.format(DATE_FORMATTER);
StringBuilder sb = new StringBuilder();
sb.append('\ufeff'); // BOM UTF-8 for Excel
sb.append("Saison;Catégorie;Nom;Prénom;Équipement;Référence;Taille;Initiales;Date Export Flocage\n");
for (Dotation d : dotations) {
if (d.getEquipement() == null || !d.getEquipement().isHasFlocageInitiales()) {
continue;
}
String initiales = d.getFlocage() != null ? d.getFlocage().trim() : "";
if (initiales.isEmpty()) {
continue;
}
String saison = d.getLicence().getSaison() != null ? d.getLicence().getSaison().getNom() : "";
String categorie = d.getLicence().getCategorie() != null ? d.getLicence().getCategorie().getNom() : "";
String nom = d.getLicence().getAdherent() != null ? d.getLicence().getAdherent().getNom() : "";
String prenom = d.getLicence().getAdherent() != null ? d.getLicence().getAdherent().getPrenom() : "";
String equipement = d.getEquipement().getNom();
String reference = d.getEquipement().getReference() != null ? d.getEquipement().getReference() : "";
String taille = d.getTaille() != null ? d.getTaille() : "";
sb.append(escapeCsv(saison)).append(";")
.append(escapeCsv(categorie)).append(";")
.append(escapeCsv(nom)).append(";")
.append(escapeCsv(prenom)).append(";")
.append(escapeCsv(equipement)).append(";")
.append(escapeCsv(reference)).append(";")
.append(escapeCsv(taille)).append(";")
.append(escapeCsv(initiales)).append(";")
.append(escapeCsv(dateExportFormatted)).append("\n");
d.setFlocageExporte(true);
d.setDateFlocage(now);
dotationRepository.save(d);
}
return sb.toString();
}
@Transactional
public String genererCsvFlocagePrenomNumero(Saison saisonActive) {
List<Dotation> dotations = dotationRepository.findByLicence_SaisonAndChoisiTrueAndCommandeeTrueAndFlocageExporteFalse(saisonActive);
LocalDateTime now = LocalDateTime.now();
String dateExportFormatted = now.format(DATE_FORMATTER);
StringBuilder sb = new StringBuilder();
sb.append('\ufeff'); // BOM UTF-8 for Excel
sb.append("Saison;Catégorie;Nom;Prénom;Équipement;Référence;Taille;Prénom Floqué;Numéro;Date Export Flocage\n");
for (Dotation d : dotations) {
if (d.getEquipement() == null) {
continue;
}
boolean handlesPrenom = d.getEquipement().isHasFlocagePrenom();
boolean handlesNumero = d.getEquipement().isHasFlocageNumero();
if (!handlesPrenom && !handlesNumero) {
continue;
}
String prenomFloque = d.getFlocage() != null ? d.getFlocage().trim() : "";
String numero = d.getNumero() != null ? d.getNumero().trim() : "";
if (prenomFloque.isEmpty() && numero.isEmpty()) {
continue;
}
String saison = d.getLicence().getSaison() != null ? d.getLicence().getSaison().getNom() : "";
String categorie = d.getLicence().getCategorie() != null ? d.getLicence().getCategorie().getNom() : "";
String nom = d.getLicence().getAdherent() != null ? d.getLicence().getAdherent().getNom() : "";
String prenom = d.getLicence().getAdherent() != null ? d.getLicence().getAdherent().getPrenom() : "";
String equipement = d.getEquipement().getNom();
String reference = d.getEquipement().getReference() != null ? d.getEquipement().getReference() : "";
String taille = d.getTaille() != null ? d.getTaille() : "";
sb.append(escapeCsv(saison)).append(";")
.append(escapeCsv(categorie)).append(";")
.append(escapeCsv(nom)).append(";")
.append(escapeCsv(prenom)).append(";")
.append(escapeCsv(equipement)).append(";")
.append(escapeCsv(reference)).append(";")
.append(escapeCsv(taille)).append(";")
.append(escapeCsv(prenomFloque)).append(";")
.append(escapeCsv(numero)).append(";")
.append(escapeCsv(dateExportFormatted)).append("\n");
d.setFlocageExporte(true);
d.setDateFlocage(now);
dotationRepository.save(d);
}
return sb.toString();
}
private String escapeCsv(String value) {
if (value == null) {
return "";
@@ -130,3 +230,4 @@ public class DotationService {
return result;
}
}
@@ -0,0 +1,2 @@
ALTER TABLE dotation ADD COLUMN flocage_exporte BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE dotation ADD COLUMN date_flocage TIMESTAMP NULL;
@@ -0,0 +1,123 @@
package com.astalange.core.service;
import com.astalange.core.entity.*;
import com.astalange.core.repository.DotationRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
public class DotationServiceTest {
@Mock
private DotationRepository dotationRepository;
@InjectMocks
private DotationService dotationService;
private Saison saison;
private Categorie categorie;
private Adherent adherent;
private Licence licence;
@BeforeEach
public void setUp() {
saison = new Saison();
saison.setId(1L);
saison.setNom("2026-2027");
categorie = new Categorie();
categorie.setId(10L);
categorie.setNom("U15");
adherent = new Adherent();
adherent.setId(100L);
adherent.setNom("Dupont");
adherent.setPrenom("Jean");
licence = new Licence();
licence.setId(500L);
licence.setSaison(saison);
licence.setCategorie(categorie);
licence.setAdherent(adherent);
}
@Test
@DisplayName("Générer CSV Flocage Initiales - Uniquement équipements avec initiales et commandés")
public void testGenererCsvFlocageInitiales() {
Equipement eqVeste = new Equipement();
eqVeste.setId(1L);
eqVeste.setNom("Veste de sortie");
eqVeste.setReference("REF-VESTE");
eqVeste.setHasFlocageInitiales(true);
Dotation d1 = new Dotation();
d1.setId(1L);
d1.setLicence(licence);
d1.setEquipement(eqVeste);
d1.setTaille("M");
d1.setFlocage("JD");
d1.setChoisi(true);
d1.setCommandee(true);
d1.setFlocageExporte(false);
when(dotationRepository.findByLicence_SaisonAndChoisiTrueAndCommandeeTrueAndFlocageExporteFalse(saison))
.thenReturn(List.of(d1));
String csv = dotationService.genererCsvFlocageInitiales(saison);
assertNotNull(csv);
assertTrue(csv.contains("JD"));
assertTrue(csv.contains("Veste de sortie"));
assertTrue(csv.contains("Dupont"));
assertTrue(d1.getFlocageExporte());
assertNotNull(d1.getDateFlocage());
verify(dotationRepository, times(1)).save(d1);
}
@Test
@DisplayName("Générer CSV Flocage Prénom / Numéro - Uniquement équipements commandés avec prénom ou numéro")
public void testGenererCsvFlocagePrenomNumero() {
Equipement eqMaillot = new Equipement();
eqMaillot.setId(2L);
eqMaillot.setNom("Maillot de match");
eqMaillot.setReference("REF-MAILLOT");
eqMaillot.setHasFlocagePrenom(true);
eqMaillot.setHasFlocageNumero(true);
Dotation d2 = new Dotation();
d2.setId(2L);
d2.setLicence(licence);
d2.setEquipement(eqMaillot);
d2.setTaille("L");
d2.setFlocage("JEAN");
d2.setNumero("10");
d2.setChoisi(true);
d2.setCommandee(true);
d2.setFlocageExporte(false);
when(dotationRepository.findByLicence_SaisonAndChoisiTrueAndCommandeeTrueAndFlocageExporteFalse(saison))
.thenReturn(List.of(d2));
String csv = dotationService.genererCsvFlocagePrenomNumero(saison);
assertNotNull(csv);
assertTrue(csv.contains("JEAN"));
assertTrue(csv.contains("10"));
assertTrue(csv.contains("Maillot de match"));
assertTrue(d2.getFlocageExporte());
assertNotNull(d2.getDateFlocage());
verify(dotationRepository, times(1)).save(d2);
}
}