feat: pdf generation

This commit is contained in:
2024-12-29 11:34:39 +01:00
parent 6b38405e94
commit aac126cb87
14 changed files with 316 additions and 223 deletions

View File

@@ -1,6 +1,12 @@
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;
import fr.titionfire.ffsaf.data.repository.ClubRepository;
import fr.titionfire.ffsaf.data.repository.CombRepository;
@@ -13,6 +19,7 @@ import fr.titionfire.ffsaf.rest.data.SimpleLicence;
import fr.titionfire.ffsaf.rest.data.SimpleMembre;
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.rest.from.ClubMemberForm;
import fr.titionfire.ffsaf.rest.from.FullMemberForm;
import fr.titionfire.ffsaf.utils.*;
@@ -26,10 +33,17 @@ import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.HttpHeaders;
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 java.io.*;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;
@WithSession
@@ -111,6 +125,11 @@ public class MembreService {
return repository.findById(id);
}
public Uni<MembreModel> getByIdWithLicence(long id) {
return repository.findById(id)
.call(m -> Mutiny.fetch(m.getLicences()));
}
public Uni<MembreModel> getByLicence(long licence) {
return repository.find("licence = ?1", licence).firstResult();
}
@@ -276,4 +295,204 @@ public class MembreService {
.invoke(meData::setLicences)
.map(__ -> meData);
}
public Uni<Response> getLicencePdf(String subject) {
return getLicencePdf(repository.find("userId = ?1", subject).firstResult()
.call(m -> Mutiny.fetch(m.getLicences())));
}
public Uni<Response> getLicencePdf(Uni<MembreModel> uniBase) {
return uniBase
.map(Unchecked.function(m -> {
LicenceModel licence = m.getLicences().stream()
.filter(licenceModel -> licenceModel.getSaison() == Utils.getSaison() && licenceModel.isValidate())
.findFirst()
.orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
make_pdf(m, out, licence);
byte[] buff = out.toByteArray();
String mimeType = "application/pdf";
Response.ResponseBuilder resp = Response.ok(buff);
resp.type(MediaType.APPLICATION_OCTET_STREAM);
resp.header(HttpHeaders.CONTENT_LENGTH, buff.length);
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
resp.header(HttpHeaders.CONTENT_DISPOSITION,
"inline; " + "filename=\"Attestation d'adhésion " + Utils.getSaison() + "-" +
(Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname() + ".pdf\"");
return resp.build();
} catch (Exception e) {
throw new IOException(e);
}
}));
}
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();
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");
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());
// 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()));
} else {
memberPhoto = Image.getInstance(
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);
// 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 Dr " + licence.getCertificate(), bodyFont));
memberTable.addCell(new Phrase("")); // Empty cell for spacing
document.add(memberTable);
// 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 ladhé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 sinscrire à tout tournoi organisé sous légide de la FFSAF sil 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();
}
}