@flowselections/layout-maker 1.69.10 → 1.69.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist-lib/components/A4StickervelKaart.d.ts +5 -0
  2. package/dist-lib/components/A4StickervelKaart.d.ts.map +1 -0
  3. package/dist-lib/components/A4StickervelKaart.js +123 -0
  4. package/dist-lib/components/KlaarOmTePrintenBlok.d.ts.map +1 -1
  5. package/dist-lib/components/KlaarOmTePrintenBlok.js +50 -7
  6. package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
  7. package/dist-lib/components/PrintQueuePage.js +4 -6
  8. package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
  9. package/dist-lib/components/PrintplekDetailPage.js +3 -1
  10. package/dist-lib/components/PrintplekkenPage.d.ts.map +1 -1
  11. package/dist-lib/components/PrintplekkenPage.js +2 -1
  12. package/dist-lib/components/StickerRouteTestKaart.d.ts +5 -0
  13. package/dist-lib/components/StickerRouteTestKaart.d.ts.map +1 -0
  14. package/dist-lib/components/StickerRouteTestKaart.js +75 -0
  15. package/dist-lib/components/UitwijkRegel.d.ts +5 -0
  16. package/dist-lib/components/UitwijkRegel.d.ts.map +1 -0
  17. package/dist-lib/components/UitwijkRegel.js +17 -0
  18. package/dist-lib/components/UitwijkTekening.d.ts +19 -0
  19. package/dist-lib/components/UitwijkTekening.d.ts.map +1 -0
  20. package/dist-lib/components/UitwijkTekening.js +21 -0
  21. package/dist-lib/index.d.ts +12 -0
  22. package/dist-lib/index.d.ts.map +1 -1
  23. package/dist-lib/index.js +14 -0
  24. package/dist-lib/integrations/supabase/types.d.ts +3714 -25
  25. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  26. package/dist-lib/integrations/supabase/types.js +1 -0
  27. package/dist-lib/lib/belading.d.ts +10 -0
  28. package/dist-lib/lib/belading.d.ts.map +1 -0
  29. package/dist-lib/lib/belading.js +49 -0
  30. package/dist-lib/lib/codelijstCache.d.ts +11 -0
  31. package/dist-lib/lib/codelijstCache.d.ts.map +1 -0
  32. package/dist-lib/lib/codelijstCache.js +117 -0
  33. package/dist-lib/lib/documentTypes.d.ts +1 -1
  34. package/dist-lib/lib/documentTypes.d.ts.map +1 -1
  35. package/dist-lib/lib/documentTypes.js +2 -1
  36. package/dist-lib/lib/eigenDocumenten.d.ts +2 -0
  37. package/dist-lib/lib/eigenDocumenten.d.ts.map +1 -1
  38. package/dist-lib/lib/eigenDocumenten.js +22 -0
  39. package/dist-lib/lib/installCheck.d.ts +36 -0
  40. package/dist-lib/lib/installCheck.d.ts.map +1 -0
  41. package/dist-lib/lib/installCheck.js +65 -0
  42. package/dist-lib/lib/kiesFormaat.d.ts +11 -0
  43. package/dist-lib/lib/kiesFormaat.d.ts.map +1 -0
  44. package/dist-lib/lib/kiesFormaat.js +32 -0
  45. package/dist-lib/lib/klaarOmTePrinten.d.ts +15 -1
  46. package/dist-lib/lib/klaarOmTePrinten.d.ts.map +1 -1
  47. package/dist-lib/lib/klaarOmTePrinten.js +19 -1
  48. package/dist-lib/lib/orderData.server.d.ts.map +1 -1
  49. package/dist-lib/lib/orderData.server.js +25 -31
  50. package/dist-lib/lib/pakbonBuilder.d.ts +6 -0
  51. package/dist-lib/lib/pakbonBuilder.d.ts.map +1 -1
  52. package/dist-lib/lib/pakbonBuilder.js +18 -5
  53. package/dist-lib/lib/pakbonContent.d.ts.map +1 -1
  54. package/dist-lib/lib/pakbonContent.js +4 -1
  55. package/dist-lib/lib/pakbonHtml.d.ts.map +1 -1
  56. package/dist-lib/lib/pakbonHtml.js +5 -2
  57. package/dist-lib/lib/pakbonPresentation.d.ts +3 -1
  58. package/dist-lib/lib/pakbonPresentation.d.ts.map +1 -1
  59. package/dist-lib/lib/pakbonPresentation.js +13 -6
  60. package/dist-lib/lib/printQueue.server.d.ts +16 -2
  61. package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
  62. package/dist-lib/lib/printQueue.server.js +305 -59
  63. package/dist-lib/lib/printService.server.d.ts.map +1 -1
  64. package/dist-lib/lib/printService.server.js +3 -2
  65. package/dist-lib/lib/printerKeuze.d.ts +15 -0
  66. package/dist-lib/lib/printerKeuze.d.ts.map +1 -0
  67. package/dist-lib/lib/printerKeuze.js +32 -0
  68. package/dist-lib/lib/queueTick.d.ts.map +1 -1
  69. package/dist-lib/lib/queueTick.js +9 -1
  70. package/dist-lib/lib/runnerRegistry.server.d.ts +10 -0
  71. package/dist-lib/lib/runnerRegistry.server.d.ts.map +1 -1
  72. package/dist-lib/lib/runnerRegistry.server.js +55 -0
  73. package/dist-lib/lib/standaardLayouts.server.d.ts +6 -0
  74. package/dist-lib/lib/standaardLayouts.server.d.ts.map +1 -1
  75. package/dist-lib/lib/standaardLayouts.server.js +13 -0
  76. package/dist-lib/lib/stickerPlaatsing.d.ts +37 -0
  77. package/dist-lib/lib/stickerPlaatsing.d.ts.map +1 -0
  78. package/dist-lib/lib/stickerPlaatsing.js +122 -0
  79. package/dist-lib/lib/stickerUitwijk.d.ts +197 -0
  80. package/dist-lib/lib/stickerUitwijk.d.ts.map +1 -0
  81. package/dist-lib/lib/stickerUitwijk.js +311 -0
  82. package/dist-lib/lib/testprint.d.ts +13 -0
  83. package/dist-lib/lib/testprint.d.ts.map +1 -1
  84. package/dist-lib/lib/testprint.js +38 -0
  85. package/dist-lib/lib/useDocumentData.js +1 -1
  86. package/dist-lib/lib/versie.generated.d.ts +1 -1
  87. package/dist-lib/lib/versie.generated.js +1 -1
  88. package/dist-lib/lib/vroegeWaarschuwing.d.ts +21 -0
  89. package/dist-lib/lib/vroegeWaarschuwing.d.ts.map +1 -0
  90. package/dist-lib/lib/vroegeWaarschuwing.js +15 -0
  91. package/package.json +1 -1
  92. package/sql/print-schema.sql +1 -0
@@ -3,6 +3,7 @@
3
3
  // Pakt wachtende opdrachten op, maakt er een PDF van en stuurt die stil naar
4
4
  // de juiste printer. Draait alleen op de server (cron / interne aanroep).
5
5
  // ============================================================================
6
+ import { voerUitwijkUit } from "./stickerPlaatsing.js";
6
7
  import { carrierUitPayload, carrierUitTransport, ENGINE_TE_OUD, geenVervoerderTekst, metVervoerder, VERVOERDER_DOCUMENTEN, voorbeeldVervoerder } from "./vervoerder.js";
7
8
  import { maakPakbonOrder, renderPakbonDocument, voorbeeldPakbonOrder, } from "./pakbonHtml.js";
8
9
  import { bouwPakbonScanInhoud, bewaarPakbonScanInhoud } from "./pakbonScan.js";
@@ -14,12 +15,15 @@ import { profielHeeftInhoud, renderProfielDocument } from "./profielHtml.js";
14
15
  import { bouwDocumentHtml, voorbeeldContext } from "./layoutPreview.js";
15
16
  import { AfbeeldingInhoudFout, htmlNaarPdfServer, PdfRenderFout } from "./htmlNaarPdf.server.js";
16
17
  import { bepaalStickerMaat, floridayStickerMaat, STICKER_MAAT_ONBEKEND, stickerFormaatCode, stickerIdUitPayload, stickerInfoUitCache, stickerNietNodig, stickerTypeLabel, STICKER_NIET_NODIG, FASE_NIET_NODIG } from "./stickerFormaat.js";
17
- import { controlelijstHtml, EIGEN_STICKER_MAAT_ONBEKEND, eigenStickerId, eigenStickerKlant, eigenStickerMaat, kiesTraystickerLogo, TRAYSTICKER_GEEN_INDELING, trayProducten, traystickerHtml } from "./eigenDocumenten.js";
18
+ import { controlelijstHtml, EIGEN_STICKER_MAAT_ONBEKEND, VOORBEELD_TRAY_PAYLOAD, eigenStickerId, eigenStickerKlant, eigenStickerMaat, kiesTraystickerLogo, TRAYSTICKER_GEEN_INDELING, trayProducten, traystickerHtml } from "./eigenDocumenten.js";
19
+ import { neemCodelijstMeldingen, startCodelijstRonde, stopCodelijstRonde } from "./codelijstCache.js";
20
+ import { kiesFormaat, testprintHoudtFormaat } from "./kiesFormaat.js";
18
21
  import { OPMAAK_LIMIET_MS, OpmaakTeLangFout, metTijdslimiet } from "./opmaakLimiet.js";
19
22
  import { stuurPdfNaarPrinter, opdrachtStatusDetail, vervaltijdVoor } from "./printService.server.js";
20
23
  import { kiesPapier } from "./papierFormaten.js";
21
24
  import { waaromDezePrinter } from "./waaromPrinter.js";
22
- import { etiketPast, leesGeladenEtiket, pdfPaginaMm } from "./etiketControle.js";
25
+ import { etiketPast, leesGeladenEtiket, maatNl, pdfPaginaMm } from "./etiketControle.js";
26
+ import { a4VelVoor, kiesUitwijkroute, leesA4StickervelWaarde, leesStickerInstellingenStrikt, uitwijkVoorPickschermen } from "./stickerUitwijk.js";
23
27
  import { documentTypeLabel as documentTypeLabelVoor } from "./documentTypes.js";
24
28
  import { PAPIERFORMATEN } from "./documentTypes.js";
25
29
  const MAX_POGINGEN = 3;
@@ -46,7 +50,10 @@ export async function controleerClient(db) {
46
50
  /** Fase met tijd en details in het logboek, zodat een vastloper nooit stil is. */
47
51
  async function faseLog(db, jobId, fase, detail) {
48
52
  try {
49
- await log(db, String(jobId), "fase", JSON.stringify({ fase, op: new Date().toISOString(), ...detail }));
53
+ const op = new Date().toISOString();
54
+ await log(db, String(jobId), "fase", JSON.stringify({ fase, op, ...detail }));
55
+ // Vrijgave per fase (layouts_vrijgeven_vastgelopen) meet vanaf de laatste fase.
56
+ await db.from("print_jobs").update({ fase_gestart_op: op }).eq("id", String(jobId)).eq("status", "bezig");
50
57
  }
51
58
  catch {
52
59
  /* loggen mag het printen nooit blokkeren */
@@ -269,7 +276,7 @@ function isEngineOpdracht(job) {
269
276
  return bron.includes("logistic") || bron.includes("engine");
270
277
  }
271
278
  /** Stickers: altijd kant-en-klare PDF op een labelprinter. */
272
- const ETIKET_PDF_SOORTEN = new Set(["sticker", "traysticker"]);
279
+ const ETIKET_PDF_SOORTEN = new Set(["sticker", "traysticker", "eigen_sticker"]);
273
280
  /** Testprint: alleen de eigen testvlag telt (geen kar, geen barcode). */
274
281
  export function isTestprintJob(job) {
275
282
  const p = (job.payload ?? {});
@@ -458,7 +465,21 @@ async function zoekLayout(db, job) {
458
465
  .order("is_standaard", { ascending: false })
459
466
  .order("updated_at", { ascending: false })
460
467
  .limit(1);
461
- const gevonden = (arr(data)[0] ?? null);
468
+ let gevonden = (arr(data)[0] ?? null);
469
+ if (!gevonden && documenttype === "eigen_sticker") {
470
+ // Engine 1.0.194: soort eigen_sticker. Bestaande eigen-stickerlayout
471
+ // (soort sticker + fs.eigen_sticker) blijft werken; niets gekopieerd.
472
+ const { data: oud } = await db
473
+ .from("document_layouts")
474
+ .select("*")
475
+ .eq("documenttype", "sticker")
476
+ .eq("actief", true)
477
+ .not("config->eigen_sticker", "is", null)
478
+ .order("is_standaard", { ascending: false })
479
+ .order("updated_at", { ascending: false })
480
+ .limit(1);
481
+ gevonden = (arr(oud)[0] ?? null);
482
+ }
462
483
  if (!gevonden && !job.render_html) {
463
484
  throw new GeenDocumentFout(`Geen layout gevonden voor documenttype '${documenttype}'. ` +
464
485
  "Maak een layout aan en zet die op actief.");
@@ -756,7 +777,14 @@ async function zoekPrinter(db, job, layout) {
756
777
  // Alleen een printer die nog echt aan de plek gekoppeld én actief is telt.
757
778
  const plekPrinter = async (plek) => {
758
779
  const { data } = await db.rpc("printplek_printer", { _plek: plek, _documenttype: type });
759
- return typeof data === "string" ? data : null;
780
+ if (typeof data === "string")
781
+ return data;
782
+ // Eigen sticker: dezelfde printerkeuze als de traysticker.
783
+ if (type === "eigen_sticker") {
784
+ const { data: tray } = await db.rpc("printplek_printer", { _plek: plek, _documenttype: "traysticker" });
785
+ return typeof tray === "string" ? tray : null;
786
+ }
787
+ return null;
760
788
  };
761
789
  if (explicietePlek) {
762
790
  printer = await pak(await plekPrinter(explicietePlek));
@@ -786,11 +814,24 @@ async function zoekPrinter(db, job, layout) {
786
814
  _papierformaat: layout?.papierformaat ?? null,
787
815
  ...(leesWerkplekId(job) ? { _werkplek_id: leesWerkplekId(job) } : {}),
788
816
  });
789
- printer = await pak(route?.printer_id);
817
+ let routeRij = route;
818
+ if (!routeRij?.printer_id && type === "eigen_sticker") {
819
+ // Eigen sticker: dezelfde printerkeuze als de traysticker.
820
+ const { data: tray } = await db.rpc("printer_routering", {
821
+ _documenttype: "traysticker",
822
+ _print_plek_id: plekId || null,
823
+ _werkplek: werkplek || null,
824
+ _layout_id: layout?.id ?? null,
825
+ _papierformaat: layout?.papierformaat ?? null,
826
+ ...(leesWerkplekId(job) ? { _werkplek_id: leesWerkplekId(job) } : {}),
827
+ });
828
+ routeRij = tray;
829
+ }
830
+ printer = await pak(routeRij?.printer_id);
790
831
  if (printer) {
791
832
  try {
792
833
  const plekNaam = plekId ? await printplekNaamVoorJob(db, job) : null;
793
- const r = (route ?? {});
834
+ const r = (routeRij ?? {});
794
835
  await log(db, job.id, "waarom", waaromDezePrinter({ bron: r.bron, papierformaat: r.papierformaat ?? null, werkplek_naam: r.werkplek_naam, printer_rol: r.printer_rol, werkplek: r.werkplek }, String(printer.weergavenaam || printer.naam || "Printer"), plekNaam));
795
836
  }
796
837
  catch { /* uitleg is informatief */ }
@@ -986,7 +1027,7 @@ export async function bouwHtml(db, job, keuze, uitkomst) {
986
1027
  noteer("render_html");
987
1028
  return meegestuurd;
988
1029
  }
989
- const p = (job.payload ?? {});
1030
+ let p = (job.payload ?? {});
990
1031
  // Vervoerder: alleen carrier_label uit de Engine. Ontbreekt hij → wachten.
991
1032
  const carrierLabel = await bepaalVervoerder(db, job, p, layout);
992
1033
  const liggend = String(layout.orientatie ?? "portrait") === "landscape";
@@ -1008,6 +1049,9 @@ export async function bouwHtml(db, job, keuze, uitkomst) {
1008
1049
  }
1009
1050
  // Eigen traysticker (fs.eigen_traysticker): één sticker per tray.
1010
1051
  if (cfg.eigen_traysticker && typeof cfg.eigen_traysticker === "object") {
1052
+ // Testprint: voorbeeldgegevens (voorbeeldorder, fusten, een samenstelling).
1053
+ if (isTestprintJob(job) && !trayProducten(p))
1054
+ p = { ...VOORBEELD_TRAY_PAYLOAD, ...p };
1011
1055
  if (!trayProducten(p))
1012
1056
  throw new WachtOpLayoutFout(TRAYSTICKER_GEEN_INDELING);
1013
1057
  const inst = await bedrijfsInstelling(db).catch(() => null);
@@ -1053,6 +1097,7 @@ export async function bouwHtml(db, job, keuze, uitkomst) {
1053
1097
  ? ((await laadPakbonData(db, { scope: "cart", id: cartId })) ??
1054
1098
  (await laadOrderVanuitDatabase(db, p)))
1055
1099
  : await laadOrderVanuitDatabase(db, p);
1100
+ await faseLog(db, job.id, "gegevens_geladen", { uit_database: !!uitDb });
1056
1101
  const bron = uitDb ??
1057
1102
  (p.voorbeeld === true && !heeftOrderInhoud(orderBron)
1058
1103
  ? voorbeeldPakbonOrder()
@@ -1123,6 +1168,7 @@ export async function bouwHtml(db, job, keuze, uitkomst) {
1123
1168
  ? ((await laadPakbonData(db, { scope: "cart", id: engineCartId })) ??
1124
1169
  (await laadOrderVanuitDatabase(db, p)))
1125
1170
  : await laadOrderVanuitDatabase(db, p);
1171
+ await faseLog(db, job.id, "gegevens_geladen", { uit_database: !!uitDb });
1126
1172
  // Een voorbeeldafdruk zonder ordergegevens krijgt een voorbeeldorder, zodat
1127
1173
  // je ziet hoe het document er in de praktijk uitziet.
1128
1174
  const bron = uitDb ??
@@ -1617,7 +1663,7 @@ async function verwerkJob(db, job) {
1617
1663
  }
1618
1664
  const keuze = klaar ? { layout: null, ontwerpWint: false } : await zoekLayout(db, job);
1619
1665
  klok.markeer("layout_resolved");
1620
- const layout = keuze.layout;
1666
+ let layout = keuze.layout;
1621
1667
  // Klantsticker/traysticker: maat vaststellen (Floriday-formaat, anders de
1622
1668
  // PDF). Onbekend = niet printen. De maat kiest ook de printer via de
1623
1669
  // formaatregels, zodat een sticker op een etiket komt dat groot genoeg is.
@@ -1685,8 +1731,20 @@ async function verwerkJob(db, job) {
1685
1731
  await geweigerd(db, job, "GEEN_GELADEN_ETIKET", `${documentTypeLabelVoor(String(job.documenttype))} gaat alleen naar een labelprinter met een ingesteld geladen etiket; printer ${String(printer.naam ?? printer.id)} heeft er geen.`);
1686
1732
  return "mislukt";
1687
1733
  }
1734
+ // Eigen sticker/traysticker: variant op de maat van het geladen etiket,
1735
+ // opgebouwd uit dezelfde velden. Een eigen ontwerp wordt nooit geschaald
1736
+ // en de opgeslagen layout wordt niet gewijzigd (alleen deze opmaak).
1737
+ if (label?.etiket && layout && eigenEtiketVariantNodig(layout, label.etiket)) {
1738
+ const e = label.etiket;
1739
+ layout = { ...layout, breedte_mm: e.breedte_mm, hoogte_mm: e.hoogte_mm, orientatie: e.breedte_mm > e.hoogte_mm ? "landscape" : "portrait" };
1740
+ keuze.layout = layout;
1741
+ await log(db, job.id, "etiket", `Eigen ontwerp opgebouwd op de etiketmaat ${maatNl(e.breedte_mm, e.hoogte_mm)} (variant, niet geschaald).`);
1742
+ }
1688
1743
  const isTest = (job.payload ?? {})["is_testprint"] === true;
1689
- if (label && isTest && label.etiket) {
1744
+ // Testprint per uitwijkroute (1.69.12): de voorbeeldsticker houdt zijn
1745
+ // eigen maat, zodat de echte uitwijkroute zichtbaar wordt.
1746
+ const routeTest = (job.payload ?? {})["uitwijk_test"] === true;
1747
+ if (label && isTest && label.etiket && !routeTest) {
1690
1748
  // Een testprint gebruikt het formaat dat echt in de printer zit.
1691
1749
  const p = (job.payload ?? {});
1692
1750
  p["voorbeeld_formaat"] = {
@@ -1705,7 +1763,10 @@ async function verwerkJob(db, job) {
1705
1763
  const opmaakStart = Date.now();
1706
1764
  await faseLog(db, job.id, "opmaken_gestart", { layout_id: layout?.id ?? null });
1707
1765
  pdfBase64 = await metTijdslimiet(OPMAAK_LIMIET_MS, async () => {
1766
+ await faseLog(db, job.id, "gegevens_laden_gestart", {});
1708
1767
  const html = await bouwHtml(db, job, keuze, uitkomst);
1768
+ for (const m of neemCodelijstMeldingen())
1769
+ await faseLog(db, job.id, String(m["fase"] ?? "codelijst"), m);
1709
1770
  await faseLog(db, job.id, "html_klaar", { ms: Date.now() - opmaakStart, tekens: html.length });
1710
1771
  if (!heeftZichtbareInhoud(html)) {
1711
1772
  throw new GeenDocumentFout("Het document was leeg: er zijn geen gegevens gevonden om af te drukken. " +
@@ -1715,12 +1776,12 @@ async function verwerkJob(db, job) {
1715
1776
  // ontwerp is leidend), maar geeft wél het papierformaat van de bewerkte
1716
1777
  // layout mee. Zonder dit zou het voorbeeld altijd op A4 uitkomen.
1717
1778
  const vf = (job.payload ?? {})["voorbeeld_formaat"];
1718
- const liggend = String(layout?.orientatie ?? vf?.["orientatie"] ?? "portrait") === "landscape";
1779
+ const liggend = String(kiesFormaat(job, layout).orientatie ?? "portrait") === "landscape";
1719
1780
  const pdf = await htmlNaarPdfServer({
1720
1781
  html,
1721
- breedteMm: Number(layout?.breedte_mm ?? vf?.["breedte_mm"] ?? 210),
1722
- hoogteMm: Number(layout?.hoogte_mm ?? vf?.["hoogte_mm"] ?? 297),
1723
- margeMm: Number(layout?.marge_boven ?? vf?.["marge_boven"] ?? 10),
1782
+ breedteMm: kiesFormaat(job, layout).breedte_mm ?? 210,
1783
+ hoogteMm: kiesFormaat(job, layout).hoogte_mm ?? 297,
1784
+ margeMm: Number(testprintHoudtFormaat(job) ? (vf?.["marge_boven"] ?? 10) : (layout?.marge_boven ?? vf?.["marge_boven"] ?? 10)),
1724
1785
  landschap: liggend,
1725
1786
  bijOvergeslagen: (src, reden) => {
1726
1787
  void faseLog(db, job.id, "afbeelding_weggelaten", { bron: src.split("?")[0]?.slice(0, 200), reden });
@@ -1737,23 +1798,47 @@ async function verwerkJob(db, job) {
1737
1798
  }
1738
1799
  const formaten = await zorgVoorFormaten(db, printer);
1739
1800
  const vfPapier = (job.payload ?? {})["voorbeeld_formaat"];
1740
- const breedteMm = Number(layout?.breedte_mm ?? vfPapier?.["breedte_mm"] ?? standaardMaat(printer).breedte);
1741
- const hoogteMm = Number(layout?.hoogte_mm ?? vfPapier?.["hoogte_mm"] ?? standaardMaat(printer).hoogte);
1801
+ void vfPapier;
1802
+ const breedteMm = kiesFormaat(job, layout).breedte_mm ?? standaardMaat(printer).breedte;
1803
+ const hoogteMm = kiesFormaat(job, layout).hoogte_mm ?? standaardMaat(printer).hoogte;
1804
+ let doelPrinter = printer;
1805
+ let uitwijk = null;
1806
+ const fitToPage = false;
1807
+ let kopieenNaarPrinter = Number(job.kopieen ?? 1);
1742
1808
  let papier = kiesPapier(formaten, breedteMm, hoogteMm);
1743
1809
  if (label) {
1744
1810
  const maat = stickerMaat ?? (klaar ? pdfPaginaMm(pdfBase64) : null) ?? { breedte_mm: breedteMm, hoogte_mm: hoogteMm };
1745
1811
  const uit = etiketPast({ ...maat, soortLabel: stickerCache?.sticker_type ? stickerTypeLabel(stickerCache.sticker_type) : documentTypeLabelVoor(String(job.documenttype ?? "Document")) }, label.etiket, label.naam, !!stickerMaat);
1746
- if (!uit.ok) {
1812
+ if (label.etiket && ETIKET_PDF_SOORTEN.has(String(job.documenttype ?? "")) && (uit.ok || uit.code === "FORMAAT_PAST_NIET")) {
1813
+ // 1.69.12: elke sticker via de uitwijkroute (vaste volgorde), papier
1814
+ // op afmeting gekozen; draaien/centreren/verkleinen in de PDF zelf.
1815
+ const keuzeUitwijk = await bepaalUitwijk(db, job, layout, !!floriday, !!klaar, maat, label, printer, formaten);
1816
+ if (!keuzeUitwijk) {
1817
+ await geweigerd(db, job, "FORMAAT_PAST_NIET", `${uit.ok ? "Geen passende papiermaat." : uit.bericht} Er is op deze printplek ook geen A4-printer om op uit te wijken.`);
1818
+ return "mislukt";
1819
+ }
1820
+ uitwijk = keuzeUitwijk.uitkomst;
1821
+ if (keuzeUitwijk.a4)
1822
+ doelPrinter = keuzeUitwijk.a4;
1823
+ const geplaatst = await voerUitwijkUit(pdfBase64, uitwijk, maat, Number(job.kopieen ?? 1));
1824
+ pdfBase64 = geplaatst.pdfBase64;
1825
+ kopieenNaarPrinter = geplaatst.kopieen;
1826
+ papier = { paper: uitwijk.paper || null, rotate: 0, uitleg: uitwijk.reden };
1827
+ await log(db, job.id, "uitwijk", `${uitwijk.reden} (${uitwijk.printerNaam}).`);
1828
+ }
1829
+ else if (!uit.ok) {
1747
1830
  await geweigerd(db, job, uit.code, uit.bericht);
1748
1831
  return "mislukt";
1749
1832
  }
1750
- papier = { paper: uit.paper, rotate: uit.rotate, uitleg: uit.uitleg };
1751
- await log(db, job.id, "etiket", `Labelprinter ${label.naam}: ${uit.uitleg}.`);
1833
+ else {
1834
+ papier = { paper: uit.paper, rotate: uit.rotate, uitleg: uit.uitleg };
1835
+ await log(db, job.id, "etiket", `Labelprinter ${label.naam}: ${uit.uitleg}.`);
1836
+ }
1752
1837
  }
1753
1838
  const verloopt = vervaltijdVoor(String(job.documenttype ?? ""));
1754
1839
  // Eén fysieke printer via meerdere computers: probeer de routes op
1755
1840
  // volgorde; valt de eerste weg, dan automatisch de volgende.
1756
- const routes = await printerRoutes(db, String(printer.id), String(printer.extern_printer_id));
1841
+ const routes = await printerRoutes(db, String(doelPrinter.id), String(doelPrinter.extern_printer_id));
1757
1842
  let externJobId = "";
1758
1843
  let laatsteFout = null;
1759
1844
  for (const [i, route] of routes.entries()) {
@@ -1764,9 +1849,9 @@ async function verwerkJob(db, job) {
1764
1849
  externPrinterId: route.extern,
1765
1850
  documentnaam: String(job.documentnaam ?? "Document"),
1766
1851
  pdfBase64,
1767
- kopieen: Number(job.kopieen ?? 1),
1852
+ kopieen: kopieenNaarPrinter,
1768
1853
  documenttype: String(job.documenttype ?? ""),
1769
- opties: { paper: papier.paper, rotate: papier.rotate, fitToPage: false },
1854
+ opties: { paper: papier.paper, rotate: papier.rotate, fitToPage },
1770
1855
  });
1771
1856
  if (i > 0) {
1772
1857
  await log(db, job.id, "route", `Verstuurd via computer ${route.computer ?? "andere route"}: de eerste computer was niet bereikbaar.`);
@@ -1791,13 +1876,14 @@ async function verwerkJob(db, job) {
1791
1876
  const { data: gekoppeldeJob } = await db
1792
1877
  .from("print_jobs")
1793
1878
  .update({
1794
- printer_id: printer.id,
1879
+ printer_id: doelPrinter.id,
1795
1880
  // layout_id blijft de aangeleverde invoer en wordt bewust niet
1796
1881
  // overschreven met de uitkomst.
1797
1882
  // Bij Floriday 1-op-1 wordt de Floriday-layout vastgelegd (alleen nieuwe opdrachten).
1798
1883
  gebruikte_layout_id: uitkomst.bron === "extern_pdf" ? null : (layout?.id ?? null),
1799
1884
  gebruikte_bron: uitkomst.bron,
1800
1885
  extern_job_id: externJobId,
1886
+ printer_keuze: await printerKeuzeVoor(db, job, doelPrinter, uitwijk),
1801
1887
  printnode_status: "new",
1802
1888
  printnode_status_op: new Date().toISOString(),
1803
1889
  verloopt_na_s: verloopt,
@@ -1819,7 +1905,9 @@ async function verwerkJob(db, job) {
1819
1905
  return "wachtend";
1820
1906
  }
1821
1907
  klok.markeer("submitted");
1822
- await log(db, job.id, "verstuurd", `Naar printer ${printer.naam ?? ""}. ${papier.uitleg} ${klok.samenvatting()}`);
1908
+ if (uitwijk)
1909
+ await legUitwijkVast(db, job, uitwijk);
1910
+ await log(db, job.id, "verstuurd", `Naar printer ${doelPrinter.naam ?? ""}. ${papier.uitleg} ${klok.samenvatting()}`);
1823
1911
  return "verstuurd";
1824
1912
  }
1825
1913
  catch (e) {
@@ -1943,7 +2031,7 @@ async function synchroniseerStatussen(db) {
1943
2031
  * runner draait niet meer) -> na 10 minuten terug naar 'wachtend'.
1944
2032
  * Beide draaien in elke ronde, ook als er niets te claimen viel.
1945
2033
  */
1946
- async function vervalControle(db) {
2034
+ async function vervalControle(db, houder = null) {
1947
2035
  const nu = Date.now();
1948
2036
  const grensVerstuurd = new Date(nu - VERVAL_BEZIG_MIN * 60000).toISOString();
1949
2037
  const grensClaim = new Date(nu - VERVAL_CLAIM_MIN * 60000).toISOString();
@@ -1977,6 +2065,12 @@ async function vervalControle(db) {
1977
2065
  await log(db, job.id, "vervallen", reden);
1978
2066
  aantal++;
1979
2067
  }
2068
+ // Vrijgave per fase (standaard 90 s), alleen als geen levende andere ronde
2069
+ // de lease houdt. Lukt de functie niet, dan het oude vangnet van 10 minuten.
2070
+ const { data: vrij, error: vrijFout } = await db.rpc("layouts_vrijgeven_vastgelopen", { p_houder: houder });
2071
+ if (!vrijFout)
2072
+ return aantal + Number(vrij ?? 0);
2073
+ console.warn(`[printwachtrij] vrijgeven per fase mislukt: ${vrijFout.message}`);
1980
2074
  const { data: vastgelopen } = await db
1981
2075
  .from("print_jobs")
1982
2076
  .select("id, pogingen")
@@ -2007,7 +2101,10 @@ async function vervalControle(db) {
2007
2101
  return aantal;
2008
2102
  }
2009
2103
  /** Hoeveel opdrachten tegelijk worden gerenderd binnen één ronde. */
2010
- const JOB_PARALLEL = 3;
2104
+ const JOB_PARALLEL = 1;
2105
+ /** Na deze looptijd pakt een ronde geen nieuwe opdracht meer (lopende wordt afgemaakt). */
2106
+ export const RONDE_BUDGET_MS = 20000;
2107
+ void JOB_PARALLEL;
2011
2108
  /** Zo lang mag één ronde het slot houden; daarna is hij vanzelf herstelbaar. */
2012
2109
  const LEASE_SECONDEN = 120;
2013
2110
  const LEASE_NAAM = "print-queue-worker";
@@ -2017,7 +2114,7 @@ const VERVOLG_COOLDOWN_MS = 1500;
2017
2114
  * Wekt de wachtrij opnieuw, maar uitsluitend wanneer er aantoonbaar wachtend
2018
2115
  * werk overblijft. Het adres van de runner staat in de database, nooit in code.
2019
2116
  */
2020
- async function wekVervolgRonde(db) {
2117
+ async function wekVervolgRonde(db, origin = null) {
2021
2118
  const { count } = await db
2022
2119
  .from("print_jobs")
2023
2120
  .select("id", { count: "exact", head: true })
@@ -2025,13 +2122,32 @@ async function wekVervolgRonde(db) {
2025
2122
  .or(`volgende_poging.is.null,volgende_poging.lte.${new Date().toISOString()}`);
2026
2123
  if (!count)
2027
2124
  return;
2028
- await new Promise((r) => setTimeout(r, VERVOLG_COOLDOWN_MS));
2125
+ void VERVOLG_COOLDOWN_MS;
2126
+ // Eerst direct vanaf de server (geen pg_net-wachtrij); pg_net is het vangnet.
2127
+ const { wekEigenRonde } = await import("./runnerRegistry.server.js");
2128
+ const direct = await wekEigenRonde(db, origin);
2129
+ if (direct.ok)
2130
+ return;
2131
+ console.warn(`[printwachtrij] direct wekken niet gelukt (${direct.reden}); vangnet wake_print_queue.`);
2029
2132
  const { error } = await db.rpc("wake_print_queue", { _min_interval_ms: 1000 });
2030
2133
  if (error)
2031
2134
  console.warn(`[printwachtrij] vervolgronde wekken mislukt: ${error.message}`);
2032
2135
  }
2033
2136
  /** Eén ronde: vastgelopen opdrachten opruimen, afdrukken en statussen bijwerken. */
2034
- export async function verwerkWachtrij(db, max = 5) {
2137
+ async function claimEen(db) {
2138
+ const { data: pdf, error: pdfError } = await db.rpc("claim_pdf_print_jobs", { _max: 1 });
2139
+ if (pdfError)
2140
+ throw new Error(pdfError.message);
2141
+ const p = arr(pdf)[0];
2142
+ if (p)
2143
+ return p;
2144
+ const { data, error } = await db.rpc("claim_cloud_print_jobs", { _max: 1 });
2145
+ if (error)
2146
+ throw new Error(error.message);
2147
+ return arr(data)[0] ?? null;
2148
+ }
2149
+ export async function verwerkWachtrij(db, max = 5, opties = {}) {
2150
+ const rondeStart = Date.now();
2035
2151
  const leeg = {
2036
2152
  opgepakt: 0,
2037
2153
  verstuurd: 0,
@@ -2052,10 +2168,11 @@ export async function verwerkWachtrij(db, max = 5) {
2052
2168
  if (slot !== true)
2053
2169
  return { ...leeg, overgeslagen: "Er draait al een printronde." };
2054
2170
  let vervolgNodig = false;
2171
+ startCodelijstRonde();
2055
2172
  try {
2056
2173
  // Eerst het vangnet: dit draait ook als er niets te claimen valt.
2057
2174
  try {
2058
- await vervalControle(db);
2175
+ await vervalControle(db, houder);
2059
2176
  }
2060
2177
  catch (e) {
2061
2178
  console.warn(`[printwachtrij] vervalcontrole mislukt: ${e instanceof Error ? e.message : "onbekend"}`);
@@ -2068,47 +2185,48 @@ export async function verwerkWachtrij(db, max = 5) {
2068
2185
  catch (e) {
2069
2186
  console.warn(`[printwachtrij] webhook koppelen mislukt: ${e instanceof Error ? e.message : "onbekend"}`);
2070
2187
  }
2071
- // PDF-opdrachten hebben een eigen claimroute. Daardoor kunnen oudere
2072
- // gepubliceerde moduleversies, die een PDF-printer nog als PrintNode-printer
2073
- // behandelen, deze opdrachten niet meer vóór de actuele runner oppakken.
2074
- const { data: pdfData, error: pdfError } = await db.rpc("claim_pdf_print_jobs", { _max: max });
2075
- if (pdfError)
2076
- throw new Error(pdfError.message);
2077
- const pdfJobs = arr(pdfData);
2078
- const resterend = Math.max(0, max - pdfJobs.length);
2079
- let gewoneJobs = [];
2080
- if (resterend > 0) {
2081
- const { data, error } = await db.rpc("claim_cloud_print_jobs", { _max: resterend });
2082
- if (error)
2083
- throw new Error(error.message);
2084
- gewoneJobs = arr(data);
2085
- }
2086
- // Begrensd parallel: meerdere pakbonnen van één order lopen gelijktijdig,
2087
- // maar één mislukte opdracht annuleert de andere nooit.
2088
- const jobs = [...pdfJobs, ...gewoneJobs];
2089
- // Vastleggen welke installatie (en versie) deze opdrachten verwerkt.
2090
- if (jobs.length > 0) {
2188
+ // Eén opdracht tegelijk (JOB_PARALLEL = 1): claim er één, verwerk hem en
2189
+ // herhaal zolang de ronde jonger is dan RONDE_BUDGET_MS. Nooit vooraf
2190
+ // claimen, zodat wachtende opdrachten 'wachtend' blijven.
2191
+ // PDF-opdrachten hebben een eigen claimroute (eerst), daarna de cloud-route.
2192
+ const uitkomsten = [];
2193
+ let stopreden = "leeg";
2194
+ let opgepakt = 0;
2195
+ while (true) {
2196
+ if (opgepakt >= max) {
2197
+ stopreden = "max";
2198
+ break;
2199
+ }
2200
+ if (Date.now() - rondeStart >= RONDE_BUDGET_MS) {
2201
+ stopreden = "tijd";
2202
+ break;
2203
+ }
2204
+ const job = await claimEen(db);
2205
+ if (!job) {
2206
+ stopreden = "leeg";
2207
+ break;
2208
+ }
2209
+ opgepakt++;
2091
2210
  try {
2092
2211
  const { eigenBasisUrl } = await import("./runnerRegistry.server.js");
2093
2212
  const { MODULE_VERSIE } = await import("./shellPoort.js");
2094
2213
  await db
2095
2214
  .from("print_jobs")
2096
2215
  .update({ verwerkt_door_runner: eigenBasisUrl(), verwerkt_met_versie: MODULE_VERSIE })
2097
- .in("id", jobs.map((j) => j.id));
2216
+ .eq("id", job.id);
2098
2217
  }
2099
2218
  catch {
2100
2219
  /* vastleggen mag het printen nooit blokkeren */
2101
2220
  }
2102
- }
2103
- const uitkomsten = await metPool(jobs, JOB_PARALLEL, async (job) => {
2104
2221
  try {
2105
- return await verwerkJob(db, job);
2222
+ uitkomsten.push(await verwerkJob(db, job));
2106
2223
  }
2107
2224
  catch (e) {
2108
2225
  console.error(`[printwachtrij] opdracht ${job.id} viel onverwacht uit: ${e instanceof Error ? e.message : "onbekend"}`);
2109
- return "mislukt";
2226
+ uitkomsten.push("mislukt");
2110
2227
  }
2111
- });
2228
+ }
2229
+ const jobs = { length: opgepakt };
2112
2230
  const resultaat = {
2113
2231
  opgepakt: jobs.length,
2114
2232
  verstuurd: uitkomsten.filter((u) => u === "verstuurd").length,
@@ -2118,10 +2236,12 @@ export async function verwerkWachtrij(db, max = 5) {
2118
2236
  bijgewerkt: await synchroniseerStatussen(db),
2119
2237
  };
2120
2238
  // Alleen wanneer de batchlimiet vol zat kan er nog werk klaarstaan.
2121
- vervolgNodig = jobs.length >= max;
2239
+ vervolgNodig = stopreden !== "leeg";
2240
+ console.info(`[printwachtrij] ronde_klaar ${JSON.stringify({ opdrachten: opgepakt, ms: Date.now() - rondeStart, stopreden, eind: new Date().toISOString() })}`);
2122
2241
  return resultaat;
2123
2242
  }
2124
2243
  finally {
2244
+ stopCodelijstRonde();
2125
2245
  const { error } = await db.rpc("release_print_queue_lease", {
2126
2246
  _naam: LEASE_NAAM,
2127
2247
  _houder: houder,
@@ -2130,7 +2250,7 @@ export async function verwerkWachtrij(db, max = 5) {
2130
2250
  console.warn(`[printwachtrij] slot vrijgeven mislukt: ${error.message}`);
2131
2251
  if (vervolgNodig) {
2132
2252
  try {
2133
- await wekVervolgRonde(db);
2253
+ await wekVervolgRonde(db, opties.origin ?? null);
2134
2254
  }
2135
2255
  catch (fout) {
2136
2256
  const melding = fout instanceof Error ? fout.message : "onbekend";
@@ -2172,6 +2292,132 @@ export async function bepaalDocumentKeuze(db, job) {
2172
2292
  * een werkplek hem als labelprinter gebruikt. Alleen dan geldt de controle,
2173
2293
  * zodat bestaande printers zonder werkplek precies blijven werken als nu.
2174
2294
  */
2295
+ /** Stickersoort voor de verkleininstelling (op configuratie en bron, nooit op naam). */
2296
+ export function stickerSoortVoor(documenttype, layout, floriday, klaar) {
2297
+ const cfg = (layout?.config ?? {});
2298
+ if (cfg.eigen_traysticker)
2299
+ return "eigen_traysticker";
2300
+ if (cfg.eigen_sticker || String(documenttype) === "eigen_sticker")
2301
+ return "eigen_sticker";
2302
+ const tray = String(documenttype) === "traysticker";
2303
+ if (floriday || (klaar && tray))
2304
+ return tray ? "floriday_traysticker" : "floriday_sticker";
2305
+ return "klantsticker";
2306
+ }
2307
+ /** Eigen ontwerp past niet op het geladen etiket: variant op de etiketmaat maken. */
2308
+ export function eigenEtiketVariantNodig(layout, etiket) {
2309
+ const cfg = (layout?.config ?? {});
2310
+ if (!cfg.eigen_traysticker && !cfg.eigen_sticker)
2311
+ return false;
2312
+ // Eigen sticker met geüploade afbeelding heeft een vaste maat: die volgt de uitwijkroute.
2313
+ if (cfg.eigen_sticker && !cfg.eigen_traysticker)
2314
+ return false;
2315
+ const b = Number(layout.breedte_mm ?? 0);
2316
+ const h = Number(layout.hoogte_mm ?? 0);
2317
+ if (!(b > 0) || !(h > 0))
2318
+ return false;
2319
+ return !etiketPast({ breedte_mm: b, hoogte_mm: h, soortLabel: "Traysticker" }, etiket, "").ok;
2320
+ }
2321
+ /**
2322
+ * Verkleininstelling via de databasefunctie (één bron met de vroege
2323
+ * waarschuwing; maakt de standaard aan als hij ontbreekt). null = niet
2324
+ * leesbaar: dan vervalt alleen de stap verkleinen, nooit wachten.
2325
+ */
2326
+ async function leesStickerInstelling(db) {
2327
+ const { data, error } = await db.rpc("layouts_sticker_verkleinen");
2328
+ if (error)
2329
+ return null;
2330
+ return leesStickerInstellingenStrikt(data);
2331
+ }
2332
+ /** Uitwijkroute voor een sticker die niet op het geladen etiket past. */
2333
+ async function bepaalUitwijk(db, job, layout, floriday, klaar, maat, label, printer, formaten = null) {
2334
+ const instellingen = await leesStickerInstelling(db).catch(() => null);
2335
+ const soort = stickerSoortVoor(String(job.documenttype ?? ""), layout, floriday, klaar);
2336
+ const etiketten = label.etiket
2337
+ ? [{ printerNaam: label.naam, printerId: String(printer.id), paper: label.etiket.standaard ? "" : label.etiket.naam, breedte_mm: label.etiket.breedte_mm, hoogte_mm: label.etiket.hoogte_mm, dpi: printerDpi(printer), formaten: formaten ? formaten : undefined }]
2338
+ : [];
2339
+ const plekId = leesPrintPlekId(job) || (await zoekPrintPlekId(db, job).catch(() => null));
2340
+ let a4 = null;
2341
+ if (plekId) {
2342
+ const { data: a4Id } = await db.rpc("printplek_printer", { _plek: plekId, _documenttype: "pakbon" });
2343
+ if (typeof a4Id === "string" && a4Id !== String(printer.id)) {
2344
+ const { data } = await db
2345
+ .from("printers")
2346
+ .select("id, naam, weergavenaam, extern_printer_id, actief, papierformaat, ondersteunde_formaten, geladen_etiket")
2347
+ .eq("id", a4Id)
2348
+ .maybeSingle();
2349
+ a4 = data && data.actief !== false && data.extern_printer_id ? data : null;
2350
+ }
2351
+ }
2352
+ // Ensure bij gebruik (eerste print): oude losse instelling overnemen.
2353
+ await db.rpc("layouts_zorg_voor_a4_stickervel").then(() => undefined, () => undefined);
2354
+ const vel = plekId ? await leesA4Stickervel(db, String(plekId)) : null;
2355
+ const velIndeling = a4VelVoor(vel, maat);
2356
+ const uitkomst = kiesUitwijkroute({
2357
+ sticker: maat,
2358
+ etiketten,
2359
+ a4Printer: a4 ? { naam: String(a4.weergavenaam || a4.naam || "A4-printer"), id: String(a4.id) } : null,
2360
+ a4VelIngesteld: !!velIndeling,
2361
+ a4VelIndeling: velIndeling,
2362
+ instelling: instellingen ? instellingen[soort] : null,
2363
+ });
2364
+ if (!uitkomst)
2365
+ return null;
2366
+ const naarA4 = uitkomst.uitwijkroute === "a4_vel" || uitkomst.uitwijkroute === "a4_snijlijnen";
2367
+ return { uitkomst, a4: naarA4 ? a4 : null };
2368
+ }
2369
+ /** A4-stickervel van de printplek (print_plekken.a4_stickervel, 1.69.12). */
2370
+ async function leesA4Stickervel(db, plekId) {
2371
+ const { data } = await db.from("print_plekken").select("a4_stickervel").eq("id", plekId).maybeSingle();
2372
+ return leesA4StickervelWaarde(data?.a4_stickervel);
2373
+ }
2374
+ /** Resolutie uit de PrintNode-gegevens; onbekend = null (de uitwijk neemt 203 dpi). */
2375
+ function printerDpi(printer) {
2376
+ const f = (printer?.ondersteunde_formaten ?? {});
2377
+ const d = Number(f?.dpi ?? (Array.isArray(f?.dpis) ? String(f.dpis[0]).split("x")[0] : NaN));
2378
+ return d > 0 ? d : null;
2379
+ }
2380
+ /**
2381
+ * Waarom deze printer, vastgelegd in dezelfde update als extern_job_id/status
2382
+ * (print_jobs.printer_keuze). Zo spreken status en uitleg elkaar nooit tegen.
2383
+ */
2384
+ async function printerKeuzeVoor(db, job, printer, uitwijk) {
2385
+ let regels = [];
2386
+ try {
2387
+ const { data } = await db
2388
+ .from("print_job_logs")
2389
+ .select("detail")
2390
+ .eq("job_id", String(job.id))
2391
+ .in("gebeurtenis", ["waarom", "etiket", "route"])
2392
+ .order("created_at", { ascending: true });
2393
+ regels = arr(data).map((r) => String(r.detail ?? "")).filter(Boolean);
2394
+ }
2395
+ catch { /* uitleg is informatief */ }
2396
+ const naam = String(printer.weergavenaam || printer.naam || "Printer");
2397
+ if (uitwijk?.reden)
2398
+ regels.push(uitwijk.reden);
2399
+ if (!regels.length)
2400
+ regels.push(`Verstuurd naar ${naam}.`);
2401
+ return { printer_id: printer.id ?? null, printer_naam: naam, regels, vastgelegd_op: new Date().toISOString() };
2402
+ }
2403
+ /** Legt vast wat er met de sticker gebeurd is (veldnamen voor Pickschermen 1.0.61). */
2404
+ async function legUitwijkVast(db, job, u) {
2405
+ // Pickschermen 1.0.61 leest uitwijkroute/printerNaam/schaal/reden; de
2406
+ // overige velden zijn alleen voor het voorbeeld in de printwachtrij.
2407
+ const waarde = {
2408
+ ...uitwijkVoorPickschermen(u),
2409
+ rotate: u.rotate,
2410
+ pagina_breedte_mm: u.pagina_breedte_mm,
2411
+ pagina_hoogte_mm: u.pagina_hoogte_mm,
2412
+ sticker_breedte_mm: u.sticker_breedte_mm,
2413
+ sticker_hoogte_mm: u.sticker_hoogte_mm,
2414
+ };
2415
+ const { error } = await db.from("print_jobs").update({ uitwijk: waarde }).eq("id", job.id);
2416
+ if (error)
2417
+ await faseLog(db, job.id, "uitwijk_niet_vastgelegd", { ...waarde, fout: error.message });
2418
+ else
2419
+ await faseLog(db, job.id, "uitwijk", waarde);
2420
+ }
2175
2421
  async function labelControleVoorbereiden(db, printer) {
2176
2422
  const etiket = leesGeladenEtiket(printer?.geladen_etiket);
2177
2423
  const naam = String(printer?.weergavenaam || printer?.naam || "onbekend");
@@ -1 +1 @@
1
- {"version":3,"file":"printService.server.d.ts","sourceRoot":"","sources":["../../src/lib/printService.server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"printService.server.d.ts","sourceRoot":"","sources":["../../src/lib/printService.server.ts"],"names":[],"mappings":"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"}
@@ -113,8 +113,9 @@ export async function haalPrinterFormaten(externPrinterId) {
113
113
  export async function stuurPdfNaarPrinter(input) {
114
114
  const o = input.opties ?? {};
115
115
  const options = {
116
- // Bewust uit: anders schaalt de printer een etiket stilzwijgend naar A4.
117
- fit_to_page: o.fitToPage === true,
116
+ // Altijd uit (1.69.12): de printer of driver mag nooit zelf schalen;
117
+ // verkleinen/centreren gebeurt in de PDF.
118
+ fit_to_page: false,
118
119
  };
119
120
  if (o.paper)
120
121
  options["paper"] = o.paper;