Merge pull request 'fix(build): create sub-app make_pdf' (#25) from dev into master
Reviewed-on: #25
This commit is contained in:
commit
9ecd5c4939
@ -45,6 +45,12 @@ jobs:
|
|||||||
mkdir -p src/main/resources/META-INF/
|
mkdir -p src/main/resources/META-INF/
|
||||||
mv src/main/webapp/dist src/main/resources/META-INF/resources
|
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
|
- name: Build backend
|
||||||
run: |
|
run: |
|
||||||
chmod 740 mvnw
|
chmod 740 mvnw
|
||||||
@ -57,7 +63,7 @@ jobs:
|
|||||||
username: ${{ secrets.SSH_USER }}
|
username: ${{ secrets.SSH_USER }}
|
||||||
port: ${{ secrets.SSH_PORT }}
|
port: ${{ secrets.SSH_PORT }}
|
||||||
key: ${{ secrets.SSH_KEY }}
|
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
|
target: ${{ secrets.TARGET_DIR }} # Need to create it first on the VPS
|
||||||
|
|
||||||
- name: Re-start ffsaf container
|
- name: Re-start ffsaf container
|
||||||
|
|||||||
7
pom.xml
7
pom.xml
@ -75,11 +75,6 @@
|
|||||||
<version>2.0.4</version>
|
<version>2.0.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.quarkiverse.openpdf</groupId>
|
|
||||||
<artifactId>quarkus-openpdf</artifactId>
|
|
||||||
<version>3.1.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-junit5</artifactId>
|
<artifactId>quarkus-junit5</artifactId>
|
||||||
@ -211,7 +206,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<skipITs>false</skipITs>
|
<skipITs>false</skipITs>
|
||||||
<quarkus.native.additional-build-args>
|
<quarkus.native.additional-build-args>
|
||||||
--initialize-at-run-time=com.fasterxml.jackson.databind.ext.DOMDeserializer\,com.lowagie
|
--initialize-at-run-time=com.fasterxml.jackson.databind.ext.DOMDeserializer
|
||||||
</quarkus.native.additional-build-args>
|
</quarkus.native.additional-build-args>
|
||||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||||
<quarkus.package.jar.enabled>false</quarkus.package.jar.enabled>
|
<quarkus.package.jar.enabled>false</quarkus.package.jar.enabled>
|
||||||
|
|||||||
@ -14,13 +14,16 @@
|
|||||||
# docker run -i --rm -p 8080:8080 quarkus/ffsaf-site
|
# 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/
|
WORKDIR /work/
|
||||||
RUN chown 1001 /work \
|
RUN chown 1001 /work \
|
||||||
&& chmod "g+rwX" /work \
|
&& chmod "g+rwX" /work \
|
||||||
&& chown 1001:root /work
|
&& chown 1001:root /work
|
||||||
COPY --chown=1001:root target/*-runner /work/application
|
COPY --chown=1001:root target/*-runner /work/application
|
||||||
COPY --chown=1001:root src/main/resources/cacerts /work/cacerts
|
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
|
RUN mkdir /work/media && chown -R 1001:root /work/media
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
package fr.titionfire.ffsaf.domain.service;
|
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.ClubModel;
|
||||||
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
||||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||||
@ -38,18 +33,20 @@ import jakarta.ws.rs.core.MediaType;
|
|||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||||
import org.hibernate.reactive.mutiny.Mutiny;
|
import org.hibernate.reactive.mutiny.Mutiny;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
@WithSession
|
@WithSession
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class MembreService {
|
public class MembreService {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(MembreService.class);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CombRepository repository;
|
CombRepository repository;
|
||||||
@ -66,6 +63,9 @@ public class MembreService {
|
|||||||
@ConfigProperty(name = "upload_dir")
|
@ConfigProperty(name = "upload_dir")
|
||||||
String media;
|
String media;
|
||||||
|
|
||||||
|
@ConfigProperty(name = "pdf-maker.jar-path")
|
||||||
|
String pdfMakerJarPath;
|
||||||
|
|
||||||
public SimpleCombModel find(int licence, String np) throws Throwable {
|
public SimpleCombModel find(int licence, String np) throws Throwable {
|
||||||
return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() ->
|
return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() ->
|
||||||
repository.find("licence = ?1 AND (lname ILIKE ?2 OR fname ILIKE ?2)",
|
repository.find("licence = ?1 AND (lname ILIKE ?2 OR fname ILIKE ?2)",
|
||||||
@ -315,11 +315,11 @@ public class MembreService {
|
|||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours"));
|
.orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours"));
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
try {
|
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";
|
String mimeType = "application/pdf";
|
||||||
|
|
||||||
Response.ResponseBuilder resp = Response.ok(buff);
|
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 {
|
private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
|
List<String> cmd = new ArrayList<>();
|
||||||
Document document = new Document();
|
cmd.add("java");
|
||||||
PdfWriter.getInstance(document, out);
|
cmd.add("-jar");
|
||||||
document.open();
|
cmd.add(pdfMakerJarPath);
|
||||||
|
|
||||||
document.addCreator("FFSAF");
|
UUID uuid = UUID.randomUUID();
|
||||||
document.addTitle(
|
|
||||||
"Attestation d'adhésion " + Utils.getSaison() + "-" + (Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname());
|
|
||||||
document.addCreationDate();
|
|
||||||
document.addProducer("https://www.ffsaf.fr");
|
|
||||||
|
|
||||||
InputStream fontStream = MembreService.class.getClassLoader().getResourceAsStream("asset/DMSans-Regular.ttf");
|
cmd.add("/tmp/" + uuid + ".pdf");
|
||||||
if (fontStream == null) {
|
cmd.add(m.getFname());
|
||||||
throw new IOException("Font file not found");
|
cmd.add(m.getLname());
|
||||||
}
|
cmd.add(m.getGenre().str);
|
||||||
BaseFont customFont = BaseFont.createFont("asset/DMSans-Regular.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED, true,
|
cmd.add(m.getCategorie().getName());
|
||||||
null, fontStream.readAllBytes());
|
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() + ".");
|
FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + ".");
|
||||||
File[] files = new File(media, "ppMembre").listFiles(filter);
|
File[] files = new File(media, "ppMembre").listFiles(filter);
|
||||||
if (files != null && files.length > 0) {
|
if (files != null && files.length > 0) {
|
||||||
File file = files[0];
|
File file = files[0];
|
||||||
memberPhoto = Image.getInstance(Files.readAllBytes(file.toPath()));
|
cmd.add(file.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
memberPhoto = Image.getInstance(
|
cmd.add("/dev/null");
|
||||||
Objects.requireNonNull(getClass().getClassLoader().getResource("asset/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;
|
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
|
||||||
if (licence.getCertificate() != null && !licence.getCertificate().isBlank()) {
|
processBuilder.redirectErrorStream(true);
|
||||||
cert = licence.getCertificate().split("¤");
|
Process process = processBuilder.start();
|
||||||
if (cert.length <= 1){
|
|
||||||
cert = new String[]{licence.getCertificate(), "--"};
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
}else{
|
|
||||||
try {
|
StringBuilder builder = new StringBuilder();
|
||||||
cert[1] = sdf.format(new SimpleDateFormat("yyyy-MM-dd").parse(cert[1]));
|
Thread t = new Thread(() -> {
|
||||||
} catch (ParseException e) {
|
try {
|
||||||
cert[1] = "--";
|
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 {
|
} else {
|
||||||
cert = new String[]{"--", "--"};
|
code = process.exitValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding member details
|
if (t.isAlive())
|
||||||
memberTable.addCell(new Phrase("NOM : " + m.getLname().toUpperCase(), bodyFont));
|
t.interrupt();
|
||||||
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
|
|
||||||
|
|
||||||
document.add(memberTable);
|
LOGGER.debug("PDF maker: " + builder);
|
||||||
|
|
||||||
// Adding spacing
|
if (code != 0) {
|
||||||
document.add(new Paragraph("\n"));
|
throw new IOException("Error code: " + code);
|
||||||
|
} else {
|
||||||
Paragraph memberClub = new Paragraph("CLUB : " + m.getClub().getName().toUpperCase(), bodyFont);
|
File file = new File("/tmp/" + uuid + ".pdf");
|
||||||
document.add(memberClub);
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
|
byte[] buff = fis.readAllBytes();
|
||||||
Paragraph memberClubNumber = new Paragraph("N° club : " + m.getClub().getNo_affiliation(), bodyFont);
|
//noinspection ResultOfMethodCallIgnored
|
||||||
document.add(memberClubNumber);
|
file.delete();
|
||||||
|
return buff;
|
||||||
// Adding spacing
|
} catch (IOException e) {
|
||||||
document.add(new Paragraph("\n"));
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
file.delete();
|
||||||
Paragraph memberBirthdate = new Paragraph(
|
}
|
||||||
"Date de naissance : " + ((m.getBirth_date() == null) ? "--" : sdf.format(m.getBirth_date())),
|
return null;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/main/pdf_gen/.gitignore
vendored
Normal file
38
src/main/pdf_gen/.gitignore
vendored
Normal file
@ -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
|
||||||
51
src/main/pdf_gen/pom.xml
Normal file
51
src/main/pdf_gen/pom.xml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>fr.titionfire</groupId>
|
||||||
|
<artifactId>pdf_gen</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.librepdf</groupId>
|
||||||
|
<artifactId>openpdf</artifactId>
|
||||||
|
<version>2.0.3</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>fr.titionfire.Main</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>make-assembly</id> <!-- this is used for inheritance merges -->
|
||||||
|
<phase>package</phase> <!-- bind to the packaging phase -->
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
223
src/main/pdf_gen/src/main/java/fr/titionfire/Main.java
Normal file
223
src/main/pdf_gen/src/main/java/fr/titionfire/Main.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/pdf_gen/src/main/java/fr/titionfire/PdfData.java
Normal file
19
src/main/pdf_gen/src/main/java/fr/titionfire/PdfData.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
BIN
src/main/pdf_gen/src/main/resources/blank-profile-picture.png
Normal file
BIN
src/main/pdf_gen/src/main/resources/blank-profile-picture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@ -1,9 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name": "com.lowagie.text.pdf.GrayColor",
|
|
||||||
"allDeclaredConstructors": true,
|
|
||||||
"allPublicConstructors": true,
|
|
||||||
"allDeclaredMethods": true,
|
|
||||||
"allPublicMethods": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@ -14,6 +14,8 @@ quarkus.hibernate-orm.physical-naming-strategy=fr.titionfire.ffsaf.data.SafcaNam
|
|||||||
quarkus.http.cors=true
|
quarkus.http.cors=true
|
||||||
quarkus.quartz.start-mode=forced
|
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.min-level=ALL
|
||||||
%dev.quarkus.log.category."fr.titionfire.ffsaf".level=ALL
|
%dev.quarkus.log.category."fr.titionfire.ffsaf".level=ALL
|
||||||
|
|
||||||
|
|||||||
@ -92,6 +92,7 @@ function sendLicence(event, dispatch) {
|
|||||||
|
|
||||||
const formData = new FormData(event.target);
|
const formData = new FormData(event.target);
|
||||||
formData.set('licence', event.target.licence?.value?.length > 0 ? event.target.licence?.value : null)
|
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(
|
toast.promise(
|
||||||
apiAxios.post(`/licence/${formData.get('membre')}`, formData),
|
apiAxios.post(`/licence/${formData.get('membre')}`, formData),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user