diff --git a/.gitea/workflows/deploy_in_prod.yml b/.gitea/workflows/deploy_in_prod.yml
index 9e706ea..1c31f63 100644
--- a/.gitea/workflows/deploy_in_prod.yml
+++ b/.gitea/workflows/deploy_in_prod.yml
@@ -45,6 +45,12 @@ jobs:
mkdir -p src/main/resources/META-INF/
mv src/main/webapp/dist src/main/resources/META-INF/resources
+ - name: Build backend make_pdf tool
+ run: |
+ cd src/main/pdf_gen
+ mvn clean compile assembly:single
+ cd ../../..
+
- name: Build backend
run: |
chmod 740 mvnw
@@ -57,7 +63,7 @@ jobs:
username: ${{ secrets.SSH_USER }}
port: ${{ secrets.SSH_PORT }}
key: ${{ secrets.SSH_KEY }}
- source: "target/*-runner,src/main/resources/cacerts,src/main/docker/Dockerfile.native,docker-compose.yml,.dockerignore"
+ source: "target/*-runner,src/main/resources/cacerts,src/main/docker/Dockerfile.native,docker-compose.yml,.dockerignore,src/main/pdf_gen/target/pdf_gen-*.jar"
target: ${{ secrets.TARGET_DIR }} # Need to create it first on the VPS
- name: Re-start ffsaf container
diff --git a/pom.xml b/pom.xml
index ed769d2..22a16d3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -75,11 +75,6 @@
2.0.4
-
- io.quarkiverse.openpdf
- quarkus-openpdf
- 3.1.2
-
io.quarkus
quarkus-junit5
@@ -211,7 +206,7 @@
false
- --initialize-at-run-time=com.fasterxml.jackson.databind.ext.DOMDeserializer\,com.lowagie
+ --initialize-at-run-time=com.fasterxml.jackson.databind.ext.DOMDeserializer
true
false
diff --git a/src/main/docker/Dockerfile.native b/src/main/docker/Dockerfile.native
index 06f4983..aae442e 100644
--- a/src/main/docker/Dockerfile.native
+++ b/src/main/docker/Dockerfile.native
@@ -14,13 +14,16 @@
# docker run -i --rm -p 8080:8080 quarkus/ffsaf-site
#
###
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9
+# replace FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9 for jvm need sub application (ie. make_pdf)
+FROM registry.access.redhat.com/ubi8/openjdk-17:1.18
+
WORKDIR /work/
RUN chown 1001 /work \
&& chmod "g+rwX" /work \
&& chown 1001:root /work
COPY --chown=1001:root target/*-runner /work/application
COPY --chown=1001:root src/main/resources/cacerts /work/cacerts
+COPY --chown=1001:root src/main/pdf_gen/target/pdf_gen-*.jar /work/make_pdf.jar
RUN mkdir /work/media && chown -R 1001:root /work/media
EXPOSE 8080
diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java
index af3415d..7d8e1a9 100644
--- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java
+++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java
@@ -1,10 +1,5 @@
package fr.titionfire.ffsaf.domain.service;
-import com.lowagie.text.*;
-import com.lowagie.text.pdf.BaseFont;
-import com.lowagie.text.pdf.PdfPCell;
-import com.lowagie.text.pdf.PdfPTable;
-import com.lowagie.text.pdf.PdfWriter;
import fr.titionfire.ffsaf.data.model.ClubModel;
import fr.titionfire.ffsaf.data.model.LicenceModel;
import fr.titionfire.ffsaf.data.model.MembreModel;
@@ -38,18 +33,20 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.hibernate.reactive.mutiny.Mutiny;
+import org.jboss.logging.Logger;
import java.io.*;
-import java.nio.file.Files;
-import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
@WithSession
@ApplicationScoped
public class MembreService {
+ private static final Logger LOGGER = Logger.getLogger(MembreService.class);
@Inject
CombRepository repository;
@@ -66,6 +63,9 @@ public class MembreService {
@ConfigProperty(name = "upload_dir")
String media;
+ @ConfigProperty(name = "pdf-maker.jar-path")
+ String pdfMakerJarPath;
+
public SimpleCombModel find(int licence, String np) throws Throwable {
return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() ->
repository.find("licence = ?1 AND (lname ILIKE ?2 OR fname ILIKE ?2)",
@@ -315,11 +315,11 @@ public class MembreService {
.findFirst()
.orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours"));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
- make_pdf(m, out, licence);
+ byte[] buff = make_pdf(m, licence);
+ if (buff == null)
+ throw new IOException("Error making pdf");
- byte[] buff = out.toByteArray();
String mimeType = "application/pdf";
Response.ResponseBuilder resp = Response.ok(buff);
@@ -336,185 +336,79 @@ public class MembreService {
}));
}
- private void make_pdf(MembreModel m, ByteArrayOutputStream out, LicenceModel licence) throws IOException {
- SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
- Document document = new Document();
- PdfWriter.getInstance(document, out);
- document.open();
+ private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException {
+ List cmd = new ArrayList<>();
+ cmd.add("java");
+ cmd.add("-jar");
+ cmd.add(pdfMakerJarPath);
- document.addCreator("FFSAF");
- document.addTitle(
- "Attestation d'adhésion " + Utils.getSaison() + "-" + (Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname());
- document.addCreationDate();
- document.addProducer("https://www.ffsaf.fr");
+ UUID uuid = UUID.randomUUID();
- InputStream fontStream = MembreService.class.getClassLoader().getResourceAsStream("asset/DMSans-Regular.ttf");
- if (fontStream == null) {
- throw new IOException("Font file not found");
- }
- BaseFont customFont = BaseFont.createFont("asset/DMSans-Regular.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED, true,
- null, fontStream.readAllBytes());
+ cmd.add("/tmp/" + uuid + ".pdf");
+ cmd.add(m.getFname());
+ cmd.add(m.getLname());
+ cmd.add(m.getGenre().str);
+ cmd.add(m.getCategorie().getName());
+ cmd.add(licence.getCertificate() == null ? "" : licence.getCertificate());
+ cmd.add(Utils.getSaison() + "");
+ cmd.add(m.getLicence() + "");
+ cmd.add(m.getClub().getName());
+ cmd.add(m.getClub().getNo_affiliation() + "");
+ cmd.add(m.getBirth_date() == null ? "--" : new SimpleDateFormat("dd/MM/yyyy").format(m.getBirth_date()));
- // Adding font
- Font headerFont = new Font(customFont, 26, Font.BOLD);
- Font subHeaderFont = new Font(customFont, 16, Font.BOLD);
- Font bigFont = new Font(customFont, 18, Font.BOLD);
- Font bodyFont = new Font(customFont, 15, Font.BOLD);
- Font smallFont = new Font(customFont, 10, Font.NORMAL);
-
- // Creating the main table
- PdfPTable mainTable = new PdfPTable(2);
- mainTable.setWidthPercentage(100);
- mainTable.setSpacingBefore(20f);
- mainTable.setSpacingAfter(0f);
- mainTable.setWidths(new float[]{120, 300});
- mainTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
-
- // Adding logo
- Image logo = Image.getInstance(
- Objects.requireNonNull(
- getClass().getClassLoader().getResource("asset/FFSSAF-bord-blanc-fond-transparent.png")));
- logo.scaleToFit(120, 120);
- PdfPCell logoCell = new PdfPCell(logo);
- logoCell.setHorizontalAlignment(Element.ALIGN_CENTER);
- logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
- logoCell.setPadding(0);
- logoCell.setRowspan(1);
- logoCell.setBorder(PdfPCell.NO_BORDER);
- mainTable.addCell(logoCell);
-
- // Adding header
- PdfPCell headerCell = new PdfPCell(new Phrase("FEDERATION FRANCE\nSOFT ARMORED FIGHTING", headerFont));
- headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
- headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
- headerCell.setBorder(PdfPCell.NO_BORDER);
- mainTable.addCell(headerCell);
-
- document.add(mainTable);
-
- Paragraph addr = new Paragraph("5 place de la Barreyre\n63320 Champeix", subHeaderFont);
- addr.setAlignment(Element.ALIGN_CENTER);
- addr.setSpacingAfter(2f);
- document.add(addr);
-
- Paragraph association = new Paragraph("Association loi 1901 W633001595\nSIRET 829 458 355 00015", smallFont);
- association.setAlignment(Element.ALIGN_CENTER);
- document.add(association);
-
- // Adding spacing
- document.add(new Paragraph("\n\n"));
-
- // Adding attestation
- PdfPTable attestationTable = new PdfPTable(1);
- attestationTable.setWidthPercentage(60);
- PdfPCell attestationCell = new PdfPCell(
- new Phrase("ATTESTATION D'ADHESION\nSaison " + Utils.getSaison() + "-" + (Utils.getSaison() + 1),
- bigFont));
- attestationCell.setHorizontalAlignment(Element.ALIGN_CENTER);
- attestationCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
- attestationCell.setPadding(20f);
- attestationTable.addCell(attestationCell);
- document.add(attestationTable);
-
- // Adding spacing
- document.add(new Paragraph("\n\n"));
-
- // Adding member details table
- PdfPTable memberTable = new PdfPTable(2);
- memberTable.setWidthPercentage(100);
- memberTable.setWidths(new float[]{130, 300});
- memberTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
-
- // Adding member photo
- Image memberPhoto;
FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + ".");
File[] files = new File(media, "ppMembre").listFiles(filter);
if (files != null && files.length > 0) {
File file = files[0];
- memberPhoto = Image.getInstance(Files.readAllBytes(file.toPath()));
+ cmd.add(file.getAbsolutePath());
} else {
- memberPhoto = Image.getInstance(
- Objects.requireNonNull(getClass().getClassLoader().getResource("asset/blank-profile-picture.png")));
+ cmd.add("/dev/null");
}
- memberPhoto.scaleToFit(120, 150);
- PdfPCell photoCell = new PdfPCell(memberPhoto);
- photoCell.setHorizontalAlignment(Element.ALIGN_CENTER);
- photoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
- photoCell.setRowspan(5);
- photoCell.setBorder(PdfPCell.NO_BORDER);
- memberTable.addCell(photoCell);
- String[] cert;
- if (licence.getCertificate() != null && !licence.getCertificate().isBlank()) {
- cert = licence.getCertificate().split("¤");
- if (cert.length <= 1){
- cert = new String[]{licence.getCertificate(), "--"};
- }else{
- try {
- cert[1] = sdf.format(new SimpleDateFormat("yyyy-MM-dd").parse(cert[1]));
- } catch (ParseException e) {
- cert[1] = "--";
- }
+ ProcessBuilder processBuilder = new ProcessBuilder(cmd);
+ processBuilder.redirectErrorStream(true);
+ Process process = processBuilder.start();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+ StringBuilder builder = new StringBuilder();
+ Thread t = new Thread(() -> {
+ try {
+ String line;
+ while ((line = reader.readLine()) != null)
+ builder.append(line).append("\n");
+ } catch (Exception ignored) {
}
+ });
+ t.start();
+
+ int code = -1;
+ if (!process.waitFor(30, TimeUnit.SECONDS)) {
+ process.destroy();
+ builder.append("Timeout...");
} else {
- cert = new String[]{"--", "--"};
+ code = process.exitValue();
}
- // Adding member details
- memberTable.addCell(new Phrase("NOM : " + m.getLname().toUpperCase(), bodyFont));
- memberTable.addCell(new Phrase("Prénom : " + m.getFname(), bodyFont));
- memberTable.addCell(new Phrase("Licence n° : " + m.getLicence(), bodyFont));
- memberTable.addCell(new Phrase("Certificat médical par " + cert[0] + ", le " + cert[1], bodyFont));
- memberTable.addCell(new Phrase("")); // Empty cell for spacing
+ if (t.isAlive())
+ t.interrupt();
- document.add(memberTable);
+ LOGGER.debug("PDF maker: " + builder);
- // Adding spacing
- document.add(new Paragraph("\n"));
-
- Paragraph memberClub = new Paragraph("CLUB : " + m.getClub().getName().toUpperCase(), bodyFont);
- document.add(memberClub);
-
- Paragraph memberClubNumber = new Paragraph("N° club : " + m.getClub().getNo_affiliation(), bodyFont);
- document.add(memberClubNumber);
-
- // Adding spacing
- document.add(new Paragraph("\n"));
-
- Paragraph memberBirthdate = new Paragraph(
- "Date de naissance : " + ((m.getBirth_date() == null) ? "--" : sdf.format(m.getBirth_date())),
- bodyFont);
- document.add(memberBirthdate);
-
- Paragraph memberGender = new Paragraph("Sexe : " + m.getGenre().str, bodyFont);
- document.add(memberGender);
-
- Paragraph memberAgeCategory = new Paragraph("Catégorie d'âge : " + m.getCategorie().getName(), bodyFont);
- document.add(memberAgeCategory);
-
- // Adding spacing
- document.add(new Paragraph("\n\n"));
-
- // Adding attestation text
- PdfPTable textTable = new PdfPTable(1);
- textTable.setWidthPercentage(100);
- PdfPCell textCell = new PdfPCell(new Phrase(
- """
- Ce document atteste que l’adhérent
- - est valablement enregistré auprès de la FFSAF,
- - est assuré dans sa pratique du Béhourd Léger et du Battle Arc en entraînement et en compétition.
-
- Il peut donc s’inscrire à tout tournoi organisé sous l’égide de la FFSAF s’il remplit les éventuelles
- conditions de qualification.
- Il peut participer à tout entraînement dans un club affilié si celui ci autorise les visiteurs.""",
- smallFont));
- textCell.setHorizontalAlignment(Element.ALIGN_LEFT);
- textCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
- textCell.setBorder(PdfPCell.NO_BORDER);
- textTable.addCell(textCell);
- document.add(textTable);
-
- // Close the document
- document.close();
+ if (code != 0) {
+ throw new IOException("Error code: " + code);
+ } else {
+ File file = new File("/tmp/" + uuid + ".pdf");
+ try (FileInputStream fis = new FileInputStream(file)) {
+ byte[] buff = fis.readAllBytes();
+ //noinspection ResultOfMethodCallIgnored
+ file.delete();
+ return buff;
+ } catch (IOException e) {
+ //noinspection ResultOfMethodCallIgnored
+ file.delete();
+ }
+ return null;
+ }
}
}
diff --git a/src/main/pdf_gen/.gitignore b/src/main/pdf_gen/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/src/main/pdf_gen/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/src/main/pdf_gen/pom.xml b/src/main/pdf_gen/pom.xml
new file mode 100644
index 0000000..7e4c3bf
--- /dev/null
+++ b/src/main/pdf_gen/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ fr.titionfire
+ pdf_gen
+ 1.0-SNAPSHOT
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ com.github.librepdf
+ openpdf
+ 2.0.3
+
+
+
+
+
+
+ maven-assembly-plugin
+
+
+
+ fr.titionfire.Main
+
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/pdf_gen/src/main/java/fr/titionfire/Main.java b/src/main/pdf_gen/src/main/java/fr/titionfire/Main.java
new file mode 100644
index 0000000..e6ba272
--- /dev/null
+++ b/src/main/pdf_gen/src/main/java/fr/titionfire/Main.java
@@ -0,0 +1,223 @@
+package fr.titionfire;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfWriter;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Objects;
+
+public class Main {
+ public static void main(String[] args) {
+ PdfData pdfData = new PdfData();
+
+ File dest = new File(args[0]);
+ pdfData.fname = args[1];
+ pdfData.lname = args[2];
+ pdfData.genre = args[3];
+ pdfData.categorie = args[4];
+ pdfData.certificate = args[5];
+ pdfData.saison = Integer.parseInt(args[6]);
+ pdfData.licence = Integer.parseInt(args[7]);
+ pdfData.club = args[8];
+ pdfData.club_no = Integer.parseInt(args[9]);
+ pdfData.birth_date = args[10];
+ pdfData.photo_file = new File(args[11]);
+
+ try {
+ FileOutputStream out = new FileOutputStream(dest);
+ new Main().make_pdf(pdfData, out);
+ } catch (IOException ignored) {
+ ignored.printStackTrace();
+ System.exit(1);
+ }
+
+ System.out.println("PDF generated successfully");
+ System.exit(0);
+ }
+
+ private void make_pdf(PdfData pdfData, FileOutputStream out) throws IOException {
+ SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
+ Document document = new Document();
+ PdfWriter.getInstance(document, out);
+ document.open();
+
+ document.addCreator("FFSAF");
+ document.addTitle(
+ "Attestation d'adhésion " + pdfData.saison + "-" + (pdfData.saison + 1) + " de " + pdfData.lname + " " + pdfData.fname);
+ document.addCreationDate();
+ document.addProducer("https://www.ffsaf.fr");
+
+ InputStream fontStream = Main.class.getClassLoader().getResourceAsStream("DMSans-Regular.ttf");
+ if (fontStream == null) {
+ throw new IOException("Font file not found");
+ }
+ BaseFont customFont = BaseFont.createFont("DMSans-Regular.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED, true,
+ null, fontStream.readAllBytes());
+
+ // Adding font
+ Font headerFont = new Font(customFont, 26, Font.BOLD);
+ Font subHeaderFont = new Font(customFont, 16, Font.BOLD);
+ Font bigFont = new Font(customFont, 18, Font.BOLD);
+ Font bodyFont = new Font(customFont, 15, Font.BOLD);
+ Font smallFont = new Font(customFont, 10, Font.NORMAL);
+
+ // Creating the main table
+ PdfPTable mainTable = new PdfPTable(2);
+ mainTable.setWidthPercentage(100);
+ mainTable.setSpacingBefore(20f);
+ mainTable.setSpacingAfter(0f);
+ mainTable.setWidths(new float[]{120, 300});
+ mainTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
+
+ // Adding logo
+ Image logo = Image.getInstance(
+ Objects.requireNonNull(
+ getClass().getClassLoader().getResource("FFSSAF-bord-blanc-fond-transparent.png")));
+ logo.scaleToFit(120, 120);
+ PdfPCell logoCell = new PdfPCell(logo);
+ logoCell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ logoCell.setPadding(0);
+ logoCell.setRowspan(1);
+ logoCell.setBorder(PdfPCell.NO_BORDER);
+ mainTable.addCell(logoCell);
+
+ // Adding header
+ PdfPCell headerCell = new PdfPCell(new Phrase("FEDERATION FRANCE\nSOFT ARMORED FIGHTING", headerFont));
+ headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ headerCell.setBorder(PdfPCell.NO_BORDER);
+ mainTable.addCell(headerCell);
+
+ document.add(mainTable);
+
+ Paragraph addr = new Paragraph("5 place de la Barreyre\n63320 Champeix", subHeaderFont);
+ addr.setAlignment(Element.ALIGN_CENTER);
+ addr.setSpacingAfter(2f);
+ document.add(addr);
+
+ Paragraph association = new Paragraph("Association loi 1901 W633001595\nSIRET 829 458 355 00015", smallFont);
+ association.setAlignment(Element.ALIGN_CENTER);
+ document.add(association);
+
+ // Adding spacing
+ document.add(new Paragraph("\n\n"));
+
+ // Adding attestation
+ PdfPTable attestationTable = new PdfPTable(1);
+ attestationTable.setWidthPercentage(60);
+ PdfPCell attestationCell = new PdfPCell(
+ new Phrase("ATTESTATION D'ADHESION\nSaison " + pdfData.saison + "-" + (pdfData.saison + 1),
+ bigFont));
+ attestationCell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ attestationCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ attestationCell.setPadding(20f);
+ attestationTable.addCell(attestationCell);
+ document.add(attestationTable);
+
+ // Adding spacing
+ document.add(new Paragraph("\n\n"));
+
+ // Adding member details table
+ PdfPTable memberTable = new PdfPTable(2);
+ memberTable.setWidthPercentage(100);
+ memberTable.setWidths(new float[]{130, 300});
+ memberTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
+
+ // Adding member photo
+ Image memberPhoto;
+ if (pdfData.photo_file != null && pdfData.photo_file.exists()) {
+ memberPhoto = Image.getInstance(Files.readAllBytes(pdfData.photo_file.toPath()));
+ } else {
+ memberPhoto = Image.getInstance(
+ Objects.requireNonNull(getClass().getClassLoader().getResource("blank-profile-picture.png")));
+ }
+ memberPhoto.scaleToFit(120, 150);
+ PdfPCell photoCell = new PdfPCell(memberPhoto);
+ photoCell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ photoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ photoCell.setRowspan(5);
+ photoCell.setBorder(PdfPCell.NO_BORDER);
+ memberTable.addCell(photoCell);
+
+ String[] cert;
+ if (pdfData.certificate != null && !pdfData.certificate.isBlank()) {
+ cert = pdfData.certificate.split("¤");
+ if (cert.length <= 1) {
+ cert = new String[]{pdfData.certificate, "--"};
+ } else {
+ try {
+ cert[1] = sdf.format(new SimpleDateFormat("yyyy-MM-dd").parse(cert[1]));
+ } catch (ParseException e) {
+ cert[1] = "--";
+ }
+ }
+ } else {
+ cert = new String[]{"--", "--"};
+ }
+
+ // Adding member details
+ memberTable.addCell(new Phrase("NOM : " + pdfData.lname.toUpperCase(), bodyFont));
+ memberTable.addCell(new Phrase("Prénom : " + pdfData.fname, bodyFont));
+ memberTable.addCell(new Phrase("Licence n° : " + pdfData.licence, bodyFont));
+ memberTable.addCell(new Phrase("Certificat médical par " + cert[0] + ", le " + cert[1], bodyFont));
+ memberTable.addCell(new Phrase("")); // Empty cell for spacing
+
+ document.add(memberTable);
+
+ // Adding spacing
+ document.add(new Paragraph("\n"));
+
+ Paragraph memberClub = new Paragraph("CLUB : " + pdfData.club.toUpperCase(), bodyFont);
+ document.add(memberClub);
+
+ Paragraph memberClubNumber = new Paragraph("N° club : " + pdfData.club_no, bodyFont);
+ document.add(memberClubNumber);
+
+ // Adding spacing
+ document.add(new Paragraph("\n"));
+
+ Paragraph memberBirthdate = new Paragraph("Date de naissance : " + pdfData.birth_date, bodyFont);
+ document.add(memberBirthdate);
+
+ Paragraph memberGender = new Paragraph("Sexe : " + pdfData.genre, bodyFont);
+ document.add(memberGender);
+
+ Paragraph memberAgeCategory = new Paragraph("Catégorie d'âge : " + pdfData.categorie, bodyFont);
+ document.add(memberAgeCategory);
+
+ // Adding spacing
+ document.add(new Paragraph("\n\n"));
+
+ // Adding attestation text
+ PdfPTable textTable = new PdfPTable(1);
+ textTable.setWidthPercentage(100);
+ PdfPCell textCell = new PdfPCell(new Phrase(
+ """
+ Ce document atteste que l’adhérent
+ - est valablement enregistré auprès de la FFSAF,
+ - est assuré dans sa pratique du Béhourd Léger et du Battle Arc en entraînement et en compétition.
+
+ Il peut donc s’inscrire à tout tournoi organisé sous l’égide de la FFSAF s’il remplit les éventuelles
+ conditions de qualification.
+ Il peut participer à tout entraînement dans un club affilié si celui ci autorise les visiteurs.""",
+ smallFont));
+ textCell.setHorizontalAlignment(Element.ALIGN_LEFT);
+ textCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ textCell.setBorder(PdfPCell.NO_BORDER);
+ textTable.addCell(textCell);
+ document.add(textTable);
+
+ // Close the document
+ document.close();
+ }
+}
\ No newline at end of file
diff --git a/src/main/pdf_gen/src/main/java/fr/titionfire/PdfData.java b/src/main/pdf_gen/src/main/java/fr/titionfire/PdfData.java
new file mode 100644
index 0000000..7e0a4f6
--- /dev/null
+++ b/src/main/pdf_gen/src/main/java/fr/titionfire/PdfData.java
@@ -0,0 +1,19 @@
+package fr.titionfire;
+
+import java.io.File;
+import java.util.Date;
+
+public class PdfData {
+ int saison;
+ int licence;
+ String fname;
+ String lname;
+ String club;
+ int club_no;
+ String categorie;
+ String genre;
+ String birth_date;
+ String certificate;
+
+ File photo_file;
+}
diff --git a/src/main/resources/asset/DMSans-Regular.ttf b/src/main/pdf_gen/src/main/resources/DMSans-Regular.ttf
similarity index 100%
rename from src/main/resources/asset/DMSans-Regular.ttf
rename to src/main/pdf_gen/src/main/resources/DMSans-Regular.ttf
diff --git a/src/main/resources/asset/FFSSAF-bord-blanc-fond-transparent.png b/src/main/pdf_gen/src/main/resources/FFSSAF-bord-blanc-fond-transparent.png
similarity index 100%
rename from src/main/resources/asset/FFSSAF-bord-blanc-fond-transparent.png
rename to src/main/pdf_gen/src/main/resources/FFSSAF-bord-blanc-fond-transparent.png
diff --git a/src/main/pdf_gen/src/main/resources/blank-profile-picture.png b/src/main/pdf_gen/src/main/resources/blank-profile-picture.png
new file mode 100644
index 0000000..9e34293
Binary files /dev/null and b/src/main/pdf_gen/src/main/resources/blank-profile-picture.png differ
diff --git a/src/main/resources/META-INF/native-image/com/lowagie/reflect-config.json b/src/main/resources/META-INF/native-image/com/lowagie/reflect-config.json
deleted file mode 100644
index 25ed93f..0000000
--- a/src/main/resources/META-INF/native-image/com/lowagie/reflect-config.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
- {
- "name": "com.lowagie.text.pdf.GrayColor",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- }
-]
diff --git a/src/main/resources/META-INF/native-image/fr/titionfire/reflect-config.json b/src/main/resources/META-INF/native-image/fr/titionfire/reflect-config.json
deleted file mode 100644
index 6dabb2f..0000000
--- a/src/main/resources/META-INF/native-image/fr/titionfire/reflect-config.json
+++ /dev/null
@@ -1,44 +0,0 @@
-[
- {
- "name": "fr.titionfire.ffsaf",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- },
- {
- "name": "sun.font.Font2D",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- },
- {
- "name": "sun.font.CompositeFont",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- },
- {
- "name": "sun.awt.SunHints",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- },
- {
- "name": "java.awt.RenderingHints",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- },
- {
- "name": "sun.font.FontUtilities",
- "allDeclaredConstructors": true,
- "allPublicConstructors": true,
- "allDeclaredMethods": true,
- "allPublicMethods": true
- }
-]
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index ee898d3..245f2f5 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -14,6 +14,8 @@ quarkus.hibernate-orm.physical-naming-strategy=fr.titionfire.ffsaf.data.SafcaNam
quarkus.http.cors=true
quarkus.quartz.start-mode=forced
+%dev.pdf-maker.jar-path=src\\main\\pdf_gen\\target\\pdf_gen-1.0-SNAPSHOT-jar-with-dependencies.jar
+pdf-maker.jar-path=/work/make_pdf.jar
%dev.quarkus.log.min-level=ALL
%dev.quarkus.log.category."fr.titionfire.ffsaf".level=ALL
diff --git a/src/main/webapp/src/pages/admin/member/LicenceCard.jsx b/src/main/webapp/src/pages/admin/member/LicenceCard.jsx
index 5c677ed..fde03d3 100644
--- a/src/main/webapp/src/pages/admin/member/LicenceCard.jsx
+++ b/src/main/webapp/src/pages/admin/member/LicenceCard.jsx
@@ -92,6 +92,7 @@ function sendLicence(event, dispatch) {
const formData = new FormData(event.target);
formData.set('licence', event.target.licence?.value?.length > 0 ? event.target.licence?.value : null)
+ formData.set('certificate', `${event.target.certificateBy?.value}¤${event.target.certificateDate?.value}`)
toast.promise(
apiAxios.post(`/licence/${formData.get('membre')}`, formData),