浏览代码

dev en cours

rajah 6 月之前
父节点
当前提交
b611f56ebc

+ 38 - 6
src/main/java/fr/triplea/demovote/dao/BulletinRepository.java

@@ -3,6 +3,7 @@ package fr.triplea.demovote.dao;
 import java.util.List;
 
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.NativeQuery;
 import org.springframework.data.repository.query.Param;
 
@@ -30,18 +31,31 @@ public interface BulletinRepository extends JpaRepository<Bulletin, Integer>
              + "FROM vote.bulletins AS u "
              + "WHERE u.numero_categorie = :categorie AND u.numero_participant = :participant ")
   BulletinShort findByCategorieAndParticipant(@Param("categorie") int cat_id, @Param("participant") int part_id);
+  
+  @NativeQuery("SELECT DISTINCT "
+      + " u.numero_bulletin, "
+      + " u.numero_categorie, "
+      + " u.numero_participant, "
+      + " CASE WHEN u.numero_production01 IS NULL THEN 0 ELSE u.numero_production01 END AS numero_production01, "
+      + " CASE WHEN u.numero_production02 IS NULL THEN 0 ELSE u.numero_production02 END AS numero_production02, "
+      + " CASE WHEN u.numero_production03 IS NULL THEN 0 ELSE u.numero_production03 END AS numero_production03, "
+      + " CASE WHEN u.numero_production04 IS NULL THEN 0 ELSE u.numero_production04 END AS numero_production04, "
+      + " CASE WHEN u.numero_production05 IS NULL THEN 0 ELSE u.numero_production05 END AS numero_production05, "
+      + " CASE WHEN u.numero_production06 IS NULL THEN 0 ELSE u.numero_production06 END AS numero_production06, "
+      + " CASE WHEN u.numero_production07 IS NULL THEN 0 ELSE u.numero_production07 END AS numero_production07, "
+      + " CASE WHEN u.numero_production08 IS NULL THEN 0 ELSE u.numero_production08 END AS numero_production08, "
+      + " CASE WHEN u.numero_production09 IS NULL THEN 0 ELSE u.numero_production09 END AS numero_production09, "
+      + " CASE WHEN u.numero_production10 IS NULL THEN 0 ELSE u.numero_production10 END AS numero_production10, "
+      + " u.flag_valide "
+      + "FROM vote.bulletins AS u "
+      + "WHERE u.numero_categorie = :categorie AND u.flag_valide IS TRUE ")
+  List<BulletinShort> findByCategorie(@Param("categorie") int cat_id);
 
   @NativeQuery("SELECT DISTINCT "
              + " u.* "
              + "FROM vote.bulletins AS u "
              + "WHERE u.numero_categorie = :categorie AND u.numero_participant = :participant ")
   Bulletin getByCategorieAndParticipant(@Param("categorie") int cat_id, @Param("participant") int part_id);
-
-  @NativeQuery("SELECT DISTINCT u.* FROM vote.bulletins AS u WHERE u.numero_categorie = :categorie ")
-  List<Bulletin> findByCategorie(@Param("categorie") int cat_id);
-
-  @NativeQuery("SELECT DISTINCT u.* FROM vote.bulletins AS u WHERE u.numero_participant = :participant ")
-  List<Bulletin> findByParticipant(@Param("participant") int part_id);
   
   @NativeQuery("SELECT DISTINCT COUNT(u.*) AS nombre "
              + "FROM vote.bulletins AS u "
@@ -57,4 +71,22 @@ public interface BulletinRepository extends JpaRepository<Bulletin, Integer>
              + "   OR (p.numero_production10 = :numero) ")
   Integer countIfProductionVoted(@Param("numero") int numeroProduction);
 
+  @Modifying(flushAutomatically = true)
+  @NativeQuery("UPDATE vote.bulletins SET flag_valide = TRUE WHERE flag_valide IS FALSE ")
+  int validateAll();
+
+  @Modifying(clearAutomatically = true)
+  @NativeQuery("DELETE FROM vote.bulletins "
+      + "WHERE (numero_production01 IS NULL) "
+      + "  AND (numero_production02 IS NULL) "
+      + "  AND (numero_production03 IS NULL) "
+      + "  AND (numero_production04 IS NULL) "
+      + "  AND (numero_production05 IS NULL) "
+      + "  AND (numero_production06 IS NULL) "
+      + "  AND (numero_production07 IS NULL) "
+      + "  AND (numero_production08 IS NULL) "
+      + "  AND (numero_production09 IS NULL) "
+      + "  AND (numero_production10 IS NULL) ")
+  int cleanAll();
+
 }

+ 18 - 0
src/main/java/fr/triplea/demovote/dao/ProductionRepository.java

@@ -10,6 +10,7 @@ import fr.triplea.demovote.dto.ProductionChoice;
 import fr.triplea.demovote.dto.ProductionFile;
 import fr.triplea.demovote.dto.ProductionItem;
 import fr.triplea.demovote.dto.ProductionShort;
+import fr.triplea.demovote.dto.ProductionVote;
 import fr.triplea.demovote.model.Production;
 
 
@@ -181,6 +182,23 @@ public interface ProductionRepository extends JpaRepository<Production, Integer>
       + "  AND p.flag_actif IS TRUE ")
   ProductionChoice findChosen(@Param("categorie") int numeroCategorie, @Param("production") int numeroProduction);
   
+  
+  @NativeQuery("SELECT DISTINCT " 
+      + "p.numero_production, "
+      + "p.type, "
+      + "p.titre, "
+      + "p.auteurs, "
+      + "p.groupes, "
+      + "p.plateforme, "
+      + "0 AS nombre_points,"
+      + "0 AS nombre_first "
+      + "FROM vote.productions AS p "
+      + "INNER JOIN vote.presentations AS s ON p.numero_production = s.numero_production "
+      + "WHERE s.numero_categorie = :numero "
+      + "  AND p.flag_actif IS TRUE "
+      + "ORDER BY s.numero_ordre ASC, p.titre ASC ")
+  List<ProductionVote> findForCalculation(@Param("numero") int numeroCategorie);
+ 
   @Override
   void delete(Production production);
   

+ 1 - 1
src/main/java/fr/triplea/demovote/dao/RefreshTokenRepository.java

@@ -14,7 +14,7 @@ public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Inte
   
   RefreshToken findByToken(String token);
 
-  @Modifying
+  @Modifying(clearAutomatically = true)
   @NativeQuery("DELETE FROM vote.refreshtoken AS r WHERE r.numero_participant = :numero ")
   int deleteByNumeroParticipant(@Param("numero") int numeroParticipant);
   

+ 2 - 1
src/main/java/fr/triplea/demovote/dto/ProductionChoice.java

@@ -14,7 +14,8 @@ public class ProductionChoice
   Integer numeroOrdre;
   byte[] vignette;
   
-  public ProductionChoice(Integer numeroProduction, String type, String titre, String auteurs, String groupes, String plateforme, Integer numeroOrdre, byte[] vignette) {
+  public ProductionChoice(Integer numeroProduction, String type, String titre, String auteurs, String groupes, String plateforme, Integer numeroOrdre, byte[] vignette)
+  {
     this.numeroProduction = numeroProduction;
     this.type = type;
     this.titre = titre;

+ 53 - 0
src/main/java/fr/triplea/demovote/dto/ProductionVote.java

@@ -0,0 +1,53 @@
+package fr.triplea.demovote.dto;
+
+public class ProductionVote 
+{ 
+  
+  Integer numeroProduction;
+  String type;
+  String titre;
+  String auteurs;
+  String groupes;
+  String plateforme;
+  Integer nombrePoints;
+  Integer nombreFirst;
+  
+  public ProductionVote(Integer numeroProduction, String type, String titre, String auteurs, String groupes, String plateforme, Integer nombrePoints, Integer nombreFirst) 
+  {
+    this.numeroProduction = numeroProduction;
+    this.type = type;
+    this.titre = titre;
+    this.auteurs = auteurs;
+    this.groupes = groupes;
+    this.plateforme = plateforme;
+    this.nombrePoints = nombrePoints;
+    this.nombreFirst = nombreFirst;
+  }
+
+  public void setNumeroProduction(Integer numeroProduction) { this.numeroProduction = numeroProduction; }
+  public Integer getNumeroProduction() { return numeroProduction; }
+  
+  public void setType(String type) { this.type = type; }
+  public String getType() { return type; }
+
+  public void setTitre(String titre) { this.titre = titre; }
+  public String getTitre() { return titre; }
+
+  public void setAuteurs(String auteurs) { this.auteurs = auteurs; }
+  public String getAuteurs() { return auteurs; }
+
+  public void setGroupes(String groupes) { this.groupes = groupes; }
+  public String getGroupes() { return groupes; }
+
+  public void setPlateforme(String plateforme) { this.plateforme = plateforme; }
+  public String getPlateforme() { return plateforme; }
+
+  public void setNombrePoints(Integer nombrePoints) { this.nombrePoints = nombrePoints; }
+  public Integer getNombrePoints() { return nombrePoints; }
+  public void addPoints(Integer points) { this.nombrePoints += points; }
+
+  public void setNombreFirst(Integer nombreFirst) { this.nombreFirst = nombreFirst; }
+  public Integer getNombreFirst() { return nombreFirst; }
+  public void setFirst() { this.nombreFirst++; }
+  
+}

+ 312 - 2
src/main/java/fr/triplea/demovote/web/controller/BulletinController.java

@@ -1,11 +1,23 @@
 package fr.triplea.demovote.web.controller;
 
+import java.awt.Color;
+import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.MessageSource;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.core.Authentication;
@@ -15,6 +27,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.servlet.LocaleResolver;
+import org.vandeseer.easytable.OverflowOnSamePageRepeatableHeaderTableDrawer;
+import org.vandeseer.easytable.settings.HorizontalAlignment;
+import org.vandeseer.easytable.structure.Row;
+import org.vandeseer.easytable.structure.Table;
+import org.vandeseer.easytable.structure.cell.TextCell;
 
 import fr.triplea.demovote.dao.BulletinRepository;
 import fr.triplea.demovote.dao.CategorieRepository;
@@ -24,25 +41,33 @@ import fr.triplea.demovote.dao.VariableRepository;
 import fr.triplea.demovote.dto.BulletinShort;
 import fr.triplea.demovote.dto.MessagesTransfer;
 import fr.triplea.demovote.dto.ProductionChoice;
+import fr.triplea.demovote.dto.ProductionShort;
+import fr.triplea.demovote.dto.ProductionVote;
 import fr.triplea.demovote.model.Bulletin;
 import fr.triplea.demovote.model.Categorie;
 import fr.triplea.demovote.model.Participant;
 import fr.triplea.demovote.model.Production;
+import fr.triplea.demovote.web.service.BulletinService;
 import jakarta.servlet.http.HttpServletRequest;
 
 @RestController
 @RequestMapping("/urne")
 public class BulletinController 
 {
+  //@SuppressWarnings("unused") 
+  private static final Logger LOG = LoggerFactory.getLogger(BulletinController.class);
+
+  // TODO : page des résultats, résultats PDF pour toutes les catégories + HTML par catégorie
 
-  // TODO : résultats
-  
   @Autowired
   private VariableRepository variableRepository;
 
   @Autowired
   private BulletinRepository bulletinRepository;
 
+  @Autowired
+  private BulletinService bulletinService;
+
   @Autowired
   private CategorieRepository categorieRepository;
 
@@ -457,5 +482,290 @@ public class BulletinController
     return numeroParticipant;
   }
 
+  @GetMapping(value = "/file")
+  @PreAuthorize("hasRole('ADMIN')")
+  public ResponseEntity<Resource> getPresentationsVersionPDF(HttpServletRequest request) 
+  { 
+    Locale locale = localeResolver.resolveLocale(request);
+
+    List<Categorie> categories = categorieRepository.findAll(0, true);
+    
+    List<ProductionShort> productions = productionRepository.findLinkedWithoutArchive();
+   
+    if ((categories != null) && (productions != null)) 
+    { 
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      
+      try 
+      {
+        PDDocument document = new PDDocument();
+        
+        document.isAllSecurityToBeRemoved();
+
+        float POINTS_PER_INCH = 72;
+        float POINTS_PER_MM = 1 / (10 * 2.54f) * POINTS_PER_INCH;
+
+        PDRectangle A4_paysage = new PDRectangle(297 * POINTS_PER_MM, 210 * POINTS_PER_MM);
+        
+        Table.TableBuilder tb = Table.builder().addColumnsOfWidth(20f, 100f, 100f, 100f, 105f, 190f, 190f).padding(4);
+
+        for (Categorie categorie: categories)
+        {
+          if (categorie.isAvailable())
+          {
+            tb.addRow(createTitleRow(categorie.getLibelle()));
+            tb.addRow(createHeaderRow(locale));
+
+            int nombre = 0;
+            
+            if ((productions.size() > 0)) 
+            { 
+              for (ProductionShort production: productions) 
+              { 
+                if (production.numeroCategorie() == categorie.getNumeroCategorie())
+                {
+                  nombre++;
+                  
+                  tb.addRow(createProductionRow(production, nombre));
+                }
+              } 
+            } 
+            
+            tb.addRow(createTitleRow(categorie.getLibelle() + " : " + nombre + " " + messageSource.getMessage("show.pdf.productions", null, locale)));
+            tb.addRow(createEmptyRow());
+           }
+        }
+
+        OverflowOnSamePageRepeatableHeaderTableDrawer.builder()
+          .table(tb.build())
+          .startX(15f)
+          .startY(A4_paysage.getUpperRightY() - 15f)
+          .lanesPerPage(1)
+          .numberOfRowsToRepeat(0)
+          .spaceInBetween(1)
+          .endY(15f) // note: if not set, table is drawn over the end of the page
+          .build()
+          .draw(() -> document, () -> new PDPage(A4_paysage), 100f);
+
+        document.save(baos);
+        document.close();
+        
+        baos.close();
+      } 
+      catch (Exception e) { LOG.error(e.toString()); }
+       
+      byte[] binaire = baos.toByteArray();
+
+      Resource r = new ByteArrayResource(binaire);
+      
+      return ResponseEntity
+              .ok()
+              .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"presentations.pdf\"")
+              .header(HttpHeaders.CONTENT_LENGTH, "" + binaire.length)
+              .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF.toString())
+              .body(r); 
+    }
+    
+    return ResponseEntity.notFound().build();
+  }
+  private Row createTitleRow(String str) 
+  {
+    return Row.builder()
+              .add(TextCell.builder().text(str).colSpan(7).fontSize(10).backgroundColor(Color.WHITE).horizontalAlignment(HorizontalAlignment.LEFT).borderWidth(0.1f).build())
+              .build();
+  }
+  private Row createEmptyRow() 
+  {
+    return Row.builder()
+              .add(TextCell.builder().text(" ").colSpan(7).fontSize(10).backgroundColor(Color.WHITE).horizontalAlignment(HorizontalAlignment.LEFT).borderWidth(0).build())
+              .build();
+  }
+  private Row createHeaderRow(Locale locale) 
+  {
+    return Row.builder()
+              .add(createHeaderCell(""))
+              .add(createHeaderCell(messageSource.getMessage("show.pdf.title", null, locale)))
+              .add(createHeaderCell(messageSource.getMessage("show.pdf.authors", null, locale)))
+              .add(createHeaderCell(messageSource.getMessage("show.pdf.groups", null, locale)))
+              .add(createHeaderCell(messageSource.getMessage("show.pdf.manager", null, locale)))
+              .add(createHeaderCell(messageSource.getMessage("show.pdf.comments", null, locale)))
+              .add(createHeaderCell(messageSource.getMessage("show.pdf.private", null, locale)))
+              .build();
+  }
+  private TextCell createHeaderCell(String str)
+  {
+    return TextCell.builder()
+                   .text(str)
+                   .backgroundColor(Color.GRAY)
+                   .textColor(Color.WHITE)
+                   .horizontalAlignment(HorizontalAlignment.LEFT)
+                   .borderWidth(0.1f)
+                   .fontSize(8)
+                   .build();
+  }
+  private Row createProductionRow(ProductionShort production, int nombre) 
+  {
+    return Row.builder()
+              .add(createCell("#" + nombre))
+              .add(createCell(production.titre()))
+              .add(createCell(production.auteurs()))
+              .add(createCell(production.groupes()))
+              .add(createCell(production.nomGestionnaire()))
+              .add(createCell(production.commentaire()))
+              .add(createCell(production.informationsPrivees()))
+              .build();
+  }
+  private TextCell createCell(String str)
+  {
+    return TextCell.builder()
+                   .text(str)
+                   .backgroundColor(Color.WHITE)
+                   .textColor(Color.BLACK)
+                   .horizontalAlignment(HorizontalAlignment.LEFT)
+                   .borderWidth(0.1f)
+                   .fontSize(8)
+                   .build();
+  }
+
+  
+  @Value("classpath:styles/diapos.css")
+  private Resource styleDiaposResource;
+  
+  @GetMapping(value = "/diapos/{id}")
+  @PreAuthorize("hasRole('ADMIN')")
+  public ResponseEntity<String> getDiaporama(@PathVariable("id") int numeroCategorie, HttpServletRequest request) 
+  {
+    Locale locale = localeResolver.resolveLocale(request);
+
+    Categorie categorie = categorieRepository.findById(numeroCategorie);
+    
+    List<ProductionVote> productions = bulletinService.decompterVotes(numeroCategorie);
+    
+    /*if ((categorie != null) && (presentations != null))
+    {
+      String libelleCategorie = categorie.getLibelle();
+         
+      StringBuffer sb = new StringBuffer();
+
+      sb.append("<!doctype html>\n");
+      sb.append("<html lang=\"").append(locale.stripExtensions().toString()).append("\">\n");
+      sb.append("<head>\n");
+      sb.append("<title>").append(libelleCategorie).append("</title>\n");
+      sb.append("<style>\n");
+      try { sb.append(StreamUtils.copyToString(styleDiaposResource.getInputStream(), Charset.defaultCharset())); } catch (IOException e) { LOG.error(e.toString()); }
+      sb.append("</style>\n");
+      sb.append("</head>\n\n");
+      sb.append("<body>\n");
+
+      sb.append("<div class=\"diapo_start\" id=\"diapo_page_0\">\n");
+      
+      sb.append("\t").append("<div class=\"diapo_compo\">").append(libelleCategorie).append("</div>\n");
+      sb.append("\t").append("<div class=\"diapo_range\">").append(messageSource.getMessage("show.file.starting", null, locale)).append("</div>\n");
+
+      sb.append("\t").append("<div class=\"diapo_hub\">\n");
+      sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" style=\"visibility:hidden;\">&#9665;</button>\n");
+      sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" onClick=\"show_next(0);\" title=\"").append(messageSource.getMessage("show.file.next", null, locale)).append("\">&#9655;</button>\n");
+      sb.append("\t").append("</div>\n");
+      
+      sb.append("</div>\n");
+
+      int n = 1;
+      
+      for (int i = 0; i < presentations.size(); i++)
+      {
+        Presentation d = presentations.get(i);
+        Production p = d.getProduction();
+
+        sb.append("<div class=\"diapo_page\" id=\"diapo_page_" + n + "\">\n");
+
+        sb.append("\t").append("<div class=\"diapo_compo\">").append(libelleCategorie).append("</div>\n");
+        sb.append("\t").append("<div class=\"diapo_order\">").append("#").append("" + (i + 1)).append("</div>\n");
+        sb.append("\t").append("<div class=\"diapo_title\">").append(p.getTitre()).append("</div>\n");
+        sb.append("\t").append("<div class=\"diapo_authors\">").append(messageSource.getMessage("show.file.by", null, locale)).append(" ").append(p.getAuteurs()).append(" / ").append(p.getGroupes()).append("</div>\n");
+        sb.append("\t").append("<div class=\"diapo_comments\">");
+        if (p.hasPlateforme()) { sb.append(messageSource.getMessage("show.file.on", null, locale)).append(" ").append(p.getPlateforme()).append("<br/>"); }
+        sb.append(p.getCommentaire()).append("</div>\n");
+
+        if (d.getEtatMedia() == 1)
+        {
+          if (d.getMimeMedia().startsWith("image/"))
+          {
+            sb.append("\t").append("<div id=\"diapo_pict_").append(n).append("\" class=\"diapo_image_container\">\n");
+            sb.append("\t").append("\t").append("<div class=\"diapo_image_content\" onClick=\"pict_hide(").append(n).append(");\"><img src=\"").append(d.getDataMediaAsString()).append("\" alt=\"\" class=\"diapo_image\" /></div>\n");
+            sb.append("\t").append("</div>\n");
+          }
+          else if (d.getMimeMedia().startsWith("audio/"))
+          {
+            sb.append("\t").append("<div id=\"diapo_file_").append(n).append("\" class=\"diapo_audio_container\">\n");
+            sb.append("\t").append("\t").append("<audio controls><source src=\"").append(d.getDataMediaAsString()).append("\" type=\"").append(d.getMimeMedia()).append("\" />").append("</audio>\n");
+            sb.append("\t").append("</div>\n");
+          }
+          else if (d.getMimeMedia().startsWith("video/"))
+          {
+            sb.append("\t").append("<div id=\"diapo_file_").append(n).append("\" class=\"diapo_video_container\">\n");
+            sb.append("\t").append("\t").append("<video controls width=\"480\" height=\"240\"><source src=\"").append(d.getDataMediaAsString()).append("\" type=\"").append(d.getMimeMedia()).append("\" />").append("</video>\n");
+            sb.append("\t").append("</div>\n");
+          }
+        }
+
+        sb.append("\t").append("<div id=\"diapo_ctrl_").append(n).append("\" class=\"diapo_hub\">\n");
+        sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" onClick=\"show_prev(").append(n).append(");\" title=\"").append(messageSource.getMessage("show.file.previous", null, locale)).append("\">&#9665;</button>\n");
+        sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" onClick=\"show_next(").append(n).append(");\" title=\"").append(messageSource.getMessage("show.file.next", null, locale)).append("\">&#9655;</button>\n");
+        if ((d.getEtatMedia() == 1))
+        {
+          if (d.getMimeMedia().startsWith("image/"))
+          {
+            sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" onClick=\"pict_open(").append(n).append(");\" title=\"").append(messageSource.getMessage("show.file.open", null, locale)).append("\">&#9713;</button>\n");
+          }
+          else
+          {
+            sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" onClick=\"file_open(").append(n).append(");\" title=\"").append(messageSource.getMessage("show.file.open", null, locale)).append("\">&#9713;</button>\n");
+          }
+        }
+        else if ((d.getEtatMedia() == 2))
+        {
+          sb.append("\t").append("\t").append("<button class=\"diapo_warning\">").append(messageSource.getMessage("show.file.acknowlegded", null, locale)).append("</button>\n");
+        }
+        else
+        {
+          sb.append("\t").append("\t").append("<button class=\"diapo_alert\">").append(messageSource.getMessage("show.file.missing", null, locale)).append("</button>\n");
+        }
+        sb.append("\t").append("</div>\n");
+
+        sb.append("</div>\n");
+        n++;
+      }
+      
+      sb.append("<div class=\"diapo_page\" id=\"diapo_page_" + n + "\">\n");
+      
+      sb.append("\t").append("<div class=\"diapo_compo\">").append(libelleCategorie).append("</div>\n");
+      sb.append("\t").append("<div class=\"diapo_range\">").append(messageSource.getMessage("show.file.ending", null, locale)).append("</div>\n");
+
+      sb.append("\t").append("<div class=\"diapo_hub\">\n");
+      sb.append("\t").append("\t").append("<button class=\"diapo_bouton\" onClick=\"show_prev(").append(n).append(");\" title=\"").append(messageSource.getMessage("show.file.previous", null, locale)).append("\">&#9665;</button>\n");
+      sb.append("\t").append("</div>\n");
+      
+      sb.append("</div>\n");
+
+      sb.append("<script type=\"text/javascript\">\n");
+      sb.append("function show_prev(num) { var cur = document.getElementById(\"diapo_page_\" + num); var prv = document.getElementById(\"diapo_page_\" + (num - 1)); if (cur) { cur.style.visibility = 'hidden'; cur.style.display = 'none'; } if (prv) { prv.style.visibility = 'visible'; prv.style.display = 'block'; } }\n");
+      sb.append("function show_next(num) { var cur = document.getElementById(\"diapo_page_\" + num); var nxt = document.getElementById(\"diapo_page_\" + (num + 1)); if (cur) { cur.style.visibility = 'hidden'; cur.style.display = 'none'; } if (nxt) { nxt.style.visibility = 'visible'; nxt.style.display = 'block'; } }\n");
+      sb.append("function pict_open(num) { var hub = document.getElementById(\"diapo_ctrl_\" + num); var pic = document.getElementById(\"diapo_pict_\" + num); if (hub) { hub.style.visibility = 'hidden'; hub.style.display = 'none'; } if (pic) { pic.style.visibility = 'visible'; pic.style.display = 'block'; } }\n");
+      sb.append("function pict_hide(num) { var hub = document.getElementById(\"diapo_ctrl_\" + num); var pic = document.getElementById(\"diapo_pict_\" + num); if (hub) { hub.style.visibility = 'visible'; hub.style.display = 'block'; } if (pic) { pic.style.visibility = 'hidden'; pic.style.display = 'none'; } }\n");
+      sb.append("function file_open(num) { var fil = document.getElementById(\"diapo_file_\" + num); if (fil) { if (fil.style.visibility == 'visible') { fil.style.visibility = 'hidden'; fil.style.display = 'none'; } else { fil.style.visibility = 'visible'; fil.style.display = 'block'; } } }\n");
+      sb.append("</script>\n");
+      sb.append("</body>\n");
+      sb.append("</html>\n");
+      
+      return ResponseEntity
+              .ok()
+              .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + libelleCategorie +".html\"")
+              .header(HttpHeaders.CONTENT_LENGTH, "" + sb.length())
+              .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML.toString())
+              .body(sb.toString());
+    }*/
+    
+    return ResponseEntity.notFound().build();
+  }  
 
 }

+ 54 - 13
src/main/java/fr/triplea/demovote/web/controller/CategorieController.java

@@ -9,6 +9,7 @@ import org.springframework.context.MessageSource;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.core.Authentication;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -19,7 +20,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.servlet.LocaleResolver;
-
+import fr.triplea.demovote.dao.BulletinRepository;
 import fr.triplea.demovote.dao.CategorieRepository;
 import fr.triplea.demovote.dao.ParticipantRepository;
 import fr.triplea.demovote.dto.MessagesTransfer;
@@ -32,6 +33,8 @@ import jakarta.servlet.http.HttpServletRequest;
 public class CategorieController 
 {
 
+    private final BulletinRepository bulletinRepository;
+
   @Autowired
   private CategorieRepository categorieRepository;
 
@@ -45,6 +48,11 @@ public class CategorieController
   private MessageSource messageSource;
 
 
+    CategorieController(BulletinRepository bulletinRepository) {
+        this.bulletinRepository = bulletinRepository;
+    }
+
+
   @GetMapping(value = "/list")
   @PreAuthorize("hasRole('USER')")
   public List<Categorie> getList(@RequestParam(required = false) Boolean admin, final Authentication authentication) 
@@ -54,9 +62,9 @@ public class CategorieController
 
   @GetMapping(value = "/form/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<Categorie> getForm(@PathVariable int id)
+  public ResponseEntity<Categorie> getForm(@PathVariable("id") int numeroCategorie)
   { 
-    Categorie c = categorieRepository.findById(id);
+    Categorie c = categorieRepository.findById(numeroCategorie);
     
     if (c != null) { return ResponseEntity.ok(c); }
     
@@ -88,11 +96,11 @@ public class CategorieController
 
   @PutMapping(value = "/update/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<Object> update(@PathVariable int id, @RequestBody(required = true) Categorie categorie, HttpServletRequest request) 
+  public ResponseEntity<Object> update(@PathVariable("id") int numeroCategorie, @RequestBody(required = true) Categorie categorie, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Categorie found = categorieRepository.findById(id);
+    Categorie found = categorieRepository.findById(numeroCategorie);
     
     if (found != null)
     {
@@ -119,11 +127,11 @@ public class CategorieController
 
   @GetMapping(value = "/open-poll/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<Object> openPoll(@PathVariable int id, HttpServletRequest request) 
+  public ResponseEntity<Object> openPoll(@PathVariable("id") int numeroCategorie, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Categorie c = categorieRepository.findById(id);
+    Categorie c = categorieRepository.findById(numeroCategorie);
     
     if (c != null)
     {
@@ -142,6 +150,7 @@ public class CategorieController
 
   @GetMapping(value = "/close-polls")
   @PreAuthorize("hasRole('ADMIN')")
+  @Transactional
   public ResponseEntity<Object> closePolls(HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
@@ -152,21 +161,53 @@ public class CategorieController
     {
       if (categories.size() > 0)
       {
+        bulletinRepository.cleanAll();    // supprime les enregistrements sans choix
+        bulletinRepository.validateAll(); // validation automatique de tous les choix
+        
         for (int i = 0; i < categories.size(); i++)
         {
           Categorie c = categories.get(i);
           
           c.setPollable(false);
-          
-          // TODO : valider les votes, dépouiller les votes et calculer les résultats pour chaque catégorie
-          
           c.setComputed(true);
           
           categorieRepository.saveAndFlush(c);
         }
+ 
+        MessagesTransfer mt = new MessagesTransfer();
+        mt.setAlerte(messageSource.getMessage("categories.poll.closed", null, locale));
+
+        return ResponseEntity.ok(mt);
+      }
+    }
+    
+    return ResponseEntity.notFound().build(); 
+  }
+
+
+  @GetMapping(value = "/show-results")
+  @PreAuthorize("hasRole('ADMIN')")
+  public ResponseEntity<Object> showResults(HttpServletRequest request) 
+  { 
+    Locale locale = localeResolver.resolveLocale(request);
+
+    List<Categorie> categories = categorieRepository.findAll(0, true);
+    
+    if (categories != null)
+    {
+      if (categories.size() > 0)
+      {
+        for (int i = 0; i < categories.size(); i++)
+        {
+          Categorie c = categories.get(i);
+          
+          c.setDisplayable(true);
+           
+          categorieRepository.saveAndFlush(c);
+        }
 
         MessagesTransfer mt = new MessagesTransfer();
-        mt.setAlerte(messageSource.getMessage("categorie.polls.closed", null, locale));
+        mt.setAlerte(messageSource.getMessage("categories.poll.displayed", null, locale));
 
         return ResponseEntity.ok(mt);
       }
@@ -177,11 +218,11 @@ public class CategorieController
 
   @DeleteMapping(value = "/delete/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<Object> disableCategorie(@PathVariable int id, HttpServletRequest request) 
+  public ResponseEntity<Object> disableCategorie(@PathVariable("id") int numeroCategorie, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Categorie c = categorieRepository.findById(id);
+    Categorie c = categorieRepository.findById(numeroCategorie);
     
     if (c != null)
     {

+ 6 - 6
src/main/java/fr/triplea/demovote/web/controller/ParticipantController.java

@@ -88,13 +88,13 @@ public class ParticipantController
  
   @GetMapping(value = "/form/{id}")
   @PreAuthorize("hasRole('ORGA')")
-  public ResponseEntity<ParticipantTransfer> getForm(@PathVariable int id, HttpServletRequest request) 
+  public ResponseEntity<ParticipantTransfer> getForm(@PathVariable("id") int numeroParticipant, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
     DateTimeFormatter dtf = this.dtf_fr; if (locale == Locale.ENGLISH) { dtf = this.dft_en; }
     
-    Participant found = participantRepository.findById(id);   
+    Participant found = participantRepository.findById(numeroParticipant);   
     
     if (found != null)
     {
@@ -262,11 +262,11 @@ public class ParticipantController
 
   @PutMapping(value = "/update/{id}")
   @PreAuthorize("hasRole('ORGA')")
-  public ResponseEntity<Object> update(@PathVariable int id, @RequestBody(required = true) ParticipantTransfer participant, final Authentication authentication, HttpServletRequest request) 
+  public ResponseEntity<Object> update(@PathVariable("id") int numeroParticipant, @RequestBody(required = true) ParticipantTransfer participant, final Authentication authentication, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Participant found = participantRepository.findById(id);
+    Participant found = participantRepository.findById(numeroParticipant);
     
     if (found != null)
     {
@@ -358,11 +358,11 @@ public class ParticipantController
 
   @DeleteMapping(value = "/delete/{id}")
   @PreAuthorize("hasRole('ORGA')")
-  public ResponseEntity<Map<String, Boolean>> disableParticipant(@PathVariable int id, HttpServletRequest request) 
+  public ResponseEntity<Map<String, Boolean>> disableParticipant(@PathVariable("id") int numeroParticipant, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Participant found = participantRepository.findById(id);
+    Participant found = participantRepository.findById(numeroParticipant);
     
     if (found != null)
     {

+ 2 - 2
src/main/java/fr/triplea/demovote/web/controller/PreferenceController.java

@@ -48,9 +48,9 @@ public class PreferenceController
 
   @PutMapping(value = "/update/{id}")
   @PreAuthorize("hasRole('USER')")
-  public ResponseEntity<Preference> update(@PathVariable int id, @RequestBody(required = true) Preference preference) 
+  public ResponseEntity<Preference> update(@PathVariable("id") int numeroPreference, @RequestBody(required = true) Preference preference) 
   { 
-    Preference found = preferenceRepository.findById(id);
+    Preference found = preferenceRepository.findById(numeroPreference);
     
     if (found != null)
     {

+ 5 - 5
src/main/java/fr/triplea/demovote/web/controller/PresentationController.java

@@ -238,13 +238,13 @@ public class PresentationController
   
   @GetMapping(value = "/diapos/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<String> getDiaporama(@PathVariable int id, HttpServletRequest request) 
+  public ResponseEntity<String> getDiaporama(@PathVariable("id") int numeroCategorie, HttpServletRequest request) 
   {
     Locale locale = localeResolver.resolveLocale(request);
 
-    Categorie categorie = categorieRepository.findById(id);
+    Categorie categorie = categorieRepository.findById(numeroCategorie);
     
-    List<Presentation> presentations = presentationRepository.findByCategorie(id);
+    List<Presentation> presentations = presentationRepository.findByCategorie(numeroCategorie);
     
     if ((categorie != null) && (presentations != null))
     {
@@ -376,9 +376,9 @@ public class PresentationController
   
   @GetMapping(value = "/list-linked/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public List<ProductionItem> getProductionListLinked(@PathVariable int id) 
+  public List<ProductionItem> getProductionListLinked(@PathVariable("id") int numeroCategorie) 
   {
-    List<ProductionItem> prods = productionRepository.findLinked(id); 
+    List<ProductionItem> prods = productionRepository.findLinked(numeroCategorie); 
     
     if (prods == null) { prods = new ArrayList<ProductionItem>(); }
 

+ 15 - 15
src/main/java/fr/triplea/demovote/web/controller/ProductionController.java

@@ -99,11 +99,11 @@ public class ProductionController
   @GetMapping(value = "/file/{id}")
   @PreAuthorize("hasRole('USER')")
   @ResponseBody
-  public ResponseEntity<Resource> getFile(@PathVariable int id, final Authentication authentication) 
+  public ResponseEntity<Resource> getFile(@PathVariable("id") int numeroProduction, final Authentication authentication) 
   {
     // TODO : après résultats affichés, download autorisé pour tous
     
-    Production p = productionRepository.findById(id);
+    Production p = productionRepository.findById(numeroProduction);
     
     if (p != null) 
     { 
@@ -143,9 +143,9 @@ public class ProductionController
 
   @GetMapping(value = "/form/{id}")
   @PreAuthorize("hasRole('USER')")
-  public ResponseEntity<Production> getForm(@PathVariable int id, final Authentication authentication)
+  public ResponseEntity<Production> getForm(@PathVariable("id") int numeroProduction, final Authentication authentication)
   { 
-    ProductionShort p = productionRepository.findByIdWithoutArchive(id);
+    ProductionShort p = productionRepository.findByIdWithoutArchive(numeroProduction);
     
     if (p != null) 
     {
@@ -162,9 +162,9 @@ public class ProductionController
 
   @GetMapping(value = "/formfile/{id}")
   @PreAuthorize("hasRole('USER')")
-  public ResponseEntity<ProductionFile> getFormFile(@PathVariable int id, final Authentication authentication)
+  public ResponseEntity<ProductionFile> getFormFile(@PathVariable("id") int numeroProduction, final Authentication authentication)
   { 
-    ProductionFile p = productionRepository.findByIdForUpload(id);
+    ProductionFile p = productionRepository.findByIdForUpload(numeroProduction);
     
     if (p != null) 
     { 
@@ -223,11 +223,11 @@ public class ProductionController
  
   @PutMapping(value = "/update/{id}")
   @PreAuthorize("hasRole('USER')")
-  public ResponseEntity<Object> update(@PathVariable int id, @RequestBody(required = true) ProductionUpdate production, final Authentication authentication, HttpServletRequest request) 
+  public ResponseEntity<Object> update(@PathVariable("id") int numeroProduction, @RequestBody(required = true) ProductionUpdate production, final Authentication authentication, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Production found = productionRepository.findById(id);
+    Production found = productionRepository.findById(numeroProduction);
     
     if (found != null)
     {
@@ -275,11 +275,11 @@ public class ProductionController
 
   @PostMapping(value = "/upload-chunk/{id}")
   @PreAuthorize("hasRole('USER')")
-  public ResponseEntity<Object> upload_chunk(@PathVariable int id, @RequestParam String fileName, @RequestParam int chunkIndex, @RequestParam MultipartFile chunkData, final Authentication authentication, HttpServletRequest request) 
+  public ResponseEntity<Object> upload_chunk(@PathVariable("id") int numeroProduction, @RequestParam String fileName, @RequestParam int chunkIndex, @RequestParam MultipartFile chunkData, final Authentication authentication, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Production found = productionRepository.findById(id);
+    Production found = productionRepository.findById(numeroProduction);
     
     if (found != null)
     {
@@ -291,7 +291,7 @@ public class ProductionController
       {
         MessagesTransfer mt = new MessagesTransfer();
 
-        File dir = new File("../uploads-temp/" + id + "-" + fileName);
+        File dir = new File("../uploads-temp/" + numeroProduction + "-" + fileName);
         
         if (!dir.exists()) { dir.mkdirs(); }
 
@@ -445,11 +445,11 @@ public class ProductionController
 
   @DeleteMapping(value = "/delete/{id}")
   @PreAuthorize("hasRole('USER')")
-  public ResponseEntity<Object> disableProduction(@PathVariable int id, final Authentication authentication, HttpServletRequest request) 
+  public ResponseEntity<Object> disableProduction(@PathVariable("id") int numeroProduction, final Authentication authentication, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Production found = productionRepository.findById(id);
+    Production found = productionRepository.findById(numeroProduction);
     
     if (found != null)
     {
@@ -457,7 +457,7 @@ public class ProductionController
 
       if ((numeroUser == 0) || (found.getParticipant().getNumeroParticipant() == numeroUser))
       {
-        boolean absence = (bulletinRepository.countIfProductionVoted(id) == 0);
+        boolean absence = (bulletinRepository.countIfProductionVoted(numeroProduction) == 0);
         
         if (absence)
         {
@@ -465,7 +465,7 @@ public class ProductionController
           
           productionRepository.saveAndFlush(found);
    
-          Presentation presente = presentationRepository.findByProduction(id);
+          Presentation presente = presentationRepository.findByProduction(numeroProduction);
           
           if (presente != null) { presentationRepository.delete(presente); }
           

+ 4 - 4
src/main/java/fr/triplea/demovote/web/controller/VariableController.java

@@ -57,9 +57,9 @@ public class VariableController
  
   @GetMapping(value = "/form/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<Variable> getForm(@PathVariable int id) 
+  public ResponseEntity<Variable> getForm(@PathVariable("id") int numeroVariable) 
   { 
-    Variable v = variableRepository.findById(id);
+    Variable v = variableRepository.findById(numeroVariable);
     
     if (v != null) { return ResponseEntity.ok(v); } 
     
@@ -91,11 +91,11 @@ public class VariableController
  
   @PutMapping(value = "/update/{id}")
   @PreAuthorize("hasRole('ADMIN')")
-  public ResponseEntity<Object> update(@PathVariable int id, @RequestBody(required = true) Variable variable, HttpServletRequest request) 
+  public ResponseEntity<Object> update(@PathVariable("id") int numeroVariable, @RequestBody(required = true) Variable variable, HttpServletRequest request) 
   { 
     Locale locale = localeResolver.resolveLocale(request);
 
-    Variable found = variableRepository.findById(id);
+    Variable found = variableRepository.findById(numeroVariable);
     
     if (found != null)
     {

+ 100 - 0
src/main/java/fr/triplea/demovote/web/service/BulletinService.java

@@ -0,0 +1,100 @@
+package fr.triplea.demovote.web.service;
+
+import java.util.Comparator;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import fr.triplea.demovote.dao.BulletinRepository;
+import fr.triplea.demovote.dao.ProductionRepository;
+import fr.triplea.demovote.dao.VariableRepository;
+import fr.triplea.demovote.dto.BulletinShort;
+import fr.triplea.demovote.dto.ProductionVote;
+import jakarta.annotation.PostConstruct;
+
+@Service
+public class BulletinService 
+{
+
+  @Autowired
+  private VariableRepository variableRepository;
+
+  @Autowired
+  private BulletinRepository bulletinRepository;
+  
+  @Autowired
+  private ProductionRepository productionRepository;
+ 
+  int points_position_01 = 3;
+  int points_position_02 = 2;
+  int points_position_03 = 1;
+  int points_position_04 = 0;
+  int points_position_05 = 0;
+  int points_position_06 = 0;
+  int points_position_07 = 0;
+  int points_position_08 = 0;
+  int points_position_09 = 0;
+  int points_position_10 = 0;
+  
+  boolean init = false;
+  
+  @PostConstruct
+  public void init()
+  {
+    if (init == false)
+    {
+      points_position_01 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_01"));
+      points_position_02 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_02"));
+      points_position_03 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_03"));
+      points_position_04 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_04"));
+      points_position_05 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_05"));
+      points_position_06 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_06"));
+      points_position_07 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_07"));
+      points_position_08 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_08"));
+      points_position_09 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_09"));
+      points_position_10 = Integer.parseInt(variableRepository.findByTypeAndCode("Résultats", "POINTS_POSITION_10"));
+
+      init = true;
+    }
+  }
+  
+  public List<ProductionVote> decompterVotes(int numeroCategorie)
+  {
+    List<BulletinShort> bulletins = bulletinRepository.findByCategorie(numeroCategorie);
+    
+    List<ProductionVote> productions = productionRepository.findForCalculation(numeroCategorie);
+    
+    if ((bulletins != null) && (productions != null))
+    {
+      if ((bulletins.size() > 0) && (productions.size() > 0))
+      {
+        for (int b = 0; b < bulletins.size(); b++)
+        {
+          BulletinShort vote = bulletins.get(b);
+ 
+          for (int p = 0; p < productions.size(); p++)
+          {
+            ProductionVote prod = productions.get(p);
+            
+            if (prod.getNumeroProduction() == vote.getNumeroProduction01()) { prod.addPoints(points_position_01); prod.setFirst(); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction02()) { prod.addPoints(points_position_02); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction03()) { prod.addPoints(points_position_03); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction04()) { prod.addPoints(points_position_04); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction05()) { prod.addPoints(points_position_05); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction06()) { prod.addPoints(points_position_06); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction07()) { prod.addPoints(points_position_07); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction08()) { prod.addPoints(points_position_08); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction09()) { prod.addPoints(points_position_09); }
+            if (prod.getNumeroProduction() == vote.getNumeroProduction10()) { prod.addPoints(points_position_10); }
+          }
+        }
+        
+        productions.sort(Comparator.comparing(ProductionVote::getNombrePoints).thenComparing(ProductionVote::getNombreFirst));
+      }
+    }
+    
+    return productions;
+  }
+    
+}

+ 3 - 0
src/main/resources/langs/messages_en.properties

@@ -11,6 +11,9 @@ participant.deleted=This entrant was removed from the list.
 categorie.created=The new compo was correctly created.
 categorie.updated=The compo informations were updated.
 categorie.deleted=This compo was removed.
+categorie.poll.opened=This compo is now opened for polling.
+categories.poll.closed=All compos polls have been closed.
+categories.poll.displayed=All compos resultats are now available for entrants.
 
 variable.created=The new environment variable was correctly created.
 variable.updated=The variable datas were updated.

+ 3 - 0
src/main/resources/langs/messages_fr.properties

@@ -11,6 +11,9 @@ participant.deleted=Le participant a 
 categorie.created=La nouvelle catégorie a bien été enregistrée.
 categorie.updated=Les informations de cette catégorie ont bien été mises à jour.
 categorie.deleted=La catégorie a été retirée.
+categorie.poll.opened=Cette catégorie est maintenant ouverte aux votes.
+categories.poll.closed=La clôture générale a été décrétée.
+categories.poll.displayed=Les résultats sont maintenant disponibles aux participants.
 
 variable.created=La nouvelle variable d'environnement a bien été enregistrée.
 variable.updated=Les données de cette variable ont bien été mises à jour.