@flowselections/logistiek-engine 1.0.239 → 1.0.240
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.
- package/db/schema/logistiek-engine.sql +1341 -0
- package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts.map +1 -1
- package/dist-lib/components/GeblokkeerdeOrdersCard.js +2 -2
- package/dist-lib/components/KarplanStatusCard.d.ts.map +1 -1
- package/dist-lib/components/KarplanStatusCard.js +7 -2
- package/dist-lib/components/StandaardgegevensCard.d.ts.map +1 -1
- package/dist-lib/components/StandaardgegevensCard.js +43 -3
- package/dist-lib/components/TaakGezondheidCard.d.ts.map +1 -1
- package/dist-lib/components/TaakGezondheidCard.js +5 -3
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts +2 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts.map +1 -1
- package/dist-lib/hooks/useGeblokkeerdeOrders.js +13 -0
- package/dist-lib/integrations/supabase/types.d.ts +658 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/engineStatusTeksten.d.ts +7 -0
- package/dist-lib/lib/engineStatusTeksten.d.ts.map +1 -0
- package/dist-lib/lib/engineStatusTeksten.js +22 -0
- package/dist-lib/lib/flowTree.js +3 -3
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/dist-lib/lib/ruleEngineSchema.js +2 -2
- package/dist-lib/lib/taakTeLaat.d.ts +7 -0
- package/dist-lib/lib/taakTeLaat.d.ts.map +1 -0
- package/dist-lib/lib/taakTeLaat.js +62 -0
- package/package.json +1 -1
|
@@ -42169,3 +42169,1344 @@ BEGIN
|
|
|
42169
42169
|
RETURN NEW;
|
|
42170
42170
|
END;
|
|
42171
42171
|
$function$;
|
|
42172
|
+
|
|
42173
|
+
-- Productiecheck 2026-11-09: versiemarkering, samenvoeggroepen met vaste karren
|
|
42174
|
+
CREATE OR REPLACE FUNCTION public.logistics_schema_versie()
|
|
42175
|
+
RETURNS text LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$ SELECT '2026-11-09'::text $$;
|
|
42176
|
+
REVOKE ALL ON FUNCTION public.logistics_schema_versie() FROM PUBLIC, anon;
|
|
42177
|
+
GRANT EXECUTE ON FUNCTION public.logistics_schema_versie() TO authenticated, service_role;
|
|
42178
|
+
|
|
42179
|
+
CREATE OR REPLACE FUNCTION public._logistics_order_karren_vast(p_order_id uuid)
|
|
42180
|
+
RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42181
|
+
SELECT EXISTS (SELECT 1 FROM logistics_active.order_carts oc
|
|
42182
|
+
WHERE oc.order_id = p_order_id
|
|
42183
|
+
AND (public.logistics_cart_is_frozen(oc.id)
|
|
42184
|
+
OR EXISTS (SELECT 1 FROM public.logistics_control_scan s WHERE s.cart_id = oc.id AND s.status <> 'geannuleerd')
|
|
42185
|
+
OR EXISTS (SELECT 1 FROM public.logistics_slip_shipping_note n
|
|
42186
|
+
WHERE n.cart_id = oc.id AND (n.status IN ('in_printwachtrij','geprint') OR n.fulfillment_order_id IS NOT NULL))))
|
|
42187
|
+
$$;
|
|
42188
|
+
REVOKE ALL ON FUNCTION public._logistics_order_karren_vast(uuid) FROM PUBLIC, anon, authenticated;
|
|
42189
|
+
GRANT EXECUTE ON FUNCTION public._logistics_order_karren_vast(uuid) TO service_role;
|
|
42190
|
+
|
|
42191
|
+
CREATE OR REPLACE FUNCTION public._logistics_buffers_vervallen_herstel(p_order_id uuid)
|
|
42192
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42193
|
+
DECLARE r record; v_groepen uuid[] := '{}'; v_orders int := 0; v_vast int := 0; v_oud text; v_stand jsonb;
|
|
42194
|
+
BEGIN
|
|
42195
|
+
v_oud := current_setting('logistics.buffer_writer', true);
|
|
42196
|
+
FOR r IN
|
|
42197
|
+
SELECT o.id, o.order_number, o.buffer_id,
|
|
42198
|
+
CASE WHEN o.deleted_at IS NOT NULL THEN 'verwijderd' ELSE 'geannuleerd' END AS reden
|
|
42199
|
+
FROM public.orders o
|
|
42200
|
+
WHERE o.buffer_id IS NOT NULL AND (p_order_id IS NULL OR o.id = p_order_id)
|
|
42201
|
+
AND public.logistics_order_vervallen(o.id)
|
|
42202
|
+
ORDER BY o.order_number
|
|
42203
|
+
FOR UPDATE OF o
|
|
42204
|
+
LOOP
|
|
42205
|
+
IF public._logistics_order_karren_vast(r.id) THEN
|
|
42206
|
+
v_vast := v_vast + 1;
|
|
42207
|
+
CONTINUE;
|
|
42208
|
+
END IF;
|
|
42209
|
+
PERFORM set_config('logistics.buffer_writer', 'engine', true);
|
|
42210
|
+
UPDATE public.orders SET buffer_id = NULL WHERE id = r.id AND buffer_id = r.buffer_id;
|
|
42211
|
+
INSERT INTO public.logistics_correctie_log (correctie, object_id, omschrijving, oud, nieuw)
|
|
42212
|
+
VALUES ('buffers_geannuleerd', r.id, coalesce(r.order_number, r.id::text) || ' (' || r.reden || ') losgemaakt uit samenvoeggroep',
|
|
42213
|
+
jsonb_build_object('buffer_id', r.buffer_id), jsonb_build_object('buffer_id', NULL));
|
|
42214
|
+
v_orders := v_orders + 1;
|
|
42215
|
+
IF NOT r.buffer_id = ANY (v_groepen) THEN v_groepen := v_groepen || r.buffer_id; END IF;
|
|
42216
|
+
END LOOP;
|
|
42217
|
+
PERFORM set_config('logistics.buffer_writer', coalesce(v_oud, ''), true);
|
|
42218
|
+
|
|
42219
|
+
IF cardinality(v_groepen) > 0 THEN
|
|
42220
|
+
FOR r IN SELECT x.id, x.order_number FROM public.orders x
|
|
42221
|
+
WHERE x.buffer_id = ANY (v_groepen) AND x.deleted_at IS NULL AND x.cancelled_at IS NULL LOOP
|
|
42222
|
+
BEGIN
|
|
42223
|
+
PERFORM public.logistics_plan_enqueue(r.id, 'correctie_buffers_geannuleerd');
|
|
42224
|
+
EXCEPTION WHEN others THEN
|
|
42225
|
+
INSERT INTO public.logistics_correctie_log (correctie, object_id, omschrijving)
|
|
42226
|
+
VALUES ('buffers_geannuleerd_fout', r.id, 'Opnieuw plannen van ' || coalesce(r.order_number, r.id::text) || ' mislukt: ' || SQLERRM);
|
|
42227
|
+
END;
|
|
42228
|
+
END LOOP;
|
|
42229
|
+
END IF;
|
|
42230
|
+
IF p_order_id IS NULL OR cardinality(v_groepen) > 0 THEN
|
|
42231
|
+
SELECT value::jsonb INTO v_stand FROM public.logistics_plan_settings WHERE key = 'buffers_geannuleerd_herstel';
|
|
42232
|
+
v_stand := jsonb_build_object(
|
|
42233
|
+
'totaalGroepen', coalesce((v_stand->>'totaalGroepen')::int, 0) + cardinality(v_groepen),
|
|
42234
|
+
'totaalOrders', coalesce((v_stand->>'totaalOrders')::int, 0) + v_orders,
|
|
42235
|
+
'laatsteGroepen', cardinality(v_groepen), 'laatsteOrders', v_orders,
|
|
42236
|
+
'laatsteOp', CASE WHEN cardinality(v_groepen) > 0 THEN to_jsonb(now()) ELSE coalesce(v_stand->'laatsteOp', 'null'::jsonb) END,
|
|
42237
|
+
'gecontroleerdOp', now());
|
|
42238
|
+
INSERT INTO public.logistics_plan_settings (key, value) VALUES ('buffers_geannuleerd_herstel', v_stand::text)
|
|
42239
|
+
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now();
|
|
42240
|
+
END IF;
|
|
42241
|
+
RETURN jsonb_build_object('groepen', cardinality(v_groepen), 'orders', v_orders, 'blijvenStaan', v_vast);
|
|
42242
|
+
END $$;
|
|
42243
|
+
REVOKE ALL ON FUNCTION public._logistics_buffers_vervallen_herstel(uuid) FROM PUBLIC, anon, authenticated;
|
|
42244
|
+
GRANT EXECUTE ON FUNCTION public._logistics_buffers_vervallen_herstel(uuid) TO service_role;
|
|
42245
|
+
|
|
42246
|
+
CREATE OR REPLACE FUNCTION public.logistics_buffers_herstel_status()
|
|
42247
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42248
|
+
DECLARE v_nog int; v_vast int;
|
|
42249
|
+
BEGIN
|
|
42250
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_buffers_herstel_status');
|
|
42251
|
+
SELECT count(*), count(*) FILTER (WHERE public._logistics_order_karren_vast(o.id))
|
|
42252
|
+
INTO v_nog, v_vast
|
|
42253
|
+
FROM public.orders o WHERE o.buffer_id IS NOT NULL AND public.logistics_order_vervallen(o.id);
|
|
42254
|
+
RETURN jsonb_build_object(
|
|
42255
|
+
'stand', (SELECT value::jsonb FROM public.logistics_plan_settings WHERE key = 'buffers_geannuleerd_herstel'),
|
|
42256
|
+
'nogInGroep', v_nog,
|
|
42257
|
+
'blijvenStaan', v_vast,
|
|
42258
|
+
'wachten', v_nog - v_vast,
|
|
42259
|
+
'fouten', coalesce((SELECT jsonb_agg(jsonb_build_object('op', l.created_at, 'melding', l.omschrijving) ORDER BY l.created_at DESC)
|
|
42260
|
+
FROM (SELECT * FROM public.logistics_correctie_log WHERE correctie = 'buffers_geannuleerd_fout'
|
|
42261
|
+
AND created_at > now() - interval '7 days' ORDER BY created_at DESC LIMIT 5) l), '[]'::jsonb));
|
|
42262
|
+
END $$;
|
|
42263
|
+
REVOKE ALL ON FUNCTION public.logistics_buffers_herstel_status() FROM PUBLIC, anon;
|
|
42264
|
+
GRANT EXECUTE ON FUNCTION public.logistics_buffers_herstel_status() TO authenticated, service_role;
|
|
42265
|
+
-- Ingehaalde orders (backfill) 2026-11-10
|
|
42266
|
+
-- Ingehaalde orders (custom_fields.backfill): nooit kar, reservering, wachtrij of melding.
|
|
42267
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_is_backfill(p_order_id uuid)
|
|
42268
|
+
RETURNS boolean
|
|
42269
|
+
LANGUAGE sql
|
|
42270
|
+
STABLE
|
|
42271
|
+
SET search_path TO 'public'
|
|
42272
|
+
AS $function$
|
|
42273
|
+
SELECT COALESCE((
|
|
42274
|
+
SELECT CASE
|
|
42275
|
+
WHEN NOT (o.custom_fields ? 'backfill') THEN false
|
|
42276
|
+
WHEN jsonb_typeof(o.custom_fields->'backfill') = 'null' THEN false
|
|
42277
|
+
WHEN jsonb_typeof(o.custom_fields->'backfill') = 'boolean' THEN (o.custom_fields->>'backfill')::boolean
|
|
42278
|
+
ELSE lower(btrim(o.custom_fields->>'backfill')) NOT IN ('', 'false', '0', 'nee', 'no')
|
|
42279
|
+
END
|
|
42280
|
+
FROM public.orders o
|
|
42281
|
+
WHERE o.id = p_order_id AND jsonb_typeof(o.custom_fields) = 'object'), false);
|
|
42282
|
+
$function$;
|
|
42283
|
+
REVOKE ALL ON FUNCTION public.logistics_order_is_backfill(uuid) FROM PUBLIC;
|
|
42284
|
+
REVOKE ALL ON FUNCTION public.logistics_order_is_backfill(uuid) FROM anon;
|
|
42285
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_is_backfill(uuid) TO authenticated, service_role;
|
|
42286
|
+
|
|
42287
|
+
|
|
42288
|
+
CREATE OR REPLACE FUNCTION public.logistics_plan_enqueue(p_order_id uuid, p_reason text DEFAULT 'change'::text)
|
|
42289
|
+
RETURNS void
|
|
42290
|
+
LANGUAGE plpgsql
|
|
42291
|
+
SECURITY DEFINER
|
|
42292
|
+
SET search_path TO 'public'
|
|
42293
|
+
AS $function$
|
|
42294
|
+
DECLARE
|
|
42295
|
+
v_ok boolean;
|
|
42296
|
+
v_id uuid;
|
|
42297
|
+
v_status text;
|
|
42298
|
+
v_decision text;
|
|
42299
|
+
v_target uuid := p_order_id;
|
|
42300
|
+
v_wacht jsonb;
|
|
42301
|
+
BEGIN
|
|
42302
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_plan_enqueue');
|
|
42303
|
+
IF COALESCE(current_setting('logistics.merging', true), '') <> '1' THEN
|
|
42304
|
+
BEGIN
|
|
42305
|
+
PERFORM set_config('logistics.merging', '1', true);
|
|
42306
|
+
v_target := COALESCE(public.logistics_merge_floriday_lines(p_order_id), p_order_id);
|
|
42307
|
+
PERFORM set_config('logistics.merging', '0', true);
|
|
42308
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42309
|
+
v_target := p_order_id;
|
|
42310
|
+
END;
|
|
42311
|
+
END IF;
|
|
42312
|
+
|
|
42313
|
+
IF public.logistics_order_is_backfill(v_target) THEN
|
|
42314
|
+
BEGIN
|
|
42315
|
+
PERFORM public.logistics_trace_order_step(
|
|
42316
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42317
|
+
'niet aangemeld', 'Ingehaalde order: krijgt geen kar, reservering of documenten', NULL);
|
|
42318
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42319
|
+
RAISE WARNING 'logistiek-engine: trace ingehaalde order mislukt: %', SQLERRM;
|
|
42320
|
+
END;
|
|
42321
|
+
RETURN;
|
|
42322
|
+
END IF;
|
|
42323
|
+
-- A2: wachttijd na een mislukte indeling respecteren bij automatische meldingen.
|
|
42324
|
+
v_wacht := public.logistics_plan_wachttijd(v_target, p_reason);
|
|
42325
|
+
IF COALESCE((v_wacht->>'wacht')::boolean, false) THEN
|
|
42326
|
+
PERFORM public.logistics_plan_wachttijd_melden(v_target, p_reason, v_wacht);
|
|
42327
|
+
RETURN;
|
|
42328
|
+
END IF;
|
|
42329
|
+
|
|
42330
|
+
SELECT (o.deleted_at IS NULL AND COALESCE(o.is_reservation, false) = false AND o.plan_locked_at IS NULL)
|
|
42331
|
+
INTO v_ok FROM public.orders o WHERE o.id = v_target;
|
|
42332
|
+
-- 1.0.194: geannuleerde orders niet opnieuw indelen (alleen als de kolommen bestaan).
|
|
42333
|
+
IF COALESCE(v_ok, false) AND public.logistics_order_geannuleerd(v_target) THEN
|
|
42334
|
+
PERFORM public.logistics_trace_order_step(
|
|
42335
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42336
|
+
'niet aangemeld', 'Order is geannuleerd', NULL);
|
|
42337
|
+
RETURN;
|
|
42338
|
+
END IF;
|
|
42339
|
+
IF NOT COALESCE(v_ok, false) THEN
|
|
42340
|
+
PERFORM public.logistics_trace_order_step(
|
|
42341
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42342
|
+
'niet aangemeld', 'Order is verwijderd, samengevoegd, een reservering of de indeling staat vast', NULL);
|
|
42343
|
+
RETURN;
|
|
42344
|
+
END IF;
|
|
42345
|
+
|
|
42346
|
+
SELECT q.id, q.status INTO v_id, v_status
|
|
42347
|
+
FROM public.logistics_plan_queue q
|
|
42348
|
+
WHERE q.order_id = v_target
|
|
42349
|
+
AND q.status IN ('pending', 'running', 'geblokkeerd')
|
|
42350
|
+
ORDER BY q.updated_at DESC
|
|
42351
|
+
LIMIT 1
|
|
42352
|
+
FOR UPDATE;
|
|
42353
|
+
|
|
42354
|
+
IF v_id IS NULL THEN
|
|
42355
|
+
BEGIN
|
|
42356
|
+
INSERT INTO public.logistics_plan_queue(order_id, reason) VALUES (v_target, p_reason);
|
|
42357
|
+
v_decision := 'nieuw aangemeld voor indeling';
|
|
42358
|
+
EXCEPTION WHEN unique_violation THEN
|
|
42359
|
+
v_decision := 'stond al in de wachtrij';
|
|
42360
|
+
END;
|
|
42361
|
+
ELSIF v_status = 'geblokkeerd' THEN
|
|
42362
|
+
UPDATE public.logistics_plan_queue
|
|
42363
|
+
SET status = 'pending', attempts = 0, reason = p_reason, reason_code = NULL,
|
|
42364
|
+
error = NULL, claimed_at = NULL, next_attempt_at = now(), updated_at = now()
|
|
42365
|
+
WHERE id = v_id;
|
|
42366
|
+
v_decision := 'blokkade opgeheven, opnieuw aangemeld';
|
|
42367
|
+
ELSE
|
|
42368
|
+
UPDATE public.logistics_plan_queue
|
|
42369
|
+
SET reason = p_reason, next_attempt_at = LEAST(next_attempt_at, now()), updated_at = now()
|
|
42370
|
+
WHERE id = v_id;
|
|
42371
|
+
v_decision := 'opnieuw aangemeld';
|
|
42372
|
+
END IF;
|
|
42373
|
+
|
|
42374
|
+
PERFORM public.logistics_trace_order_step(
|
|
42375
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'geslaagd',
|
|
42376
|
+
v_decision, p_reason, 'Karrenindeling');
|
|
42377
|
+
|
|
42378
|
+
PERFORM public.logistics_plan_kick();
|
|
42379
|
+
END;
|
|
42380
|
+
$function$;
|
|
42381
|
+
|
|
42382
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_changed(p_order_id uuid, p_reason text DEFAULT 'wijziging'::text)
|
|
42383
|
+
RETURNS void
|
|
42384
|
+
LANGUAGE plpgsql
|
|
42385
|
+
SECURITY DEFINER
|
|
42386
|
+
SET search_path TO 'public'
|
|
42387
|
+
AS $function$
|
|
42388
|
+
DECLARE v_number text; v_ok boolean; v_wacht jsonb; v_fp text;
|
|
42389
|
+
v_reason text := COALESCE(NULLIF(btrim(p_reason), ''), 'wijziging');
|
|
42390
|
+
BEGIN
|
|
42391
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_changed');
|
|
42392
|
+
IF p_order_id IS NULL THEN RETURN; END IF;
|
|
42393
|
+
IF COALESCE(current_setting('logistics.replanning', true), '') = '1' THEN RETURN; END IF;
|
|
42394
|
+
IF public.logistics_order_is_backfill(p_order_id) THEN
|
|
42395
|
+
BEGIN
|
|
42396
|
+
PERFORM public.logistics_trace_order_step(
|
|
42397
|
+
p_order_id, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42398
|
+
'niet aangemeld', 'Ingehaalde order: krijgt geen kar, reservering of documenten', NULL);
|
|
42399
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42400
|
+
RAISE WARNING 'logistiek-engine: trace ingehaalde order mislukt: %', SQLERRM;
|
|
42401
|
+
END;
|
|
42402
|
+
RETURN;
|
|
42403
|
+
END IF;
|
|
42404
|
+
v_fp := public.logistics_order_fp(p_order_id);
|
|
42405
|
+
IF v_reason = 'order_gewijzigd' THEN
|
|
42406
|
+
IF EXISTS (SELECT 1 FROM public.logistics_order_change_fp f WHERE f.order_id = p_order_id AND f.fp = v_fp) THEN RETURN; END IF;
|
|
42407
|
+
INSERT INTO public.logistics_order_change_fp(order_id, fp, updated_at) VALUES (p_order_id, v_fp, now())
|
|
42408
|
+
ON CONFLICT (order_id) DO UPDATE SET fp = EXCLUDED.fp, updated_at = now();
|
|
42409
|
+
END IF;
|
|
42410
|
+
IF public.logistics_order_afgemeld(p_order_id)
|
|
42411
|
+
OR EXISTS (SELECT 1 FROM public.logistics_shared_cart_peers(p_order_id) p
|
|
42412
|
+
WHERE public.logistics_order_afgemeld(p.peer_order_id)) THEN
|
|
42413
|
+
IF EXISTS (SELECT 1 FROM public.logistics_order_change_fp f WHERE f.order_id = p_order_id AND f.frozen_fp = v_fp) THEN RETURN; END IF;
|
|
42414
|
+
INSERT INTO public.logistics_order_change_fp(order_id, frozen_fp, updated_at) VALUES (p_order_id, v_fp, now())
|
|
42415
|
+
ON CONFLICT (order_id) DO UPDATE SET frozen_fp = EXCLUDED.frozen_fp, updated_at = now();
|
|
42416
|
+
BEGIN
|
|
42417
|
+
PERFORM public.logistics_trace_order_step(p_order_id, 'stap:orders_combineren', 'wijziging na afmelding', 'overgeslagen',
|
|
42418
|
+
'niet opnieuw ingedeeld', 'order al afgemeld; kar bevroren (' || v_reason || ')', 'Karrenindeling');
|
|
42419
|
+
EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
42420
|
+
RETURN;
|
|
42421
|
+
END IF;
|
|
42422
|
+
v_wacht := public.logistics_plan_wachttijd(p_order_id, v_reason);
|
|
42423
|
+
IF COALESCE((v_wacht->>'wacht')::boolean, false) THEN
|
|
42424
|
+
PERFORM public.logistics_plan_wachttijd_melden(p_order_id, v_reason, v_wacht);
|
|
42425
|
+
RETURN;
|
|
42426
|
+
END IF;
|
|
42427
|
+
SELECT o.order_number, (o.deleted_at IS NULL AND COALESCE(o.is_reservation, false) = false AND o.plan_locked_at IS NULL)
|
|
42428
|
+
INTO v_number, v_ok FROM public.orders o WHERE o.id = p_order_id;
|
|
42429
|
+
IF v_number IS NULL OR NOT COALESCE(v_ok, false) THEN
|
|
42430
|
+
PERFORM public.logistics_plan_enqueue(p_order_id, v_reason); RETURN;
|
|
42431
|
+
END IF;
|
|
42432
|
+
IF public.logistics_order_frozen(p_order_id) THEN
|
|
42433
|
+
BEGIN
|
|
42434
|
+
PERFORM public.logistics_trace_order_step(p_order_id, 'stap:orders_combineren', 'wijziging uit een andere module', 'waarschuwing',
|
|
42435
|
+
'niet opnieuw ingedeeld',
|
|
42436
|
+
'De order is gewijzigd (' || v_reason || '), maar er zijn al geprinte, gescande of gecontroleerde karren. Die blijven staan.',
|
|
42437
|
+
'Karrenindeling');
|
|
42438
|
+
EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
42439
|
+
PERFORM public.logistics_plan_enqueue(p_order_id, v_reason); RETURN;
|
|
42440
|
+
END IF;
|
|
42441
|
+
BEGIN
|
|
42442
|
+
PERFORM set_config('logistics.replanning', '1', true);
|
|
42443
|
+
PERFORM public.logistics_replan_order_journey(v_number, v_reason);
|
|
42444
|
+
PERFORM set_config('logistics.replanning', '0', true);
|
|
42445
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42446
|
+
PERFORM set_config('logistics.replanning', '0', true);
|
|
42447
|
+
PERFORM public.logistics_plan_enqueue(p_order_id, v_reason);
|
|
42448
|
+
END;
|
|
42449
|
+
END;
|
|
42450
|
+
$function$;
|
|
42451
|
+
|
|
42452
|
+
CREATE OR REPLACE FUNCTION public.logistics_reserved_order_excluded(p_order_id uuid)
|
|
42453
|
+
RETURNS boolean
|
|
42454
|
+
LANGUAGE plpgsql
|
|
42455
|
+
STABLE SECURITY DEFINER
|
|
42456
|
+
SET search_path TO 'public'
|
|
42457
|
+
AS $function$
|
|
42458
|
+
DECLARE r record; a jsonb;
|
|
42459
|
+
BEGIN
|
|
42460
|
+
PERFORM public.logistics_acc_guard('server', 'logistics_reserved_order_excluded');
|
|
42461
|
+
SELECT o.deleted_at, o.cancelled_at, o.status INTO r FROM public.orders o WHERE o.id = p_order_id;
|
|
42462
|
+
IF NOT FOUND THEN RETURN false; END IF;
|
|
42463
|
+
IF public.logistics_order_is_backfill(p_order_id) THEN RETURN true; END IF;
|
|
42464
|
+
IF r.deleted_at IS NOT NULL OR r.cancelled_at IS NOT NULL
|
|
42465
|
+
OR lower(coalesce(r.status, '')) IN ('geannuleerd', 'cancelled') THEN
|
|
42466
|
+
RETURN true;
|
|
42467
|
+
END IF;
|
|
42468
|
+
BEGIN
|
|
42469
|
+
a := public.logistics_order_is_archived(p_order_id);
|
|
42470
|
+
RETURN coalesce((a->>'gearchiveerd')::boolean, false);
|
|
42471
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42472
|
+
RETURN false; -- leesfout: order blijft meetellen (fail closed)
|
|
42473
|
+
END;
|
|
42474
|
+
END $function$;
|
|
42475
|
+
|
|
42476
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_stock_trigger()
|
|
42477
|
+
RETURNS trigger
|
|
42478
|
+
LANGUAGE plpgsql
|
|
42479
|
+
SECURITY DEFINER
|
|
42480
|
+
SET search_path TO 'public'
|
|
42481
|
+
AS $function$
|
|
42482
|
+
DECLARE
|
|
42483
|
+
oid uuid := COALESCE(NEW.order_id, OLD.order_id);
|
|
42484
|
+
BEGIN
|
|
42485
|
+
IF public.logistics_order_is_backfill(oid) THEN RETURN NULL; END IF;
|
|
42486
|
+
BEGIN
|
|
42487
|
+
PERFORM public.logistics_scan_order_stock(oid);
|
|
42488
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42489
|
+
NULL;
|
|
42490
|
+
END;
|
|
42491
|
+
RETURN NULL;
|
|
42492
|
+
END;
|
|
42493
|
+
$function$;
|
|
42494
|
+
|
|
42495
|
+
CREATE OR REPLACE FUNCTION public.logistics_open_orders_zonder_kar()
|
|
42496
|
+
RETURNS TABLE(order_id uuid, order_number text, delivery_date text, laatste_reden text)
|
|
42497
|
+
LANGUAGE sql
|
|
42498
|
+
STABLE SECURITY DEFINER
|
|
42499
|
+
SET search_path TO 'public'
|
|
42500
|
+
AS $function$
|
|
42501
|
+
SELECT public.logistics_acc_guard('ingelogd', 'logistics_open_orders_zonder_kar');
|
|
42502
|
+
WITH lq AS (
|
|
42503
|
+
SELECT DISTINCT ON (q.order_id) q.order_id, q.status, q.reason_code, q.error
|
|
42504
|
+
FROM public.logistics_plan_queue q ORDER BY q.order_id, q.updated_at DESC
|
|
42505
|
+
)
|
|
42506
|
+
SELECT o.id, o.order_number, o.delivery_date, lq.error
|
|
42507
|
+
FROM public.orders o
|
|
42508
|
+
LEFT JOIN lq ON lq.order_id = o.id
|
|
42509
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
42510
|
+
AND lower(coalesce(o.status,'')) NOT IN ('cancelled','geannuleerd','deleted','verwijderd','afgehandeld','completed','delivered','geleverd')
|
|
42511
|
+
AND o.delivery_date ~ '^\d{4}-\d{2}-\d{2}'
|
|
42512
|
+
AND (left(o.delivery_date,10)::date >= public.logistics_local_today()
|
|
42513
|
+
OR (left(o.delivery_date,10)::date >= public.logistics_local_today() - 7 AND o.updated_at > now() - interval '24 hours'))
|
|
42514
|
+
AND EXISTS (SELECT 1 FROM public.order_items oi WHERE oi.order_id = o.id)
|
|
42515
|
+
AND NOT public.logistics_order_is_backfill(o.id)
|
|
42516
|
+
AND NOT coalesce(public.logistics_order_buffer_excluded(o.id), false)
|
|
42517
|
+
AND NOT (coalesce(lq.status,'') IN ('geblokkeerd','pending','running'))
|
|
42518
|
+
AND NOT (coalesce(lq.status,'') = 'gearchiveerd'
|
|
42519
|
+
AND coalesce(lq.reason_code,'') IN ('belading_onwaarschijnlijk','belading_onvolledig','belading_onbekend','artikel_kiezen','ladingdrager_onbekend'))
|
|
42520
|
+
AND NOT EXISTS (SELECT 1 FROM logistics_active.order_carts c WHERE c.order_id = o.id)
|
|
42521
|
+
AND NOT EXISTS (SELECT 1 FROM public.order_items oi
|
|
42522
|
+
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
42523
|
+
JOIN logistics_active.order_carts c ON c.id = ci.cart_id
|
|
42524
|
+
WHERE oi.order_id = o.id);
|
|
42525
|
+
$function$;
|
|
42526
|
+
|
|
42527
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_plan_overview(p_days integer DEFAULT 2)
|
|
42528
|
+
RETURNS TABLE(order_ref text, delivery_date date, plan_ready boolean, cart_total integer, released boolean, reason text)
|
|
42529
|
+
LANGUAGE plpgsql
|
|
42530
|
+
STABLE SECURITY DEFINER
|
|
42531
|
+
SET search_path TO 'public'
|
|
42532
|
+
AS $function$
|
|
42533
|
+
DECLARE
|
|
42534
|
+
v_days integer := GREATEST(COALESCE(p_days, 2), 1);
|
|
42535
|
+
r record;
|
|
42536
|
+
v_status jsonb;
|
|
42537
|
+
BEGIN
|
|
42538
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_plan_overview');
|
|
42539
|
+
FOR r IN
|
|
42540
|
+
SELECT o.order_number, public.logistics_order_date(o.delivery_date::text) AS ddate
|
|
42541
|
+
FROM public.orders o
|
|
42542
|
+
WHERE o.deleted_at IS NULL
|
|
42543
|
+
AND NOT public.logistics_order_is_backfill(o.id)
|
|
42544
|
+
AND public.logistics_order_date(o.delivery_date::text) >= (now() AT TIME ZONE coalesce(public.logistics_tz(), 'Europe/Amsterdam'))::date
|
|
42545
|
+
AND public.logistics_order_date(o.delivery_date::text) < (now() AT TIME ZONE coalesce(public.logistics_tz(), 'Europe/Amsterdam'))::date + v_days
|
|
42546
|
+
ORDER BY 2, 1
|
|
42547
|
+
LOOP
|
|
42548
|
+
v_status := public.logistics_cart_plan_status(r.order_number);
|
|
42549
|
+
order_ref := r.order_number;
|
|
42550
|
+
delivery_date := r.ddate;
|
|
42551
|
+
plan_ready := COALESCE((v_status->>'ready')::boolean, false);
|
|
42552
|
+
cart_total := COALESCE((v_status->>'cartTotal')::integer, 0);
|
|
42553
|
+
released := COALESCE((v_status->>'released')::boolean, false);
|
|
42554
|
+
reason := v_status->>'reason';
|
|
42555
|
+
RETURN NEXT;
|
|
42556
|
+
END LOOP;
|
|
42557
|
+
END;
|
|
42558
|
+
$function$;
|
|
42559
|
+
|
|
42560
|
+
CREATE OR REPLACE FUNCTION public.logistics_schema_versie()
|
|
42561
|
+
RETURNS text LANGUAGE sql IMMUTABLE SET search_path TO 'public'
|
|
42562
|
+
AS $function$ SELECT '2026-11-10'::text $function$;
|
|
42563
|
+
-- ==== migratie 20261110090236
|
|
42564
|
+
|
|
42565
|
+
CREATE TABLE IF NOT EXISTS public.logistics_merge_meldingen (
|
|
42566
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
42567
|
+
soort text NOT NULL,
|
|
42568
|
+
order_id uuid,
|
|
42569
|
+
group_key text,
|
|
42570
|
+
aantal integer,
|
|
42571
|
+
fout text,
|
|
42572
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
42573
|
+
);
|
|
42574
|
+
CREATE INDEX IF NOT EXISTS logistics_merge_meldingen_created_idx ON public.logistics_merge_meldingen (created_at DESC);
|
|
42575
|
+
GRANT ALL ON public.logistics_merge_meldingen TO service_role;
|
|
42576
|
+
ALTER TABLE public.logistics_merge_meldingen ENABLE ROW LEVEL SECURITY;
|
|
42577
|
+
|
|
42578
|
+
CREATE TABLE IF NOT EXISTS public.logistics_merge_herstel_log (
|
|
42579
|
+
merged_order_id uuid PRIMARY KEY,
|
|
42580
|
+
kept_order_id uuid,
|
|
42581
|
+
categorie text NOT NULL,
|
|
42582
|
+
regels_terug integer NOT NULL DEFAULT 0,
|
|
42583
|
+
hersteld_at timestamptz NOT NULL DEFAULT now(),
|
|
42584
|
+
details jsonb
|
|
42585
|
+
);
|
|
42586
|
+
GRANT ALL ON public.logistics_merge_herstel_log TO service_role;
|
|
42587
|
+
ALTER TABLE public.logistics_merge_herstel_log ENABLE ROW LEVEL SECURITY;
|
|
42588
|
+
|
|
42589
|
+
CREATE OR REPLACE FUNCTION public._logistics_merge_melding(p_soort text, p_order_id uuid, p_key text, p_aantal integer, p_fout text)
|
|
42590
|
+
RETURNS void LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42591
|
+
BEGIN
|
|
42592
|
+
INSERT INTO public.logistics_merge_meldingen(soort, order_id, group_key, aantal, fout)
|
|
42593
|
+
VALUES (p_soort, p_order_id, p_key, p_aantal, left(p_fout, 2000));
|
|
42594
|
+
DELETE FROM public.logistics_merge_meldingen WHERE created_at < now() - interval '90 days';
|
|
42595
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42596
|
+
RAISE WARNING 'logistiek-engine: samenvoegmelding vastleggen mislukt (%): %', p_soort, SQLERRM;
|
|
42597
|
+
END $$;
|
|
42598
|
+
REVOKE ALL ON FUNCTION public._logistics_merge_melding(text, uuid, text, integer, text) FROM PUBLIC, anon, authenticated;
|
|
42599
|
+
GRANT EXECUTE ON FUNCTION public._logistics_merge_melding(text, uuid, text, integer, text) TO service_role;
|
|
42600
|
+
|
|
42601
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_merge_key_v2(p_order_id uuid)
|
|
42602
|
+
RETURNS text LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42603
|
+
DECLARE o record; v_dag date; v_loc text; v_pick text; v_ts timestamptz;
|
|
42604
|
+
BEGIN
|
|
42605
|
+
SELECT id, customer_id, delivery_date, custom_fields INTO o FROM public.orders WHERE id = p_order_id;
|
|
42606
|
+
IF NOT FOUND OR o.customer_id IS NULL OR o.delivery_date IS NULL THEN RETURN NULL; END IF;
|
|
42607
|
+
BEGIN
|
|
42608
|
+
v_dag := public.logistics_order_date(o.delivery_date::text);
|
|
42609
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42610
|
+
v_dag := NULL;
|
|
42611
|
+
END;
|
|
42612
|
+
IF v_dag IS NULL THEN RETURN NULL; END IF;
|
|
42613
|
+
IF jsonb_typeof(o.custom_fields) IS DISTINCT FROM 'object' THEN RETURN NULL; END IF;
|
|
42614
|
+
v_loc := nullif(btrim(coalesce(o.custom_fields->>'delivery_location_gln', o.custom_fields->>'delivery_location_id',
|
|
42615
|
+
o.custom_fields->>'delivery_location', '')), '');
|
|
42616
|
+
v_pick := nullif(btrim(coalesce(o.custom_fields->>'pickup_moment', o.custom_fields->>'pickup_datetime', '')), '');
|
|
42617
|
+
IF v_loc IS NULL OR v_pick IS NULL THEN RETURN NULL; END IF;
|
|
42618
|
+
BEGIN
|
|
42619
|
+
v_ts := public.logistics_pickup_ts(v_pick, v_dag);
|
|
42620
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42621
|
+
v_ts := NULL;
|
|
42622
|
+
END;
|
|
42623
|
+
RETURN concat_ws('|', 'v2', o.customer_id::text, v_dag::text, lower(v_loc), coalesce(v_ts::text, lower(v_pick)));
|
|
42624
|
+
END $$;
|
|
42625
|
+
REVOKE ALL ON FUNCTION public.logistics_order_merge_key_v2(uuid) FROM PUBLIC, anon;
|
|
42626
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_merge_key_v2(uuid) TO authenticated, service_role;
|
|
42627
|
+
|
|
42628
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_mergeable(p_order_id uuid)
|
|
42629
|
+
RETURNS boolean LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42630
|
+
DECLARE v_ok boolean; v_dag date; v_dd text;
|
|
42631
|
+
BEGIN
|
|
42632
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_mergeable');
|
|
42633
|
+
SELECT o.delivery_date INTO v_dd FROM public.orders o WHERE o.id = p_order_id;
|
|
42634
|
+
IF NOT FOUND OR v_dd IS NULL THEN RETURN false; END IF;
|
|
42635
|
+
BEGIN
|
|
42636
|
+
v_dag := public.logistics_order_date(v_dd);
|
|
42637
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42638
|
+
RETURN false;
|
|
42639
|
+
END;
|
|
42640
|
+
IF v_dag IS NULL OR v_dag < (now() AT TIME ZONE 'Europe/Amsterdam')::date THEN RETURN false; END IF;
|
|
42641
|
+
SELECT (o.deleted_at IS NULL
|
|
42642
|
+
AND o.cancelled_at IS NULL
|
|
42643
|
+
AND o.plan_locked_at IS NULL
|
|
42644
|
+
AND COALESCE(o.is_reservation, false) = false
|
|
42645
|
+
AND o.order_source = 'floriday'
|
|
42646
|
+
AND lower(btrim(COALESCE(o.status, ''))) NOT IN
|
|
42647
|
+
('verzonden', 'afgehandeld', 'gereed voor facturatie', 'gepickt', 'geannuleerd',
|
|
42648
|
+
'cancelled', 'canceled', 'annulering', 'gereserveerd')
|
|
42649
|
+
AND NOT public.logistics_order_is_backfill(o.id)
|
|
42650
|
+
AND NOT EXISTS (SELECT 1 FROM logistics_active.order_carts oc WHERE oc.order_id = o.id)
|
|
42651
|
+
AND NOT EXISTS (SELECT 1 FROM public.pick_queue q WHERE q.order_number = o.order_number)
|
|
42652
|
+
AND NOT public.logistics_order_print_actief(o.order_number))
|
|
42653
|
+
INTO v_ok
|
|
42654
|
+
FROM public.orders o
|
|
42655
|
+
WHERE o.id = p_order_id;
|
|
42656
|
+
RETURN COALESCE(v_ok, false);
|
|
42657
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42658
|
+
PERFORM public._logistics_merge_melding('fout', p_order_id, NULL, NULL, 'controle samenvoegen: ' || SQLERRM);
|
|
42659
|
+
RETURN false;
|
|
42660
|
+
END $$;
|
|
42661
|
+
|
|
42662
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_floriday_lines(p_order_id uuid)
|
|
42663
|
+
RETURNS uuid LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42664
|
+
DECLARE
|
|
42665
|
+
v_key text; v_keep uuid; v_keepnr text; v_cust uuid; r record;
|
|
42666
|
+
v_moved int; v_logged int; v_total int := 0; v_count int := 0; v_groep int;
|
|
42667
|
+
v_lines text[] := ARRAY[]::text[];
|
|
42668
|
+
BEGIN
|
|
42669
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_merge_floriday_lines');
|
|
42670
|
+
IF p_order_id IS NULL THEN RETURN p_order_id; END IF;
|
|
42671
|
+
IF COALESCE(current_setting('logistics.merge_uit', true), '') = '1' THEN RETURN p_order_id; END IF;
|
|
42672
|
+
IF NOT public.logistics_merge_lines_enabled() THEN RETURN p_order_id; END IF;
|
|
42673
|
+
IF NOT public.logistics_order_mergeable(p_order_id) THEN RETURN p_order_id; END IF;
|
|
42674
|
+
IF NOT EXISTS (SELECT 1 FROM logistics_active.order_items i WHERE i.order_id = p_order_id) THEN RETURN p_order_id; END IF;
|
|
42675
|
+
|
|
42676
|
+
v_key := public.logistics_order_merge_key_v2(p_order_id);
|
|
42677
|
+
IF v_key IS NULL THEN RETURN p_order_id; END IF;
|
|
42678
|
+
IF NOT pg_try_advisory_xact_lock(hashtext('logistics_merge:' || v_key)) THEN RETURN p_order_id; END IF;
|
|
42679
|
+
SELECT customer_id INTO v_cust FROM public.orders WHERE id = p_order_id;
|
|
42680
|
+
|
|
42681
|
+
CREATE TEMP TABLE IF NOT EXISTS _logistics_merge_groep (id uuid, order_number text, sales text, created_at timestamptz) ON COMMIT DROP;
|
|
42682
|
+
TRUNCATE _logistics_merge_groep;
|
|
42683
|
+
INSERT INTO _logistics_merge_groep
|
|
42684
|
+
SELECT o.id, o.order_number, o.floriday_sales_order_id, o.created_at
|
|
42685
|
+
FROM public.orders o
|
|
42686
|
+
WHERE o.customer_id = v_cust AND o.deleted_at IS NULL AND o.order_source = 'floriday'
|
|
42687
|
+
AND EXISTS (SELECT 1 FROM logistics_active.order_items i WHERE i.order_id = o.id)
|
|
42688
|
+
AND public.logistics_order_merge_key_v2(o.id) = v_key
|
|
42689
|
+
AND public.logistics_order_mergeable(o.id);
|
|
42690
|
+
SELECT count(*) INTO v_groep FROM _logistics_merge_groep;
|
|
42691
|
+
IF v_groep < 2 THEN RETURN p_order_id; END IF;
|
|
42692
|
+
IF v_groep > 20 THEN
|
|
42693
|
+
IF NOT EXISTS (SELECT 1 FROM public.logistics_merge_meldingen m
|
|
42694
|
+
WHERE m.soort = 'groep_te_groot' AND m.group_key = v_key AND m.created_at > now() - interval '1 day') THEN
|
|
42695
|
+
PERFORM public._logistics_merge_melding('groep_te_groot', p_order_id, v_key, v_groep,
|
|
42696
|
+
v_groep || ' orders met dezelfde klant, leverdag, afleverlocatie en ophaalmoment; niet samengevoegd.');
|
|
42697
|
+
END IF;
|
|
42698
|
+
RETURN p_order_id;
|
|
42699
|
+
END IF;
|
|
42700
|
+
|
|
42701
|
+
SELECT g.id, g.order_number INTO v_keep, v_keepnr FROM _logistics_merge_groep g
|
|
42702
|
+
ORDER BY g.order_number ASC NULLS LAST, g.created_at ASC LIMIT 1;
|
|
42703
|
+
|
|
42704
|
+
FOR r IN SELECT * FROM _logistics_merge_groep g WHERE g.id <> v_keep ORDER BY g.order_number ASC NULLS LAST LOOP
|
|
42705
|
+
BEGIN
|
|
42706
|
+
INSERT INTO public.logistics_order_merge_lines(
|
|
42707
|
+
group_key, from_order_id, from_order_number, to_order_id, to_order_number,
|
|
42708
|
+
order_item_id, product_id, product_name, quantity, source_line_key,
|
|
42709
|
+
sales_order_id, ordered_at, reason)
|
|
42710
|
+
SELECT v_key, r.id, r.order_number, v_keep, v_keepnr,
|
|
42711
|
+
i.id, i.product_id, i.product_name, i.quantity, i.source_line_key,
|
|
42712
|
+
r.sales, r.created_at, 'Zelfde klant, leverdag, afleverlocatie en ophaalmoment'
|
|
42713
|
+
FROM logistics_active.order_items i WHERE i.order_id = r.id;
|
|
42714
|
+
GET DIAGNOSTICS v_logged = ROW_COUNT;
|
|
42715
|
+
UPDATE public.order_items SET order_id = v_keep WHERE order_id = r.id AND quarantined_at IS NULL;
|
|
42716
|
+
GET DIAGNOSTICS v_moved = ROW_COUNT;
|
|
42717
|
+
IF v_moved <> v_logged THEN RAISE EXCEPTION 'aantal verplaatste regels (%) wijkt af van het logboek (%)', v_moved, v_logged; END IF;
|
|
42718
|
+
IF v_moved = 0 THEN RAISE EXCEPTION 'geen regels verplaatst; order blijft staan'; END IF;
|
|
42719
|
+
INSERT INTO public.logistics_order_merges(group_key, kept_order_id, kept_order_number,
|
|
42720
|
+
merged_order_id, merged_order_number, sales_order_id, items_moved)
|
|
42721
|
+
VALUES (v_key, v_keep, v_keepnr, r.id, r.order_number, r.sales, v_moved)
|
|
42722
|
+
ON CONFLICT (merged_order_id) DO NOTHING;
|
|
42723
|
+
UPDATE public.orders SET deleted_at = now(),
|
|
42724
|
+
notes = COALESCE(NULLIF(notes, ''), '')
|
|
42725
|
+
|| CASE WHEN COALESCE(notes, '') = '' THEN '' ELSE E'\n' END
|
|
42726
|
+
|| 'Samengevoegd met ' || COALESCE(v_keepnr, '') || '.',
|
|
42727
|
+
updated_at = now()
|
|
42728
|
+
WHERE id = r.id;
|
|
42729
|
+
v_total := v_total + v_moved; v_count := v_count + 1;
|
|
42730
|
+
v_lines := v_lines || (COALESCE(r.order_number, '') || ': ' || v_moved::text || ' regel(s)');
|
|
42731
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42732
|
+
PERFORM public._logistics_merge_melding('fout', r.id, v_key, NULL,
|
|
42733
|
+
'samenvoegen ' || COALESCE(r.order_number, '?') || ' met ' || COALESCE(v_keepnr, '?') || ': ' || SQLERRM);
|
|
42734
|
+
END;
|
|
42735
|
+
END LOOP;
|
|
42736
|
+
|
|
42737
|
+
IF v_count > 0 THEN
|
|
42738
|
+
UPDATE public.orders o SET total = to_char(COALESCE((
|
|
42739
|
+
SELECT SUM(COALESCE(i.quantity, 0) * COALESCE(i.unit_price, 0))
|
|
42740
|
+
FROM logistics_active.order_items i WHERE i.order_id = o.id), 0), 'FM9999999990.00'),
|
|
42741
|
+
updated_at = now()
|
|
42742
|
+
WHERE o.id = v_keep;
|
|
42743
|
+
PERFORM public.logistics_trace_order_step(
|
|
42744
|
+
v_keep, 'stap:bestelregels_samenvoegen', 'bestelregels samenvoegen', 'geslaagd',
|
|
42745
|
+
'samengevoegd tot ' || COALESCE(v_keepnr, 'één bestelling'),
|
|
42746
|
+
v_count::text || ' order(s), ' || v_total::text || ' regel(s) verplaatst: ' || array_to_string(v_lines, '; '),
|
|
42747
|
+
'Orders combineren');
|
|
42748
|
+
END IF;
|
|
42749
|
+
IF EXISTS (SELECT 1 FROM public.orders WHERE id = p_order_id AND deleted_at IS NOT NULL) THEN RETURN v_keep; END IF;
|
|
42750
|
+
RETURN p_order_id;
|
|
42751
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42752
|
+
PERFORM public._logistics_merge_melding('fout', p_order_id, v_key, NULL, 'samenvoegen: ' || SQLERRM);
|
|
42753
|
+
RETURN p_order_id;
|
|
42754
|
+
END $$;
|
|
42755
|
+
|
|
42756
|
+
CREATE OR REPLACE FUNCTION public.logistics_plan_enqueue(p_order_id uuid, p_reason text DEFAULT 'change'::text)
|
|
42757
|
+
RETURNS void
|
|
42758
|
+
LANGUAGE plpgsql
|
|
42759
|
+
SECURITY DEFINER
|
|
42760
|
+
SET search_path TO 'public'
|
|
42761
|
+
AS $function$
|
|
42762
|
+
DECLARE
|
|
42763
|
+
v_ok boolean;
|
|
42764
|
+
v_id uuid;
|
|
42765
|
+
v_status text;
|
|
42766
|
+
v_decision text;
|
|
42767
|
+
v_target uuid := p_order_id;
|
|
42768
|
+
v_wacht jsonb;
|
|
42769
|
+
BEGIN
|
|
42770
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_plan_enqueue');
|
|
42771
|
+
IF COALESCE(current_setting('logistics.plan_uit', true), '') = '1' THEN RETURN; END IF;
|
|
42772
|
+
IF COALESCE(current_setting('logistics.merging', true), '') <> '1' THEN
|
|
42773
|
+
BEGIN
|
|
42774
|
+
PERFORM set_config('logistics.merging', '1', true);
|
|
42775
|
+
v_target := COALESCE(public.logistics_merge_floriday_lines(p_order_id), p_order_id);
|
|
42776
|
+
PERFORM set_config('logistics.merging', '0', true);
|
|
42777
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42778
|
+
PERFORM public._logistics_merge_melding('fout', p_order_id, NULL, NULL, 'samenvoegen bij aanmelden: ' || SQLERRM);
|
|
42779
|
+
v_target := p_order_id;
|
|
42780
|
+
END;
|
|
42781
|
+
END IF;
|
|
42782
|
+
|
|
42783
|
+
IF public.logistics_order_is_backfill(v_target) THEN
|
|
42784
|
+
BEGIN
|
|
42785
|
+
PERFORM public.logistics_trace_order_step(
|
|
42786
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42787
|
+
'niet aangemeld', 'Ingehaalde order: krijgt geen kar, reservering of documenten', NULL);
|
|
42788
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42789
|
+
RAISE WARNING 'logistiek-engine: trace ingehaalde order mislukt: %', SQLERRM;
|
|
42790
|
+
END;
|
|
42791
|
+
RETURN;
|
|
42792
|
+
END IF;
|
|
42793
|
+
v_wacht := public.logistics_plan_wachttijd(v_target, p_reason);
|
|
42794
|
+
IF COALESCE((v_wacht->>'wacht')::boolean, false) THEN
|
|
42795
|
+
PERFORM public.logistics_plan_wachttijd_melden(v_target, p_reason, v_wacht);
|
|
42796
|
+
RETURN;
|
|
42797
|
+
END IF;
|
|
42798
|
+
|
|
42799
|
+
SELECT (o.deleted_at IS NULL AND COALESCE(o.is_reservation, false) = false AND o.plan_locked_at IS NULL)
|
|
42800
|
+
INTO v_ok FROM public.orders o WHERE o.id = v_target;
|
|
42801
|
+
IF COALESCE(v_ok, false) AND public.logistics_order_geannuleerd(v_target) THEN
|
|
42802
|
+
PERFORM public.logistics_trace_order_step(
|
|
42803
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42804
|
+
'niet aangemeld', 'Order is geannuleerd', NULL);
|
|
42805
|
+
RETURN;
|
|
42806
|
+
END IF;
|
|
42807
|
+
IF NOT COALESCE(v_ok, false) THEN
|
|
42808
|
+
PERFORM public.logistics_trace_order_step(
|
|
42809
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'overgeslagen',
|
|
42810
|
+
'niet aangemeld', 'Order is verwijderd, samengevoegd, een reservering of de indeling staat vast', NULL);
|
|
42811
|
+
RETURN;
|
|
42812
|
+
END IF;
|
|
42813
|
+
|
|
42814
|
+
SELECT q.id, q.status INTO v_id, v_status
|
|
42815
|
+
FROM public.logistics_plan_queue q
|
|
42816
|
+
WHERE q.order_id = v_target
|
|
42817
|
+
AND q.status IN ('pending', 'running', 'geblokkeerd')
|
|
42818
|
+
ORDER BY q.updated_at DESC
|
|
42819
|
+
LIMIT 1
|
|
42820
|
+
FOR UPDATE;
|
|
42821
|
+
|
|
42822
|
+
IF v_id IS NULL THEN
|
|
42823
|
+
BEGIN
|
|
42824
|
+
INSERT INTO public.logistics_plan_queue(order_id, reason) VALUES (v_target, p_reason);
|
|
42825
|
+
v_decision := 'nieuw aangemeld voor indeling';
|
|
42826
|
+
EXCEPTION WHEN unique_violation THEN
|
|
42827
|
+
v_decision := 'stond al in de wachtrij';
|
|
42828
|
+
END;
|
|
42829
|
+
ELSIF v_status = 'geblokkeerd' THEN
|
|
42830
|
+
UPDATE public.logistics_plan_queue
|
|
42831
|
+
SET status = 'pending', attempts = 0, reason = p_reason, reason_code = NULL,
|
|
42832
|
+
error = NULL, claimed_at = NULL, next_attempt_at = now(), updated_at = now()
|
|
42833
|
+
WHERE id = v_id;
|
|
42834
|
+
v_decision := 'blokkade opgeheven, opnieuw aangemeld';
|
|
42835
|
+
ELSE
|
|
42836
|
+
UPDATE public.logistics_plan_queue
|
|
42837
|
+
SET reason = p_reason, next_attempt_at = LEAST(next_attempt_at, now()), updated_at = now()
|
|
42838
|
+
WHERE id = v_id;
|
|
42839
|
+
v_decision := 'opnieuw aangemeld';
|
|
42840
|
+
END IF;
|
|
42841
|
+
|
|
42842
|
+
PERFORM public.logistics_trace_order_step(
|
|
42843
|
+
v_target, 'stap:orders_combineren', 'order aanmelden voor indeling', 'geslaagd',
|
|
42844
|
+
v_decision, p_reason, 'Karrenindeling');
|
|
42845
|
+
|
|
42846
|
+
PERFORM public.logistics_plan_kick();
|
|
42847
|
+
END;
|
|
42848
|
+
$function$;
|
|
42849
|
+
|
|
42850
|
+
CREATE OR REPLACE FUNCTION public._logistics_merge_herstel_kandidaten()
|
|
42851
|
+
RETURNS TABLE(merged_order_id uuid, merged_order_number text, kept_order_id uuid, kept_order_number text,
|
|
42852
|
+
categorie text, regels integer, status text, leverdag date, reden text)
|
|
42853
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42854
|
+
DECLARE r record; v_dag date; v_onzeker text; v_vandaag date := (now() AT TIME ZONE 'Europe/Amsterdam')::date;
|
|
42855
|
+
BEGIN
|
|
42856
|
+
FOR r IN
|
|
42857
|
+
SELECT m.merged_order_id, m.merged_order_number, m.kept_order_id, m.kept_order_number, m.items_moved,
|
|
42858
|
+
o.status, o.delivery_date
|
|
42859
|
+
FROM public.logistics_order_merges m
|
|
42860
|
+
JOIN public.orders o ON o.id = m.merged_order_id
|
|
42861
|
+
WHERE o.deleted_at IS NOT NULL
|
|
42862
|
+
AND NOT EXISTS (SELECT 1 FROM public.logistics_merge_herstel_log h WHERE h.merged_order_id = m.merged_order_id)
|
|
42863
|
+
LOOP
|
|
42864
|
+
v_onzeker := NULL;
|
|
42865
|
+
BEGIN
|
|
42866
|
+
v_dag := public.logistics_order_date(r.delivery_date::text);
|
|
42867
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42868
|
+
v_dag := NULL;
|
|
42869
|
+
END;
|
|
42870
|
+
IF v_dag IS NULL THEN v_onzeker := 'leverdag onleesbaar'; END IF;
|
|
42871
|
+
IF v_onzeker IS NULL AND (SELECT count(*) FROM public.logistics_order_merge_lines l WHERE l.from_order_id = r.merged_order_id)
|
|
42872
|
+
<> COALESCE(r.items_moved, 0) THEN
|
|
42873
|
+
v_onzeker := 'logboek en aantal verplaatste regels verschillen';
|
|
42874
|
+
END IF;
|
|
42875
|
+
IF v_onzeker IS NULL AND EXISTS (
|
|
42876
|
+
SELECT 1 FROM public.logistics_order_merge_lines l
|
|
42877
|
+
LEFT JOIN public.order_items i ON i.id = l.order_item_id
|
|
42878
|
+
WHERE l.from_order_id = r.merged_order_id
|
|
42879
|
+
AND (i.id IS NULL OR i.order_id IS DISTINCT FROM r.kept_order_id)) THEN
|
|
42880
|
+
v_onzeker := 'regel staat niet meer bij de verzamelorder';
|
|
42881
|
+
END IF;
|
|
42882
|
+
IF v_onzeker IS NULL AND EXISTS (
|
|
42883
|
+
SELECT 1 FROM public.logistics_order_merge_lines l
|
|
42884
|
+
WHERE l.from_order_id = r.merged_order_id
|
|
42885
|
+
AND EXISTS (SELECT 1 FROM public.logistics_order_merge_lines l2
|
|
42886
|
+
WHERE l2.order_item_id = l.order_item_id AND l2.from_order_id <> l.from_order_id)) THEN
|
|
42887
|
+
v_onzeker := 'regel komt bij meer dan één order vandaan';
|
|
42888
|
+
END IF;
|
|
42889
|
+
merged_order_id := r.merged_order_id; merged_order_number := r.merged_order_number;
|
|
42890
|
+
kept_order_id := r.kept_order_id; kept_order_number := r.kept_order_number;
|
|
42891
|
+
regels := COALESCE(r.items_moved, 0); status := r.status; leverdag := v_dag; reden := v_onzeker;
|
|
42892
|
+
categorie := CASE
|
|
42893
|
+
WHEN v_onzeker IS NOT NULL THEN 'onzeker'
|
|
42894
|
+
WHEN v_dag < v_vandaag THEN 'verleden'
|
|
42895
|
+
WHEN lower(btrim(COALESCE(r.status, ''))) = 'nog te picken' THEN 'urgent'
|
|
42896
|
+
ELSE 'toekomst_overig' END;
|
|
42897
|
+
RETURN NEXT;
|
|
42898
|
+
END LOOP;
|
|
42899
|
+
END $$;
|
|
42900
|
+
REVOKE ALL ON FUNCTION public._logistics_merge_herstel_kandidaten() FROM PUBLIC, anon, authenticated;
|
|
42901
|
+
GRANT EXECUTE ON FUNCTION public._logistics_merge_herstel_kandidaten() TO service_role;
|
|
42902
|
+
|
|
42903
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_herstel_voorbeeld()
|
|
42904
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42905
|
+
DECLARE v jsonb;
|
|
42906
|
+
BEGIN
|
|
42907
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_merge_herstel_voorbeeld');
|
|
42908
|
+
SELECT jsonb_object_agg(c.categorie, jsonb_build_object('orders', c.n, 'regelsTerug', c.regels,
|
|
42909
|
+
'voorbeelden', to_jsonb(c.vb[1:10]))) INTO v
|
|
42910
|
+
FROM (SELECT k.categorie, count(*) n, COALESCE(sum(k.regels), 0) regels,
|
|
42911
|
+
array_agg(jsonb_build_object('order', k.merged_order_number, 'verzamelorder', k.kept_order_number,
|
|
42912
|
+
'status', k.status, 'leverdag', k.leverdag, 'regels', k.regels, 'reden', k.reden)
|
|
42913
|
+
ORDER BY k.leverdag DESC NULLS LAST, k.merged_order_number) vb
|
|
42914
|
+
FROM public._logistics_merge_herstel_kandidaten() k GROUP BY k.categorie) c;
|
|
42915
|
+
RETURN jsonb_build_object(
|
|
42916
|
+
'categorieen', COALESCE(v, '{}'::jsonb),
|
|
42917
|
+
'alHersteld', (SELECT COALESCE(jsonb_object_agg(categorie, n), '{}'::jsonb)
|
|
42918
|
+
FROM (SELECT categorie, count(*) n FROM public.logistics_merge_herstel_log GROUP BY 1) h),
|
|
42919
|
+
'volgorde', jsonb_build_array('urgent', 'toekomst_overig', 'verleden'),
|
|
42920
|
+
'toelichting', 'onzeker wordt nooit automatisch hersteld');
|
|
42921
|
+
END $$;
|
|
42922
|
+
REVOKE ALL ON FUNCTION public.logistics_merge_herstel_voorbeeld() FROM PUBLIC, anon, authenticated;
|
|
42923
|
+
GRANT EXECUTE ON FUNCTION public.logistics_merge_herstel_voorbeeld() TO service_role;
|
|
42924
|
+
|
|
42925
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_herstel_uitvoeren(p_categorie text, p_max integer DEFAULT 200)
|
|
42926
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
42927
|
+
DECLARE
|
|
42928
|
+
k record; v_terug int; v_ok int := 0; v_regels int := 0; v_fouten jsonb := '[]'::jsonb;
|
|
42929
|
+
v_kept uuid[] := ARRAY[]::uuid[]; v_opgeruimd int := 0; v_rest int;
|
|
42930
|
+
v_notes_re text := E'\\n?Samengevoegd met [^\\n]*\\.';
|
|
42931
|
+
BEGIN
|
|
42932
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_merge_herstel_uitvoeren');
|
|
42933
|
+
IF p_categorie IS NULL OR p_categorie NOT IN ('urgent', 'toekomst_overig', 'verleden') THEN
|
|
42934
|
+
RAISE EXCEPTION 'Onbekende categorie %; kies urgent, toekomst_overig of verleden.', p_categorie;
|
|
42935
|
+
END IF;
|
|
42936
|
+
PERFORM set_config('logistics.merge_uit', '1', true);
|
|
42937
|
+
PERFORM set_config('logistics.merging', '1', true);
|
|
42938
|
+
|
|
42939
|
+
FOR k IN SELECT * FROM public._logistics_merge_herstel_kandidaten() c
|
|
42940
|
+
WHERE c.categorie = p_categorie
|
|
42941
|
+
ORDER BY c.leverdag, c.merged_order_number
|
|
42942
|
+
LIMIT greatest(least(COALESCE(p_max, 200), 2000), 1)
|
|
42943
|
+
LOOP
|
|
42944
|
+
BEGIN
|
|
42945
|
+
PERFORM set_config('logistics.plan_uit', CASE WHEN p_categorie = 'urgent' THEN '0' ELSE '1' END, true);
|
|
42946
|
+
UPDATE public.orders o
|
|
42947
|
+
SET deleted_at = NULL,
|
|
42948
|
+
notes = NULLIF(btrim(regexp_replace(COALESCE(o.notes, ''), v_notes_re, '', 'g')), ''),
|
|
42949
|
+
custom_fields = CASE WHEN p_categorie = 'verleden'
|
|
42950
|
+
THEN (CASE WHEN jsonb_typeof(o.custom_fields) = 'object' THEN o.custom_fields ELSE '{}'::jsonb END)
|
|
42951
|
+
|| jsonb_build_object('backfill', jsonb_build_object('categorie', 'herstel_samenvoegen', 'at', now()))
|
|
42952
|
+
ELSE o.custom_fields END,
|
|
42953
|
+
updated_at = now()
|
|
42954
|
+
WHERE o.id = k.merged_order_id AND o.deleted_at IS NOT NULL;
|
|
42955
|
+
IF NOT FOUND THEN RAISE EXCEPTION 'order is al actief'; END IF;
|
|
42956
|
+
|
|
42957
|
+
UPDATE public.order_items i SET order_id = k.merged_order_id
|
|
42958
|
+
FROM public.logistics_order_merge_lines l
|
|
42959
|
+
WHERE l.from_order_id = k.merged_order_id AND l.order_item_id = i.id AND i.order_id = k.kept_order_id;
|
|
42960
|
+
GET DIAGNOSTICS v_terug = ROW_COUNT;
|
|
42961
|
+
IF v_terug <> k.regels THEN
|
|
42962
|
+
RAISE EXCEPTION '% van % regels teruggezet; niets gewijzigd', v_terug, k.regels;
|
|
42963
|
+
END IF;
|
|
42964
|
+
|
|
42965
|
+
UPDATE public.orders o SET total = to_char(COALESCE((
|
|
42966
|
+
SELECT SUM(COALESCE(i.quantity, 0) * COALESCE(i.unit_price, 0))
|
|
42967
|
+
FROM logistics_active.order_items i WHERE i.order_id = o.id), 0), 'FM9999999990.00'),
|
|
42968
|
+
updated_at = now()
|
|
42969
|
+
WHERE o.id IN (k.merged_order_id, k.kept_order_id);
|
|
42970
|
+
|
|
42971
|
+
INSERT INTO public.logistics_merge_herstel_log(merged_order_id, kept_order_id, categorie, regels_terug, details)
|
|
42972
|
+
VALUES (k.merged_order_id, k.kept_order_id, p_categorie, v_terug,
|
|
42973
|
+
jsonb_build_object('order', k.merged_order_number, 'verzamelorder', k.kept_order_number, 'status', k.status));
|
|
42974
|
+
|
|
42975
|
+
IF p_categorie = 'urgent' THEN
|
|
42976
|
+
PERFORM public.logistics_plan_enqueue(k.merged_order_id, 'herstel_samenvoegen');
|
|
42977
|
+
END IF;
|
|
42978
|
+
PERFORM set_config('logistics.plan_uit', '0', true);
|
|
42979
|
+
v_ok := v_ok + 1; v_regels := v_regels + v_terug;
|
|
42980
|
+
IF NOT (k.kept_order_id = ANY (v_kept)) THEN v_kept := v_kept || k.kept_order_id; END IF;
|
|
42981
|
+
EXCEPTION WHEN OTHERS THEN
|
|
42982
|
+
PERFORM set_config('logistics.plan_uit', '0', true);
|
|
42983
|
+
v_fouten := v_fouten || jsonb_build_object('order', k.merged_order_number, 'fout', SQLERRM);
|
|
42984
|
+
PERFORM public._logistics_merge_melding('herstel_fout', k.merged_order_id, NULL, NULL,
|
|
42985
|
+
'herstel ' || COALESCE(k.merged_order_number, '?') || ': ' || SQLERRM);
|
|
42986
|
+
END;
|
|
42987
|
+
END LOOP;
|
|
42988
|
+
|
|
42989
|
+
WITH weg AS (
|
|
42990
|
+
DELETE FROM public.logistics_plan_queue q
|
|
42991
|
+
USING public.orders o
|
|
42992
|
+
WHERE q.order_id = o.id AND q.order_id = ANY (v_kept)
|
|
42993
|
+
AND q.status IN ('pending', 'geblokkeerd')
|
|
42994
|
+
AND (lower(btrim(COALESCE(o.status, ''))) <> 'nog te picken'
|
|
42995
|
+
OR public.logistics_order_date(o.delivery_date::text) < (now() AT TIME ZONE 'Europe/Amsterdam')::date)
|
|
42996
|
+
RETURNING q.id)
|
|
42997
|
+
SELECT count(*) INTO v_opgeruimd FROM weg;
|
|
42998
|
+
|
|
42999
|
+
PERFORM set_config('logistics.merge_uit', '0', true);
|
|
43000
|
+
PERFORM set_config('logistics.merging', '0', true);
|
|
43001
|
+
SELECT count(*) INTO v_rest FROM public._logistics_merge_herstel_kandidaten() c WHERE c.categorie = p_categorie;
|
|
43002
|
+
RETURN jsonb_build_object('categorie', p_categorie, 'hersteld', v_ok, 'regelsTerug', v_regels,
|
|
43003
|
+
'wachtrijOpgeruimd', v_opgeruimd, 'nogTeDoen', v_rest, 'fouten', v_fouten);
|
|
43004
|
+
END $$;
|
|
43005
|
+
REVOKE ALL ON FUNCTION public.logistics_merge_herstel_uitvoeren(text, integer) FROM PUBLIC, anon, authenticated;
|
|
43006
|
+
GRANT EXECUTE ON FUNCTION public.logistics_merge_herstel_uitvoeren(text, integer) TO service_role;
|
|
43007
|
+
|
|
43008
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_status()
|
|
43009
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43010
|
+
BEGIN
|
|
43011
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_merge_status');
|
|
43012
|
+
RETURN jsonb_build_object(
|
|
43013
|
+
'samenvoegenAan', public.logistics_merge_lines_enabled(),
|
|
43014
|
+
'groepTeGroot', (SELECT COALESCE(sum(x.aantal), 0) FROM (
|
|
43015
|
+
SELECT DISTINCT ON (m.group_key) m.aantal FROM public.logistics_merge_meldingen m
|
|
43016
|
+
WHERE m.soort = 'groep_te_groot' AND m.created_at > now() - interval '7 days'
|
|
43017
|
+
ORDER BY m.group_key, m.created_at DESC) x),
|
|
43018
|
+
'nieuwVerwijderd', (SELECT count(*) FROM public.orders o
|
|
43019
|
+
WHERE o.deleted_at IS NOT NULL AND o.created_at > now() - interval '7 days'
|
|
43020
|
+
AND o.deleted_at - o.created_at < interval '2 minutes'
|
|
43021
|
+
AND NOT EXISTS (SELECT 1 FROM public.logistics_merge_herstel_log h WHERE h.merged_order_id = o.id)),
|
|
43022
|
+
'fouten', (SELECT count(*) FROM public.logistics_merge_meldingen m
|
|
43023
|
+
WHERE m.soort IN ('fout', 'herstel_fout') AND m.created_at > now() - interval '7 days'),
|
|
43024
|
+
'laatsteFout', (SELECT jsonb_build_object('op', m.created_at, 'melding', m.fout) FROM public.logistics_merge_meldingen m
|
|
43025
|
+
WHERE m.soort IN ('fout', 'herstel_fout') ORDER BY m.created_at DESC LIMIT 1),
|
|
43026
|
+
'hersteld', (SELECT COALESCE(jsonb_object_agg(categorie, n), '{}'::jsonb)
|
|
43027
|
+
FROM (SELECT categorie, count(*) n FROM public.logistics_merge_herstel_log GROUP BY 1) h));
|
|
43028
|
+
END $$;
|
|
43029
|
+
REVOKE ALL ON FUNCTION public.logistics_merge_status() FROM PUBLIC, anon;
|
|
43030
|
+
GRANT EXECUTE ON FUNCTION public.logistics_merge_status() TO authenticated, service_role;
|
|
43031
|
+
|
|
43032
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_coverage_check()
|
|
43033
|
+
RETURNS jsonb LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $function$
|
|
43034
|
+
SELECT public.logistics_acc_guard('server', 'logistics_cart_coverage_check');
|
|
43035
|
+
WITH o AS (
|
|
43036
|
+
SELECT id, order_number, order_source, status, buffer_id,
|
|
43037
|
+
(status IN ('Verzonden','Gereed voor facturatie')) afgehandeld
|
|
43038
|
+
FROM orders WHERE deleted_at IS NULL AND cancelled_at IS NULL AND buffer_id IS NOT NULL
|
|
43039
|
+
AND (status IN ('Verzonden','Gereed voor facturatie') OR NOT public.logistics_order_is_backfill(id))
|
|
43040
|
+
), r AS (
|
|
43041
|
+
SELECT o.*, oi.id item, oi.quantity q, COALESCE(NULLIF(oi.plants_per_crate,0),1) ppc,
|
|
43042
|
+
(SELECT count(*) FROM logistics_active.order_items d WHERE d.order_id=o.id AND d.product_id IS NOT DISTINCT FROM oi.product_id) > 1 dubbel,
|
|
43043
|
+
(SELECT sum(ci.crates) FROM logistics_active.order_cart_items ci JOIN logistics_active.order_carts c ON c.id=ci.cart_id
|
|
43044
|
+
WHERE ci.order_item_id=oi.id AND (c.order_id=o.id OR (c.order_id IS DISTINCT FROM o.id AND c.buffer_id=o.buffer_id))) c_goed,
|
|
43045
|
+
(SELECT sum(ci.crates*COALESCE(ci.plants_per_crate,1)) FROM logistics_active.order_cart_items ci JOIN logistics_active.order_carts c ON c.id=ci.cart_id
|
|
43046
|
+
WHERE ci.order_item_id=oi.id AND (c.order_id=o.id OR (c.order_id IS DISTINCT FROM o.id AND c.buffer_id=o.buffer_id))) p_goed,
|
|
43047
|
+
EXISTS (SELECT 1 FROM logistics_active.order_cart_items ci JOIN logistics_active.order_carts c ON c.id=ci.cart_id
|
|
43048
|
+
WHERE ci.order_item_id=oi.id AND c.order_id IS DISTINCT FROM o.id AND c.buffer_id IS DISTINCT FROM o.buffer_id) verkeerd,
|
|
43049
|
+
(SELECT q.reason_code FROM logistics_plan_queue q WHERE q.order_id=o.id AND q.status='geblokkeerd' ORDER BY q.enqueued_at DESC LIMIT 1) blok
|
|
43050
|
+
FROM o JOIN logistics_active.order_items oi ON oi.order_id=o.id
|
|
43051
|
+
), k AS (
|
|
43052
|
+
SELECT r.*, CASE
|
|
43053
|
+
WHEN verkeerd THEN 'verkeerde_karinhoud'
|
|
43054
|
+
WHEN blok IS NOT NULL AND c_goed IS NULL THEN 'geblokkeerd'
|
|
43055
|
+
WHEN c_goed IS NULL THEN 'geen_kar'
|
|
43056
|
+
WHEN q IN (c_goed, p_goed) THEN 'gelijk'
|
|
43057
|
+
WHEN abs(p_goed - q) < ppc THEN 'gelijk_afgerond'
|
|
43058
|
+
ELSE 'echt_verschil' END klasse
|
|
43059
|
+
FROM r
|
|
43060
|
+
), po AS (
|
|
43061
|
+
SELECT id, order_number, order_source, status, buffer_id, afgehandeld,
|
|
43062
|
+
(array_agg(klasse ORDER BY CASE klasse WHEN 'verkeerde_karinhoud' THEN 1 WHEN 'geblokkeerd' THEN 2 WHEN 'geen_kar' THEN 3
|
|
43063
|
+
WHEN 'echt_verschil' THEN 4 WHEN 'gelijk_afgerond' THEN 5 ELSE 6 END))[1] klasse,
|
|
43064
|
+
sum(q) q, sum(c_goed) c_goed, sum(p_goed) p_goed, max(blok) blok, bool_or(dubbel) dubbel, count(*) regels
|
|
43065
|
+
FROM k GROUP BY id, order_number, order_source, status, buffer_id, afgehandeld
|
|
43066
|
+
)
|
|
43067
|
+
SELECT jsonb_build_object(
|
|
43068
|
+
'gemetenOp', now(),
|
|
43069
|
+
'perOrder', true,
|
|
43070
|
+
'totaal', (SELECT jsonb_object_agg(klasse, n) FROM (SELECT klasse, count(*) n FROM po GROUP BY 1) s),
|
|
43071
|
+
'lopend', (SELECT COALESCE(jsonb_object_agg(klasse, n),'{}') FROM (SELECT klasse, count(*) n FROM po WHERE NOT afgehandeld GROUP BY 1) s),
|
|
43072
|
+
'afgehandeld', (SELECT COALESCE(jsonb_object_agg(klasse, n),'{}') FROM (SELECT klasse, count(*) n FROM po WHERE afgehandeld GROUP BY 1) s),
|
|
43073
|
+
'dubbeleRegels', (SELECT count(*) FROM k WHERE dubbel),
|
|
43074
|
+
'afwijkingen', (SELECT COALESCE(jsonb_agg(jsonb_build_object('order',order_number,'bron',order_source,'status',status,
|
|
43075
|
+
'buffer',buffer_id,'klasse',klasse,'besteld',q,'fusten',c_goed,'planten',p_goed,'blokkade',blok,'dubbel',dubbel,
|
|
43076
|
+
'afgehandeld',afgehandeld,'regels',regels)
|
|
43077
|
+
ORDER BY afgehandeld, order_number),'[]')
|
|
43078
|
+
FROM po WHERE klasse NOT IN ('gelijk','gelijk_afgerond'))
|
|
43079
|
+
);
|
|
43080
|
+
$function$;
|
|
43081
|
+
|
|
43082
|
+
CREATE OR REPLACE FUNCTION public.logistics_tick_http_log(p_steps jsonb)
|
|
43083
|
+
RETURNS void LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43084
|
+
DECLARE v_fouten jsonb := coalesce(p_steps->'stickerSyncFouten', '[]'::jsonb);
|
|
43085
|
+
BEGIN
|
|
43086
|
+
PERFORM public.logistics_acc_guard('server', 'logistics_tick_http_log');
|
|
43087
|
+
INSERT INTO public.logistics_tick_runs(started_at, finished_at, duration_ms, has_error, steps)
|
|
43088
|
+
VALUES (coalesce((p_steps->>'gestart')::timestamptz, now()), now(),
|
|
43089
|
+
nullif(p_steps->>'duurMs', '')::int,
|
|
43090
|
+
false,
|
|
43091
|
+
jsonb_build_object('bron', 'http') || p_steps);
|
|
43092
|
+
INSERT INTO public.logistics_tick_state(key, value, updated_at)
|
|
43093
|
+
VALUES ('sticker_sync', jsonb_build_object('at', now(), 'fouten', v_fouten), now())
|
|
43094
|
+
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now();
|
|
43095
|
+
END $$;
|
|
43096
|
+
|
|
43097
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_samenvoegen()
|
|
43098
|
+
RETURNS TABLE(onderdeel text, ok boolean, toelichting text)
|
|
43099
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43100
|
+
DECLARE f text;
|
|
43101
|
+
BEGIN
|
|
43102
|
+
FOREACH f IN ARRAY ARRAY['logistics_order_is_backfill(uuid)', 'logistics_order_merge_key_v2(uuid)',
|
|
43103
|
+
'logistics_order_mergeable(uuid)', 'logistics_merge_floriday_lines(uuid)',
|
|
43104
|
+
'logistics_merge_herstel_voorbeeld()', 'logistics_merge_herstel_uitvoeren(text,integer)',
|
|
43105
|
+
'logistics_merge_status()', 'logistics_trace_event(uuid,text,text,text)', 'logistics_schema_versie()'] LOOP
|
|
43106
|
+
onderdeel := 'functie ' || f;
|
|
43107
|
+
ok := to_regprocedure('public.' || f) IS NOT NULL;
|
|
43108
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: werk de Engine bij via Supabase bijwerken' END;
|
|
43109
|
+
RETURN NEXT;
|
|
43110
|
+
END LOOP;
|
|
43111
|
+
onderdeel := 'tabel logistics_merge_herstel_log';
|
|
43112
|
+
ok := to_regclass('public.logistics_merge_herstel_log') IS NOT NULL;
|
|
43113
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: werk de Engine bij via Supabase bijwerken' END;
|
|
43114
|
+
RETURN NEXT;
|
|
43115
|
+
END $$;
|
|
43116
|
+
REVOKE ALL ON FUNCTION public.logistics_install_check_samenvoegen() FROM PUBLIC, anon;
|
|
43117
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_samenvoegen() TO authenticated, service_role;
|
|
43118
|
+
|
|
43119
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check()
|
|
43120
|
+
RETURNS TABLE(onderdeel text, ok boolean, toelichting text)
|
|
43121
|
+
LANGUAGE plpgsql
|
|
43122
|
+
SECURITY DEFINER
|
|
43123
|
+
SET search_path TO 'public'
|
|
43124
|
+
AS $function$
|
|
43125
|
+
DECLARE c text; f text; t text; v_fav text; n bigint; s record;
|
|
43126
|
+
BEGIN
|
|
43127
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_install_check');
|
|
43128
|
+
FOREACH f IN ARRAY ARRAY['logistics_pickup_at(text,date)',
|
|
43129
|
+
'logistics_pickup_ts(text,date)', 'logistics_pickup_herbereken()'] LOOP
|
|
43130
|
+
onderdeel := 'functie ' || f;
|
|
43131
|
+
ok := to_regprocedure('public.' || f) IS NOT NULL;
|
|
43132
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: werk de Engine bij via Supabase bijwerken' END;
|
|
43133
|
+
RETURN NEXT;
|
|
43134
|
+
END LOOP;
|
|
43135
|
+
FOREACH f IN ARRAY ARRAY[
|
|
43136
|
+
'f:logistics_try_uuid','f:logistics_tz','f:logistics_is_beheer','f:logistics_buffer_payload','f:logistics_apply_order_buffer',
|
|
43137
|
+
'f:logistics_apply_buffer_decision','f:logistics_rebuffer_pending','f:logistics_departure_calc','f:logistics_own_transport_departure',
|
|
43138
|
+
'f:logistics_order_departure','f:logistics_brief_transport','f:logistics_order_frozen','f:logistics_order_is_frozen',
|
|
43139
|
+
'f:logistics_order_finalize_run','f:run_logistics_tasks_dispatch','f:enqueue_cart_replan_if_unlocked','f:logistics_tick',
|
|
43140
|
+
't:logistics_tick_runs',
|
|
43141
|
+
'f:logistics_belading_bevestig','f:logistics_cart_seq_dubbel','f:logistics_plan_retry_later','f:logistics_own_traysticker_sync',
|
|
43142
|
+
't:logistics_belading_bevestigingen',
|
|
43143
|
+
'f:logistics_sticker_copies','f:logistics_sticker_etiket_status','f:logistics_sticker_order_counts','f:logistics_sticker_sync',
|
|
43144
|
+
'c:logistics_sticker_prints.kopieen_bron',
|
|
43145
|
+
'f:logistics_carrier_settings_ensure','t:logistics_carrier_settings','t:logistics_carrier_recalc_queue','t:logistics_carrier_events',
|
|
43146
|
+
'f:logistics_carrier_status','f:logistics_carrier_set_backfill','f:logistics_carrier_preview_existing','c:control_get_todays_carts.carrier_name',
|
|
43147
|
+
'f:logistics_plan_fail_log'] LOOP
|
|
43148
|
+
onderdeel := CASE substr(f, 3) WHEN 'run_logistics_tasks_dispatch' THEN 'Voorraad: ' WHEN 'enqueue_cart_replan_if_unlocked' THEN 'Verkoop: ' ELSE 'Engine: ' END || substr(f, 3);
|
|
43149
|
+
ok := CASE left(f, 1)
|
|
43150
|
+
WHEN 'f' THEN EXISTS (SELECT 1 FROM pg_proc p WHERE p.pronamespace = 'public'::regnamespace AND p.proname = substr(f, 3))
|
|
43151
|
+
WHEN 't' THEN to_regclass('public.' || substr(f, 3)) IS NOT NULL
|
|
43152
|
+
ELSE CASE WHEN split_part(substr(f, 3), '.', 1) = 'control_get_todays_carts'
|
|
43153
|
+
THEN coalesce(pg_get_function_result(to_regprocedure('public.control_get_todays_carts()')), '') LIKE '%carrier_name%'
|
|
43154
|
+
ELSE EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='public'
|
|
43155
|
+
AND table_name = split_part(substr(f, 3), '.', 1) AND column_name = split_part(substr(f, 3), '.', 2)) END
|
|
43156
|
+
END;
|
|
43157
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' WHEN substr(f, 3) = 'run_logistics_tasks_dispatch' THEN 'ontbreekt: hoort bij Voorraad; werk Voorraad bij' WHEN substr(f, 3) = 'enqueue_cart_replan_if_unlocked' THEN 'ontbreekt: hoort bij Verkoop; werk Verkoop bij' ELSE 'ontbreekt: Engine-migratie (1.0.182 t/m 1.0.188) in dev uitvoeren en via schemasync verspreiden' END;
|
|
43158
|
+
RETURN NEXT;
|
|
43159
|
+
END LOOP;
|
|
43160
|
+
FOREACH c IN ARRAY ARRAY['carrier_id','carrier_source','carrier_reason','carrier_resolved_at','carrier_set_by','carrier_set_at'] LOOP
|
|
43161
|
+
onderdeel := 'orders.' || c;
|
|
43162
|
+
ok := EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='orders' AND column_name=c);
|
|
43163
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: Engine-migratie' END; RETURN NEXT;
|
|
43164
|
+
END LOOP;
|
|
43165
|
+
FOREACH f IN ARRAY ARRAY['logistics_resolve_carrier(uuid)','logistics_resolve_carrier_many(uuid[])',
|
|
43166
|
+
'logistics_resolve_carrier_for_location(uuid,uuid)','logistics_resolve_carrier_for_location_many(uuid[],uuid)',
|
|
43167
|
+
'logistics_resolve_carrier_for_location_many(jsonb)',
|
|
43168
|
+
'logistics_set_order_carrier(uuid,uuid)','logistics_carrier_recalc_run(integer)'] LOOP
|
|
43169
|
+
onderdeel := 'functie ' || f; ok := to_regprocedure('public.' || f) IS NOT NULL;
|
|
43170
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: Engine-migratie' END; RETURN NEXT;
|
|
43171
|
+
END LOOP;
|
|
43172
|
+
FOREACH t IN ARRAY ARRAY['orders:trg_logistics_orders_carrier_fill','orders:trg_logistics_orders_carrier_changed',
|
|
43173
|
+
'carriers:trg_logistics_carriers_enqueue','customer_delivery_locations:trg_logistics_locations_enqueue'] LOOP
|
|
43174
|
+
onderdeel := 'trigger ' || split_part(t, ':', 2);
|
|
43175
|
+
ok := EXISTS (SELECT 1 FROM pg_trigger g WHERE g.tgname = split_part(t, ':', 2)
|
|
43176
|
+
AND g.tgrelid = to_regclass('public.' || split_part(t, ':', 1)));
|
|
43177
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: Engine-migratie' END; RETURN NEXT;
|
|
43178
|
+
END LOOP;
|
|
43179
|
+
onderdeel := 'minuutronde rekent vervoerders';
|
|
43180
|
+
ok := EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'logistics_tick' AND prosrc LIKE '%logistics_carrier_recalc_run%');
|
|
43181
|
+
toelichting := CASE WHEN ok THEN 'ja' ELSE 'nee' END; RETURN NEXT;
|
|
43182
|
+
FOREACH c IN ARRAY ARRAY['carrier_kind','is_favorite','archived_at','delivery_location_glns'] LOOP
|
|
43183
|
+
onderdeel := 'Afhandeling: carriers.' || c;
|
|
43184
|
+
ok := EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='carriers' AND column_name=c);
|
|
43185
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: Afhandeling' END; RETURN NEXT;
|
|
43186
|
+
END LOOP;
|
|
43187
|
+
FOREACH f IN ARRAY ARRAY['afh_favorite_carrier','afh_city_code','afh_normalize_country','afh_normalize_nl_province'] LOOP
|
|
43188
|
+
onderdeel := 'Afhandeling: ' || f || '()';
|
|
43189
|
+
ok := EXISTS (SELECT 1 FROM pg_proc p WHERE p.pronamespace = 'public'::regnamespace AND p.proname = f);
|
|
43190
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: Afhandeling' END; RETURN NEXT;
|
|
43191
|
+
END LOOP;
|
|
43192
|
+
onderdeel := 'Favoriete vervoerder ingesteld en bruikbaar';
|
|
43193
|
+
IF to_regprocedure('public.afh_favorite_carrier()') IS NULL THEN ok := false; toelichting := 'functie ontbreekt';
|
|
43194
|
+
ELSE
|
|
43195
|
+
BEGIN v_fav := public.logistics_carrier_favorite_id()::text; EXCEPTION WHEN OTHERS THEN v_fav := NULL; END;
|
|
43196
|
+
ok := public.logistics_try_uuid(v_fav) IS NOT NULL AND public.logistics_carrier_skip_reason(public.logistics_try_uuid(v_fav)) IS NULL;
|
|
43197
|
+
toelichting := CASE WHEN ok THEN 'ja' WHEN v_fav IS NULL THEN 'geen favoriet ingesteld (Afhandeling → Vervoerders)'
|
|
43198
|
+
ELSE public.logistics_carrier_skip_reason(public.logistics_try_uuid(v_fav)) END;
|
|
43199
|
+
END IF;
|
|
43200
|
+
RETURN NEXT;
|
|
43201
|
+
onderdeel := 'Klanten: customers.default_carrier_id';
|
|
43202
|
+
ok := EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='customers' AND column_name='default_carrier_id');
|
|
43203
|
+
toelichting := CASE WHEN ok THEN 'aanwezig' ELSE 'ontbreekt: Klanten' END; RETURN NEXT;
|
|
43204
|
+
IF to_regclass('public.logistics_carrier_settings') IS NOT NULL AND to_regclass('public.orders') IS NOT NULL
|
|
43205
|
+
AND EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='orders' AND column_name='carrier_source') THEN
|
|
43206
|
+
SELECT * INTO s FROM public.logistics_carrier_settings_ensure();
|
|
43207
|
+
EXECUTE $q$SELECT count(*) FROM public.orders o
|
|
43208
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
43209
|
+
AND coalesce(o.delivery_date, '') ~ '^\d{4}-\d{2}-\d{2}' AND public.logistics_order_date(o.delivery_date::text) >= (now() AT TIME ZONE coalesce(public.logistics_tz(), 'Europe/Amsterdam'))::date
|
|
43210
|
+
AND (o.carrier_source = 'geen' OR (o.carrier_source IS NULL AND o.created_at >= $1))$q$ INTO n USING s.installed_at;
|
|
43211
|
+
onderdeel := 'Open orders zonder vervoerder'; ok := n = 0; toelichting := n || ' order(s)'; RETURN NEXT;
|
|
43212
|
+
onderdeel := 'Schakelaar bestaande orders'; ok := true;
|
|
43213
|
+
toelichting := CASE WHEN coalesce(s.backfill_existing, false) THEN 'aan' ELSE 'uit (bestaande orders wachten op akkoord)' END; RETURN NEXT;
|
|
43214
|
+
END IF;
|
|
43215
|
+
SELECT count(*) INTO n FROM public.logistics_trace_events e
|
|
43216
|
+
WHERE e.actor IN ('trg_logistics_plan_order_items', 'trg_logistics_plan_orders')
|
|
43217
|
+
AND e.status = 'mislukt' AND e.created_at > now() - interval '24 hours';
|
|
43218
|
+
onderdeel := 'Mislukte herplanning (laatste 24 uur)'; ok := n = 0;
|
|
43219
|
+
toelichting := CASE WHEN n = 0 THEN 'geen' ELSE n || ' keer; laatste: ' || coalesce((SELECT coalesce(e.order_ref, '?') || ': ' || coalesce(e.error, '') FROM public.logistics_trace_events e
|
|
43220
|
+
WHERE e.actor IN ('trg_logistics_plan_order_items', 'trg_logistics_plan_orders') AND e.status = 'mislukt'
|
|
43221
|
+
ORDER BY e.created_at DESC LIMIT 1), '') END;
|
|
43222
|
+
RETURN NEXT;
|
|
43223
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_194();
|
|
43224
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_196();
|
|
43225
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_197();
|
|
43226
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_198();
|
|
43227
|
+
RETURN QUERY SELECT * FROM public.logistics_access_check();
|
|
43228
|
+
RETURN QUERY SELECT * FROM public.logistics_overload_check();
|
|
43229
|
+
RETURN QUERY SELECT * FROM public.logistics_check_190();
|
|
43230
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_productiebon();
|
|
43231
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_samenvoegen();
|
|
43232
|
+
END $function$;
|
|
43233
|
+
|
|
43234
|
+
CREATE OR REPLACE FUNCTION public.logistics_schema_versie()
|
|
43235
|
+
RETURNS text LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $function$ SELECT '2026-11-10b'::text $function$;
|
|
43236
|
+
|
|
43237
|
+
-- ==== migratie 20261110090544
|
|
43238
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_floriday_lines(p_order_id uuid)
|
|
43239
|
+
RETURNS uuid LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43240
|
+
DECLARE
|
|
43241
|
+
v_key text; v_keep uuid; v_keepnr text; v_cust uuid; r record; v_ids uuid[];
|
|
43242
|
+
v_moved int; v_logged int; v_total int := 0; v_count int := 0; v_groep int;
|
|
43243
|
+
v_lines text[] := ARRAY[]::text[];
|
|
43244
|
+
BEGIN
|
|
43245
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_merge_floriday_lines');
|
|
43246
|
+
IF p_order_id IS NULL THEN RETURN p_order_id; END IF;
|
|
43247
|
+
IF COALESCE(current_setting('logistics.merge_uit', true), '') = '1' THEN RETURN p_order_id; END IF;
|
|
43248
|
+
IF NOT public.logistics_merge_lines_enabled() THEN RETURN p_order_id; END IF;
|
|
43249
|
+
IF NOT public.logistics_order_mergeable(p_order_id) THEN RETURN p_order_id; END IF;
|
|
43250
|
+
IF NOT EXISTS (SELECT 1 FROM logistics_active.order_items i WHERE i.order_id = p_order_id) THEN RETURN p_order_id; END IF;
|
|
43251
|
+
|
|
43252
|
+
v_key := public.logistics_order_merge_key_v2(p_order_id);
|
|
43253
|
+
IF v_key IS NULL THEN RETURN p_order_id; END IF;
|
|
43254
|
+
IF NOT pg_try_advisory_xact_lock(hashtext('logistics_merge:' || v_key)) THEN RETURN p_order_id; END IF;
|
|
43255
|
+
SELECT customer_id INTO v_cust FROM public.orders WHERE id = p_order_id;
|
|
43256
|
+
|
|
43257
|
+
SELECT array_agg(o.id ORDER BY o.order_number ASC NULLS LAST, o.created_at ASC) INTO v_ids
|
|
43258
|
+
FROM public.orders o
|
|
43259
|
+
WHERE o.customer_id = v_cust AND o.deleted_at IS NULL AND o.order_source = 'floriday'
|
|
43260
|
+
AND EXISTS (SELECT 1 FROM logistics_active.order_items i WHERE i.order_id = o.id)
|
|
43261
|
+
AND public.logistics_order_merge_key_v2(o.id) = v_key
|
|
43262
|
+
AND public.logistics_order_mergeable(o.id);
|
|
43263
|
+
v_groep := COALESCE(cardinality(v_ids), 0);
|
|
43264
|
+
IF v_groep < 2 THEN RETURN p_order_id; END IF;
|
|
43265
|
+
IF v_groep > 20 THEN
|
|
43266
|
+
IF NOT EXISTS (SELECT 1 FROM public.logistics_merge_meldingen m
|
|
43267
|
+
WHERE m.soort = 'groep_te_groot' AND m.group_key = v_key AND m.created_at > now() - interval '1 day') THEN
|
|
43268
|
+
PERFORM public._logistics_merge_melding('groep_te_groot', p_order_id, v_key, v_groep,
|
|
43269
|
+
v_groep || ' orders met dezelfde klant, leverdag, afleverlocatie en ophaalmoment; niet samengevoegd.');
|
|
43270
|
+
END IF;
|
|
43271
|
+
RETURN p_order_id;
|
|
43272
|
+
END IF;
|
|
43273
|
+
|
|
43274
|
+
v_keep := v_ids[1];
|
|
43275
|
+
SELECT order_number INTO v_keepnr FROM public.orders WHERE id = v_keep;
|
|
43276
|
+
-- Geen geneste samenvoegronde tijdens het verplaatsen van regels.
|
|
43277
|
+
PERFORM set_config('logistics.merge_uit', '1', true);
|
|
43278
|
+
|
|
43279
|
+
FOR r IN SELECT o.id, o.order_number, o.floriday_sales_order_id AS sales, o.created_at
|
|
43280
|
+
FROM public.orders o WHERE o.id = ANY (v_ids) AND o.id <> v_keep
|
|
43281
|
+
ORDER BY o.order_number ASC NULLS LAST LOOP
|
|
43282
|
+
BEGIN
|
|
43283
|
+
INSERT INTO public.logistics_order_merge_lines(
|
|
43284
|
+
group_key, from_order_id, from_order_number, to_order_id, to_order_number,
|
|
43285
|
+
order_item_id, product_id, product_name, quantity, source_line_key,
|
|
43286
|
+
sales_order_id, ordered_at, reason)
|
|
43287
|
+
SELECT v_key, r.id, r.order_number, v_keep, v_keepnr,
|
|
43288
|
+
i.id, i.product_id, i.product_name, i.quantity, i.source_line_key,
|
|
43289
|
+
r.sales, r.created_at, 'Zelfde klant, leverdag, afleverlocatie en ophaalmoment'
|
|
43290
|
+
FROM logistics_active.order_items i WHERE i.order_id = r.id;
|
|
43291
|
+
GET DIAGNOSTICS v_logged = ROW_COUNT;
|
|
43292
|
+
UPDATE public.order_items SET order_id = v_keep WHERE order_id = r.id AND quarantined_at IS NULL;
|
|
43293
|
+
GET DIAGNOSTICS v_moved = ROW_COUNT;
|
|
43294
|
+
IF v_moved <> v_logged THEN RAISE EXCEPTION 'aantal verplaatste regels (%) wijkt af van het logboek (%)', v_moved, v_logged; END IF;
|
|
43295
|
+
IF v_moved = 0 THEN RAISE EXCEPTION 'geen regels verplaatst; order blijft staan'; END IF;
|
|
43296
|
+
INSERT INTO public.logistics_order_merges(group_key, kept_order_id, kept_order_number,
|
|
43297
|
+
merged_order_id, merged_order_number, sales_order_id, items_moved)
|
|
43298
|
+
VALUES (v_key, v_keep, v_keepnr, r.id, r.order_number, r.sales, v_moved)
|
|
43299
|
+
ON CONFLICT (merged_order_id) DO NOTHING;
|
|
43300
|
+
UPDATE public.orders SET deleted_at = now(),
|
|
43301
|
+
notes = COALESCE(NULLIF(notes, ''), '')
|
|
43302
|
+
|| CASE WHEN COALESCE(notes, '') = '' THEN '' ELSE E'\n' END
|
|
43303
|
+
|| 'Samengevoegd met ' || COALESCE(v_keepnr, '') || '.',
|
|
43304
|
+
updated_at = now()
|
|
43305
|
+
WHERE id = r.id;
|
|
43306
|
+
v_total := v_total + v_moved; v_count := v_count + 1;
|
|
43307
|
+
v_lines := v_lines || (COALESCE(r.order_number, '') || ': ' || v_moved::text || ' regel(s)');
|
|
43308
|
+
EXCEPTION WHEN OTHERS THEN
|
|
43309
|
+
PERFORM public._logistics_merge_melding('fout', r.id, v_key, NULL,
|
|
43310
|
+
'samenvoegen ' || COALESCE(r.order_number, '?') || ' met ' || COALESCE(v_keepnr, '?') || ': ' || SQLERRM);
|
|
43311
|
+
END;
|
|
43312
|
+
END LOOP;
|
|
43313
|
+
PERFORM set_config('logistics.merge_uit', '0', true);
|
|
43314
|
+
|
|
43315
|
+
IF v_count > 0 THEN
|
|
43316
|
+
UPDATE public.orders o SET total = to_char(COALESCE((
|
|
43317
|
+
SELECT SUM(COALESCE(i.quantity, 0) * COALESCE(i.unit_price, 0))
|
|
43318
|
+
FROM logistics_active.order_items i WHERE i.order_id = o.id), 0), 'FM9999999990.00'),
|
|
43319
|
+
updated_at = now()
|
|
43320
|
+
WHERE o.id = v_keep;
|
|
43321
|
+
PERFORM public.logistics_trace_order_step(
|
|
43322
|
+
v_keep, 'stap:bestelregels_samenvoegen', 'bestelregels samenvoegen', 'geslaagd',
|
|
43323
|
+
'samengevoegd tot ' || COALESCE(v_keepnr, 'één bestelling'),
|
|
43324
|
+
v_count::text || ' order(s), ' || v_total::text || ' regel(s) verplaatst: ' || array_to_string(v_lines, '; '),
|
|
43325
|
+
'Orders combineren');
|
|
43326
|
+
END IF;
|
|
43327
|
+
IF EXISTS (SELECT 1 FROM public.orders WHERE id = p_order_id AND deleted_at IS NOT NULL) THEN RETURN v_keep; END IF;
|
|
43328
|
+
RETURN p_order_id;
|
|
43329
|
+
EXCEPTION WHEN OTHERS THEN
|
|
43330
|
+
PERFORM set_config('logistics.merge_uit', '0', true);
|
|
43331
|
+
PERFORM public._logistics_merge_melding('fout', p_order_id, v_key, NULL, 'samenvoegen: ' || SQLERRM);
|
|
43332
|
+
RETURN p_order_id;
|
|
43333
|
+
END $$;
|
|
43334
|
+
|
|
43335
|
+
CREATE OR REPLACE FUNCTION public._logistics_merge_herstel_kandidaten()
|
|
43336
|
+
RETURNS TABLE(merged_order_id uuid, merged_order_number text, kept_order_id uuid, kept_order_number text,
|
|
43337
|
+
categorie text, regels integer, status text, leverdag date, reden text)
|
|
43338
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43339
|
+
DECLARE r record; v_dag date; v_onzeker text; v_vandaag date := (now() AT TIME ZONE 'Europe/Amsterdam')::date;
|
|
43340
|
+
BEGIN
|
|
43341
|
+
FOR r IN
|
|
43342
|
+
SELECT m.merged_order_id, m.merged_order_number, m.kept_order_id, m.kept_order_number, m.items_moved,
|
|
43343
|
+
o.status, o.delivery_date
|
|
43344
|
+
FROM public.logistics_order_merges m
|
|
43345
|
+
JOIN public.orders o ON o.id = m.merged_order_id
|
|
43346
|
+
WHERE o.deleted_at IS NOT NULL
|
|
43347
|
+
AND COALESCE(m.group_key, '') NOT LIKE 'v2|%'
|
|
43348
|
+
AND NOT EXISTS (SELECT 1 FROM public.logistics_merge_herstel_log h WHERE h.merged_order_id = m.merged_order_id)
|
|
43349
|
+
LOOP
|
|
43350
|
+
v_onzeker := NULL;
|
|
43351
|
+
BEGIN
|
|
43352
|
+
v_dag := public.logistics_order_date(r.delivery_date::text);
|
|
43353
|
+
EXCEPTION WHEN OTHERS THEN
|
|
43354
|
+
v_dag := NULL;
|
|
43355
|
+
END;
|
|
43356
|
+
IF v_dag IS NULL THEN v_onzeker := 'leverdag onleesbaar'; END IF;
|
|
43357
|
+
IF v_onzeker IS NULL AND (SELECT count(*) FROM public.logistics_order_merge_lines l WHERE l.from_order_id = r.merged_order_id)
|
|
43358
|
+
<> COALESCE(r.items_moved, 0) THEN
|
|
43359
|
+
v_onzeker := 'logboek en aantal verplaatste regels verschillen';
|
|
43360
|
+
END IF;
|
|
43361
|
+
IF v_onzeker IS NULL AND EXISTS (
|
|
43362
|
+
SELECT 1 FROM public.logistics_order_merge_lines l
|
|
43363
|
+
LEFT JOIN public.order_items i ON i.id = l.order_item_id
|
|
43364
|
+
WHERE l.from_order_id = r.merged_order_id
|
|
43365
|
+
AND (i.id IS NULL OR i.order_id IS DISTINCT FROM r.kept_order_id)) THEN
|
|
43366
|
+
v_onzeker := 'regel staat niet meer bij de verzamelorder';
|
|
43367
|
+
END IF;
|
|
43368
|
+
IF v_onzeker IS NULL AND EXISTS (
|
|
43369
|
+
SELECT 1 FROM public.logistics_order_merge_lines l
|
|
43370
|
+
WHERE l.from_order_id = r.merged_order_id
|
|
43371
|
+
AND EXISTS (SELECT 1 FROM public.logistics_order_merge_lines l2
|
|
43372
|
+
WHERE l2.order_item_id = l.order_item_id AND l2.from_order_id <> l.from_order_id)) THEN
|
|
43373
|
+
v_onzeker := 'regel komt bij meer dan één order vandaan';
|
|
43374
|
+
END IF;
|
|
43375
|
+
merged_order_id := r.merged_order_id; merged_order_number := r.merged_order_number;
|
|
43376
|
+
kept_order_id := r.kept_order_id; kept_order_number := r.kept_order_number;
|
|
43377
|
+
regels := COALESCE(r.items_moved, 0); status := r.status; leverdag := v_dag; reden := v_onzeker;
|
|
43378
|
+
categorie := CASE
|
|
43379
|
+
WHEN v_onzeker IS NOT NULL THEN 'onzeker'
|
|
43380
|
+
WHEN v_dag < v_vandaag THEN 'verleden'
|
|
43381
|
+
WHEN lower(btrim(COALESCE(r.status, ''))) = 'nog te picken' THEN 'urgent'
|
|
43382
|
+
ELSE 'toekomst_overig' END;
|
|
43383
|
+
RETURN NEXT;
|
|
43384
|
+
END LOOP;
|
|
43385
|
+
END $$;
|
|
43386
|
+
|
|
43387
|
+
REVOKE EXECUTE ON FUNCTION public.logistics_order_merge_key_v2(uuid) FROM authenticated;
|
|
43388
|
+
|
|
43389
|
+
-- ==== migratie 20261110090709
|
|
43390
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_floriday_lines(p_order_id uuid)
|
|
43391
|
+
RETURNS uuid LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43392
|
+
DECLARE
|
|
43393
|
+
v_key text; v_keep uuid; v_keepnr text; v_cust uuid; r record; v_ids uuid[];
|
|
43394
|
+
v_moved int; v_logged int; v_total int := 0; v_count int := 0; v_groep int;
|
|
43395
|
+
v_lines text[] := ARRAY[]::text[];
|
|
43396
|
+
BEGIN
|
|
43397
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_merge_floriday_lines');
|
|
43398
|
+
IF p_order_id IS NULL THEN RETURN p_order_id; END IF;
|
|
43399
|
+
IF COALESCE(current_setting('logistics.merge_uit', true), '') = '1' THEN RETURN p_order_id; END IF;
|
|
43400
|
+
IF NOT public.logistics_merge_lines_enabled() THEN RETURN p_order_id; END IF;
|
|
43401
|
+
IF NOT public.logistics_order_mergeable(p_order_id) THEN RETURN p_order_id; END IF;
|
|
43402
|
+
IF NOT EXISTS (SELECT 1 FROM logistics_active.order_items i WHERE i.order_id = p_order_id) THEN RETURN p_order_id; END IF;
|
|
43403
|
+
|
|
43404
|
+
v_key := public.logistics_order_merge_key_v2(p_order_id);
|
|
43405
|
+
IF v_key IS NULL THEN RETURN p_order_id; END IF;
|
|
43406
|
+
IF NOT pg_try_advisory_xact_lock(hashtext('logistics_merge:' || v_key)) THEN RETURN p_order_id; END IF;
|
|
43407
|
+
SELECT customer_id INTO v_cust FROM public.orders WHERE id = p_order_id;
|
|
43408
|
+
|
|
43409
|
+
SELECT array_agg(o.id ORDER BY o.order_number ASC NULLS LAST, o.created_at ASC) INTO v_ids
|
|
43410
|
+
FROM public.orders o
|
|
43411
|
+
WHERE o.customer_id = v_cust AND o.deleted_at IS NULL AND o.order_source = 'floriday'
|
|
43412
|
+
AND EXISTS (SELECT 1 FROM logistics_active.order_items i WHERE i.order_id = o.id)
|
|
43413
|
+
AND public.logistics_order_merge_key_v2(o.id) = v_key
|
|
43414
|
+
AND public.logistics_order_mergeable(o.id);
|
|
43415
|
+
v_groep := COALESCE(cardinality(v_ids), 0);
|
|
43416
|
+
IF v_groep < 2 THEN RETURN p_order_id; END IF;
|
|
43417
|
+
v_keep := v_ids[1];
|
|
43418
|
+
-- Grens: eerder samengevoegde orders bij dezelfde bewaarorder tellen mee.
|
|
43419
|
+
v_groep := v_groep + (SELECT count(*) FROM public.logistics_order_merges m WHERE m.kept_order_id = v_keep AND m.group_key = v_key);
|
|
43420
|
+
IF v_groep > 20 THEN
|
|
43421
|
+
IF NOT EXISTS (SELECT 1 FROM public.logistics_merge_meldingen m
|
|
43422
|
+
WHERE m.soort = 'groep_te_groot' AND m.group_key = v_key AND m.created_at > now() - interval '1 day') THEN
|
|
43423
|
+
PERFORM public._logistics_merge_melding('groep_te_groot', p_order_id, v_key, v_groep,
|
|
43424
|
+
v_groep || ' orders met dezelfde klant, leverdag, afleverlocatie en ophaalmoment; niet samengevoegd.');
|
|
43425
|
+
END IF;
|
|
43426
|
+
RETURN p_order_id;
|
|
43427
|
+
END IF;
|
|
43428
|
+
|
|
43429
|
+
SELECT order_number INTO v_keepnr FROM public.orders WHERE id = v_keep;
|
|
43430
|
+
PERFORM set_config('logistics.merge_uit', '1', true);
|
|
43431
|
+
|
|
43432
|
+
FOR r IN SELECT o.id, o.order_number, o.floriday_sales_order_id AS sales, o.created_at
|
|
43433
|
+
FROM public.orders o WHERE o.id = ANY (v_ids) AND o.id <> v_keep
|
|
43434
|
+
ORDER BY o.order_number ASC NULLS LAST LOOP
|
|
43435
|
+
BEGIN
|
|
43436
|
+
INSERT INTO public.logistics_order_merge_lines(
|
|
43437
|
+
group_key, from_order_id, from_order_number, to_order_id, to_order_number,
|
|
43438
|
+
order_item_id, product_id, product_name, quantity, source_line_key,
|
|
43439
|
+
sales_order_id, ordered_at, reason)
|
|
43440
|
+
SELECT v_key, r.id, r.order_number, v_keep, v_keepnr,
|
|
43441
|
+
i.id, i.product_id, i.product_name, i.quantity, i.source_line_key,
|
|
43442
|
+
r.sales, r.created_at, 'Zelfde klant, leverdag, afleverlocatie en ophaalmoment'
|
|
43443
|
+
FROM logistics_active.order_items i WHERE i.order_id = r.id;
|
|
43444
|
+
GET DIAGNOSTICS v_logged = ROW_COUNT;
|
|
43445
|
+
UPDATE public.order_items SET order_id = v_keep WHERE order_id = r.id AND quarantined_at IS NULL;
|
|
43446
|
+
GET DIAGNOSTICS v_moved = ROW_COUNT;
|
|
43447
|
+
IF v_moved <> v_logged THEN RAISE EXCEPTION 'aantal verplaatste regels (%) wijkt af van het logboek (%)', v_moved, v_logged; END IF;
|
|
43448
|
+
IF v_moved = 0 THEN RAISE EXCEPTION 'geen regels verplaatst; order blijft staan'; END IF;
|
|
43449
|
+
INSERT INTO public.logistics_order_merges(group_key, kept_order_id, kept_order_number,
|
|
43450
|
+
merged_order_id, merged_order_number, sales_order_id, items_moved)
|
|
43451
|
+
VALUES (v_key, v_keep, v_keepnr, r.id, r.order_number, r.sales, v_moved)
|
|
43452
|
+
ON CONFLICT (merged_order_id) DO NOTHING;
|
|
43453
|
+
UPDATE public.orders SET deleted_at = now(),
|
|
43454
|
+
notes = COALESCE(NULLIF(notes, ''), '')
|
|
43455
|
+
|| CASE WHEN COALESCE(notes, '') = '' THEN '' ELSE E'\n' END
|
|
43456
|
+
|| 'Samengevoegd met ' || COALESCE(v_keepnr, '') || '.',
|
|
43457
|
+
updated_at = now()
|
|
43458
|
+
WHERE id = r.id;
|
|
43459
|
+
v_total := v_total + v_moved; v_count := v_count + 1;
|
|
43460
|
+
v_lines := v_lines || (COALESCE(r.order_number, '') || ': ' || v_moved::text || ' regel(s)');
|
|
43461
|
+
EXCEPTION WHEN OTHERS THEN
|
|
43462
|
+
PERFORM public._logistics_merge_melding('fout', r.id, v_key, NULL,
|
|
43463
|
+
'samenvoegen ' || COALESCE(r.order_number, '?') || ' met ' || COALESCE(v_keepnr, '?') || ': ' || SQLERRM);
|
|
43464
|
+
END;
|
|
43465
|
+
END LOOP;
|
|
43466
|
+
PERFORM set_config('logistics.merge_uit', '0', true);
|
|
43467
|
+
|
|
43468
|
+
IF v_count > 0 THEN
|
|
43469
|
+
UPDATE public.orders o SET total = to_char(COALESCE((
|
|
43470
|
+
SELECT SUM(COALESCE(i.quantity, 0) * COALESCE(i.unit_price, 0))
|
|
43471
|
+
FROM logistics_active.order_items i WHERE i.order_id = o.id), 0), 'FM9999999990.00'),
|
|
43472
|
+
updated_at = now()
|
|
43473
|
+
WHERE o.id = v_keep;
|
|
43474
|
+
PERFORM public.logistics_trace_order_step(
|
|
43475
|
+
v_keep, 'stap:bestelregels_samenvoegen', 'bestelregels samenvoegen', 'geslaagd',
|
|
43476
|
+
'samengevoegd tot ' || COALESCE(v_keepnr, 'één bestelling'),
|
|
43477
|
+
v_count::text || ' order(s), ' || v_total::text || ' regel(s) verplaatst: ' || array_to_string(v_lines, '; '),
|
|
43478
|
+
'Orders combineren');
|
|
43479
|
+
END IF;
|
|
43480
|
+
IF EXISTS (SELECT 1 FROM public.orders WHERE id = p_order_id AND deleted_at IS NOT NULL) THEN RETURN v_keep; END IF;
|
|
43481
|
+
RETURN p_order_id;
|
|
43482
|
+
EXCEPTION WHEN OTHERS THEN
|
|
43483
|
+
PERFORM set_config('logistics.merge_uit', '0', true);
|
|
43484
|
+
PERFORM public._logistics_merge_melding('fout', p_order_id, v_key, NULL, 'samenvoegen: ' || SQLERRM);
|
|
43485
|
+
RETURN p_order_id;
|
|
43486
|
+
END $$;
|
|
43487
|
+
|
|
43488
|
+
-- ==== migratie 20261110090737
|
|
43489
|
+
CREATE OR REPLACE FUNCTION public.logistics_merge_status()
|
|
43490
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
43491
|
+
BEGIN
|
|
43492
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_merge_status');
|
|
43493
|
+
RETURN jsonb_build_object(
|
|
43494
|
+
'samenvoegenAan', public.logistics_merge_lines_enabled(),
|
|
43495
|
+
'groepTeGroot', (SELECT COALESCE(sum(x.aantal), 0) FROM (
|
|
43496
|
+
SELECT DISTINCT ON (m.group_key) m.aantal FROM public.logistics_merge_meldingen m
|
|
43497
|
+
WHERE m.soort = 'groep_te_groot' AND m.created_at > now() - interval '7 days'
|
|
43498
|
+
ORDER BY m.group_key, m.created_at DESC) x),
|
|
43499
|
+
'nieuwVerwijderd', (SELECT count(*) FROM public.orders o
|
|
43500
|
+
WHERE o.deleted_at IS NOT NULL AND o.created_at > now() - interval '7 days'
|
|
43501
|
+
AND o.deleted_at - o.created_at < interval '2 minutes'
|
|
43502
|
+
AND NOT EXISTS (SELECT 1 FROM public.logistics_order_merges m
|
|
43503
|
+
WHERE m.merged_order_id = o.id AND m.items_moved > 0 AND m.group_key LIKE 'v2|%')
|
|
43504
|
+
AND NOT EXISTS (SELECT 1 FROM public.logistics_merge_herstel_log h WHERE h.merged_order_id = o.id)),
|
|
43505
|
+
'fouten', (SELECT count(*) FROM public.logistics_merge_meldingen m
|
|
43506
|
+
WHERE m.soort IN ('fout', 'herstel_fout') AND m.created_at > now() - interval '7 days'),
|
|
43507
|
+
'laatsteFout', (SELECT jsonb_build_object('op', m.created_at, 'melding', m.fout) FROM public.logistics_merge_meldingen m
|
|
43508
|
+
WHERE m.soort IN ('fout', 'herstel_fout') ORDER BY m.created_at DESC LIMIT 1),
|
|
43509
|
+
'hersteld', (SELECT COALESCE(jsonb_object_agg(categorie, n), '{}'::jsonb)
|
|
43510
|
+
FROM (SELECT categorie, count(*) n FROM public.logistics_merge_herstel_log GROUP BY 1) h));
|
|
43511
|
+
END $$;
|
|
43512
|
+
|