u
This commit is contained in:
@@ -57,7 +57,6 @@
|
|||||||
},
|
},
|
||||||
"allowScripts": {
|
"allowScripts": {
|
||||||
"github:sebseb7/react-canvas-label-editor#7f0e31b66ff22da011e872b201017398b14e9dd9": true,
|
"github:sebseb7/react-canvas-label-editor#7f0e31b66ff22da011e872b201017398b14e9dd9": true,
|
||||||
"canvas@3.2.3": true,
|
|
||||||
"better-sqlite3@13.0.3": true
|
"better-sqlite3@13.0.3": true
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import PDFDocument from 'pdfkit';
|
import PDFDocument from 'pdfkit';
|
||||||
import { createCanvas } from 'canvas';
|
|
||||||
import JsBarcode from 'jsbarcode';
|
import JsBarcode from 'jsbarcode';
|
||||||
import { optimizeImage } from 'wasm-image-optimization';
|
import { optimizeImage } from 'wasm-image-optimization';
|
||||||
import { getStore } from '../db/store.js';
|
import { getStore } from '../db/store.js';
|
||||||
@@ -91,31 +90,26 @@ const COL_DELIV = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a PNG barcode buffer for embedding in PDFDocument.
|
* Computes barcode binary bit patterns using JsBarcode's object renderer.
|
||||||
* Reuses a single canvas instance on format fallback.
|
* Zero native dependencies (pure JS).
|
||||||
*/
|
*/
|
||||||
export function generateBarcodePng(text, preferredFormat = 'CODE128', options = {}) {
|
export function getBarcodeData(text, preferredFormat = 'CODE128') {
|
||||||
const str = text ? String(text).trim() : '';
|
const str = text ? String(text).trim() : '';
|
||||||
if (!str) return null;
|
if (!str) return null;
|
||||||
|
|
||||||
const width = options.width || 120;
|
const encode = (format) => {
|
||||||
const height = options.height || 36;
|
const target = {};
|
||||||
const canvas = createCanvas(width, height);
|
JsBarcode(target, str, { format, displayValue: false });
|
||||||
const baseOpts = {
|
const binary = target.encodings.map((e) => e.data).join('');
|
||||||
displayValue: options.displayValue ?? true,
|
return binary ? { binary, totalModules: binary.length } : null;
|
||||||
fontSize: options.fontSize || 9,
|
|
||||||
textMargin: options.textMargin || 1,
|
|
||||||
margin: options.margin || 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JsBarcode(canvas, str, { ...baseOpts, format: preferredFormat });
|
return encode(preferredFormat);
|
||||||
return canvas.toBuffer('image/png');
|
|
||||||
} catch {
|
} catch {
|
||||||
if (preferredFormat !== 'CODE128') {
|
if (preferredFormat !== 'CODE128') {
|
||||||
try {
|
try {
|
||||||
JsBarcode(canvas, str, { ...baseOpts, format: 'CODE128' });
|
return encode('CODE128');
|
||||||
return canvas.toBuffer('image/png');
|
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -124,6 +118,36 @@ export function generateBarcodePng(text, preferredFormat = 'CODE128', options =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the barcode onto the PDFKit document as crisp vector rectangles.
|
||||||
|
*/
|
||||||
|
export function drawBarcode(doc, barcode, x, y, width, height, color = PALETTE.primary) {
|
||||||
|
if (!barcode?.binary || !width || !height) return;
|
||||||
|
const { binary, totalModules } = barcode;
|
||||||
|
if (!totalModules) return;
|
||||||
|
|
||||||
|
const moduleWidth = width / totalModules;
|
||||||
|
|
||||||
|
doc.save();
|
||||||
|
doc.fillColor(color);
|
||||||
|
|
||||||
|
let run = 0;
|
||||||
|
for (let i = 0; i < binary.length; i++) {
|
||||||
|
if (binary[i] === '1') {
|
||||||
|
run++;
|
||||||
|
} else if (run > 0) {
|
||||||
|
doc.rect(x + (i - run) * moduleWidth, y, run * moduleWidth, height);
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (run > 0) {
|
||||||
|
doc.rect(x + (binary.length - run) * moduleWidth, y, run * moduleWidth, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.fill();
|
||||||
|
doc.restore();
|
||||||
|
}
|
||||||
|
|
||||||
async function resolveThumbPng(store, googleAuthId, picHash, smallthumbbinary) {
|
async function resolveThumbPng(store, googleAuthId, picHash, smallthumbbinary) {
|
||||||
if (smallthumbbinary) {
|
if (smallthumbbinary) {
|
||||||
try {
|
try {
|
||||||
@@ -470,14 +494,14 @@ export function generateManifestPdf({
|
|||||||
doc.font('Helvetica-Bold').fontSize(7).fillColor(PALETTE.primary)
|
doc.font('Helvetica-Bold').fontSize(7).fillColor(PALETTE.primary)
|
||||||
.text(line.ownSku || '–', COL_DELIV.ownSku, y + 2, { width: COL_DELIV.ownSkuW, ellipsis: true });
|
.text(line.ownSku || '–', COL_DELIV.ownSku, y + 2, { width: COL_DELIV.ownSkuW, ellipsis: true });
|
||||||
if (line.ownSkuBarcode) {
|
if (line.ownSkuBarcode) {
|
||||||
try { doc.image(line.ownSkuBarcode, COL_DELIV.ownSku, centerY, { width: 88, height: 20 }); } catch { /* ignore */ }
|
try { drawBarcode(doc, line.ownSkuBarcode, COL_DELIV.ownSku, centerY, 88, 20); } catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.ean) {
|
if (line.ean) {
|
||||||
doc.font('Helvetica').fontSize(6.5).fillColor(PALETTE.muted)
|
doc.font('Helvetica').fontSize(6.5).fillColor(PALETTE.muted)
|
||||||
.text(line.ean, COL_DELIV.ean, y + 2, { width: COL_DELIV.eanW, ellipsis: true });
|
.text(line.ean, COL_DELIV.ean, y + 2, { width: COL_DELIV.eanW, ellipsis: true });
|
||||||
if (line.eanBarcode) {
|
if (line.eanBarcode) {
|
||||||
try { doc.image(line.eanBarcode, COL_DELIV.ean, centerY, { width: 76, height: 20 }); } catch { /* ignore */ }
|
try { drawBarcode(doc, line.eanBarcode, COL_DELIV.ean, centerY, 76, 20); } catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
doc.font('Helvetica').fontSize(8).fillColor(PALETTE.muted)
|
doc.font('Helvetica').fontSize(8).fillColor(PALETTE.muted)
|
||||||
@@ -798,8 +822,8 @@ async function enrichDeliveryLines(store, googleAuthId, companyId, partnerId, li
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const currentStock = trackStock ? Number(stockRes?.rows?.[0]?.stock ?? 0) : null;
|
const currentStock = trackStock ? Number(stockRes?.rows?.[0]?.stock ?? 0) : null;
|
||||||
const ownSkuBarcode = ownSku ? generateBarcodePng(ownSku, 'CODE128', { width: 110, height: 26, displayValue: false }) : null;
|
const ownSkuBarcode = ownSku ? getBarcodeData(ownSku, 'CODE128') : null;
|
||||||
const eanBarcode = ean ? generateBarcodePng(ean, 'EAN13', { width: 100, height: 26, displayValue: false }) : null;
|
const eanBarcode = ean ? getBarcodeData(ean, 'EAN13') : null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ownSku,
|
ownSku,
|
||||||
|
|||||||
Reference in New Issue
Block a user