@flowselections/floriday-voorraad 1.0.145 → 1.0.149

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 (100) hide show
  1. package/dist-lib/components/voorraad/ArtikelWizard.d.ts +3 -1
  2. package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
  3. package/dist-lib/components/voorraad/ArtikelWizard.js +56 -52
  4. package/dist-lib/components/voorraad/EditArtikelPage.d.ts.map +1 -1
  5. package/dist-lib/components/voorraad/EditArtikelPage.js +15 -23
  6. package/dist-lib/components/voorraad/OrderHistoryCard.d.ts +3 -1
  7. package/dist-lib/components/voorraad/OrderHistoryCard.d.ts.map +1 -1
  8. package/dist-lib/components/voorraad/OrderHistoryCard.js +7 -3
  9. package/dist-lib/components/voorraad/ProductCustomFieldsCard.d.ts +5 -1
  10. package/dist-lib/components/voorraad/ProductCustomFieldsCard.d.ts.map +1 -1
  11. package/dist-lib/components/voorraad/ProductCustomFieldsCard.js +37 -18
  12. package/dist-lib/components/voorraad/ProductSalePriceField.d.ts.map +1 -1
  13. package/dist-lib/components/voorraad/ProductSalePriceField.js +11 -8
  14. package/dist-lib/components/voorraad/StepSamenstelling.d.ts.map +1 -1
  15. package/dist-lib/components/voorraad/StepSamenstelling.js +35 -10
  16. package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts +3 -1
  17. package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts.map +1 -1
  18. package/dist-lib/components/voorraad/StockMutationHistoryCard.js +16 -10
  19. package/dist-lib/components/voorraad/TrayStickerCard.d.ts +5 -1
  20. package/dist-lib/components/voorraad/TrayStickerCard.d.ts.map +1 -1
  21. package/dist-lib/components/voorraad/TrayStickerCard.js +64 -66
  22. package/dist-lib/components/voorraad/ValidationOverviewTable.d.ts +0 -5
  23. package/dist-lib/components/voorraad/ValidationOverviewTable.d.ts.map +1 -1
  24. package/dist-lib/components/voorraad/ValidationOverviewTable.js +10 -4
  25. package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts +3 -0
  26. package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts.map +1 -0
  27. package/dist-lib/components/voorraad/VoorraadBeheerCard.js +44 -0
  28. package/dist-lib/components/voorraad/VoorraadPage.d.ts +1 -13
  29. package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
  30. package/dist-lib/components/voorraad/VoorraadPage.js +102 -140
  31. package/dist-lib/components/voorraad/VoorraadSturingCard.d.ts +6 -0
  32. package/dist-lib/components/voorraad/VoorraadSturingCard.d.ts.map +1 -0
  33. package/dist-lib/components/voorraad/VoorraadSturingCard.js +47 -0
  34. package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts +6 -0
  35. package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts.map +1 -0
  36. package/dist-lib/components/voorraad/artikel/ArtikelPagina.js +313 -0
  37. package/dist-lib/components/voorraad/artikel/TwijfelKiezen.d.ts +7 -0
  38. package/dist-lib/components/voorraad/artikel/TwijfelKiezen.d.ts.map +1 -0
  39. package/dist-lib/components/voorraad/artikel/TwijfelKiezen.js +54 -0
  40. package/dist-lib/components/voorraad/artikel/opslaan-context.d.ts +21 -0
  41. package/dist-lib/components/voorraad/artikel/opslaan-context.d.ts.map +1 -0
  42. package/dist-lib/components/voorraad/artikel/opslaan-context.js +15 -0
  43. package/dist-lib/components/voorraad/lijst/ImporteerKnop.d.ts +5 -0
  44. package/dist-lib/components/voorraad/lijst/ImporteerKnop.d.ts.map +1 -0
  45. package/dist-lib/components/voorraad/lijst/ImporteerKnop.js +20 -0
  46. package/dist-lib/components/voorraad/lijst/LijstExportKnop.d.ts +6 -0
  47. package/dist-lib/components/voorraad/lijst/LijstExportKnop.d.ts.map +1 -0
  48. package/dist-lib/components/voorraad/lijst/LijstExportKnop.js +43 -0
  49. package/dist-lib/components/voorraad/lijst/SnelActieDialogen.d.ts +16 -0
  50. package/dist-lib/components/voorraad/lijst/SnelActieDialogen.d.ts.map +1 -0
  51. package/dist-lib/components/voorraad/lijst/SnelActieDialogen.js +95 -0
  52. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts +21 -0
  53. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts.map +1 -0
  54. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.js +39 -0
  55. package/dist-lib/hooks/useVoorraadCustomFields.d.ts +2 -1
  56. package/dist-lib/hooks/useVoorraadCustomFields.d.ts.map +1 -1
  57. package/dist-lib/hooks/useVoorraadCustomFields.js +8 -4
  58. package/dist-lib/hooks/useVoorraadLijst.d.ts +21 -0
  59. package/dist-lib/hooks/useVoorraadLijst.d.ts.map +1 -0
  60. package/dist-lib/hooks/useVoorraadLijst.js +71 -0
  61. package/dist-lib/index.d.ts.map +1 -1
  62. package/dist-lib/index.js +4 -0
  63. package/dist-lib/integrations/supabase/types.d.ts +748 -1
  64. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  65. package/dist-lib/lib/artikel-gewijzigd.d.ts +4 -0
  66. package/dist-lib/lib/artikel-gewijzigd.d.ts.map +1 -0
  67. package/dist-lib/lib/artikel-gewijzigd.js +7 -0
  68. package/dist-lib/lib/artikel-pagina.d.ts +68 -0
  69. package/dist-lib/lib/artikel-pagina.d.ts.map +1 -0
  70. package/dist-lib/lib/artikel-pagina.js +97 -0
  71. package/dist-lib/lib/count-stock.d.ts +17 -0
  72. package/dist-lib/lib/count-stock.d.ts.map +1 -0
  73. package/dist-lib/lib/count-stock.js +26 -0
  74. package/dist-lib/lib/floriday-import-validator.d.ts +9 -0
  75. package/dist-lib/lib/floriday-import-validator.d.ts.map +1 -1
  76. package/dist-lib/lib/floriday-import-validator.js +13 -0
  77. package/dist-lib/lib/floriday-versie-ronde.d.ts +59 -0
  78. package/dist-lib/lib/floriday-versie-ronde.d.ts.map +1 -0
  79. package/dist-lib/lib/floriday-versie-ronde.functions.d.ts +10 -0
  80. package/dist-lib/lib/floriday-versie-ronde.functions.d.ts.map +1 -0
  81. package/dist-lib/lib/floriday-versie-ronde.functions.js +22 -0
  82. package/dist-lib/lib/floriday-versie-ronde.js +106 -0
  83. package/dist-lib/lib/pending-photos.d.ts +20 -0
  84. package/dist-lib/lib/pending-photos.d.ts.map +1 -0
  85. package/dist-lib/lib/pending-photos.js +90 -0
  86. package/dist-lib/lib/voorraad-custom-fields.d.ts +16 -1
  87. package/dist-lib/lib/voorraad-custom-fields.d.ts.map +1 -1
  88. package/dist-lib/lib/voorraad-custom-fields.js +12 -6
  89. package/dist-lib/lib/voorraad-lijst.d.ts +92 -0
  90. package/dist-lib/lib/voorraad-lijst.d.ts.map +1 -0
  91. package/dist-lib/lib/voorraad-lijst.js +86 -0
  92. package/dist-lib/server-hooks/floriday-stock-reconcile.d.ts.map +1 -1
  93. package/dist-lib/server-hooks/floriday-stock-reconcile.js +5 -0
  94. package/dist-lib/server-hooks/floriday-versieronde.d.ts +2 -0
  95. package/dist-lib/server-hooks/floriday-versieronde.d.ts.map +1 -0
  96. package/dist-lib/server-hooks/floriday-versieronde.js +29 -0
  97. package/dist-lib/server-hooks/guard.js +1 -1
  98. package/package.json +1 -1
  99. package/sql/AGENTS.md +6 -0
  100. package/sql/floriday-voorraad-schema.sql +1355 -22
@@ -0,0 +1,4 @@
1
+ /** Gebeurtenis die tabbladen sturen na een opslag, zodat de kop van de artikelpagina direct bijwerkt. */
2
+ export declare const ARTIKEL_GEWIJZIGD = "voorraad:artikel-gewijzigd";
3
+ export declare function meldArtikelGewijzigd(id: string | null | undefined): void;
4
+ //# sourceMappingURL=artikel-gewijzigd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artikel-gewijzigd.d.ts","sourceRoot":"","sources":["../../src/lib/artikel-gewijzigd.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,eAAO,MAAM,iBAAiB,+BAA+B,CAAC;AAE9D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,QAGjE"}
@@ -0,0 +1,7 @@
1
+ /** Gebeurtenis die tabbladen sturen na een opslag, zodat de kop van de artikelpagina direct bijwerkt. */
2
+ export const ARTIKEL_GEWIJZIGD = "voorraad:artikel-gewijzigd";
3
+ export function meldArtikelGewijzigd(id) {
4
+ if (!id || typeof window === "undefined")
5
+ return;
6
+ window.dispatchEvent(new CustomEvent(ARTIKEL_GEWIJZIGD, { detail: { id } }));
7
+ }
@@ -0,0 +1,68 @@
1
+ import type { LijstRij, LijstStatus } from "./voorraad-lijst.js";
2
+ import type { VoorraadCustomField } from "./voorraad-custom-fields.js";
3
+ /** Velden die "Opslaan" mag wijzigen. Voorraad hoort hier nooit bij (die gaat via directe boekingen). */
4
+ export declare const ARTIKEL_VELDEN: readonly ["product", "article_number", "sale_price", "unit", "barcode"];
5
+ export type ArtikelVeld = (typeof ARTIKEL_VELDEN)[number];
6
+ export type Velden = Record<ArtikelVeld, string | number | null>;
7
+ export declare const VELD_LABEL: Record<ArtikelVeld, string>;
8
+ export interface ArtikelDetail {
9
+ gevonden: boolean;
10
+ id: string;
11
+ velden: Velden;
12
+ naam: string;
13
+ artikelnummer: string | null;
14
+ foto: string | null;
15
+ floriday_id: string | null;
16
+ heeft_koppeling: boolean;
17
+ soort: "NORMAL" | "SET" | "GROUP";
18
+ is_onderdeel: boolean;
19
+ voorraad_sleutel: string | null;
20
+ liggend: number;
21
+ gereserveerd: number;
22
+ inkomend: number;
23
+ minimum: number;
24
+ vrij: number;
25
+ open_orders: number;
26
+ floriday_stuurt: boolean;
27
+ telmoment: string | null;
28
+ notitie: string | null;
29
+ verpakking_ok: boolean;
30
+ gearchiveerd_at: string | null;
31
+ orders_gearchiveerd?: number;
32
+ floriday_verwijderd_at?: string | null;
33
+ trade_item_key?: string | null;
34
+ controle?: {
35
+ mutatie_sleutels: string[] | null;
36
+ zelfde_sleutel_ids: string[];
37
+ };
38
+ eigen_velden?: {
39
+ definities: VoorraadCustomField[];
40
+ waarden: Record<string, unknown>;
41
+ };
42
+ }
43
+ export interface Conflict {
44
+ veld: ArtikelVeld | VoorraadVeld;
45
+ bij_openen: unknown;
46
+ jouw: unknown;
47
+ hun: unknown;
48
+ }
49
+ /** Alleen de velden die de gebruiker echt wijzigde; de server vergelijkt alleen die met de stand bij openen. */
50
+ export declare function gewijzigdeVelden(oud: Velden, nieuw: Velden): Partial<Velden>;
51
+ /** Prijs uit invoer ("1,25" of "1.25"); leeg = null; ongeldig = NaN. */
52
+ export declare function prijsUitInvoer(s: string): number | null;
53
+ /** Eén status voor de kop, zelfde volgorde als de lijst. */
54
+ export declare function artikelStatus(d: Pick<ArtikelDetail, "gearchiveerd_at" | "verpakking_ok" | "heeft_koppeling" | "floriday_id" | "velden" | "floriday_verwijderd_at">): LijstStatus;
55
+ /** Welke Floriday-actie de kop toont. */
56
+ export declare function floridayActie(d: Pick<ArtikelDetail, "heeft_koppeling" | "floriday_id" | "gearchiveerd_at" | "floriday_verwijderd_at">): "sturen" | "op_floriday" | null;
57
+ /** Tabbladen; Floriday alleen bij een gekoppeld artikel in een shell met koppeling. */
58
+ export declare function artikelTabs(d: Pick<ArtikelDetail, "heeft_koppeling" | "floriday_id" | "floriday_verwijderd_at">): string[];
59
+ export declare function alsLijstRij(d: ArtikelDetail): LijstRij;
60
+ /** Voorraadinstellingen die ook onder "Opslaan" vallen. Liggend hoort hier nooit bij. */
61
+ export declare const VOORRAAD_VELDEN: readonly ["minimum_stock", "incoming_stock", "notes"];
62
+ export type VoorraadVeld = (typeof VOORRAAD_VELDEN)[number];
63
+ export type VoorraadVelden = Record<VoorraadVeld, string | number | null>;
64
+ export declare const VOORRAAD_LABEL: Record<VoorraadVeld, string>;
65
+ /** Aantal uit invoer: leeg = 0, anders heel getal ≥ 0, anders NaN. */
66
+ export declare function aantalUitInvoer(s: string): number;
67
+ export declare function gewijzigdeVoorraad(oud: VoorraadVelden, nieuw: VoorraadVelden): Partial<VoorraadVelden>;
68
+ //# sourceMappingURL=artikel-pagina.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artikel-pagina.d.ts","sourceRoot":"","sources":["../../src/lib/artikel-pagina.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,yGAAyG;AACzG,eAAO,MAAM,cAAc,yEAA0E,CAAC;AACtG,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;AAEjE,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAMlD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;IAClC,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE;QAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,kBAAkB,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC/E,YAAY,CAAC,EAAE;QAAE,UAAU,EAAE,mBAAmB,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CACxF;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,WAAW,GAAG,YAAY,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;CACd;AASD,gHAAgH;AAChH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5E;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvD;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,aAAa,GAAG,QAAQ,GAAG,wBAAwB,CAAC,GAAG,WAAW,CAShL;AAED,yCAAyC;AACzC,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,iBAAiB,GAAG,aAAa,GAAG,iBAAiB,GAAG,wBAAwB,CAAC,GAAG,QAAQ,GAAG,aAAa,GAAG,IAAI,CAIvK;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,iBAAiB,GAAG,aAAa,GAAG,wBAAwB,CAAC,GAAG,MAAM,EAAE,CAI1H;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,aAAa,GAAG,QAAQ,CAStD;AAED,yFAAyF;AACzF,eAAO,MAAM,eAAe,uDAAwD,CAAC;AACrF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;AAC1E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAIvD,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAItG"}
@@ -0,0 +1,97 @@
1
+ /** Velden die "Opslaan" mag wijzigen. Voorraad hoort hier nooit bij (die gaat via directe boekingen). */
2
+ export const ARTIKEL_VELDEN = ["product", "article_number", "sale_price", "unit", "barcode"];
3
+ export const VELD_LABEL = {
4
+ product: "Naam",
5
+ article_number: "Artikelnummer",
6
+ sale_price: "Verkoopprijs per stuk",
7
+ unit: "Eenheid",
8
+ barcode: "Barcode",
9
+ };
10
+ function norm(v) {
11
+ if (v === undefined || v === null)
12
+ return null;
13
+ if (typeof v === "number")
14
+ return v;
15
+ const s = String(v).trim();
16
+ return s === "" ? null : s;
17
+ }
18
+ /** Alleen de velden die de gebruiker echt wijzigde; de server vergelijkt alleen die met de stand bij openen. */
19
+ export function gewijzigdeVelden(oud, nieuw) {
20
+ const uit = {};
21
+ for (const k of ARTIKEL_VELDEN) {
22
+ if (norm(oud[k]) !== norm(nieuw[k]))
23
+ uit[k] = norm(nieuw[k]);
24
+ }
25
+ return uit;
26
+ }
27
+ /** Prijs uit invoer ("1,25" of "1.25"); leeg = null; ongeldig = NaN. */
28
+ export function prijsUitInvoer(s) {
29
+ const t = s.trim().replace(",", ".");
30
+ if (t === "")
31
+ return null;
32
+ const n = Number(t);
33
+ return Number.isFinite(n) ? n : Number.NaN;
34
+ }
35
+ /** Eén status voor de kop, zelfde volgorde als de lijst. */
36
+ export function artikelStatus(d) {
37
+ if (d.gearchiveerd_at)
38
+ return "gearchiveerd";
39
+ if (d.heeft_koppeling && d.floriday_verwijderd_at)
40
+ return "verwijderd_floriday";
41
+ if (!d.verpakking_ok)
42
+ return "verpakking";
43
+ if (d.heeft_koppeling && !d.floriday_id)
44
+ return "niet_gekoppeld";
45
+ const prijs = d.velden.sale_price;
46
+ const eenheid = String(d.velden.unit ?? "").trim().toLowerCase();
47
+ if (eenheid !== "stuks" || prijs === null || Number(prijs) <= 0)
48
+ return "prijs";
49
+ return "ok";
50
+ }
51
+ /** Welke Floriday-actie de kop toont. */
52
+ export function floridayActie(d) {
53
+ if (!d.heeft_koppeling || d.gearchiveerd_at)
54
+ return null;
55
+ if (d.floriday_verwijderd_at)
56
+ return "op_floriday";
57
+ return d.floriday_id ? "sturen" : "op_floriday";
58
+ }
59
+ /** Tabbladen; Floriday alleen bij een gekoppeld artikel in een shell met koppeling. */
60
+ export function artikelTabs(d) {
61
+ const t = ["voorraad", "verpakking", "koppelingen"];
62
+ if (d.heeft_koppeling && d.floriday_id && !d.floriday_verwijderd_at)
63
+ t.push("floriday");
64
+ return t;
65
+ }
66
+ export function alsLijstRij(d) {
67
+ return {
68
+ id: d.id, naam: d.naam, artikelnummer: d.artikelnummer, foto: d.foto, floriday_id: d.floriday_id,
69
+ prijs: d.velden.sale_price === null ? null : Number(d.velden.sale_price),
70
+ eenheid: d.velden.unit ?? null, soort: d.soort, is_onderdeel: d.is_onderdeel,
71
+ liggend: d.liggend, gereserveerd: d.gereserveerd, minimum: d.minimum, inkomend: d.inkomend, vrij: d.vrij,
72
+ voorraad_sleutel: d.voorraad_sleutel, gearchiveerd_at: d.gearchiveerd_at,
73
+ onder_minimum: d.minimum > 0 && d.liggend - d.gereserveerd < d.minimum, status: artikelStatus(d),
74
+ };
75
+ }
76
+ /** Voorraadinstellingen die ook onder "Opslaan" vallen. Liggend hoort hier nooit bij. */
77
+ export const VOORRAAD_VELDEN = ["minimum_stock", "incoming_stock", "notes"];
78
+ export const VOORRAAD_LABEL = {
79
+ minimum_stock: "Minimum",
80
+ incoming_stock: "Inkomend",
81
+ notes: "Vaste artikelnotitie",
82
+ };
83
+ /** Aantal uit invoer: leeg = 0, anders heel getal ≥ 0, anders NaN. */
84
+ export function aantalUitInvoer(s) {
85
+ const t = s.trim();
86
+ if (t === "")
87
+ return 0;
88
+ const n = Number(t);
89
+ return Number.isInteger(n) && n >= 0 ? n : Number.NaN;
90
+ }
91
+ export function gewijzigdeVoorraad(oud, nieuw) {
92
+ const uit = {};
93
+ for (const k of VOORRAAD_VELDEN)
94
+ if (norm(oud[k]) !== norm(nieuw[k]))
95
+ uit[k] = norm(nieuw[k]);
96
+ return uit;
97
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * "Op voorraad" = artikelen met liggende voorraad (fysiek > 0).
3
+ * "Vrij beschikbaar" = artikelen waarvan liggend min gereserveerd > 0.
4
+ */
5
+ export declare function countStock(items: Array<{
6
+ quantity?: number | null;
7
+ availableQuantity?: number | null;
8
+ minQuantity?: number | null;
9
+ }>): {
10
+ total: number;
11
+ inStock: number;
12
+ outOfStock: number;
13
+ belowMin: number;
14
+ fullyReserved: number;
15
+ freeAvailable: number;
16
+ };
17
+ //# sourceMappingURL=count-stock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"count-stock.d.ts","sourceRoot":"","sources":["../../src/lib/count-stock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;;;;;;;EAgBpI"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * "Op voorraad" = artikelen met liggende voorraad (fysiek > 0).
3
+ * "Vrij beschikbaar" = artikelen waarvan liggend min gereserveerd > 0.
4
+ */
5
+ export function countStock(items) {
6
+ let inStock = 0;
7
+ let outOfStock = 0;
8
+ let belowMin = 0;
9
+ let fullyReserved = 0;
10
+ let freeAvailable = 0;
11
+ for (const i of items) {
12
+ const physical = Number(i.quantity ?? 0);
13
+ const avail = Number(i.availableQuantity ?? i.quantity ?? 0);
14
+ if (physical > 0)
15
+ inStock++;
16
+ else
17
+ outOfStock++;
18
+ if (avail > 0)
19
+ freeAvailable++;
20
+ if (physical > 0 && avail <= 0)
21
+ fullyReserved++;
22
+ if ((i.minQuantity ?? 0) > 0 && avail < (i.minQuantity ?? 0))
23
+ belowMin++;
24
+ }
25
+ return { total: items.length, inStock, outOfStock, belowMin, fullyReserved, freeAvailable };
26
+ }
@@ -23,4 +23,13 @@ export interface ValidationResult {
23
23
  missingKeys: string[];
24
24
  }
25
25
  export declare function validateDraftForPublish(d: Partial<WizardData>): ValidationResult;
26
+ /**
27
+ * Vult naam en artikelcode in het Floriday-concept aan met de eigen artikelgegevens,
28
+ * zodat "Nog nodig" geen artikelcode of naam noemt die op het artikel wél is ingevuld.
29
+ * Wat in het concept staat, wint; alleen lege velden worden aangevuld.
30
+ */
31
+ export declare function conceptMetArtikel(concept: Partial<WizardData> | null | undefined, artikel: {
32
+ name?: string | null;
33
+ articleNumber?: string | null;
34
+ }): Partial<WizardData>;
26
35
  //# sourceMappingURL=floriday-import-validator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floriday-import-validator.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-import-validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,QAAQ,GACR,kBAAkB,GAClB,kBAAkB,GAClB,gBAAgB,GAChB,iBAAiB,GACjB,WAAW,CAAC;AAEhB,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC;CAC5C;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,iBAAiB,EA0B1D,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,gBAAgB,CAUhF"}
1
+ {"version":3,"file":"floriday-import-validator.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-import-validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,QAAQ,GACR,kBAAkB,GAClB,kBAAkB,GAClB,gBAAgB,GAChB,iBAAiB,GACjB,WAAW,CAAC;AAEhB,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC;CAC5C;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,iBAAiB,EA0B1D,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,gBAAgB,CAUhF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/C,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC/D,OAAO,CAAC,UAAU,CAAC,CAKrB"}
@@ -39,3 +39,16 @@ export function validateDraftForPublish(d) {
39
39
  }
40
40
  return { ok: missing.length === 0, missing, missingKeys };
41
41
  }
42
+ /**
43
+ * Vult naam en artikelcode in het Floriday-concept aan met de eigen artikelgegevens,
44
+ * zodat "Nog nodig" geen artikelcode of naam noemt die op het artikel wél is ingevuld.
45
+ * Wat in het concept staat, wint; alleen lege velden worden aangevuld.
46
+ */
47
+ export function conceptMetArtikel(concept, artikel) {
48
+ const c = { ...(concept ?? {}) };
49
+ if (!c.name?.trim() && artikel.name?.trim())
50
+ c.name = artikel.name.trim();
51
+ if (!c.articleCode?.trim() && artikel.articleNumber?.trim())
52
+ c.articleCode = artikel.articleNumber.trim();
53
+ return c;
54
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Controleronde van Floriday-versies (1.0.148). Puur, zodat het zonder Floriday te testen is.
3
+ *
4
+ * Per trade item in de cache vragen we `GET /trade-items/{id}` op:
5
+ * - 200 met hetzelfde id → actueel;
6
+ * - 200 met een ander `tradeItemId` (Floriday stuurt de oude id door) → vervangen, met opvolger;
7
+ * - 200 met `isDeleted` → vervallen;
8
+ * - 404/410 → vervallen (komt niet voor in de actuele Floriday-lijst);
9
+ * - al het andere (429, 5xx, omleiding die niet gevolgd is, netwerkfout) → fout.
10
+ * Een ronde is alleen volledig als elk item een uitkomst zonder fout heeft;
11
+ * de database markeert pas iets na een volledige ronde zonder fouten.
12
+ */
13
+ import type { FloridayReadResult } from "./floriday-read-contract.js";
14
+ export type VersieStatus = "actueel" | "vervangen" | "vervallen";
15
+ export interface VersieUitkomst {
16
+ floriday_id: string;
17
+ status: VersieStatus;
18
+ opvolger_id?: string | null;
19
+ bron: "floriday_doorverwijzing" | "floriday_niet_gevonden" | "floriday_is_deleted" | "floriday_actueel";
20
+ }
21
+ export type VersieOordeel = {
22
+ kind: "uitkomst";
23
+ uitkomst: VersieUitkomst;
24
+ } | {
25
+ kind: "fout";
26
+ reden: string;
27
+ };
28
+ export declare function beoordeelVersie(floridayId: string, r: FloridayReadResult | null | undefined): VersieOordeel;
29
+ export interface VersieRonde {
30
+ volledig: boolean;
31
+ fouten: number;
32
+ uitkomsten: VersieUitkomst[];
33
+ foutvoorbeelden: string[];
34
+ }
35
+ /** Bundelt de oordelen; `ids` is de volledige lijst die gecontroleerd moest worden. */
36
+ export declare function maakRonde(ids: string[], oordelen: Map<string, VersieOordeel>): VersieRonde;
37
+ export type PortieUitkomst = VersieUitkomst | {
38
+ floriday_id: string;
39
+ status: "fout";
40
+ reden: string;
41
+ };
42
+ /**
43
+ * Eén portie van de automatische ronde: 10 per verzoek, pauze ertussen.
44
+ * 429 → één keer opnieuw na de gevraagde wachttijd; nog steeds 429 = niet verwerkt (volgende run).
45
+ * Gooit het lezen zelf (geen verbinding), dan stopt de portie met `verbindingsfout`.
46
+ */
47
+ export declare function verwerkVersiePortie(ids: string[], lees: (paden: string[]) => Promise<FloridayReadResult[]>, opties?: {
48
+ pauzeMs?: number;
49
+ slaap?: (ms: number) => Promise<void>;
50
+ }): Promise<{
51
+ uitkomsten: PortieUitkomst[];
52
+ verbindingsfout: string | null;
53
+ uitgesteld: number;
54
+ }>;
55
+ /** Blok "Beheer" en de knop alleen voor beheerders. */
56
+ export declare function toonVersieBeheer(status: {
57
+ beheerder?: boolean;
58
+ } | null | undefined): boolean;
59
+ //# sourceMappingURL=floriday-versie-ronde.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floriday-versie-ronde.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-versie-ronde.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,yBAAyB,GAAG,wBAAwB,GAAG,qBAAqB,GAAG,kBAAkB,CAAC;CACzG;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7G,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CAqB3G;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,WAAW,CAW1F;AAED,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErG;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EAAE,EACb,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC,EACxD,MAAM,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACvE,OAAO,CAAC;IAAE,UAAU,EAAE,cAAc,EAAE,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAuC/F;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE5F"}
@@ -0,0 +1,10 @@
1
+ export declare const floridayVersiesControleren: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, undefined, undefined, undefined, undefined>, import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
2
+ supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
3
+ userId: string;
4
+ claims: import("@supabase/auth-js").JwtPayload;
5
+ }, undefined, undefined, undefined>], undefined, Promise<{
6
+ ok: boolean;
7
+ gewekt?: boolean;
8
+ melding?: string;
9
+ }>>;
10
+ //# sourceMappingURL=floriday-versie-ronde.functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floriday-versie-ronde.functions.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-versie-ronde.functions.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,0BAA0B;;;;;QAUd,OAAO;aAAW,OAAO;cAAY,MAAM;GAChE,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Alleen voor beheerders (blok "Beheer"): de automatische versieronde nu starten.
3
+ * De ronde zelf loopt op de server in porties; hier wordt hij alleen gewekt.
4
+ */
5
+ import { createServerFn } from "@tanstack/react-start";
6
+ import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
7
+ import { normalizeErrors } from "./normalize-errors-middleware.js";
8
+ export const floridayVersiesControleren = createServerFn({ method: "POST" })
9
+ .middleware([normalizeErrors, requireSupabaseAuth])
10
+ .handler(async ({ context }) => {
11
+ const { data: beheerder, error: rolFout } = await context.supabase.rpc("voorraad_is_beheerder");
12
+ if (rolFout)
13
+ throw new Error(rolFout.message);
14
+ if (!beheerder)
15
+ throw new Error("Alleen een beheerder kan de controle van Floriday-artikelen starten.");
16
+ const { getAdminClient } = await import("./supabase-admin.server.js");
17
+ const admin = getAdminClient();
18
+ const { data, error } = await admin.rpc("run_floriday_versieronde", { p_nieuw: true });
19
+ if (error)
20
+ throw new Error(error.message);
21
+ return data;
22
+ });
@@ -0,0 +1,106 @@
1
+ export function beoordeelVersie(floridayId, r) {
2
+ if (!r)
3
+ return { kind: "fout", reden: "geen antwoord" };
4
+ if (r.status === 404 || r.status === 410) {
5
+ return { kind: "uitkomst", uitkomst: { floriday_id: floridayId, status: "vervallen", bron: "floriday_niet_gevonden" } };
6
+ }
7
+ if (!r.ok || r.status < 200 || r.status >= 300) {
8
+ return { kind: "fout", reden: `status ${r.status}${r.error ? `: ${r.error}` : ""}` };
9
+ }
10
+ const data = (r.data ?? {});
11
+ const terug = typeof data.tradeItemId === "string" ? data.tradeItemId.trim() : "";
12
+ if (!terug)
13
+ return { kind: "fout", reden: "antwoord zonder tradeItemId" };
14
+ if (data.isDeleted === true) {
15
+ return { kind: "uitkomst", uitkomst: { floriday_id: floridayId, status: "vervallen", bron: "floriday_is_deleted" } };
16
+ }
17
+ if (terug.toLowerCase() !== floridayId.trim().toLowerCase()) {
18
+ return {
19
+ kind: "uitkomst",
20
+ uitkomst: { floriday_id: floridayId, status: "vervangen", opvolger_id: terug, bron: "floriday_doorverwijzing" },
21
+ };
22
+ }
23
+ return { kind: "uitkomst", uitkomst: { floriday_id: floridayId, status: "actueel", bron: "floriday_actueel" } };
24
+ }
25
+ /** Bundelt de oordelen; `ids` is de volledige lijst die gecontroleerd moest worden. */
26
+ export function maakRonde(ids, oordelen) {
27
+ const uitkomsten = [];
28
+ const foutvoorbeelden = [];
29
+ let fouten = 0;
30
+ for (const id of ids) {
31
+ const o = oordelen.get(id);
32
+ if (!o) {
33
+ fouten++;
34
+ if (foutvoorbeelden.length < 5)
35
+ foutvoorbeelden.push(`${id}: niet gecontroleerd`);
36
+ continue;
37
+ }
38
+ if (o.kind === "fout") {
39
+ fouten++;
40
+ if (foutvoorbeelden.length < 5)
41
+ foutvoorbeelden.push(`${id}: ${o.reden}`);
42
+ continue;
43
+ }
44
+ uitkomsten.push(o.uitkomst);
45
+ }
46
+ return { volledig: fouten === 0 && uitkomsten.length === ids.length, fouten, uitkomsten, foutvoorbeelden };
47
+ }
48
+ /**
49
+ * Eén portie van de automatische ronde: 10 per verzoek, pauze ertussen.
50
+ * 429 → één keer opnieuw na de gevraagde wachttijd; nog steeds 429 = niet verwerkt (volgende run).
51
+ * Gooit het lezen zelf (geen verbinding), dan stopt de portie met `verbindingsfout`.
52
+ */
53
+ export async function verwerkVersiePortie(ids, lees, opties = {}) {
54
+ const slaap = opties.slaap ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
55
+ const pauze = opties.pauzeMs ?? 1000;
56
+ const uitkomsten = [];
57
+ let uitgesteld = 0;
58
+ for (let i = 0; i < ids.length; i += 10) {
59
+ const groep = ids.slice(i, i + 10);
60
+ if (i > 0)
61
+ await slaap(pauze);
62
+ let res;
63
+ try {
64
+ res = await lees(groep.map((id) => `/trade-items/${id}`));
65
+ }
66
+ catch (e) {
67
+ return { uitkomsten, verbindingsfout: e?.message ?? String(e), uitgesteld };
68
+ }
69
+ const opnieuw = [];
70
+ let wacht = 0;
71
+ groep.forEach((id, k) => {
72
+ const r = res[k];
73
+ if (r && r.status === 429) {
74
+ opnieuw.push(id);
75
+ wacht = Math.max(wacht, r.retryAfterMs ?? 2000);
76
+ return;
77
+ }
78
+ const o = beoordeelVersie(id, r);
79
+ uitkomsten.push(o.kind === "uitkomst" ? o.uitkomst : { floriday_id: id, status: "fout", reden: o.reden });
80
+ });
81
+ if (opnieuw.length) {
82
+ await slaap(Math.min(wacht, 10000));
83
+ let res2;
84
+ try {
85
+ res2 = await lees(opnieuw.map((id) => `/trade-items/${id}`));
86
+ }
87
+ catch (e) {
88
+ return { uitkomsten, verbindingsfout: e?.message ?? String(e), uitgesteld };
89
+ }
90
+ opnieuw.forEach((id, k) => {
91
+ const r = res2[k];
92
+ if (r && r.status === 429) {
93
+ uitgesteld++;
94
+ return;
95
+ }
96
+ const o = beoordeelVersie(id, r);
97
+ uitkomsten.push(o.kind === "uitkomst" ? o.uitkomst : { floriday_id: id, status: "fout", reden: o.reden });
98
+ });
99
+ }
100
+ }
101
+ return { uitkomsten, verbindingsfout: null, uitgesteld };
102
+ }
103
+ /** Blok "Beheer" en de knop alleen voor beheerders. */
104
+ export function toonVersieBeheer(status) {
105
+ return status?.beheerder === true;
106
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Foto's gaan pas naar Floriday bij "Naar Floriday sturen" / "Op Floriday zetten".
3
+ * Bij het kiezen krijgt een foto een tijdelijke verwijzing "pending:<id>"; het bestand
4
+ * blijft in deze sessie bewaard. Bij versturen vervangt resolvePendingPhotos elke
5
+ * verwijzing door de echte Floriday-URL.
6
+ */
7
+ export declare const PENDING_PREFIX = "pending:";
8
+ export declare function registerPendingPhoto(file: File): string;
9
+ export declare function isPendingPhoto(url: unknown): url is string;
10
+ /** Aantal foto's dat bij versturen nog naar Floriday moet. */
11
+ export declare function countPendingPhotos(value: unknown): number;
12
+ export type UploadFn = (file: File) => Promise<{
13
+ url: string | null;
14
+ imageId?: string | null;
15
+ }>;
16
+ /** Uploadt alle wachtende foto's en geeft een kopie met echte URL's terug. */
17
+ export declare function resolvePendingPhotos<T>(value: T, upload: UploadFn, files?: Map<string, File>): Promise<T>;
18
+ /** Overzicht vooraf: welke onderdelen wijzigen ten opzichte van de laatst opgeslagen stand. */
19
+ export declare function wijzigingenOverzicht(basis: string | null, nu: Record<string, unknown>): string[];
20
+ //# sourceMappingURL=pending-photos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-photos.d.ts","sourceRoot":"","sources":["../../src/lib/pending-photos.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,cAAc,aAAa,CAAC;AAGzC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAIvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAE1D;AAED,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWzD;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC;AAEhG,8EAA8E;AAC9E,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAyB1H;AAYD,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAQhG"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Foto's gaan pas naar Floriday bij "Naar Floriday sturen" / "Op Floriday zetten".
3
+ * Bij het kiezen krijgt een foto een tijdelijke verwijzing "pending:<id>"; het bestand
4
+ * blijft in deze sessie bewaard. Bij versturen vervangt resolvePendingPhotos elke
5
+ * verwijzing door de echte Floriday-URL.
6
+ */
7
+ export const PENDING_PREFIX = "pending:";
8
+ const bestanden = new Map();
9
+ export function registerPendingPhoto(file) {
10
+ const id = `${PENDING_PREFIX}${typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : String(Math.random()).slice(2)}`;
11
+ bestanden.set(id, file);
12
+ return id;
13
+ }
14
+ export function isPendingPhoto(url) {
15
+ return typeof url === "string" && url.startsWith(PENDING_PREFIX);
16
+ }
17
+ /** Aantal foto's dat bij versturen nog naar Floriday moet. */
18
+ export function countPendingPhotos(value) {
19
+ if (Array.isArray(value))
20
+ return value.reduce((n, v) => n + countPendingPhotos(v), 0);
21
+ if (value && typeof value === "object") {
22
+ let n = 0;
23
+ for (const [k, v] of Object.entries(value)) {
24
+ if ((k === "url" || k === "photoUrl") && isPendingPhoto(v))
25
+ n++;
26
+ else if (v && typeof v === "object")
27
+ n += countPendingPhotos(v);
28
+ }
29
+ return n;
30
+ }
31
+ return 0;
32
+ }
33
+ /** Uploadt alle wachtende foto's en geeft een kopie met echte URL's terug. */
34
+ export async function resolvePendingPhotos(value, upload, files = bestanden) {
35
+ if (Array.isArray(value)) {
36
+ const uit = [];
37
+ for (const v of value)
38
+ uit.push(await resolvePendingPhotos(v, upload, files));
39
+ return uit;
40
+ }
41
+ if (value && typeof value === "object") {
42
+ const uit = { ...value };
43
+ for (const [k, v] of Object.entries(uit)) {
44
+ if ((k === "url" || k === "photoUrl") && isPendingPhoto(v)) {
45
+ const f = files.get(v);
46
+ if (!f)
47
+ throw new Error("Een gekozen foto is niet meer beschikbaar. Kies de foto opnieuw.");
48
+ const res = await upload(f);
49
+ if (!res.url)
50
+ throw new Error(`${f.name}: Floriday gaf geen URL terug.`);
51
+ uit[k] = res.url;
52
+ if (k === "url")
53
+ uit.imageId = res.imageId ?? null;
54
+ else
55
+ uit.photoImageId = res.imageId ?? undefined;
56
+ files.delete(v);
57
+ }
58
+ else if (v && typeof v === "object") {
59
+ uit[k] = await resolvePendingPhotos(v, upload, files);
60
+ }
61
+ }
62
+ return uit;
63
+ }
64
+ return value;
65
+ }
66
+ const VELD_NAAM = {
67
+ productGroup: "Productgroep", vbnCode: "VBN-code", vbnName: "VBN-naam", articleCode: "Artikelcode", name: "Naam",
68
+ nameEn: "Naam (Engels)", gtin: "GTIN", collections: "Collecties", articleType: "Soort artikel",
69
+ visibleInExplorer: "Zichtbaar in Floriday", botanicalName: "Botanische naam", countryOfOrigin: "Land van herkomst",
70
+ producerCode: "Kwekerscode", lotNumber: "Partijnummer", features: "Eigenschappen", customerOrganizationIds: "Klanten",
71
+ images: "Foto's", warehouseId: "Magazijn", packingConfigurations: "Belading", additionalPackaging: "Extra verpakking",
72
+ availabilityMode: "Beschikbaarheid", weeks: "Weken", offerForSale: "Aanbieden", salePricePerPiece: "Verkoopprijs per stuk",
73
+ saleStockPieces: "Voorraad aanbieden", offerStartDate: "Startdatum aanbod", priceGroupPrices: "Prijzen per prijsgroep",
74
+ };
75
+ /** Overzicht vooraf: welke onderdelen wijzigen ten opzichte van de laatst opgeslagen stand. */
76
+ export function wijzigingenOverzicht(basis, nu) {
77
+ let oud = {};
78
+ try {
79
+ oud = basis ? JSON.parse(basis) : {};
80
+ }
81
+ catch {
82
+ oud = {};
83
+ }
84
+ const uit = [];
85
+ for (const k of Object.keys(VELD_NAAM)) {
86
+ if (JSON.stringify(oud[k] ?? null) !== JSON.stringify(nu[k] ?? null))
87
+ uit.push(VELD_NAAM[k]);
88
+ }
89
+ return uit;
90
+ }
@@ -17,6 +17,21 @@ export declare function updateVoorraadCustomField(id: string, patch: Partial<Omi
17
17
  export declare function deleteVoorraadCustomField(id: string): Promise<void>;
18
18
  /** Waarden van eigen velden staan in `products.custom_fields` (jsonb). */
19
19
  export declare function fetchProductCustomValues(productId: string): Promise<Record<string, unknown>>;
20
- export declare function saveProductCustomValues(productId: string, values: Record<string, unknown>): Promise<void>;
20
+ export interface VeldConflict {
21
+ veld: string;
22
+ bij_openen: unknown;
23
+ jouw?: unknown;
24
+ hun: unknown;
25
+ }
26
+ /**
27
+ * Slaat eigen velden op met controle per veld: alleen velden die de gebruiker
28
+ * wijzigde worden vergeleken met hun stand bij openen (`oud`).
29
+ */
30
+ export declare function saveProductCustomValues(productId: string, oud: Record<string, unknown>, nieuw: Record<string, unknown>): Promise<{
31
+ ok: true;
32
+ } | {
33
+ ok: false;
34
+ conflicten: VeldConflict[];
35
+ }>;
21
36
  export declare function formatCustomValue(value: unknown): string;
22
37
  //# sourceMappingURL=voorraad-custom-fields.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"voorraad-custom-fields.d.ts","sourceRoot":"","sources":["../../src/lib/voorraad-custom-fields.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElF,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAWhF;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzE;AAED,0EAA0E;AAC1E,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CASlC;AAED,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIxD"}
1
+ {"version":3,"file":"voorraad-custom-fields.d.ts","sourceRoot":"","sources":["../../src/lib/voorraad-custom-fields.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElF,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAWhF;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzE;AAED,0EAA0E;AAC1E,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CASlC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CASnE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIxD"}