@@ -0,0 +1,101 @@
|
||||
import PDFDocument from 'pdfkit';
|
||||
|
||||
function addSectionTitle(doc, title) {
|
||||
doc.moveDown(0.5);
|
||||
doc.fontSize(14).font('Helvetica-Bold').text(title);
|
||||
doc.moveDown(0.3);
|
||||
doc.fontSize(10).font('Helvetica');
|
||||
}
|
||||
|
||||
function ensurePageSpace(doc, neededHeight = 80) {
|
||||
if (doc.y + neededHeight > doc.page.height - doc.page.margins.bottom) {
|
||||
doc.addPage();
|
||||
}
|
||||
}
|
||||
|
||||
function keyValue(doc, key, value) {
|
||||
doc.font('Helvetica-Bold').text(`${key}: `, { continued: true });
|
||||
doc.font('Helvetica').text(String(value ?? '-'));
|
||||
}
|
||||
|
||||
function tableRow(doc, cols, widths, opts = {}) {
|
||||
const startX = doc.x;
|
||||
const y = doc.y;
|
||||
const lineHeight = opts.lineHeight || 14;
|
||||
|
||||
let x = startX;
|
||||
for (let i = 0; i < cols.length; i++) {
|
||||
const text = cols[i] == null ? '-' : String(cols[i]);
|
||||
doc.text(text, x, y, {
|
||||
width: widths[i],
|
||||
lineBreak: false
|
||||
});
|
||||
x += widths[i];
|
||||
}
|
||||
doc.y = y + lineHeight;
|
||||
}
|
||||
|
||||
export function generateOrderDossierPdf({ orderId, createdAt, customerName, config, cuttingList, packing }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const doc = new PDFDocument({ size: 'A4', margin: 40 });
|
||||
const chunks = [];
|
||||
|
||||
doc.on('data', (chunk) => chunks.push(chunk));
|
||||
doc.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
doc.on('error', reject);
|
||||
|
||||
doc.fontSize(18).font('Helvetica-Bold').text(`Dossier technique commande #${orderId}`);
|
||||
doc.fontSize(10).font('Helvetica').text(`Généré le ${new Date().toLocaleString('fr-CH')}`);
|
||||
if (createdAt) doc.text(`Commande du ${new Date(createdAt).toLocaleString('fr-CH')}`);
|
||||
if (customerName) doc.text(`Client: ${customerName}`);
|
||||
|
||||
addSectionTitle(doc, 'Configuration');
|
||||
keyValue(doc, 'Dimensions', `${config.widthMm} x ${config.heightMm} x ${config.depthMm} mm`);
|
||||
keyValue(doc, 'Installation', config.installationType === 'niche' ? 'Encastree' : 'Libre');
|
||||
keyValue(doc, 'Portes', config.doorType === 'sliding' ? 'Coulissantes' : 'Battantes');
|
||||
keyValue(doc, 'Modules', config.moduleCount || 0);
|
||||
|
||||
addSectionTitle(doc, 'Liste de decoupage');
|
||||
const cutWidths = [170, 130, 40, 130];
|
||||
tableRow(doc, ['Piece', 'L x H x Ep.', 'Qte', 'Finition'], cutWidths, { lineHeight: 16 });
|
||||
doc.moveTo(doc.x, doc.y).lineTo(doc.page.width - doc.page.margins.right, doc.y).stroke();
|
||||
doc.moveDown(0.2);
|
||||
|
||||
for (const piece of (cuttingList?.pieces || [])) {
|
||||
ensurePageSpace(doc, 18);
|
||||
tableRow(
|
||||
doc,
|
||||
[
|
||||
piece.description,
|
||||
`${piece.widthMm}x${piece.heightMm}x${piece.thicknessMm}`,
|
||||
piece.quantity,
|
||||
piece.finishLabel || '-'
|
||||
],
|
||||
cutWidths
|
||||
);
|
||||
}
|
||||
|
||||
addSectionTitle(doc, 'Colisage');
|
||||
const packWidths = [50, 170, 70, 70];
|
||||
tableRow(doc, ['Colis', 'Niveau', 'Poids', 'Pieces'], packWidths, { lineHeight: 16 });
|
||||
doc.moveTo(doc.x, doc.y).lineTo(doc.page.width - doc.page.margins.right, doc.y).stroke();
|
||||
doc.moveDown(0.2);
|
||||
|
||||
for (const box of (packing?.boxes || [])) {
|
||||
ensurePageSpace(doc, 18);
|
||||
tableRow(
|
||||
doc,
|
||||
[
|
||||
box.id,
|
||||
box.level || '-',
|
||||
`${Number(box.totalWeightKg || 0).toFixed(1)} kg`,
|
||||
box.pieces?.length || 0
|
||||
],
|
||||
packWidths
|
||||
);
|
||||
}
|
||||
|
||||
doc.end();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user