@flowselections/floriday-voorraad 1.0.139 → 1.0.143

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 (34) hide show
  1. package/dist-lib/components/voorraad/NieuwArtikelPage.d.ts.map +1 -1
  2. package/dist-lib/components/voorraad/NieuwArtikelPage.js +22 -3
  3. package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts.map +1 -1
  4. package/dist-lib/components/voorraad/StockMutationHistoryCard.js +3 -2
  5. package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
  6. package/dist-lib/components/voorraad/VoorraadPage.js +2 -0
  7. package/dist-lib/components/voorraad/VoorraadStockCard.d.ts.map +1 -1
  8. package/dist-lib/components/voorraad/VoorraadStockCard.js +28 -60
  9. package/dist-lib/hooks/useEnsureVoorraadDefaults.d.ts +7 -0
  10. package/dist-lib/hooks/useEnsureVoorraadDefaults.d.ts.map +1 -0
  11. package/dist-lib/hooks/useEnsureVoorraadDefaults.js +25 -0
  12. package/dist-lib/hooks/useTradeItemStock.d.ts +4 -1
  13. package/dist-lib/hooks/useTradeItemStock.d.ts.map +1 -1
  14. package/dist-lib/hooks/useTradeItemStock.js +31 -44
  15. package/dist-lib/integrations/supabase/types.d.ts +421 -0
  16. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  17. package/dist-lib/lib/__tests__/release-140.test.d.ts +2 -0
  18. package/dist-lib/lib/__tests__/release-140.test.d.ts.map +1 -0
  19. package/dist-lib/lib/__tests__/release-140.test.js +42 -0
  20. package/dist-lib/lib/db-error-message.d.ts +7 -0
  21. package/dist-lib/lib/db-error-message.d.ts.map +1 -0
  22. package/dist-lib/lib/db-error-message.js +36 -0
  23. package/dist-lib/lib/engine-carrier.d.ts +15 -0
  24. package/dist-lib/lib/engine-carrier.d.ts.map +1 -0
  25. package/dist-lib/lib/engine-carrier.js +27 -0
  26. package/dist-lib/lib/simple-packing.d.ts +2 -4
  27. package/dist-lib/lib/simple-packing.d.ts.map +1 -1
  28. package/dist-lib/lib/simple-packing.js +5 -12
  29. package/dist-lib/lib/stock-save.d.ts +11 -0
  30. package/dist-lib/lib/stock-save.d.ts.map +1 -1
  31. package/dist-lib/lib/stock-save.js +17 -0
  32. package/package.json +4 -2
  33. package/sql/AGENTS.md +4 -0
  34. package/sql/floriday-voorraad-schema.sql +441 -82
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=release-140.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-140.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/release-140.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { readFileSync } from "node:fs";
3
+ import { opslaanMelding, valuesAfterSave, OPSLAAN_MISLUKT_TEKST } from "../stock-save.js";
4
+ import { dbFoutTekst } from "../db-error-message.js";
5
+ // @ts-expect-error plain ESM script
6
+ import { controleerSchema } from "../../../scripts/check-schema-version.mjs";
7
+ const saved = { physical_stock: 10, minimum_stock: 0, reserved_stock: 2, incoming_stock: 0, notes: null };
8
+ const entered = { ...saved, physical_stock: 100 };
9
+ describe("1.0.140 opslaan bij dichte poort", () => {
10
+ it("bevestigde opslag met dichte poort: 'Opgeslagen; er is niets naar Floriday gestuurd.'", () => {
11
+ const m = opslaanMelding({ opgeslagen: true, floriday_klaargezet_toegestaan: false }, true);
12
+ expect(m).toEqual({ ok: true, tekst: "Opgeslagen; er is niets naar Floriday gestuurd." });
13
+ });
14
+ it("teruggedraaide opslag (fout, geen antwoord) = mislukt en oude waarden terug", () => {
15
+ const m = opslaanMelding(null, true);
16
+ expect(m).toEqual({ ok: false, tekst: OPSLAAN_MISLUKT_TEKST });
17
+ expect(valuesAfterSave(m.ok, entered, saved).physical_stock).toBe(10);
18
+ });
19
+ it("antwoord zonder bevestiging telt niet als opgeslagen", () => {
20
+ expect(opslaanMelding({ opgeslagen: false }, true).ok).toBe(false);
21
+ });
22
+ });
23
+ describe("1.0.140 databasefouten in gewone taal", () => {
24
+ it("ontbrekende controlewaarde wordt 'nog niet beschikbaar'", () => {
25
+ const t = dbFoutTekst({ code: "23514", message: 'new row for relation "stock_mutation_log" violates check constraint' }, "Afboeken");
26
+ expect(t).toBe("Afboeken is nog niet beschikbaar in deze omgeving, neem contact op met de beheerder.");
27
+ });
28
+ it("oude poortfout toont geen technische tekst", () => {
29
+ const t = dbFoutTekst({ message: "Uitgaand Floriday-verkeer (stock_publish) is uitgeschakeld" }, "Opslaan");
30
+ expect(t).not.toContain("stock_publish");
31
+ });
32
+ });
33
+ describe("1.0.140 schemacontrole", () => {
34
+ it("ouder schema blokkeert", () => {
35
+ expect(controleerSchema("-- @flowselections/floriday-voorraad 1.0.136 x", "1.0.140").length).toBeGreaterThan(0);
36
+ });
37
+ it("het meegeleverde schema hoort bij de versie in package.json", () => {
38
+ const versie = JSON.parse(readFileSync("package.json", "utf8")).version;
39
+ const sql = readFileSync("sql/floriday-voorraad-schema.sql", "utf8");
40
+ expect(controleerSchema(sql, versie)).toEqual([]);
41
+ });
42
+ });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Databasefouten nooit letterlijk tonen (1.0.140). De technische tekst gaat
3
+ * alleen naar de console; de gebruiker krijgt gewone taal.
4
+ */
5
+ export type DbFoutActie = "Opslaan" | "Afboeken" | "Geschiedenis laden" | "Deze actie";
6
+ export declare function dbFoutTekst(e: unknown, actie?: DbFoutActie): string;
7
+ //# sourceMappingURL=db-error-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-error-message.d.ts","sourceRoot":"","sources":["../../src/lib/db-error-message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,oBAAoB,GAAG,YAAY,CAAC;AAmBvF,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,GAAE,WAA0B,GAAG,MAAM,CA0BjF"}
@@ -0,0 +1,36 @@
1
+ /** Eigen Nederlandse meldingen uit onze functies (ERRCODE 22023/P0002/42501) mogen wel door. */
2
+ const EIGEN_MELDINGEN = [
3
+ /^Kies een reden/i,
4
+ /^Vul een (aantal|voorraadaantal)/i,
5
+ /^Je kunt niet meer afboeken/i,
6
+ /^Voorraadaantallen mogen niet negatief/i,
7
+ /^Geen voorraadregel/i,
8
+ /^Je hebt geen schrijfrechten/i,
9
+ /^Onvoldoende voorraad/i,
10
+ ];
11
+ export function dbFoutTekst(e, actie = "Deze actie") {
12
+ const err = (e ?? {});
13
+ const raw = String(err.message ?? (e instanceof Error ? e.message : e ?? ""));
14
+ const code = String(err.code ?? "");
15
+ const lower = raw.toLowerCase();
16
+ if (typeof console !== "undefined")
17
+ console.warn(`[voorraad] ${actie} mislukt:`, raw, code);
18
+ const eigen = EIGEN_MELDINGEN.find((re) => re.test(raw.trim()));
19
+ if (eigen)
20
+ return raw.trim();
21
+ if (lower.includes("uitgaand floriday-verkeer") || lower.includes("stock_publish")) {
22
+ return `${actie} is nog niet beschikbaar in deze omgeving (de databaseversie is ouder dan de app), neem contact op met de beheerder.`;
23
+ }
24
+ if (code === "42883" || code === "PGRST202" || code === "23514" ||
25
+ lower.includes("could not find the function") || lower.includes("does not exist") ||
26
+ lower.includes("violates check constraint")) {
27
+ return `${actie} is nog niet beschikbaar in deze omgeving, neem contact op met de beheerder.`;
28
+ }
29
+ if (code === "42501" || lower.includes("permission denied") || lower.includes("niet ingelogd")) {
30
+ return "Je hebt geen rechten voor deze actie. Log opnieuw in of vraag de beheerder.";
31
+ }
32
+ if (lower.includes("failed to fetch") || lower.includes("network")) {
33
+ return "Geen verbinding. Controleer je internet en probeer het opnieuw.";
34
+ }
35
+ return `${actie} is niet gelukt. Probeer het opnieuw of neem contact op met de beheerder.`;
36
+ }
@@ -0,0 +1,15 @@
1
+ export type EngineCarrier = {
2
+ code: string | null;
3
+ melding: string | null;
4
+ };
5
+ export declare const ENGINE_ONTBREEKT = "De Logistiek Engine is niet ge\u00EFnstalleerd, daardoor kan de ladingdrager niet worden vertaald. Neem contact op met de beheerder.";
6
+ /** Zet het antwoord (of de fout) van de Engine om; puur, zodat het te testen is. */
7
+ export declare function interpretEngineCarrier(invoer: string, data: {
8
+ code?: string | null;
9
+ fout?: string | null;
10
+ } | null | undefined, error: {
11
+ code?: string;
12
+ message?: string;
13
+ } | null | undefined): EngineCarrier;
14
+ export declare function resolveEngineCarrier(client: any, code: string): Promise<EngineCarrier>;
15
+ //# sourceMappingURL=engine-carrier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-carrier.d.ts","sourceRoot":"","sources":["../../src/lib/engine-carrier.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAE5E,eAAO,MAAM,gBAAgB,yIACsG,CAAC;AAEpI,oFAAoF;AACpF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EACvE,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAC5D,aAAa,CAUf;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAI5F"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Ladingdrager → Engine-code. De enige bron is de Logistiek Engine
3
+ * (logistics_ladingdrager_resolve over logistics_floriday_carrier_map).
4
+ * Geen eigen terugvallijst: ontbreekt de Engine of de vertaling, dan een melding.
5
+ */
6
+ import { isMissingFunctionError } from "./buyer-organizations.js";
7
+ export const ENGINE_ONTBREEKT = "De Logistiek Engine is niet geïnstalleerd, daardoor kan de ladingdrager niet worden vertaald. Neem contact op met de beheerder.";
8
+ /** Zet het antwoord (of de fout) van de Engine om; puur, zodat het te testen is. */
9
+ export function interpretEngineCarrier(invoer, data, error) {
10
+ if (error) {
11
+ if (isMissingFunctionError(error))
12
+ return { code: null, melding: ENGINE_ONTBREEKT };
13
+ return { code: null, melding: "De ladingdrager kon niet bij de Logistiek Engine worden gecontroleerd. Probeer het opnieuw." };
14
+ }
15
+ if (data?.code)
16
+ return { code: data.code, melding: null };
17
+ return {
18
+ code: null,
19
+ melding: `De Logistiek Engine kan ladingdrager "${invoer}" niet vertalen${data?.fout ? ` (${data.fout})` : ""}. Kies een andere ladingdrager of vraag de beheerder de vertaling toe te voegen.`,
20
+ };
21
+ }
22
+ export async function resolveEngineCarrier(client, code) {
23
+ if (!code.trim())
24
+ return { code: null, melding: null };
25
+ const { data, error } = await client.rpc("logistics_ladingdrager_resolve", { p_code: code });
26
+ return interpretEngineCarrier(code, data, error);
27
+ }
@@ -14,16 +14,14 @@ export interface SimplePacking {
14
14
  loadCarrier: string;
15
15
  }
16
16
  export declare const EMPTY_SIMPLE_PACKING: SimplePacking;
17
- /** Floriday-ladingdrager → code van de Engine (load_carrier_types.code). */
18
- export declare const ENGINE_CARRIER_CODE: Record<string, string>;
19
17
  /** Namen van de velden die nog ontbreken of ongeldig zijn (leeg = compleet). */
20
18
  export declare function missingPackingFields(p: SimplePacking): string[];
21
19
  /** Hoofdverpakking voor product_packings; gooit als iets ontbreekt. */
22
20
  export declare function simplePackingToRow(p: SimplePacking): ProductPackingRow;
23
21
  /** Regel voor logistics_product_oordeel_belading (Engine). */
24
- export declare function engineOordeelRegel(productId: string, p: SimplePacking): {
22
+ export declare function engineOordeelRegel(productId: string, p: SimplePacking, engineCarrierCode: string | null): {
25
23
  product_id: string;
26
- carrier_code: string;
24
+ carrier_code: string | null;
27
25
  plants_per_crate: number | null;
28
26
  crates_per_layer: number | null;
29
27
  layers_per_cart: number | null;
@@ -1 +1 @@
1
- {"version":3,"file":"simple-packing.d.ts","sourceRoot":"","sources":["../../src/lib/simple-packing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,oBAAoB,EAAE,aAMlC,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAOtD,CAAC;AAOF,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,EAAE,CAQ/D;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,aAAa,GAAG,iBAAiB,CActE;AAED,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa;;;;;;EAQrE"}
1
+ {"version":3,"file":"simple-packing.d.ts","sourceRoot":"","sources":["../../src/lib/simple-packing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,oBAAoB,EAAE,aAMlC,CAAC;AAUF,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,EAAE,CAQ/D;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,aAAa,GAAG,iBAAiB,CActE;AAED,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI;;;;;;EAQvG"}
@@ -5,15 +5,8 @@ export const EMPTY_SIMPLE_PACKING = {
5
5
  layersPerLoadCarrier: "",
6
6
  loadCarrier: "",
7
7
  };
8
- /** Floriday-ladingdrager → code van de Engine (load_carrier_types.code). */
9
- export const ENGINE_CARRIER_CODE = {
10
- AUCTION_TROLLEY: "trolley",
11
- DANISH_TROLLEY: "danish_container",
12
- EURO_TROLLEY: "euro_rolcontainer",
13
- PALLET: "pallet",
14
- EURO_PALLET: "euro_pallet",
15
- NONE: "loose",
16
- };
8
+ // De vertaling Floriday-ladingdrager → Engine-code komt alleen van de Engine
9
+ // (zie ../lib/engine-carrier.ts); hier staat bewust geen eigen lijst.
17
10
  function posInt(v) {
18
11
  const n = Number(String(v).trim());
19
12
  return Number.isInteger(n) && n > 0 ? n : null;
@@ -29,7 +22,7 @@ export function missingPackingFields(p) {
29
22
  out.push("fusten per laag");
30
23
  if (posInt(p.layersPerLoadCarrier) === null)
31
24
  out.push("lagen per kar");
32
- if (!ENGINE_CARRIER_CODE[p.loadCarrier])
25
+ if (!p.loadCarrier.trim())
33
26
  out.push("ladingdrager");
34
27
  return out;
35
28
  }
@@ -51,10 +44,10 @@ export function simplePackingToRow(p) {
51
44
  };
52
45
  }
53
46
  /** Regel voor logistics_product_oordeel_belading (Engine). */
54
- export function engineOordeelRegel(productId, p) {
47
+ export function engineOordeelRegel(productId, p, engineCarrierCode) {
55
48
  return {
56
49
  product_id: productId,
57
- carrier_code: ENGINE_CARRIER_CODE[p.loadCarrier] ?? null,
50
+ carrier_code: engineCarrierCode,
58
51
  plants_per_crate: posInt(p.piecesPerPackage),
59
52
  crates_per_layer: posInt(p.packagesPerLayer),
60
53
  layers_per_cart: posInt(p.layersPerLoadCarrier),
@@ -29,4 +29,15 @@ export type AfboekReden = (typeof AFBOEK_REDENEN)[number]["value"];
29
29
  export declare function afboekFout(aantal: number, reden: string | null, liggend: number): string | null;
30
30
  /** Melding na een geslaagde lokale opslag van een Floriday-artikel. */
31
31
  export declare function floridayNaOpslaanTekst(isFloridayArtikel: boolean, poortOpen: boolean | null): string | null;
32
+ /**
33
+ * 1.0.140: alleen een bevestiging van de database ({ opgeslagen: true }) telt
34
+ * als opgeslagen. Alles anders (fout, leeg antwoord, teruggedraaid) = mislukt.
35
+ */
36
+ export declare function opslagBevestigd(result: unknown): boolean;
37
+ export declare const OPSLAAN_MISLUKT_TEKST = "Opslaan mislukt, er is niets gewijzigd";
38
+ /** Melding na opslaan; null-resultaat of fout = mislukt (waarden terugzetten). */
39
+ export declare function opslaanMelding(result: unknown, isFloridayArtikel: boolean): {
40
+ ok: boolean;
41
+ tekst: string;
42
+ };
32
43
  //# sourceMappingURL=stock-save.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stock-save.d.ts","sourceRoot":"","sources":["../../src/lib/stock-save.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAG3F;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;EAKjB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAEnE,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/F;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAI3G"}
1
+ {"version":3,"file":"stock-save.d.ts","sourceRoot":"","sources":["../../src/lib/stock-save.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAG3F;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;EAKjB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAEnE,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/F;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAI3G;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAExD;AAED,eAAO,MAAM,qBAAqB,2CAA2C,CAAC;AAE9E,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAK1G"}
@@ -26,3 +26,20 @@ export function floridayNaOpslaanTekst(isFloridayArtikel, poortOpen) {
26
26
  return null;
27
27
  return "Lokaal opgeslagen. Er gaat niets naar Floriday: versturen staat uit.";
28
28
  }
29
+ /**
30
+ * 1.0.140: alleen een bevestiging van de database ({ opgeslagen: true }) telt
31
+ * als opgeslagen. Alles anders (fout, leeg antwoord, teruggedraaid) = mislukt.
32
+ */
33
+ export function opslagBevestigd(result) {
34
+ return !!result && typeof result === "object" && result.opgeslagen === true;
35
+ }
36
+ export const OPSLAAN_MISLUKT_TEKST = "Opslaan mislukt, er is niets gewijzigd";
37
+ /** Melding na opslaan; null-resultaat of fout = mislukt (waarden terugzetten). */
38
+ export function opslaanMelding(result, isFloridayArtikel) {
39
+ if (!opslagBevestigd(result))
40
+ return { ok: false, tekst: OPSLAAN_MISLUKT_TEKST };
41
+ const klaar = result.floriday_klaargezet_toegestaan === true;
42
+ if (isFloridayArtikel && !klaar)
43
+ return { ok: true, tekst: "Opgeslagen; er is niets naar Floriday gestuurd." };
44
+ return { ok: true, tekst: "Voorraad opgeslagen" };
45
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/floriday-voorraad",
3
- "version": "1.0.139",
3
+ "version": "1.0.143",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "main": "./dist-lib/index.js",
@@ -32,6 +32,8 @@
32
32
  "preview": "vite preview",
33
33
  "lint": "eslint .",
34
34
  "test": "vitest run",
35
+ "check:schema": "node scripts/check-schema-version.mjs",
36
+ "prepublishOnly": "node scripts/check-schema-version.mjs",
35
37
  "test:watch": "vitest"
36
38
  },
37
39
  "peerDependencies": {
@@ -49,7 +51,7 @@
49
51
  "devDependencies": {
50
52
  "@cloudflare/vite-plugin": "^1.25.5",
51
53
  "@eslint/js": "^9.32.0",
52
- "@flowselections/core": "1.0.34",
54
+ "@flowselections/core": "1.0.35",
53
55
  "@lovable.dev/vite-tanstack-config": "2.26.5",
54
56
  "@rsbuild/core": "^1.0.0",
55
57
  "@tailwindcss/vite": "^4.2.1",
package/sql/AGENTS.md CHANGED
@@ -5,3 +5,7 @@
5
5
  - An order line counts as cancelled for fust when `order_items.quarantined_at` is set or its order is cancelled (`voorraad_order_geannuleerd`: status geannuleerd/cancelled case-insensitive, `cancelled_at` or `deleted_at`): `sync_order_item_fusten` wants 0 and triggers on order_items (quarantine on/off) and orders (those three fields) book the difference against the line's own bookings, because quarantined or cancelled orders otherwise kept fust booked.
6
6
  - The correct fust count per order line comes only from `voorraad_fust_juist(order_item_id)` (same rule as `sync_order_item_fusten`; removed, quarantined, externally fulfilled or cancelled = 0); fust corrections compare against it, because every hand-built copy of the rule drifted.
7
7
  - Local stock saves never depend on the Floriday write gate: every Voorraad queue insert first checks `voorraad_floriday_klaarzetten_toegestaan()` and runs in its own exception block, because the Engine gate trigger raises and rolled back the local save.
8
+ - A note per stock change travels via tx setting `stock.change_note` (read by the deferred log trigger at commit, so never clear it inside the call); `trade_item_stock.notes` is the fixed article note and changes only when the caller asks (`stock.keep_notes`), because appending each save stacked notes.
9
+ - `sql/floriday-voorraad-schema.sql` must name the newest `supabase/migrations` file in its "Laatste migratie" header and contain the required objects; `scripts/check-schema-version.mjs` (prepublishOnly + test) blocks publishing otherwise; the header version is informational and never higher than package.json, because 1.0.139 shipped a stale schema and the dashboard bumps versions without schema changes.
10
+ - Default data only via `voorraad_ensure_defaults()` (system data upserted by code keeping `naam_aangepast`, retired codes set inactive; customer settings only inserted when missing, with column defaults equal to reader fallbacks); bump `voorraad_defaults_versie()` on every list change, because new shells get the schema without data and the fast exit compares that version.
11
+ - Load carrier → Engine code only via the Engine's `logistics_ladingdrager_resolve`; no own mapping list or fallback, because two lists drift.