@flowselections/logistiek-engine 1.0.233 → 1.0.235

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.
@@ -1,13 +1,13 @@
1
1
  // src/lib/autoSend.functions.ts — Beheer: is de sleutel op te halen en is er een Shell-adres? (alleen ja/nee)
2
2
  import { createServerFn } from "@tanstack/react-start";
3
3
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
4
- import { readableServerErrors } from "../lib/readableServerErrors.js";
4
+ import { readableServerErrors } from "./readableServerErrors.js";
5
5
  export const getAutoSendConfig = createServerFn({ method: "GET" })
6
6
  .middleware([readableServerErrors, requireSupabaseAuth])
7
7
  .handler(async () => {
8
8
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
9
- const { leesShellAdres } = await import("../lib/autoSend.server.js");
10
- const { haalAutoSendSleutel } = await import("../lib/centralSecrets.server.js");
9
+ const { leesShellAdres } = await import("./autoSend.server.js");
10
+ const { haalAutoSendSleutel } = await import("./centralSecrets.server.js");
11
11
  const s = await haalAutoSendSleutel();
12
12
  const adres = await leesShellAdres(supabaseAdmin);
13
13
  const { data: ontbreekt } = await supabaseAdmin.rpc("logistics_auto_send_route_missing");
@@ -1,7 +1,7 @@
1
1
  // Alleen-lezen controle: staat elke bestelregel correct op een kar?
2
2
  import { createServerFn } from "@tanstack/react-start";
3
3
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
4
- import { readableServerErrors } from "../lib/readableServerErrors.js";
4
+ import { readableServerErrors } from "./readableServerErrors.js";
5
5
  export const getCartCoverage = createServerFn({ method: "GET" })
6
6
  .middleware([readableServerErrors, requireSupabaseAuth])
7
7
  .handler(async () => {
@@ -5,7 +5,7 @@
5
5
  // ============================================================================
6
6
  import { createServerFn } from "@tanstack/react-start";
7
7
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
8
- import { readableServerErrors } from "../lib/readableServerErrors.js";
8
+ import { readableServerErrors } from "./readableServerErrors.js";
9
9
  /** Actieve Floriday-koppeling voor de banner in het instellingenscherm. */
10
10
  export const getFloridayConnection = createServerFn({ method: "GET" })
11
11
  .middleware([readableServerErrors, requireSupabaseAuth])
@@ -3,7 +3,7 @@
3
3
  // ============================================================================
4
4
  import { createServerFn } from "@tanstack/react-start";
5
5
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
6
- import { readableServerErrors } from "../lib/readableServerErrors.js";
6
+ import { readableServerErrors } from "./readableServerErrors.js";
7
7
  /** Zet een order opnieuw in de wachtrij (handmatig opnieuw proberen). */
8
8
  export const retryFloridayPush = createServerFn({ method: "POST" })
9
9
  .middleware([readableServerErrors, requireSupabaseAuth])
@@ -9,6 +9,14 @@ export declare function leesOrderIds(raw: string): {
9
9
  ok: false;
10
10
  fout: string;
11
11
  };
12
+ /**
13
+ * Ronde A (overgang): twee aanroepvormen worden geaccepteerd tot alle shells over zijn.
14
+ * 1. oud: header x-logistics-key = module_runtime_config 'logistics_tick_apikey'
15
+ * 2. nieuw: flowselections_cron_post — header apikey = openbare sleutel van deze
16
+ * omgeving én x-flowselections-cron-key = flowselections_cron_secret().
17
+ * Leesfouten worden gelogd; ontbreekt alle configuratie, dan "geen_configuratie".
18
+ */
19
+ export declare function controleerAanroeper(request: Request, supabase: SupabaseClient): Promise<"ok" | "geweigerd" | "geen_configuratie">;
12
20
  type WaitUntil = (p: Promise<unknown>) => void;
13
21
  export declare function handleLogisticsPlanNow(request: Request, supabase: SupabaseClient, opts?: {
14
22
  moduleProject?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"logistics-plan-now.server.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/logistics-plan-now.server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAW5D,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAgBnG;AAED,KAAK,SAAS,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;AAc/C,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,EACxB,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,CAAA;CAAE,GACxD,OAAO,CAAC,QAAQ,CAAC,CA6CnB"}
1
+ {"version":3,"file":"logistics-plan-now.server.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/logistics-plan-now.server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAW5D,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAgBnG;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,GAAG,WAAW,GAAG,mBAAmB,CAAC,CA8BnD;AAED,KAAK,SAAS,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;AAc/C,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,EACxB,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,CAAA;CAAE,GACxD,OAAO,CAAC,QAAQ,CAAC,CAqCnB"}
@@ -13,7 +13,7 @@
13
13
  import { engineIdent, runLockedTickRound } from "./logistics-tick.server.js";
14
14
  const CORS_HEADERS = {
15
15
  "Access-Control-Allow-Origin": "*",
16
- "Access-Control-Allow-Headers": "x-logistics-key, content-type",
16
+ "Access-Control-Allow-Headers": "x-logistics-key, x-flowselections-cron-key, apikey, content-type",
17
17
  "Access-Control-Allow-Methods": "POST, OPTIONS",
18
18
  };
19
19
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -51,6 +51,45 @@ export function leesOrderIds(raw) {
51
51
  }
52
52
  return { ok: true, ids: ids };
53
53
  }
54
+ /**
55
+ * Ronde A (overgang): twee aanroepvormen worden geaccepteerd tot alle shells over zijn.
56
+ * 1. oud: header x-logistics-key = module_runtime_config 'logistics_tick_apikey'
57
+ * 2. nieuw: flowselections_cron_post — header apikey = openbare sleutel van deze
58
+ * omgeving én x-flowselections-cron-key = flowselections_cron_secret().
59
+ * Leesfouten worden gelogd; ontbreekt alle configuratie, dan "geen_configuratie".
60
+ */
61
+ export async function controleerAanroeper(request, supabase) {
62
+ let configAanwezig = false;
63
+ const oud = request.headers.get("x-logistics-key") ?? "";
64
+ const { data: cfg, error: cfgError } = await supabase
65
+ .from("module_runtime_config")
66
+ .select("value")
67
+ .eq("key", "logistics_tick_apikey")
68
+ .maybeSingle();
69
+ if (cfgError)
70
+ console.error("[logistics-plan-now] oude sleutel niet leesbaar:", cfgError.message);
71
+ const verwachtOud = String(cfg?.value ?? "").trim();
72
+ if (verwachtOud) {
73
+ configAanwezig = true;
74
+ if (oud && gelijkeSleutel(oud, verwachtOud))
75
+ return "ok";
76
+ }
77
+ const platform = request.headers.get("x-flowselections-cron-key") ?? "";
78
+ const apikey = request.headers.get("apikey") ?? "";
79
+ const openbaar = (process.env["SUPABASE_PUBLISHABLE_KEY"] ?? process.env["SUPABASE_ANON_KEY"] ?? "")
80
+ .replace(/^["']|["']$/g, "");
81
+ const { data: geheim, error: geheimError } = await supabase.rpc("flowselections_cron_secret");
82
+ if (geheimError)
83
+ console.error("[logistics-plan-now] platformsleutel niet leesbaar:", geheimError.message);
84
+ const verwachtPlatform = typeof geheim === "string" ? geheim : "";
85
+ if (verwachtPlatform && openbaar) {
86
+ configAanwezig = true;
87
+ if (platform && apikey && gelijkeSleutel(platform, verwachtPlatform) && gelijkeSleutel(apikey, openbaar)) {
88
+ return "ok";
89
+ }
90
+ }
91
+ return configAanwezig ? "geweigerd" : "geen_configuratie";
92
+ }
54
93
  async function vindWaitUntil(opts) {
55
94
  if (opts?.waitUntil)
56
95
  return opts.waitUntil;
@@ -75,22 +114,14 @@ export async function handleLogisticsPlanNow(request, supabase, opts) {
75
114
  return new Response(null, { status: 204, headers: CORS_HEADERS });
76
115
  if (request.method !== "POST")
77
116
  return json(405, { ok: false, error: "Alleen POST" });
78
- const { data: cfg, error: cfgError } = await supabase
79
- .from("module_runtime_config")
80
- .select("value")
81
- .eq("key", "logistics_tick_apikey")
82
- .maybeSingle();
83
- const expected = String(cfg?.value ?? "").trim();
84
- if (cfgError || !expected) {
85
- return json(500, {
117
+ const toegang = await controleerAanroeper(request, supabase);
118
+ if (toegang === "geen_configuratie") {
119
+ return json(200, {
86
120
  ok: false,
87
- error: cfgError
88
- ? `Sleutel kon niet worden gelezen: ${cfgError.message}`
89
- : "logistics_tick_apikey ontbreekt in module_runtime_config; vul deze voor deze omgeving in.",
121
+ melding: "Geen sleutel ingesteld (logistics_tick_apikey en platformsleutel ontbreken); niets gestart.",
90
122
  });
91
123
  }
92
- const given = request.headers.get("x-logistics-key") ?? "";
93
- if (!gelijkeSleutel(given, expected))
124
+ if (toegang !== "ok")
94
125
  return json(401, { ok: false, error: "Unauthorized" });
95
126
  const body = leesOrderIds(await request.text());
96
127
  if (!body.ok)
@@ -3,7 +3,7 @@
3
3
  // ============================================================================
4
4
  import { createServerFn } from "@tanstack/react-start";
5
5
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
6
- import { readableServerErrors } from "../lib/readableServerErrors.js";
6
+ import { readableServerErrors } from "./readableServerErrors.js";
7
7
  export const replanOrderLoadCarriers = createServerFn({ method: "POST" })
8
8
  .middleware([readableServerErrors, requireSupabaseAuth])
9
9
  .inputValidator((data) => {
@@ -3,7 +3,7 @@
3
3
  // ============================================================================
4
4
  import { createServerFn } from "@tanstack/react-start";
5
5
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
6
- import { readableServerErrors } from "../lib/readableServerErrors.js";
6
+ import { readableServerErrors } from "./readableServerErrors.js";
7
7
  export const startRecalcJob = createServerFn({ method: "POST" })
8
8
  .middleware([readableServerErrors, requireSupabaseAuth])
9
9
  .inputValidator((data) => data ?? {})
@@ -7,7 +7,7 @@
7
7
  // ============================================================================
8
8
  import { createServerFn } from "@tanstack/react-start";
9
9
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
10
- import { readableServerErrors } from "../lib/readableServerErrors.js";
10
+ import { readableServerErrors } from "./readableServerErrors.js";
11
11
  export const recalculateLogistics = createServerFn({ method: "POST" })
12
12
  .middleware([readableServerErrors, requireSupabaseAuth])
13
13
  .inputValidator((data) => data ?? {})
@@ -27,7 +27,7 @@ export const recalculateLogistics = createServerFn({ method: "POST" })
27
27
  args: { p_from: iso(today), p_to: iso(until) },
28
28
  },
29
29
  ];
30
- const { scheduleTasksPerOrder } = await import("../lib/scheduleTasks.server.js");
30
+ const { scheduleTasksPerOrder } = await import("./scheduleTasks.server.js");
31
31
  const steps = [await scheduleTasksPerOrder(context.supabase)];
32
32
  for (const call of calls) {
33
33
  const { error } = await context.supabase.rpc(call.fn, call.args);
@@ -1,2 +1,2 @@
1
- export declare const MODULE_VERSION = "1.0.233";
1
+ export declare const MODULE_VERSION = "1.0.235";
2
2
  //# sourceMappingURL=moduleVersion.d.ts.map
@@ -1,2 +1,2 @@
1
1
  // Automatisch gegenereerd door prebuild:lib; niet handmatig aanpassen.
2
- export const MODULE_VERSION = "1.0.233";
2
+ export const MODULE_VERSION = "1.0.235";
@@ -3,7 +3,7 @@
3
3
  // geen karren, geen wachtrij, geen events, geen blokkades, geen bufferbesluit.
4
4
  import { createServerFn } from "@tanstack/react-start";
5
5
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
6
- import { readableServerErrors } from "../lib/readableServerErrors.js";
6
+ import { readableServerErrors } from "./readableServerErrors.js";
7
7
  import { bouwPlanPreview } from "./planPreview.js";
8
8
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9
9
  export const logisticsPlanPreview = createServerFn({ method: "POST" })
@@ -1,7 +1,7 @@
1
1
  // Alleen-lezen overzicht van de vergelijkende planner (dry-run).
2
2
  import { createServerFn } from "@tanstack/react-start";
3
3
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
4
- import { readableServerErrors } from "../lib/readableServerErrors.js";
4
+ import { readableServerErrors } from "./readableServerErrors.js";
5
5
  import { summarizeDiffRuns } from "./plannerDiff.js";
6
6
  export const getPlannerDiffOverview = createServerFn({ method: "GET" })
7
7
  .middleware([readableServerErrors, requireSupabaseAuth])
@@ -6,7 +6,7 @@
6
6
  // ============================================================================
7
7
  import { createServerFn } from "@tanstack/react-start";
8
8
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
9
- import { readableServerErrors } from "../lib/readableServerErrors.js";
9
+ import { readableServerErrors } from "./readableServerErrors.js";
10
10
  const ROLLEN = ["admin", "superadmin", "developer"];
11
11
  async function magBeheren(sb, userId) {
12
12
  for (const rol of ROLLEN) {
@@ -48,7 +48,7 @@ export const startShellAdresControle = createServerFn({ method: "POST" })
48
48
  export const registreerMinuutrondeSleutel = createServerFn({ method: "POST" })
49
49
  .middleware([readableServerErrors, requireSupabaseAuth])
50
50
  .handler(async () => {
51
- const { minuutrondeStartProbleem } = await import("../lib/shellAdres.js");
51
+ const { minuutrondeStartProbleem } = await import("./shellAdres.js");
52
52
  const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
53
53
  const sleutel = (process.env["SUPABASE_PUBLISHABLE_KEY"] ?? process.env["SUPABASE_ANON_KEY"] ?? "")
54
54
  .replace(/^["']|["']$/g, "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/logistiek-engine",
3
- "version": "1.0.233",
3
+ "version": "1.0.235",
4
4
  "flowselections": {
5
5
  "moduleId": "logistiek-engine",
6
6
  "pages": [
@@ -102,6 +102,96 @@
102
102
  "schema": {
103
103
  "file": "db/schema/logistiek-engine.sql",
104
104
  "order": 60
105
+ },
106
+ "crons": [
107
+ {
108
+ "name": "cron-history-prune-weekly",
109
+ "schedule": "10 4 * * 0",
110
+ "kind": "sql",
111
+ "sql": "SELECT public.logistics_prune_cron_history(7)"
112
+ },
113
+ {
114
+ "name": "logistics_cart_barcode_opschonen",
115
+ "schedule": "*/10 1-4 * * *",
116
+ "kind": "sql",
117
+ "sql": "SELECT public.logistics_cart_barcode_opschonen(10000)"
118
+ },
119
+ {
120
+ "name": "logistics-base-url-check",
121
+ "schedule": "7 * * * *",
122
+ "kind": "sql",
123
+ "sql": "SELECT public.logistics_tick_base_url_check()"
124
+ },
125
+ {
126
+ "name": "logistics-history-prune",
127
+ "schedule": "20 3 * * *",
128
+ "kind": "sql",
129
+ "sql": "SELECT public.logistics_cleanup_history(50000)"
130
+ },
131
+ {
132
+ "name": "logistics-order-finalize-prune",
133
+ "schedule": "23 3 * * *",
134
+ "kind": "sql",
135
+ "sql": "SELECT public.logistics_order_finalize_prune(7)"
136
+ },
137
+ {
138
+ "name": "logistics-order-finalize-reconcile",
139
+ "schedule": "*/15 * * * *",
140
+ "kind": "sql",
141
+ "sql": "SELECT public.logistics_order_finalize_reconcile(14, 200)"
142
+ },
143
+ {
144
+ "name": "logistics-packing-reconcile",
145
+ "schedule": "17 * * * *",
146
+ "kind": "sql",
147
+ "sql": "SELECT public.logistics_packing_reconcile(500, 100)"
148
+ },
149
+ {
150
+ "name": "logistics-plan-coverage-check",
151
+ "schedule": "*/15 * * * *",
152
+ "kind": "sql",
153
+ "sql": "SELECT public.logistics_plan_coverage_check(50)"
154
+ },
155
+ {
156
+ "name": "logistics-reapply-buffer-decisions",
157
+ "schedule": "*/5 * * * *",
158
+ "kind": "sql",
159
+ "sql": "SELECT public.logistics_reapply_buffer_decisions()"
160
+ },
161
+ {
162
+ "name": "logistics-recalc-tick",
163
+ "schedule": "* * * * *",
164
+ "kind": "sql",
165
+ "sql": "SELECT public.logistics_recalc_tick_kick()"
166
+ },
167
+ {
168
+ "name": "logistics-reserved-stock-nightly",
169
+ "schedule": "10 2 * * *",
170
+ "kind": "sql",
171
+ "sql": "SELECT public.logistics_reserved_stock_nightly()"
172
+ },
173
+ {
174
+ "name": "logistics-tasks-prune",
175
+ "schedule": "41 3 * * *",
176
+ "kind": "sql",
177
+ "sql": "SELECT public.logistics_tasks_prune(30)"
178
+ },
179
+ {
180
+ "name": "logistics-tick",
181
+ "schedule": "* * * * *",
182
+ "kind": "sql",
183
+ "sql": "SELECT public.logistics_tick()"
184
+ },
185
+ {
186
+ "name": "logistics-tick-runs-prune",
187
+ "schedule": "33 3 * * *",
188
+ "kind": "sql",
189
+ "sql": "SELECT public.logistics_tick_runs_prune()"
190
+ }
191
+ ],
192
+ "install": {
193
+ "ensureDefaults": "logistics_ensure_defaults",
194
+ "installCheck": "logistics_install_check"
105
195
  }
106
196
  },
107
197
  "private": false,