@flowselections/layout-maker 1.51.3 → 1.53.1

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 (53) hide show
  1. package/README.md +0 -1
  2. package/dist-lib/components/LivePrintstatusRegel.d.ts +2 -0
  3. package/dist-lib/components/LivePrintstatusRegel.d.ts.map +1 -0
  4. package/dist-lib/components/LivePrintstatusRegel.js +37 -0
  5. package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
  6. package/dist-lib/components/PrintQueuePage.js +78 -43
  7. package/dist-lib/components/PrintenPage.d.ts.map +1 -1
  8. package/dist-lib/components/PrintenPage.js +3 -2
  9. package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
  10. package/dist-lib/components/PrintplekDetailPage.js +30 -2
  11. package/dist-lib/index.d.ts +7 -1
  12. package/dist-lib/index.d.ts.map +1 -1
  13. package/dist-lib/index.js +6 -1
  14. package/dist-lib/integrations/supabase/moduleClient.d.ts +1 -31688
  15. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  16. package/dist-lib/integrations/supabase/types.d.ts +3362 -128
  17. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  18. package/dist-lib/lib/foutTekst.d.ts +10 -0
  19. package/dist-lib/lib/foutTekst.d.ts.map +1 -1
  20. package/dist-lib/lib/foutTekst.js +28 -0
  21. package/dist-lib/lib/printApi.d.ts +33 -0
  22. package/dist-lib/lib/printApi.d.ts.map +1 -1
  23. package/dist-lib/lib/printApi.js +45 -1
  24. package/dist-lib/lib/printQueue.server.d.ts +6 -0
  25. package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
  26. package/dist-lib/lib/printQueue.server.js +72 -20
  27. package/dist-lib/lib/printService.functions.d.ts +76 -0
  28. package/dist-lib/lib/printService.functions.d.ts.map +1 -1
  29. package/dist-lib/lib/printService.functions.js +130 -0
  30. package/dist-lib/lib/printService.server.d.ts +35 -0
  31. package/dist-lib/lib/printService.server.d.ts.map +1 -1
  32. package/dist-lib/lib/printService.server.js +104 -13
  33. package/dist-lib/lib/printnodeStatus.d.ts +14 -0
  34. package/dist-lib/lib/printnodeStatus.d.ts.map +1 -0
  35. package/dist-lib/lib/printnodeStatus.js +43 -0
  36. package/dist-lib/lib/printnodeWebhook.d.ts +23 -0
  37. package/dist-lib/lib/printnodeWebhook.d.ts.map +1 -0
  38. package/dist-lib/lib/printnodeWebhook.js +137 -0
  39. package/dist-lib/lib/printnodeWebhookBeheer.server.d.ts +45 -0
  40. package/dist-lib/lib/printnodeWebhookBeheer.server.d.ts.map +1 -0
  41. package/dist-lib/lib/printnodeWebhookBeheer.server.js +116 -0
  42. package/dist-lib/lib/queueTick.d.ts.map +1 -1
  43. package/dist-lib/lib/queueTick.js +9 -0
  44. package/dist-lib/lib/shellAdres.d.ts +10 -0
  45. package/dist-lib/lib/shellAdres.d.ts.map +1 -0
  46. package/dist-lib/lib/shellAdres.js +36 -0
  47. package/dist-lib/lib/standaardLayouts.server.d.ts +6 -0
  48. package/dist-lib/lib/standaardLayouts.server.d.ts.map +1 -0
  49. package/dist-lib/lib/standaardLayouts.server.js +61 -0
  50. package/dist-lib/lib/useDocumentData.d.ts +10 -1
  51. package/dist-lib/lib/useDocumentData.d.ts.map +1 -1
  52. package/dist-lib/lib/useDocumentData.js +16 -117
  53. package/package.json +2 -2
@@ -1,3 +1,13 @@
1
+ export interface DubbelOrigineel {
2
+ jobId: string | null;
3
+ printerId: string | null;
4
+ aangemaaktOp: string | null;
5
+ }
6
+ /**
7
+ * Herkent een geweigerd dubbel origineel (één origineel per kar per
8
+ * documentsoort) en geeft het bestaande opdracht-id, de printer en de tijd.
9
+ */
10
+ export declare function leesDubbelOrigineel(err: unknown): DubbelOrigineel | null;
1
11
  /** Maakt van een (Supabase-)fout een zin die de gebruiker zelf kan herleiden. */
2
12
  export declare function leesbareFout(err: unknown, prefix?: string): string;
3
13
  //# sourceMappingURL=foutTekst.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"foutTekst.d.ts","sourceRoot":"","sources":["../../src/lib/foutTekst.ts"],"names":[],"mappings":"AAIA,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,SAAoB,GAAG,MAAM,CAoB7E"}
1
+ {"version":3,"file":"foutTekst.d.ts","sourceRoot":"","sources":["../../src/lib/foutTekst.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAiBxE;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,SAAoB,GAAG,MAAM,CAyB7E"}
@@ -1,10 +1,38 @@
1
1
  // ============================================================================
2
2
  // src/lib/foutTekst.ts — databasefouten omzetten naar leesbare tekst.
3
3
  // ============================================================================
4
+ /**
5
+ * Herkent een geweigerd dubbel origineel (één origineel per kar per
6
+ * documentsoort) en geeft het bestaande opdracht-id, de printer en de tijd.
7
+ */
8
+ export function leesDubbelOrigineel(err) {
9
+ const e = (err ?? {});
10
+ const msg = String(e.message ?? "");
11
+ const isDubbel = msg.includes("DUBBEL_ORIGINEEL") ||
12
+ (e.code === "23505" && msg.includes("print_jobs_een_origineel_per_kar"));
13
+ if (!isDubbel)
14
+ return null;
15
+ try {
16
+ const d = JSON.parse(String(e.details ?? "{}"));
17
+ return {
18
+ jobId: d["job_id"] ?? null,
19
+ printerId: d["printer_id"] ?? null,
20
+ aangemaaktOp: d["created_at"] ?? null,
21
+ };
22
+ }
23
+ catch {
24
+ return { jobId: null, printerId: null, aangemaaktOp: null };
25
+ }
26
+ }
4
27
  /** Maakt van een (Supabase-)fout een zin die de gebruiker zelf kan herleiden. */
5
28
  export function leesbareFout(err, prefix = "Opslaan mislukt") {
6
29
  const e = (err ?? {});
7
30
  const msg = String(e.message ?? (typeof err === "string" ? err : "")).trim();
31
+ const dubbel = leesDubbelOrigineel(err);
32
+ if (dubbel) {
33
+ const tijd = dubbel.aangemaaktOp ? new Date(dubbel.aangemaaktOp).toLocaleString("nl-NL") : "eerder";
34
+ return `${prefix}: voor deze kar is al een origineel gemaakt (opdracht ${dubbel.jobId ?? "?"}, ${tijd}). Gebruik "Opnieuw printen" voor een herprint.`;
35
+ }
8
36
  if (msg.includes("PRINTER_NIET_OP_PLEK")) {
9
37
  const m = msg.match(/werkplek\s+(.+?)\.?$/);
10
38
  return `${prefix}: deze printer is niet gekoppeld aan de printplek${m ? ` van werkplek ${m[1]}` : ""}. Koppel hem eerst aan de printplek.`;
@@ -1,3 +1,4 @@
1
+ import { type DubbelOrigineel } from "./foutTekst.js";
1
2
  import type { DocumentType } from "./documentTypes.js";
2
3
  export interface PrintDocumentInput {
3
4
  /** Documentsoort, bijv. "pakbon" of "productiebon". */
@@ -36,6 +37,38 @@ export declare class DubbeleAanvraagFout extends Error {
36
37
  name: string;
37
38
  constructor();
38
39
  }
40
+ /**
41
+ * Fout wanneer er voor deze kar en documentsoort al een origineel bestaat.
42
+ * Bevat het bestaande opdracht-id, de printer en de tijd.
43
+ */
44
+ export declare class DubbelOrigineelFout extends Error {
45
+ name: string;
46
+ readonly code = "DUBBEL_ORIGINEEL";
47
+ readonly bestaandJobId: string | null;
48
+ readonly printerId: string | null;
49
+ readonly aangemaaktOp: string | null;
50
+ constructor(d: DubbelOrigineel);
51
+ }
52
+ export interface MisluktePrintopdrachtInput {
53
+ documenttype: DocumentType | string;
54
+ documentnaam: string;
55
+ /** Waarom het document niet gemaakt kon worden (verplicht). */
56
+ reden: string;
57
+ layoutId?: string | null;
58
+ printplekId?: string | null;
59
+ werkplek?: string | null;
60
+ herkomst?: string | null;
61
+ payload?: Record<string, unknown>;
62
+ idempotentieSleutel?: string | null;
63
+ }
64
+ /**
65
+ * Legt een opdracht vast waarvan het document niet gemaakt kon worden
66
+ * (bijv. een verzendbrief). Hij staat dan als "mislukt" met de reden in de
67
+ * Printwachtrij, met "Opnieuw proberen".
68
+ */
69
+ export declare function meldMisluktePrintopdracht(input: MisluktePrintopdrachtInput): Promise<{
70
+ jobId: string;
71
+ }>;
39
72
  /** Fout wanneer nergens een printer voor dit document is ingesteld. */
40
73
  export declare class GeenPrinterFout extends Error {
41
74
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"printApi.d.ts","sourceRoot":"","sources":["../../src/lib/printApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"printApi.d.ts","sourceRoot":"","sources":["../../src/lib/printApi.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  // ============================================================================
4
4
  // Andere modules gebruiken uitsluitend deze functies; zij hoeven de tabellen
5
5
  // van deze module niet te kennen.
6
+ import { leesDubbelOrigineel } from "./foutTekst.js";
6
7
  import { supabase } from "./supabaseClient.js";
7
8
  import { printplekNaam, printplekVoorComputer } from "./printplekken.js";
8
9
  import { routeringVoor } from "./printRoutering.js";
@@ -88,8 +89,12 @@ async function zetInWachtrij(rij) {
88
89
  .insert({ status: "wachtend", ...rij })
89
90
  .select("id")
90
91
  .maybeSingle();
91
- if (error)
92
+ if (error) {
93
+ const dubbel = leesDubbelOrigineel(error);
94
+ if (dubbel)
95
+ throw new DubbelOrigineelFout(dubbel);
92
96
  throw error;
97
+ }
93
98
  const id = data?.id ?? null;
94
99
  // Direct laten verwerken; wacht niet op de cron-ronde. Mislukt dit, dan
95
100
  // blijft de opdracht gewoon wachtend staan voor een volgende poging.
@@ -105,6 +110,45 @@ export class DubbeleAanvraagFout extends Error {
105
110
  this.name = "DubbeleAanvraagFout";
106
111
  }
107
112
  }
113
+ /**
114
+ * Fout wanneer er voor deze kar en documentsoort al een origineel bestaat.
115
+ * Bevat het bestaande opdracht-id, de printer en de tijd.
116
+ */
117
+ export class DubbelOrigineelFout extends Error {
118
+ constructor(d) {
119
+ super(`DUBBEL_ORIGINEEL: voor deze kar is al een origineel gemaakt (opdracht ${d.jobId ?? "?"}). Gebruik een herprint.`);
120
+ this.name = "DubbelOrigineelFout";
121
+ this.code = "DUBBEL_ORIGINEEL";
122
+ this.bestaandJobId = d.jobId;
123
+ this.printerId = d.printerId;
124
+ this.aangemaaktOp = d.aangemaaktOp;
125
+ }
126
+ }
127
+ /**
128
+ * Legt een opdracht vast waarvan het document niet gemaakt kon worden
129
+ * (bijv. een verzendbrief). Hij staat dan als "mislukt" met de reden in de
130
+ * Printwachtrij, met "Opnieuw proberen".
131
+ */
132
+ export async function meldMisluktePrintopdracht(input) {
133
+ const reden = String(input.reden ?? "").trim();
134
+ if (!reden)
135
+ throw new Error("Geef een reden mee voor de mislukte opdracht.");
136
+ const { data, error } = await supabase.rpc("layout_print_document", {
137
+ _documenttype: String(input.documenttype),
138
+ _documentnaam: input.documentnaam,
139
+ _layout_id: input.layoutId ?? null,
140
+ _print_plek_id: input.printplekId ?? null,
141
+ _werkplek: input.werkplek ?? null,
142
+ _herkomst: input.herkomst ?? null,
143
+ _payload: input.payload ?? {},
144
+ _idempotentie_sleutel: input.idempotentieSleutel ?? null,
145
+ _mislukt_reden: reden,
146
+ });
147
+ if (error)
148
+ throw error;
149
+ const rij = Array.isArray(data) ? data[0] : null;
150
+ return { jobId: String(rij?.job_id ?? "") };
151
+ }
108
152
  /** Fout wanneer nergens een printer voor dit document is ingesteld. */
109
153
  export class GeenPrinterFout extends Error {
110
154
  constructor(melding) {
@@ -64,6 +64,12 @@ export declare const MAX_WACHT_OP_LAYOUT = 3;
64
64
  * eindeloos blijft rondgaan en onder de gewone opschoning valt.
65
65
  */
66
66
  export declare function wachtOpLayout(db: PrintDb, job: Job, reden: string): Promise<"wachtend" | "mislukt">;
67
+ /**
68
+ * Verwerkt één stabiele PrintNode-status (uit /states of de webhook) op een
69
+ * opdracht. Gedeeld door polling en webhook, zodat beide hetzelfde doen.
70
+ */
71
+ export declare function pasPrintNodeStatusToe(db: PrintDb, jobId: string, printnode: string, bericht: string): Promise<void>;
72
+ export declare function mislukGrensMinuten(verlooptNaS: number | null, documenttype: string | null): number;
67
73
  export interface WachtrijResultaat {
68
74
  opgepakt: number;
69
75
  verstuurd: number;
@@ -1 +1 @@
1
- {"version":3,"file":"printQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/printQueue.server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAkC5D,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE/B,mFAAmF;AACnF,MAAM,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEpD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW1E;AAoDD,2EAA2E;AAC3E,qBAAa,gBAAiB,SAAQ,KAAK;IAChC,IAAI,SAAsB;CACpC;AAED,+EAA+E;AAC/E,qBAAa,iBAAkB,SAAQ,KAAK;IACjC,IAAI,SAAuB;CACrC;AAED,oFAAoF;AACpF,qBAAa,kBAAmB,SAAQ,gBAAgB;IAC7C,IAAI,SAAwB;CACtC;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvE,yEAAyE;AACzE,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,aAAa,CAAC;AAE1F,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAcnD,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAI7D;AASD,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAQnD;AA2PD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+BnF;AAsRD;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,WAAW,EAClB,QAAQ,CAAC,EAAE,YAAY,GACtB,OAAO,CAAC,MAAM,CAAC,CAuZjB;AAGD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAY1D;AAqBD,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAsCzG;AAoZD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA2BD,oFAAoF;AACpF,wBAAsB,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,SAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwFtF;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,GAAG,GACP,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA4B1D"}
1
+ {"version":3,"file":"printQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/printQueue.server.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@ import { heeftOrderInhoud, laadOrderVanuitDatabase, laadPakbonData } from "./ord
12
12
  import { profielHeeftInhoud, renderProfielDocument } from "./profielHtml.js";
13
13
  import { bouwDocumentHtml, voorbeeldContext } from "./layoutPreview.js";
14
14
  import { htmlNaarPdfServer, PdfRenderFout } from "./htmlNaarPdf.server.js";
15
- import { stuurPdfNaarPrinter, opdrachtStatus } from "./printService.server.js";
15
+ import { stuurPdfNaarPrinter, opdrachtStatusDetail, vervaltijdVoor } from "./printService.server.js";
16
16
  import { kiesPapier } from "./papierFormaten.js";
17
17
  import { PAPIERFORMATEN } from "./documentTypes.js";
18
18
  const MAX_POGINGEN = 3;
@@ -1269,7 +1269,10 @@ async function verwerkJob(db, job) {
1269
1269
  const breedteMm = Number(layout?.breedte_mm ?? vfPapier?.["breedte_mm"] ?? standaardMaat(printer).breedte);
1270
1270
  const hoogteMm = Number(layout?.hoogte_mm ?? vfPapier?.["hoogte_mm"] ?? standaardMaat(printer).hoogte);
1271
1271
  const papier = kiesPapier(formaten, breedteMm, hoogteMm);
1272
+ const verloopt = vervaltijdVoor(String(job.documenttype ?? ""));
1272
1273
  const externJobId = await stuurPdfNaarPrinter({
1274
+ jobId: String(job.id),
1275
+ expireAfter: verloopt,
1273
1276
  externPrinterId: String(printer.extern_printer_id),
1274
1277
  documentnaam: String(job.documentnaam ?? "Document"),
1275
1278
  pdfBase64,
@@ -1291,6 +1294,9 @@ async function verwerkJob(db, job) {
1291
1294
  gebruikte_layout_id: uitkomst.bron === "extern_pdf" ? null : (layout?.id ?? null),
1292
1295
  gebruikte_bron: uitkomst.bron,
1293
1296
  extern_job_id: externJobId,
1297
+ printnode_status: "new",
1298
+ printnode_status_op: new Date().toISOString(),
1299
+ verloopt_na_s: verloopt,
1294
1300
  verwerkingsfase: "afleveren",
1295
1301
  fase_voltooid_op: new Date().toISOString(),
1296
1302
  foutcode: null,
@@ -1323,8 +1329,50 @@ async function verwerkJob(db, job) {
1323
1329
  return "mislukt";
1324
1330
  }
1325
1331
  }
1332
+ /**
1333
+ * Verwerkt één stabiele PrintNode-status (uit /states of de webhook) op een
1334
+ * opdracht. Gedeeld door polling en webhook, zodat beide hetzelfde doen.
1335
+ */
1336
+ export async function pasPrintNodeStatusToe(db, jobId, printnode, bericht) {
1337
+ const s = printnode.toLowerCase();
1338
+ const nu = new Date().toISOString();
1339
+ const upd = {
1340
+ printnode_status: s,
1341
+ printnode_bericht: bericht ? bericht.slice(0, 500) : null,
1342
+ printnode_status_op: nu,
1343
+ updated_at: nu,
1344
+ };
1345
+ if (s === "done") {
1346
+ upd["status"] = "voltooid";
1347
+ upd["voltooid_op"] = nu;
1348
+ upd["foutmelding"] = null;
1349
+ }
1350
+ else if (s === "error") {
1351
+ upd["status"] = "mislukt";
1352
+ upd["voltooid_op"] = nu;
1353
+ upd["foutcode"] = "PRINTER_FOUT";
1354
+ upd["foutmelding"] = (bericht ? `De printer meldde een fout: ${bericht}` : "De printer meldde een fout.").slice(0, 500);
1355
+ }
1356
+ else if (s === "expired") {
1357
+ upd["status"] = "mislukt";
1358
+ upd["voltooid_op"] = nu;
1359
+ upd["foutcode"] = "VERLOPEN";
1360
+ upd["foutmelding"] = "Verlopen — niet geprint. De computer was niet op tijd bereikbaar.";
1361
+ }
1362
+ await db.from("print_jobs").update(upd).eq("id", jobId).neq("status", "geannuleerd");
1363
+ if (s === "done" || s === "error" || s === "expired") {
1364
+ await log(db, jobId, s === "done" ? "voltooid" : s === "expired" ? "verlopen" : "mislukt", bericht || undefined);
1365
+ }
1366
+ }
1326
1367
  /** Na deze tijd is een opdracht bij de printdienst niet meer te vertrouwen. */
1327
- const VERVAL_BEZIG_MIN = 30;
1368
+ // "expired" van PrintNode is leidend. Zonder enige status pas na de vervaltijd
1369
+ // van die opdracht/documentsoort + 15 minuten. 75 = kortste grens (3600 s + 15 min).
1370
+ const VERVAL_BEZIG_MIN = 75;
1371
+ const MARGE_MIN = 15;
1372
+ export function mislukGrensMinuten(verlooptNaS, documenttype) {
1373
+ const s = Number(verlooptNaS) > 0 ? Number(verlooptNaS) : vervaltijdVoor(documenttype) ?? 3600;
1374
+ return Math.max(VERVAL_BEZIG_MIN, Math.ceil(s / 60) + MARGE_MIN);
1375
+ }
1328
1376
  /** Een claim zonder verzending mag hooguit zo lang blijven hangen. */
1329
1377
  const VERVAL_CLAIM_MIN = 10;
1330
1378
  /** Hoeveel statuscontroles hooguit per ronde, en met welke gelijktijdigheid. */
@@ -1348,21 +1396,11 @@ async function synchroniseerStatussen(db) {
1348
1396
  return 0;
1349
1397
  const uitkomsten = await metPool(jobs, STATUS_PARALLEL, async (job) => {
1350
1398
  try {
1351
- const status = await opdrachtStatus(String(job.extern_job_id));
1352
- if (status === "voltooid" || status === "mislukt") {
1353
- await db
1354
- .from("print_jobs")
1355
- .update({
1356
- status,
1357
- voltooid_op: new Date().toISOString(),
1358
- foutmelding: status === "mislukt" ? "De printer meldde een fout." : null,
1359
- updated_at: new Date().toISOString(),
1360
- })
1361
- .eq("id", job.id)
1362
- .neq("status", "geannuleerd");
1363
- await log(db, job.id, status);
1364
- return 1;
1365
- }
1399
+ const d = await opdrachtStatusDetail(String(job.extern_job_id));
1400
+ if (!d.printnode)
1401
+ return 0;
1402
+ await pasPrintNodeStatusToe(db, String(job.id), d.printnode, d.bericht);
1403
+ return d.status === "voltooid" || d.status === "mislukt" ? 1 : 0;
1366
1404
  return 0;
1367
1405
  }
1368
1406
  catch (e) {
@@ -1400,13 +1438,19 @@ async function vervalControle(db) {
1400
1438
  let aantal = 0;
1401
1439
  const { data: verstuurd } = await db
1402
1440
  .from("print_jobs")
1403
- .select("id")
1441
+ .select("id, documenttype, verloopt_na_s, opgepakt_op, updated_at")
1404
1442
  .eq("status", "bezig")
1405
1443
  .not("extern_job_id", "is", null)
1406
1444
  .or(`opgepakt_op.lt.${grensVerstuurd},and(opgepakt_op.is.null,updated_at.lt.${grensVerstuurd})`)
1407
- .limit(50);
1445
+ .order("opgepakt_op", { ascending: true, nullsFirst: true })
1446
+ .limit(200);
1408
1447
  for (const job of arr(verstuurd)) {
1409
- const reden = `De printdienst bevestigde de status van deze opdracht ${VERVAL_BEZIG_MIN} minuten ` +
1448
+ const j = job;
1449
+ const grensMin = mislukGrensMinuten(j.verloopt_na_s ?? null, j.documenttype ?? null);
1450
+ const sinds = new Date(String(j.opgepakt_op ?? j.updated_at ?? 0)).getTime();
1451
+ if (nu - sinds < grensMin * 60000)
1452
+ continue;
1453
+ const reden = `De printdienst bevestigde de status van deze opdracht ${grensMin} minuten ` +
1410
1454
  "lang niet. Of hij is afgedrukt is niet vast te stellen; controleer de printer en print zo nodig opnieuw.";
1411
1455
  await db
1412
1456
  .from("print_jobs")
@@ -1504,6 +1548,14 @@ export async function verwerkWachtrij(db, max = 5) {
1504
1548
  catch (e) {
1505
1549
  console.warn(`[printwachtrij] vervalcontrole mislukt: ${e instanceof Error ? e.message : "onbekend"}`);
1506
1550
  }
1551
+ // Live printstatus: koppel de webhook zelf als dat nog niet gebeurd is.
1552
+ try {
1553
+ const { zorgVoorWebhookKoppeling } = await import("./printnodeWebhookBeheer.server.js");
1554
+ await zorgVoorWebhookKoppeling(db);
1555
+ }
1556
+ catch (e) {
1557
+ console.warn(`[printwachtrij] webhook koppelen mislukt: ${e instanceof Error ? e.message : "onbekend"}`);
1558
+ }
1507
1559
  // PDF-opdrachten hebben een eigen claimroute. Daardoor kunnen oudere
1508
1560
  // gepubliceerde moduleversies, die een PDF-printer nog als PrintNode-printer
1509
1561
  // behandelen, deze opdrachten niet meer vóór de actuele runner oppakken.
@@ -81,4 +81,80 @@ export declare const netwerkComputers: import("@tanstack/start-client-core").Opt
81
81
  fout: string;
82
82
  computers?: undefined;
83
83
  }>>;
84
+ /**
85
+ * Maakt de standaardlayouts aan met de servicerol, alleen als er nog géén
86
+ * enkele layout bestaat. Zo schrijft een pagina nooit met de gebruikerssessie.
87
+ */
88
+ export declare const zorgVoorStandaardLayoutsFn: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
89
+ supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
90
+ userId: string;
91
+ claims: import("@supabase/auth-js").JwtPayload;
92
+ }, undefined, undefined, undefined>], undefined, Promise<{
93
+ ok: true;
94
+ aangemaakt: number;
95
+ fout?: undefined;
96
+ } | {
97
+ ok: false;
98
+ aangemaakt: 0;
99
+ fout: string;
100
+ }>>;
101
+ /** Echte tellingen per status over alle opdrachten (niet alleen de laatste 200). */
102
+ export declare const printTellingen: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
103
+ supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
104
+ userId: string;
105
+ claims: import("@supabase/auth-js").JwtPayload;
106
+ }, undefined, undefined, undefined>], undefined, Promise<Record<string, number>>>;
107
+ /**
108
+ * "Opnieuw printen" / "Opnieuw proberen" vanuit de wachtrij.
109
+ * - Mislukte aanlevering (geen document): maakt het document opnieuw aan via
110
+ * de layoutroute (layout_print_document), als nieuw origineel.
111
+ * - Anders: een herprint-opdracht met een nieuw id en hetzelfde document.
112
+ */
113
+ export declare const opnieuwPrinten: import("@tanstack/start-client-core").RequiredFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
114
+ supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
115
+ userId: string;
116
+ claims: import("@supabase/auth-js").JwtPayload;
117
+ }, undefined, undefined, undefined>], (input: {
118
+ jobId: string;
119
+ }) => {
120
+ jobId: string;
121
+ }, Promise<{
122
+ ok: false;
123
+ fout: string;
124
+ jobId?: undefined;
125
+ } | {
126
+ ok: true;
127
+ jobId: string;
128
+ fout?: undefined;
129
+ }>>;
130
+ /** Live printstatus (webhook) — nooit het geheim. */
131
+ export declare const webhookStatus: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
132
+ supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
133
+ userId: string;
134
+ claims: import("@supabase/auth-js").JwtPayload;
135
+ }, undefined, undefined, undefined>], undefined, Promise<{
136
+ aan: boolean;
137
+ url: string | null;
138
+ fout: string | null;
139
+ melding: string | null;
140
+ gekoppeldOp: string | null;
141
+ laatstOntvangenOp: string | null;
142
+ veldBevestigd: boolean;
143
+ ok: true;
144
+ } | {
145
+ ok: false;
146
+ fout: string;
147
+ }>>;
148
+ /** Herstel: nieuw geheim en webhook bijwerken. Alleen beheerders. */
149
+ export declare const webhookOpnieuwKoppelen: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
150
+ supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
151
+ userId: string;
152
+ claims: import("@supabase/auth-js").JwtPayload;
153
+ }, undefined, undefined, undefined>], undefined, Promise<{
154
+ ok: true;
155
+ reden?: undefined;
156
+ } | {
157
+ ok: false;
158
+ reden: string;
159
+ }>>;
84
160
  //# sourceMappingURL=printService.functions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"printService.functions.d.ts","sourceRoot":"","sources":["../../src/lib/printService.functions.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,eAAe;;;;;;;;;;;;GASxB,CAAC;AAEL,eAAO,MAAM,qBAAqB;;;;8CAER;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;;;GAmBC,CAAC;AAEL,eAAO,MAAM,WAAW;;;;8CAEE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;GAU7C,CAAC;AAEL,eAAO,MAAM,uBAAuB;;;;+CAET;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;;;;;;GAqE5C,CAAC;AAEL,eAAO,MAAM,gBAAgB;;;;;;;;;;;;GAYzB,CAAC"}
1
+ {"version":3,"file":"printService.functions.d.ts","sourceRoot":"","sources":["../../src/lib/printService.functions.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,eAAe;;;;;;;;;;;;GASxB,CAAC;AAEL,eAAO,MAAM,qBAAqB;;;;8CAER;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;;;GAmBC,CAAC;AAEL,eAAO,MAAM,WAAW;;;;8CAEE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;GAU7C,CAAC;AAEL,eAAO,MAAM,uBAAuB;;;;+CAET;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;;;;;;GAqE5C,CAAC;AAEL,eAAO,MAAM,gBAAgB;;;;;;;;;;;;GAYzB,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;GAUnC,CAAC;AAEL,oFAAoF;AACpF,eAAO,MAAM,cAAc;;;;iFAevB,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;8CAED;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;GAyDvC,CAAC;AAEL,qDAAqD;AACrD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;GAUtB,CAAC;AAEL,qEAAqE;AACrE,eAAO,MAAM,sBAAsB;;;;;;;;;;GAoB/B,CAAC"}
@@ -135,3 +135,133 @@ export const netwerkComputers = createServerFn({ method: "POST" })
135
135
  };
136
136
  }
137
137
  });
138
+ /**
139
+ * Maakt de standaardlayouts aan met de servicerol, alleen als er nog géén
140
+ * enkele layout bestaat. Zo schrijft een pagina nooit met de gebruikerssessie.
141
+ */
142
+ export const zorgVoorStandaardLayoutsFn = createServerFn({ method: "POST" })
143
+ .middleware([requireSupabaseAuth])
144
+ .handler(async () => {
145
+ try {
146
+ const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
147
+ const { zorgVoorStandaardLayoutsServer } = await import("./standaardLayouts.server.js");
148
+ return { ok: true, aangemaakt: await zorgVoorStandaardLayoutsServer(supabaseAdmin) };
149
+ }
150
+ catch (e) {
151
+ return { ok: false, aangemaakt: 0, fout: e instanceof Error ? e.message : "Mislukt" };
152
+ }
153
+ });
154
+ /** Echte tellingen per status over alle opdrachten (niet alleen de laatste 200). */
155
+ export const printTellingen = createServerFn({ method: "POST" })
156
+ .middleware([requireSupabaseAuth])
157
+ .handler(async ({ context }) => {
158
+ const statussen = ["wachtend", "bezig", "voltooid", "mislukt", "geannuleerd"];
159
+ const uitkomst = {};
160
+ await Promise.all(statussen.map(async (s) => {
161
+ const { count } = await context.supabase
162
+ .from("print_jobs")
163
+ .select("id", { count: "exact", head: true })
164
+ .eq("status", s);
165
+ uitkomst[s] = count ?? 0;
166
+ }));
167
+ return uitkomst;
168
+ });
169
+ /**
170
+ * "Opnieuw printen" / "Opnieuw proberen" vanuit de wachtrij.
171
+ * - Mislukte aanlevering (geen document): maakt het document opnieuw aan via
172
+ * de layoutroute (layout_print_document), als nieuw origineel.
173
+ * - Anders: een herprint-opdracht met een nieuw id en hetzelfde document.
174
+ */
175
+ export const opnieuwPrinten = createServerFn({ method: "POST" })
176
+ .middleware([requireSupabaseAuth])
177
+ .inputValidator((input) => {
178
+ const id = String(input?.jobId ?? "");
179
+ if (!/^[0-9a-f-]{36}$/i.test(id))
180
+ throw new Error("Ongeldig opdracht-id");
181
+ return { jobId: id };
182
+ })
183
+ .handler(async ({ data, context }) => {
184
+ const { data: j, error } = await context.supabase
185
+ .from("print_jobs")
186
+ .select("id, layout_id, printer_id, documenttype, documentnaam, kopieen, payload, herkomst, pdf_base64, pdf_url, render_html, foutcode")
187
+ .eq("id", data.jobId)
188
+ .maybeSingle();
189
+ if (error || !j)
190
+ return { ok: false, fout: "Opdracht niet gevonden." };
191
+ const job = j;
192
+ const payload = (job["payload"] && typeof job["payload"] === "object" ? job["payload"] : {});
193
+ if (job["foutcode"] === "AANLEVERING_MISLUKT") {
194
+ const { data: r, error: e } = await context.supabase.rpc("layout_print_document", {
195
+ _documenttype: String(job["documenttype"]),
196
+ _documentnaam: String(job["documentnaam"] ?? job["documenttype"]),
197
+ _layout_id: job["layout_id"] ?? null,
198
+ _print_plek_id: payload["print_plek_id"] ?? null,
199
+ _werkplek: payload["werkplek"] ?? null,
200
+ _kopieen: Number(job["kopieen"] ?? 1),
201
+ _payload: { ...payload, opnieuw_van: job["id"] },
202
+ });
203
+ if (e) {
204
+ const { leesbareFout } = await import("./foutTekst.js");
205
+ return { ok: false, fout: leesbareFout(e, "Opnieuw proberen mislukt") };
206
+ }
207
+ const rij = Array.isArray(r) ? r[0] : null;
208
+ return { ok: true, jobId: String(rij?.job_id ?? "") };
209
+ }
210
+ const { data: nieuw, error: e2 } = await context.supabase
211
+ .from("print_jobs")
212
+ .insert({
213
+ status: "wachtend",
214
+ layout_id: job["layout_id"] ?? null,
215
+ printer_id: job["printer_id"] ?? null,
216
+ documenttype: job["documenttype"],
217
+ documentnaam: job["documentnaam"] ?? "Herprint",
218
+ kopieen: job["kopieen"] ?? 1,
219
+ herkomst: job["herkomst"] ?? null,
220
+ pdf_base64: job["pdf_base64"] ?? null,
221
+ pdf_url: job["pdf_url"] ?? null,
222
+ render_html: job["render_html"] ?? null,
223
+ is_herprint: true,
224
+ bron_job_id: job["id"],
225
+ payload: { ...payload, is_herprint: true, bron_job_id: job["id"] },
226
+ })
227
+ .select("id")
228
+ .single();
229
+ if (e2) {
230
+ const { leesbareFout } = await import("./foutTekst.js");
231
+ return { ok: false, fout: leesbareFout(e2, "Opnieuw printen mislukt") };
232
+ }
233
+ return { ok: true, jobId: String(nieuw.id) };
234
+ });
235
+ /** Live printstatus (webhook) — nooit het geheim. */
236
+ export const webhookStatus = createServerFn({ method: "POST" })
237
+ .middleware([requireSupabaseAuth])
238
+ .handler(async () => {
239
+ try {
240
+ const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
241
+ const { leesKoppeling, veiligeStatus } = await import("./printnodeWebhookBeheer.server.js");
242
+ return { ok: true, ...veiligeStatus(await leesKoppeling(supabaseAdmin)) };
243
+ }
244
+ catch (e) {
245
+ return { ok: false, fout: e instanceof Error ? e.message : "Status ophalen mislukt" };
246
+ }
247
+ });
248
+ /** Herstel: nieuw geheim en webhook bijwerken. Alleen beheerders. */
249
+ export const webhookOpnieuwKoppelen = createServerFn({ method: "POST" })
250
+ .middleware([requireSupabaseAuth])
251
+ .handler(async ({ context }) => {
252
+ const ctx = context;
253
+ const rollen = await Promise.all(["admin", "superadmin", "developer"].map((r) => ctx.supabase.rpc("has_role", { _user_id: ctx.userId, _role: r }).then((x) => x.data === true)));
254
+ if (!rollen.some(Boolean))
255
+ return { ok: false, reden: "Alleen een beheerder kan opnieuw koppelen." };
256
+ const { getRequest } = await import("@tanstack/react-start/server");
257
+ let oorsprong = null;
258
+ try {
259
+ const req = getRequest();
260
+ oorsprong = req.headers.get("origin") ?? new URL(req.url).origin;
261
+ }
262
+ catch { /* geen oorsprong */ }
263
+ const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
264
+ const { koppelWebhook } = await import("./printnodeWebhookBeheer.server.js");
265
+ const u = await koppelWebhook(supabaseAdmin, { oorsprong });
266
+ return u.ok ? { ok: true } : { ok: false, reden: u.reden ?? "Koppelen mislukt." };
267
+ });
@@ -21,11 +21,30 @@ export interface PrintOpties {
21
21
  }
22
22
  export interface PrintOpdrachtInput {
23
23
  externPrinterId: string;
24
+ /** print_jobs.id: wordt idempotentiesleutel én staat in `source`. */
25
+ jobId?: string | null;
26
+ /** Seconden dat PrintNode de opdracht mag bewaren als hij niet direct kan printen. */
27
+ expireAfter?: number | null;
24
28
  documentnaam: string;
25
29
  pdfBase64: string;
26
30
  kopieen?: number;
27
31
  opties?: PrintOpties;
28
32
  }
33
+ /** Fout voor een 409 van PrintNode: deze idempotentiesleutel is al ontvangen. */
34
+ export declare class AlOntvangenFout extends Error {
35
+ constructor();
36
+ }
37
+ /** Vaste bronaanduiding; bevat het opdracht-id zodat we hem op id terugvinden. */
38
+ export declare const SOURCE_PREFIX = "Layouts en printers \u00B7 ";
39
+ export declare function sourceVoorJob(jobId: string | null | undefined): string;
40
+ /**
41
+ * Standaard vervaltijd per documentsoort (seconden). Vast in de code, geen
42
+ * instellingenscherm. Onbekende soorten: geen expireAfter (PrintNode-standaard).
43
+ */
44
+ export declare const VERVALTIJD_PER_SOORT: Record<string, number>;
45
+ export declare function vervaltijdVoor(documenttype: string | null | undefined): number | null;
46
+ /** PrintNode-aanroep met dezelfde sleutel en child-account-koppen als bij printen. */
47
+ export declare function printnodeVraag<T>(pad: string, init?: RequestInit): Promise<T>;
29
48
  /** Alle printers die via de printclients in het netwerk beschikbaar zijn. */
30
49
  export declare function haalNetwerkPrinters(): Promise<NetwerkPrinter[]>;
31
50
  /** Papierformaten en laden van één printer, rechtstreeks bij de printdienst. */
@@ -35,6 +54,22 @@ export declare function haalPrinterFormaten(externPrinterId: string): Promise<{
35
54
  }>;
36
55
  /** Stuurt een PDF rechtstreeks naar de printer. Geeft het externe opdrachtnummer terug. */
37
56
  export declare function stuurPdfNaarPrinter(input: PrintOpdrachtInput): Promise<string>;
57
+ /**
58
+ * Zoekt een PrintNode-opdracht op exact `source` (bevat print_jobs.id).
59
+ * De lijst staat nieuwste eerst; we bladeren hooguit een paar pagina's.
60
+ */
61
+ export declare function zoekPrintJobOpSource(source: string): Promise<string | null>;
62
+ /** Stabiele PrintNode-statussen (zie documentatie "Print Job States"). */
63
+ export type PrintNodeStatus = "new" | "sent_to_client" | "done" | "error" | "expired";
64
+ export declare const STABIELE_STATUSSEN: readonly PrintNodeStatus[];
65
+ /** Vertaalt een stabiele PrintNode-status naar de wachtrijstatus. */
66
+ export declare function wachtrijStatusVoor(s: string): OpdrachtStatus;
67
+ /** Laatste stabiele status + bericht van een opdracht. */
68
+ export declare function opdrachtStatusDetail(externJobId: string): Promise<{
69
+ printnode: string;
70
+ bericht: string;
71
+ status: OpdrachtStatus;
72
+ }>;
38
73
  /** Verwijdert een nog niet afgedrukte opdracht bij de externe printdienst. */
39
74
  export declare function annuleerExternePrintOpdracht(externJobId: string): Promise<void>;
40
75
  export type OpdrachtStatus = "wachtend" | "bezig" | "voltooid" | "mislukt";