@flowselections/logistiek-engine 1.0.202 → 1.0.206
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 +885 -0
- package/dist-lib/components/BeladingIndelingCard.d.ts.map +1 -1
- package/dist-lib/components/BeladingIndelingCard.js +15 -3
- package/dist-lib/components/LadingdragersPage.d.ts.map +1 -1
- package/dist-lib/components/LadingdragersPage.js +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +415 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/extraPlaten.d.ts +9 -0
- package/dist-lib/lib/extraPlaten.d.ts.map +1 -1
- package/dist-lib/lib/extraPlaten.js +15 -0
- package/dist-lib/lib/floridayCartCarriers.d.ts +3 -0
- package/dist-lib/lib/floridayCartCarriers.d.ts.map +1 -1
- package/dist-lib/lib/floridayCartCarriers.js +6 -1
- package/dist-lib/lib/floridayPush.server.d.ts.map +1 -1
- package/dist-lib/lib/floridayPush.server.js +5 -3
- package/dist-lib/lib/loadCarrierPlanner.d.ts +68 -1
- package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanner.js +293 -280
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +16 -3
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/dist-lib/lib/quarantaine.d.ts +9 -0
- package/dist-lib/lib/quarantaine.d.ts.map +1 -0
- package/dist-lib/lib/quarantaine.js +13 -0
- package/dist-lib/lib/shippingNoteQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/shippingNoteQueue.server.js +11 -0
- package/dist-lib/lib/stickerQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/stickerQueue.server.js +13 -0
- package/package.json +1 -1
|
@@ -34940,3 +34940,888 @@ DO $d$ BEGIN
|
|
|
34940
34940
|
SELECT id, order_number, buffer_id INTO o FROM public.orders WHERE id = p_order_id;');
|
|
34941
34941
|
END IF;
|
|
34942
34942
|
END $d$;
|
|
34943
|
+
|
|
34944
|
+
-- 1.0.201 vervolg — kar_te_hoog, guards pakbonfuncties, productoordeel, Beheerlink (additief, idempotent)
|
|
34945
|
+
-- 1.0.201 vervolg: te hoge karren, guards op pakbonfuncties, productoordeel, Beheerlink altijd gevuld.
|
|
34946
|
+
|
|
34947
|
+
-- Rekenhulp zonder gegevens: blokkade voor één kar.
|
|
34948
|
+
CREATE OR REPLACE FUNCTION public.logistics_kar_blokkade(p_kar text, p_lagen numeric, p_max numeric)
|
|
34949
|
+
RETURNS jsonb LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$
|
|
34950
|
+
SELECT CASE WHEN p_lagen IS NOT NULL AND coalesce(p_max, 0) > 0 AND p_lagen > p_max + 0.001
|
|
34951
|
+
THEN jsonb_build_object('teHoog', true, 'blokkade', jsonb_build_object('code', 'kar_te_hoog',
|
|
34952
|
+
'tekst', format('Kar %s heeft %s lagen, maximaal %s. Deel de order opnieuw in of pas de belading aan.',
|
|
34953
|
+
coalesce(nullif(btrim(p_kar), ''), '?'),
|
|
34954
|
+
replace(trim_scale(round(p_lagen, 2))::text, '.', ','),
|
|
34955
|
+
replace(trim_scale(round(p_max, 2))::text, '.', ','))))
|
|
34956
|
+
ELSE jsonb_build_object('teHoog', false, 'blokkade', NULL) END
|
|
34957
|
+
$$;
|
|
34958
|
+
|
|
34959
|
+
-- Karren aanvullen (platen + blokkade). Geeft alleen de meegegeven kar terug, maar leest ladingdragernamen: guard.
|
|
34960
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_platen_verrijk(p_cart jsonb)
|
|
34961
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34962
|
+
DECLARE v_l numeric := nullif(p_cart->>'layersUsed', '')::numeric;
|
|
34963
|
+
BEGIN
|
|
34964
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_platen_verrijk');
|
|
34965
|
+
RETURN p_cart || jsonb_build_object(
|
|
34966
|
+
'additionalLayers', public.logistics_extra_platen(v_l),
|
|
34967
|
+
'ladingdragerTekst', public.logistics_ladingdrager_tekst(p_cart->>'carrierType', v_l,
|
|
34968
|
+
coalesce(nullif(p_cart->>'layerUtilizationPct', '')::numeric, nullif(p_cart->>'occupancyPct', '')::numeric)))
|
|
34969
|
+
|| public.logistics_kar_blokkade(coalesce(p_cart->>'cartNumber', p_cart->>'cart_number', p_cart->>'seq'), v_l,
|
|
34970
|
+
nullif(p_cart->>'maxLayers', '')::numeric);
|
|
34971
|
+
END $$;
|
|
34972
|
+
|
|
34973
|
+
-- Guard op de kopie van de pakbonfunctie.
|
|
34974
|
+
DO $d$ BEGIN
|
|
34975
|
+
IF to_regprocedure('public.logistics_cart_slip_plan_v200(uuid)') IS NOT NULL
|
|
34976
|
+
AND position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_cart_slip_plan_v200(uuid)'::regprocedure)) = 0 THEN
|
|
34977
|
+
EXECUTE regexp_replace(pg_get_functiondef('public.logistics_cart_slip_plan_v200(uuid)'::regprocedure),
|
|
34978
|
+
'\nBEGIN\n', E'\nBEGIN\n PERFORM public.logistics_acc_guard(''ingelogd'', ''logistics_cart_slip_plan_v200'');\n');
|
|
34979
|
+
END IF;
|
|
34980
|
+
END $d$;
|
|
34981
|
+
|
|
34982
|
+
-- Pakbonfunctie: guard + per kar teHoog/blokkade.
|
|
34983
|
+
DO $do$ BEGIN
|
|
34984
|
+
IF to_regprocedure('public.logistics_cart_slip_plan_v200(uuid)') IS NOT NULL THEN
|
|
34985
|
+
EXECUTE $f$
|
|
34986
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_slip_plan(p_order_id uuid)
|
|
34987
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $b$
|
|
34988
|
+
DECLARE b jsonb;
|
|
34989
|
+
BEGIN
|
|
34990
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_slip_plan');
|
|
34991
|
+
b := public.logistics_cart_slip_plan_v200(p_order_id);
|
|
34992
|
+
IF b IS NULL OR jsonb_typeof(b->'carts') IS DISTINCT FROM 'array' THEN RETURN b; END IF;
|
|
34993
|
+
RETURN b || jsonb_build_object('carts', (
|
|
34994
|
+
SELECT coalesce(jsonb_agg(public.logistics_cart_platen_verrijk(t.e) ORDER BY t.o), '[]'::jsonb)
|
|
34995
|
+
FROM jsonb_array_elements(b->'carts') WITH ORDINALITY t(e, o)));
|
|
34996
|
+
END $b$;
|
|
34997
|
+
$f$;
|
|
34998
|
+
END IF;
|
|
34999
|
+
END $do$;
|
|
35000
|
+
|
|
35001
|
+
-- Te hoge karren per order (via de buffer, dus ook gedeelde karren).
|
|
35002
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_te_hoge_karren(p_order_ids uuid[])
|
|
35003
|
+
RETURNS TABLE(order_id uuid, cart_id uuid, cart_number integer, lagen numeric, max_lagen numeric, blokkade jsonb)
|
|
35004
|
+
LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
35005
|
+
BEGIN
|
|
35006
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_te_hoge_karren');
|
|
35007
|
+
RETURN QUERY
|
|
35008
|
+
SELECT u.order_id, u.cart_id, coalesce(u.display_seq, u.cart_number), c.total_layers_used::numeric, c.max_layers::numeric,
|
|
35009
|
+
public.logistics_kar_blokkade(coalesce(u.display_seq, u.cart_number)::text, c.total_layers_used, c.max_layers)->'blokkade'
|
|
35010
|
+
FROM public.logistics_order_unit_carts_core(p_order_ids) u
|
|
35011
|
+
JOIN logistics_active.order_carts c ON c.id = u.cart_id
|
|
35012
|
+
WHERE (public.logistics_kar_blokkade(NULL, c.total_layers_used, c.max_layers)->>'teHoog')::boolean;
|
|
35013
|
+
END $$;
|
|
35014
|
+
|
|
35015
|
+
-- Reden bij geen indeling: kar_te_hoog eerst, actieUrl altijd gevuld.
|
|
35016
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_geen_indeling_core(p_order_id uuid)
|
|
35017
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35018
|
+
DECLARE o record; q record; d record; t record; v_code text; v_tekst text; v_soort text; v_actie text;
|
|
35019
|
+
c_beheer constant text := '/logistiek-engine/beheer';
|
|
35020
|
+
BEGIN
|
|
35021
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_geen_indeling_core');
|
|
35022
|
+
SELECT id, order_number, buffer_id INTO o FROM public.orders WHERE id = p_order_id;
|
|
35023
|
+
IF NOT FOUND THEN RETURN NULL; END IF;
|
|
35024
|
+
SELECT * INTO t FROM public.logistics_order_te_hoge_karren(ARRAY[p_order_id]) ORDER BY cart_number LIMIT 1;
|
|
35025
|
+
IF FOUND THEN
|
|
35026
|
+
v_code := 'kar_te_hoog'; v_tekst := t.blokkade->>'tekst'; v_actie := 'belading_aanpassen';
|
|
35027
|
+
ELSE
|
|
35028
|
+
SELECT status, reason, reason_code INTO q FROM public.logistics_plan_queue
|
|
35029
|
+
WHERE order_id = p_order_id ORDER BY updated_at DESC NULLS LAST LIMIT 1;
|
|
35030
|
+
IF FOUND AND q.status = 'geblokkeerd' THEN
|
|
35031
|
+
v_code := coalesce(q.reason_code, 'geblokkeerd'); v_tekst := q.reason;
|
|
35032
|
+
ELSE
|
|
35033
|
+
SELECT dd.result, dd.explanation, dd.input_snapshot INTO d
|
|
35034
|
+
FROM public.logistics_decisions dd
|
|
35035
|
+
WHERE dd.slot = 'beladingindeling'
|
|
35036
|
+
AND ((dd.subject_type = 'order' AND dd.subject_id = o.id::text)
|
|
35037
|
+
OR (dd.subject_type = 'buffer' AND o.buffer_id IS NOT NULL AND dd.subject_id = o.buffer_id::text)
|
|
35038
|
+
OR (o.order_number IS NOT NULL AND coalesce(dd.input_snapshot->'members', '[]'::jsonb) ? o.order_number))
|
|
35039
|
+
ORDER BY dd.created_at DESC LIMIT 1;
|
|
35040
|
+
IF FOUND AND coalesce((d.result->>'blocked')::boolean, false) THEN
|
|
35041
|
+
v_code := coalesce(d.result->>'reason_code', 'geblokkeerd'); v_tekst := d.explanation;
|
|
35042
|
+
v_soort := d.input_snapshot->>'soort';
|
|
35043
|
+
ELSIF q.status IN ('pending', 'running') THEN
|
|
35044
|
+
v_code := 'wacht_op_indeling'; v_tekst := 'De karindeling wordt gemaakt; dit duurt meestal enkele seconden.';
|
|
35045
|
+
ELSE
|
|
35046
|
+
v_code := 'onbekend';
|
|
35047
|
+
v_tekst := 'Er is nog geen karindeling en er is geen blokkade vastgelegd. De minuutronde probeert het opnieuw; blijft dit staan, meld het aan beheer.';
|
|
35048
|
+
END IF;
|
|
35049
|
+
END IF;
|
|
35050
|
+
IF v_code LIKE 'belading%' OR v_code = 'ladingdrager_niet_in_beheer' THEN v_actie := 'belading_aanpassen'; END IF;
|
|
35051
|
+
END IF;
|
|
35052
|
+
RETURN jsonb_build_object('code', v_code, 'soort', v_soort,
|
|
35053
|
+
'tekst', coalesce(nullif(btrim(v_tekst), ''), 'Geen indeling; de reden is niet bekend.'),
|
|
35054
|
+
'actie', coalesce(v_actie, 'beheer'),
|
|
35055
|
+
'actieLabel', CASE WHEN v_actie IS NOT NULL THEN 'Belading aanpassen' ELSE 'Naar Engine-beheer' END,
|
|
35056
|
+
'actieUrl', CASE WHEN v_actie IS NOT NULL THEN c_beheer || '#gegevens-voor-karindeling' ELSE c_beheer END);
|
|
35057
|
+
END $$;
|
|
35058
|
+
|
|
35059
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_geen_indeling_many(p_order_ids uuid[])
|
|
35060
|
+
RETURNS TABLE(order_id uuid, geen_indeling jsonb) LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35061
|
+
BEGIN
|
|
35062
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_geen_indeling_many');
|
|
35063
|
+
IF coalesce(cardinality(p_order_ids), 0) > 1000 THEN
|
|
35064
|
+
RAISE EXCEPTION 'Maximaal 1000 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
35065
|
+
END IF;
|
|
35066
|
+
RETURN QUERY
|
|
35067
|
+
WITH th AS (SELECT DISTINCT h.order_id FROM public.logistics_order_te_hoge_karren(p_order_ids) h)
|
|
35068
|
+
SELECT b.order_id,
|
|
35069
|
+
CASE WHEN (b.state IN ('geen_indeling', 'deels') AND NOT coalesce(x.full_fulfilled, false)) OR th.order_id IS NOT NULL
|
|
35070
|
+
THEN public.logistics_order_geen_indeling_core(b.order_id) END
|
|
35071
|
+
FROM public.logistics_order_plan_coverage_list_v152(p_order_ids) b
|
|
35072
|
+
LEFT JOIN public.logistics_external_fulfillment x ON x.order_id = b.order_id
|
|
35073
|
+
LEFT JOIN th ON th.order_id = b.order_id;
|
|
35074
|
+
END $$;
|
|
35075
|
+
|
|
35076
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_plan_coverage_list_v201(p_order_ids uuid[])
|
|
35077
|
+
RETURNS TABLE(order_id uuid, order_number text, buffer_id uuid, state text, label text, progress_pct integer, reason text,
|
|
35078
|
+
cart_count integer, pick_row_count integer, pick_status text, picked_at timestamptz,
|
|
35079
|
+
buffer_order_count integer, buffer_cart_count integer, geen_indeling jsonb)
|
|
35080
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35081
|
+
BEGIN
|
|
35082
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_plan_coverage_list_v201');
|
|
35083
|
+
IF coalesce(cardinality(p_order_ids), 0) > 1000 THEN
|
|
35084
|
+
RAISE EXCEPTION 'Maximaal 1000 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
35085
|
+
END IF;
|
|
35086
|
+
RETURN QUERY
|
|
35087
|
+
WITH th AS (SELECT DISTINCT h.order_id FROM public.logistics_order_te_hoge_karren(p_order_ids) h)
|
|
35088
|
+
SELECT l.order_id, l.order_number, l.buffer_id, l.state,
|
|
35089
|
+
CASE WHEN th.order_id IS NOT NULL THEN 'Ingedeeld — kar te hoog' ELSE l.label END,
|
|
35090
|
+
l.progress_pct, l.reason, l.cart_count, l.pick_row_count, l.pick_status, l.picked_at,
|
|
35091
|
+
l.buffer_order_count, l.buffer_cart_count,
|
|
35092
|
+
CASE WHEN l.state IN ('geen_indeling', 'deels') OR th.order_id IS NOT NULL THEN public.logistics_order_geen_indeling_core(l.order_id) END
|
|
35093
|
+
FROM public.logistics_order_plan_coverage_list(p_order_ids) l
|
|
35094
|
+
LEFT JOIN th ON th.order_id = l.order_id;
|
|
35095
|
+
END $$;
|
|
35096
|
+
|
|
35097
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_plan_coverage(p_order_id uuid)
|
|
35098
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35099
|
+
DECLARE b jsonb; x jsonb; v_hoog boolean;
|
|
35100
|
+
BEGIN
|
|
35101
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_plan_coverage');
|
|
35102
|
+
b := public.logistics_order_plan_coverage_v165(p_order_id);
|
|
35103
|
+
x := public.logistics_order_external_state(p_order_id);
|
|
35104
|
+
IF jsonb_typeof(b->'carts') = 'array' THEN
|
|
35105
|
+
b := b || jsonb_build_object('carts', (
|
|
35106
|
+
SELECT coalesce(jsonb_agg(
|
|
35107
|
+
CASE WHEN c.id IS NULL THEN t.e || jsonb_build_object('additionalLayers', NULL, 'layersUsed', NULL, 'teHoog', false, 'blokkade', NULL)
|
|
35108
|
+
ELSE public.logistics_cart_platen_verrijk(t.e || jsonb_build_object(
|
|
35109
|
+
'layersUsed', c.total_layers_used, 'occupancyPct', c.occupancy_pct, 'maxLayers', c.max_layers,
|
|
35110
|
+
'layerUtilizationPct', CASE WHEN coalesce(c.max_layers, 0) > 0 AND c.total_layers_used IS NOT NULL
|
|
35111
|
+
THEN round(100.0 * c.total_layers_used / c.max_layers, 1) END)) END
|
|
35112
|
+
ORDER BY t.o), '[]'::jsonb)
|
|
35113
|
+
FROM jsonb_array_elements(b->'carts') WITH ORDINALITY t(e, o)
|
|
35114
|
+
LEFT JOIN logistics_active.order_carts c ON c.id::text = t.e->>'cartId'));
|
|
35115
|
+
END IF;
|
|
35116
|
+
IF x IS NOT NULL AND (x->>'full')::boolean THEN
|
|
35117
|
+
b := b || jsonb_build_object('state', 'afgehandeld_extern', 'label', 'Afgehandeld in Floriday',
|
|
35118
|
+
'reason', 'De order is in Floriday afgehandeld; de Engine plant en print er niets meer voor.');
|
|
35119
|
+
END IF;
|
|
35120
|
+
v_hoog := EXISTS (SELECT 1 FROM jsonb_array_elements(coalesce(b->'carts', '[]'::jsonb)) e WHERE (e->>'teHoog')::boolean)
|
|
35121
|
+
OR EXISTS (SELECT 1 FROM public.logistics_order_te_hoge_karren(ARRAY[p_order_id]));
|
|
35122
|
+
IF v_hoog AND b->>'state' IS DISTINCT FROM 'afgehandeld_extern' THEN
|
|
35123
|
+
b := b || jsonb_build_object('label', 'Ingedeeld — kar te hoog');
|
|
35124
|
+
END IF;
|
|
35125
|
+
b := b || jsonb_build_object('geenIndeling',
|
|
35126
|
+
CASE WHEN b->>'state' IN ('geen_indeling', 'deels') OR (v_hoog AND b->>'state' IS DISTINCT FROM 'afgehandeld_extern')
|
|
35127
|
+
THEN public.logistics_order_geen_indeling_core(p_order_id) END);
|
|
35128
|
+
RETURN b || jsonb_build_object('externalFulfilled', x);
|
|
35129
|
+
END $$;
|
|
35130
|
+
|
|
35131
|
+
-- Kar-check voor de server (sticker- en verzendbriefronde).
|
|
35132
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_te_hoog(p_cart_id uuid)
|
|
35133
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35134
|
+
DECLARE c record;
|
|
35135
|
+
BEGIN
|
|
35136
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_te_hoog');
|
|
35137
|
+
SELECT oc.cart_number, oc.total_layers_used, oc.max_layers INTO c FROM logistics_active.order_carts oc WHERE oc.id = p_cart_id;
|
|
35138
|
+
IF NOT FOUND THEN RETURN jsonb_build_object('teHoog', false, 'blokkade', NULL); END IF;
|
|
35139
|
+
RETURN public.logistics_kar_blokkade(c.cart_number::text, c.total_layers_used, c.max_layers);
|
|
35140
|
+
END $$;
|
|
35141
|
+
|
|
35142
|
+
-- LayerSpace (zelfde algoritme als dimensionPlanner.ts): maximaal aantal fusten per laag, beide startrichtingen.
|
|
35143
|
+
CREATE OR REPLACE FUNCTION public.logistics_max_fusten_per_laag(p_ll numeric, p_lw numeric, p_fl numeric, p_fw numeric)
|
|
35144
|
+
RETURNS integer LANGUAGE plpgsql IMMUTABLE SET search_path TO 'public' AS $$
|
|
35145
|
+
DECLARE best int := 0; rnd int; a0 numeric; b0 numeric; n int; placed boolean;
|
|
35146
|
+
dep numeric[]; used numeric[]; total numeric; i int; k int; oa numeric; ob numeric; e numeric := 1e-9;
|
|
35147
|
+
BEGIN
|
|
35148
|
+
IF coalesce(p_ll,0) <= 0 OR coalesce(p_lw,0) <= 0 OR coalesce(p_fl,0) <= 0 OR coalesce(p_fw,0) <= 0 THEN RETURN NULL; END IF;
|
|
35149
|
+
FOR rnd IN 1..2 LOOP
|
|
35150
|
+
IF rnd = 1 THEN a0 := p_fl; b0 := p_fw; ELSE a0 := p_fw; b0 := p_fl; END IF;
|
|
35151
|
+
dep := '{}'; used := '{}'; total := 0; n := 0;
|
|
35152
|
+
LOOP
|
|
35153
|
+
EXIT WHEN n >= 100000;
|
|
35154
|
+
placed := false;
|
|
35155
|
+
FOR k IN 1..2 LOOP
|
|
35156
|
+
IF k = 1 THEN oa := a0; ob := b0; ELSE oa := b0; ob := a0; END IF;
|
|
35157
|
+
CONTINUE WHEN oa > p_ll OR ob > p_lw;
|
|
35158
|
+
FOR i IN 1..coalesce(array_length(dep,1),0) LOOP
|
|
35159
|
+
CONTINUE WHEN NOT (used[i] + oa <= p_ll + e);
|
|
35160
|
+
IF ob <= dep[i] + e THEN used[i] := used[i] + oa; placed := true; EXIT; END IF;
|
|
35161
|
+
IF i = array_length(dep,1) AND total - dep[i] + ob <= p_lw + e THEN
|
|
35162
|
+
total := total - dep[i] + ob; dep[i] := ob; used[i] := used[i] + oa; placed := true; EXIT;
|
|
35163
|
+
END IF;
|
|
35164
|
+
END LOOP;
|
|
35165
|
+
EXIT WHEN placed;
|
|
35166
|
+
IF total + ob <= p_lw + e THEN dep := dep || ob; used := used || oa; total := total + ob; placed := true; EXIT; END IF;
|
|
35167
|
+
END LOOP;
|
|
35168
|
+
EXIT WHEN NOT placed;
|
|
35169
|
+
n := n + 1;
|
|
35170
|
+
END LOOP;
|
|
35171
|
+
best := greatest(best, n);
|
|
35172
|
+
END LOOP;
|
|
35173
|
+
RETURN best;
|
|
35174
|
+
END $$;
|
|
35175
|
+
|
|
35176
|
+
-- Productoordeel (zelfde regel als "Gegevens voor karindeling").
|
|
35177
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_oordeel_many(p_product_ids uuid[])
|
|
35178
|
+
RETURNS TABLE(product_id uuid, oordeel text, tekst text, "actieUrl" text)
|
|
35179
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35180
|
+
#variable_conflict use_column
|
|
35181
|
+
DECLARE r record; c record; v_carrier text; ls int; fh numeric; ph numeric; cpl numeric; lpc numeric; laag numeric;
|
|
35182
|
+
blok text[]; waar text[]; mist text[]; hmist text[]; naam text; bron text;
|
|
35183
|
+
c_url constant text := '/logistiek-engine/beheer#gegevens-voor-karindeling';
|
|
35184
|
+
BEGIN
|
|
35185
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_oordeel_many');
|
|
35186
|
+
IF coalesce(cardinality(p_product_ids), 0) = 0 THEN RETURN; END IF;
|
|
35187
|
+
IF cardinality(p_product_ids) > 1000 THEN
|
|
35188
|
+
RAISE EXCEPTION 'Maximaal 1000 producten per aanroep (ontvangen: %).', cardinality(p_product_ids) USING ERRCODE = '22023';
|
|
35189
|
+
END IF;
|
|
35190
|
+
SELECT nullif(btrim(coalesce(s.settings->'karrenindeling'->'fields'->>'default_carrier_type', s.settings->'karrenindeling'->>'default_carrier_type')), '')
|
|
35191
|
+
INTO v_carrier FROM public.logistics_rule_configs s WHERE s.is_active ORDER BY s.updated_at DESC LIMIT 1;
|
|
35192
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm, t.max_crates_per_layer, t.layers_per_carrier INTO c
|
|
35193
|
+
FROM public.load_carrier_types t
|
|
35194
|
+
WHERE t.is_active AND (t.code = v_carrier OR (v_carrier IS NULL AND t.is_default))
|
|
35195
|
+
ORDER BY (t.code = v_carrier) DESC NULLS LAST LIMIT 1;
|
|
35196
|
+
naam := coalesce(c.name, c.code, 'de ladingdrager');
|
|
35197
|
+
|
|
35198
|
+
FOR r IN SELECT * FROM public.logistics_data_gereedheid(p_product_ids) LOOP
|
|
35199
|
+
blok := '{}'; waar := '{}'; hmist := '{}';
|
|
35200
|
+
mist := array_remove(coalesce(r.ontbrekend, '{}'), 'weight');
|
|
35201
|
+
bron := coalesce(r.velden->'crates_per_layer'->>'bron', 'product');
|
|
35202
|
+
cpl := coalesce(nullif(r.velden->'crates_per_layer'->>'waarde', '')::numeric, 0);
|
|
35203
|
+
lpc := coalesce(nullif(r.velden->'layers_per_cart'->>'waarde', '')::numeric, 0);
|
|
35204
|
+
fh := nullif(r.velden->'fust_height_mm'->>'waarde', '')::numeric / 10.0;
|
|
35205
|
+
ph := nullif(r.velden->'plant_height_cm'->>'waarde', '')::numeric;
|
|
35206
|
+
ls := public.logistics_max_fusten_per_laag(c.layer_length_cm, c.layer_width_cm,
|
|
35207
|
+
nullif(r.velden->'fust_length_mm'->>'waarde', '')::numeric / 10.0, nullif(r.velden->'fust_width_mm'->>'waarde', '')::numeric / 10.0);
|
|
35208
|
+
IF coalesce(fh,0) > 0 AND coalesce(ph,0) > 0 AND coalesce(c.max_height_cm,0) > 0 THEN
|
|
35209
|
+
laag := greatest(fh, ph);
|
|
35210
|
+
IF lpc * laag > c.max_height_cm + 1e-9 THEN
|
|
35211
|
+
blok := blok || format('%s lagen × %s cm = %s cm, terwijl %s %s cm hoog is; er passen maximaal %s lagen',
|
|
35212
|
+
lpc, trim_scale(round(laag,1)), trim_scale(round(lpc*laag,1)), naam, trim_scale(round(c.max_height_cm::numeric,1)), floor(c.max_height_cm / laag));
|
|
35213
|
+
END IF;
|
|
35214
|
+
ELSE
|
|
35215
|
+
IF coalesce(fh,0) <= 0 THEN hmist := hmist || 'fusthoogte'::text; END IF;
|
|
35216
|
+
IF coalesce(ph,0) <= 0 THEN hmist := hmist || 'planthoogte'::text; END IF;
|
|
35217
|
+
IF coalesce(c.max_height_cm,0) <= 0 THEN hmist := hmist || ('hoogte van ' || naam); END IF;
|
|
35218
|
+
END IF;
|
|
35219
|
+
IF ls IS NOT NULL AND cpl > ls THEN
|
|
35220
|
+
blok := blok || format('%s fust per laag (bron: %s), maar op een laag van %s passen er maximaal %s', cpl, bron, naam, ls);
|
|
35221
|
+
END IF;
|
|
35222
|
+
IF coalesce(c.max_crates_per_layer,0) > 0 AND cpl > c.max_crates_per_layer THEN
|
|
35223
|
+
blok := blok || format('%s fust per laag (bron: %s), maar %s staat maximaal %s fust per laag toe', cpl, bron, naam, c.max_crates_per_layer);
|
|
35224
|
+
END IF;
|
|
35225
|
+
IF cardinality(blok) = 0 AND cardinality(hmist) > 0 AND coalesce(c.layers_per_carrier,0) > 0 AND lpc > c.layers_per_carrier THEN
|
|
35226
|
+
waar := waar || format('%s lagen opgegeven, standaard %s; niet te controleren omdat de %s ontbreekt', lpc, c.layers_per_carrier, array_to_string(hmist, ', '));
|
|
35227
|
+
END IF;
|
|
35228
|
+
IF 'weight' = ANY(coalesce(r.ontbrekend, '{}')) THEN waar := waar || 'gewicht per fust ontbreekt'::text; END IF;
|
|
35229
|
+
|
|
35230
|
+
product_id := r.product_id; "actieUrl" := c_url;
|
|
35231
|
+
IF cardinality(blok) > 0 THEN
|
|
35232
|
+
oordeel := 'onmogelijk'; tekst := format('%s past niet op %s: %s.', r.product, naam, array_to_string(blok, '; '));
|
|
35233
|
+
ELSIF cardinality(mist) > 0 THEN
|
|
35234
|
+
oordeel := 'mist_gegevens'; tekst := r.uitleg;
|
|
35235
|
+
ELSIF cardinality(waar) > 0 THEN
|
|
35236
|
+
oordeel := 'waarschuwing'; tekst := format('%s: %s.', r.product, array_to_string(waar, '; '));
|
|
35237
|
+
ELSE
|
|
35238
|
+
oordeel := 'compleet'; tekst := format('%s: gegevens voor karindeling compleet.', r.product);
|
|
35239
|
+
END IF;
|
|
35240
|
+
RETURN NEXT;
|
|
35241
|
+
END LOOP;
|
|
35242
|
+
END $$;
|
|
35243
|
+
|
|
35244
|
+
GRANT EXECUTE ON FUNCTION public.logistics_kar_blokkade(text, numeric, numeric) TO authenticated, service_role;
|
|
35245
|
+
GRANT EXECUTE ON FUNCTION public.logistics_max_fusten_per_laag(numeric, numeric, numeric, numeric) TO authenticated, service_role;
|
|
35246
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_te_hoge_karren(uuid[]) TO authenticated, service_role;
|
|
35247
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_te_hoog(uuid) TO authenticated, service_role;
|
|
35248
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_oordeel_many(uuid[]) TO authenticated, service_role;
|
|
35249
|
+
|
|
35250
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_201b()
|
|
35251
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35252
|
+
SELECT 'kar_te_hoog-regel', to_regprocedure('public.logistics_kar_blokkade(text,numeric,numeric)') IS NOT NULL, 'Blokkade per kar (teHoog/blokkade)'
|
|
35253
|
+
UNION ALL SELECT 'guard pakbonfunctie', position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_cart_slip_plan(uuid)'::regprocedure)) > 0, 'logistics_cart_slip_plan controleert de aanroeper'
|
|
35254
|
+
UNION ALL SELECT 'guard pakbonkopie', to_regprocedure('public.logistics_cart_slip_plan_v200(uuid)') IS NULL OR position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_cart_slip_plan_v200(uuid)'::regprocedure)) > 0, 'logistics_cart_slip_plan_v200 controleert de aanroeper'
|
|
35255
|
+
UNION ALL SELECT 'guard kar-aanvulling', position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_cart_platen_verrijk(jsonb)'::regprocedure)) > 0, 'logistics_cart_platen_verrijk controleert de aanroeper'
|
|
35256
|
+
UNION ALL SELECT 'productoordeel', to_regprocedure('public.logistics_product_oordeel_many(uuid[])') IS NOT NULL, 'Oordeel per product voor het orderformulier'
|
|
35257
|
+
$$;
|
|
35258
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_201b() TO authenticated, service_role;
|
|
35259
|
+
|
|
35260
|
+
-- ============================================================================
|
|
35261
|
+
-- 1.0.204: capaciteit gemengde kar, vastzetten na vastliggen, geenIndeling.regels, productoordeel met gekozen belading
|
|
35262
|
+
-- ============================================================================
|
|
35263
|
+
-- 1.0.204: capaciteit gemengde kar, vastzetten na vastliggen, geenIndeling.regels, productoordeel met gekozen belading.
|
|
35264
|
+
|
|
35265
|
+
-- Kern (geen guard, SECURITY INVOKER): capaciteit en lagen van één kar.
|
|
35266
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_capaciteit_core(p_cart_id uuid)
|
|
35267
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
35268
|
+
WITH c AS (SELECT oc.cart_number, oc.total_layers_used, oc.max_layers FROM logistics_active.order_carts oc WHERE oc.id = p_cart_id),
|
|
35269
|
+
i AS (SELECT count(*) n, count(*) FILTER (WHERE coalesce(ci.crates_per_layer, 0) > 0) ncpl,
|
|
35270
|
+
sum(ci.crates::numeric / nullif(ci.crates_per_layer, 0)) lagen, max(nullif(ci.layers_per_cart, 0)) lpc
|
|
35271
|
+
FROM logistics_active.order_cart_items ci WHERE ci.cart_id = p_cart_id),
|
|
35272
|
+
v AS (SELECT c.cart_number,
|
|
35273
|
+
CASE WHEN i.n > 0 AND i.n = i.ncpl THEN round(i.lagen, 2) ELSE c.total_layers_used::numeric END lagen,
|
|
35274
|
+
coalesce(i.lpc::numeric, nullif(c.max_layers, 0)::numeric) cap,
|
|
35275
|
+
CASE WHEN i.lpc IS NOT NULL THEN 'product' WHEN coalesce(c.max_layers, 0) > 0 THEN 'ladingdrager' END bron
|
|
35276
|
+
FROM c, i)
|
|
35277
|
+
SELECT jsonb_build_object('layersUsed', v.lagen, 'maxLayers', v.cap, 'capaciteitBron', v.bron,
|
|
35278
|
+
'vulgraadPct', CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END,
|
|
35279
|
+
'layerUtilizationPct', CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END)
|
|
35280
|
+
|| public.logistics_kar_blokkade(v.cart_number::text, v.lagen, v.cap)
|
|
35281
|
+
FROM v
|
|
35282
|
+
$$;
|
|
35283
|
+
|
|
35284
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_platen_verrijk(p_cart jsonb)
|
|
35285
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35286
|
+
DECLARE v_id uuid; k jsonb; c jsonb := p_cart; v_l numeric;
|
|
35287
|
+
BEGIN
|
|
35288
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_platen_verrijk');
|
|
35289
|
+
BEGIN v_id := nullif(coalesce(p_cart->>'cartId', p_cart->>'cart_id'), '')::uuid; EXCEPTION WHEN invalid_text_representation THEN v_id := NULL; END;
|
|
35290
|
+
IF v_id IS NOT NULL THEN k := public.logistics_cart_capaciteit_core(v_id); END IF;
|
|
35291
|
+
IF k IS NOT NULL THEN
|
|
35292
|
+
c := c || jsonb_build_object('layersUsed', k->'layersUsed', 'maxLayers', k->'maxLayers', 'capaciteitBron', k->'capaciteitBron',
|
|
35293
|
+
'vulgraadPct', k->'vulgraadPct', 'layerUtilizationPct', k->'layerUtilizationPct');
|
|
35294
|
+
END IF;
|
|
35295
|
+
v_l := nullif(c->>'layersUsed', '')::numeric;
|
|
35296
|
+
RETURN c || jsonb_build_object(
|
|
35297
|
+
'additionalLayers', public.logistics_extra_platen(v_l),
|
|
35298
|
+
'ladingdragerTekst', public.logistics_ladingdrager_tekst(c->>'carrierType', v_l,
|
|
35299
|
+
coalesce(nullif(c->>'vulgraadPct', '')::numeric, nullif(c->>'layerUtilizationPct', '')::numeric, nullif(c->>'occupancyPct', '')::numeric)))
|
|
35300
|
+
|| public.logistics_kar_blokkade(coalesce(c->>'cartNumber', c->>'cart_number', c->>'seq'), v_l, nullif(c->>'maxLayers', '')::numeric);
|
|
35301
|
+
END $$;
|
|
35302
|
+
|
|
35303
|
+
-- Te hoge karren: alleen karren met eigen regels van de order.
|
|
35304
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_te_hoge_karren(p_order_ids uuid[])
|
|
35305
|
+
RETURNS TABLE(order_id uuid, cart_id uuid, cart_number integer, lagen numeric, max_lagen numeric, blokkade jsonb)
|
|
35306
|
+
LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
35307
|
+
BEGIN
|
|
35308
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_te_hoge_karren');
|
|
35309
|
+
RETURN QUERY
|
|
35310
|
+
SELECT x.order_id, x.cart_id, x.nr, (x.k->>'layersUsed')::numeric, (x.k->>'maxLayers')::numeric,
|
|
35311
|
+
public.logistics_kar_blokkade(x.nr::text, (x.k->>'layersUsed')::numeric, (x.k->>'maxLayers')::numeric)->'blokkade'
|
|
35312
|
+
FROM (SELECT u.order_id, u.cart_id, coalesce(u.display_seq, u.cart_number) nr, public.logistics_cart_capaciteit_core(u.cart_id) k
|
|
35313
|
+
FROM public.logistics_order_unit_carts_core(p_order_ids) u
|
|
35314
|
+
WHERE EXISTS (SELECT 1 FROM logistics_active.order_cart_items ci JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35315
|
+
WHERE ci.cart_id = u.cart_id AND oi.order_id = u.order_id)) x
|
|
35316
|
+
WHERE coalesce((x.k->>'teHoog')::boolean, false);
|
|
35317
|
+
END $$;
|
|
35318
|
+
|
|
35319
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_te_hoog(p_cart_id uuid)
|
|
35320
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35321
|
+
DECLARE k jsonb;
|
|
35322
|
+
BEGIN
|
|
35323
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_te_hoog');
|
|
35324
|
+
k := public.logistics_cart_capaciteit_core(p_cart_id);
|
|
35325
|
+
IF k IS NULL THEN RETURN jsonb_build_object('teHoog', false, 'blokkade', NULL); END IF;
|
|
35326
|
+
RETURN jsonb_build_object('teHoog', k->'teHoog', 'blokkade', k->'blokkade');
|
|
35327
|
+
END $$;
|
|
35328
|
+
|
|
35329
|
+
-- Korte zinnen uit een redentekst.
|
|
35330
|
+
CREATE OR REPLACE FUNCTION public.logistics_tekst_regels(p_tekst text)
|
|
35331
|
+
RETURNS jsonb LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$
|
|
35332
|
+
SELECT coalesce(jsonb_agg(z ORDER BY o), '[]'::jsonb)
|
|
35333
|
+
FROM (SELECT btrim(regexp_replace(s, '[;\s]+$', '')) z, o
|
|
35334
|
+
FROM regexp_split_to_table(coalesce(p_tekst, ''), '(?<=[.;])\s+') WITH ORDINALITY t(s, o)) q
|
|
35335
|
+
WHERE z <> ''
|
|
35336
|
+
$$;
|
|
35337
|
+
|
|
35338
|
+
-- Vastliggend (geprint/gescand/in pick), zonder guard: alleen voor gebruik in bewaakte functies.
|
|
35339
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_vast_core(p_cart_id uuid)
|
|
35340
|
+
RETURNS boolean LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
35341
|
+
SELECT p_cart_id IS NOT NULL AND (
|
|
35342
|
+
EXISTS (SELECT 1 FROM public.print_jobs pj
|
|
35343
|
+
WHERE pj.payload->>'cart_id' = p_cart_id::text AND pj.documenttype = 'pakbon'
|
|
35344
|
+
AND coalesce(pj.is_herprint, false) = false AND pj.status IN ('wachtend', 'bezig', 'voltooid')
|
|
35345
|
+
AND coalesce(pj.foutcode, '') NOT IN ('verlopen', 'expired')
|
|
35346
|
+
AND coalesce(pj.verwerkingsfase, '') NOT IN ('verlopen', 'expired'))
|
|
35347
|
+
OR EXISTS (SELECT 1 FROM public.cart_control_items ci WHERE ci.cart_number_id = p_cart_id)
|
|
35348
|
+
OR EXISTS (SELECT 1 FROM public.pick_queue q WHERE q.cancelled_at IS NULL
|
|
35349
|
+
AND jsonb_typeof(q.printed_cart_ids) = 'array' AND q.printed_cart_ids ? p_cart_id::text))
|
|
35350
|
+
$$;
|
|
35351
|
+
|
|
35352
|
+
-- Karindeling verouderd: vastgezette belading wijkt af van wat op de karren staat.
|
|
35353
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_indeling_verouderd_core(p_order_id uuid)
|
|
35354
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
35355
|
+
WITH a AS (
|
|
35356
|
+
SELECT oi.id, coalesce(oi.product_name, 'regel') naam, ci.cart_id,
|
|
35357
|
+
(oi.plants_per_crate IS DISTINCT FROM ci.plants_per_crate
|
|
35358
|
+
OR oi.crates_per_layer IS DISTINCT FROM ci.crates_per_layer
|
|
35359
|
+
OR oi.layers_per_cart IS DISTINCT FROM ci.layers_per_cart) afwijkend
|
|
35360
|
+
FROM public.order_items oi
|
|
35361
|
+
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
35362
|
+
WHERE oi.order_id = p_order_id AND oi.packing_locked_at IS NOT NULL)
|
|
35363
|
+
SELECT CASE WHEN bool_or(afwijkend) THEN jsonb_build_object(
|
|
35364
|
+
'verouderd', true,
|
|
35365
|
+
'producten', to_jsonb(array_agg(DISTINCT naam) FILTER (WHERE afwijkend)),
|
|
35366
|
+
'vastliggendeKarren', (SELECT count(DISTINCT a2.cart_id) FROM a a2 WHERE public.logistics_cart_vast_core(a2.cart_id)),
|
|
35367
|
+
'tekst', 'De belading is gewijzigd, maar de karindeling is nog oud. Deel de niet-geprinte karren opnieuw in.')
|
|
35368
|
+
ELSE NULL END
|
|
35369
|
+
FROM a
|
|
35370
|
+
$$;
|
|
35371
|
+
|
|
35372
|
+
-- geenIndeling met korte zinnen.
|
|
35373
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_geen_indeling_core(p_order_id uuid)
|
|
35374
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35375
|
+
DECLARE o record; q record; d record; t record; v_code text; v_tekst text; v_soort text; v_actie text;
|
|
35376
|
+
c_beheer constant text := '/logistiek-engine/beheer';
|
|
35377
|
+
BEGIN
|
|
35378
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_geen_indeling_core');
|
|
35379
|
+
SELECT id, order_number, buffer_id INTO o FROM public.orders WHERE id = p_order_id;
|
|
35380
|
+
IF NOT FOUND THEN RETURN NULL; END IF;
|
|
35381
|
+
SELECT * INTO t FROM public.logistics_order_te_hoge_karren(ARRAY[p_order_id]) ORDER BY cart_number LIMIT 1;
|
|
35382
|
+
IF FOUND THEN
|
|
35383
|
+
v_code := 'kar_te_hoog'; v_tekst := t.blokkade->>'tekst'; v_actie := 'belading_aanpassen';
|
|
35384
|
+
ELSE
|
|
35385
|
+
SELECT status, reason, reason_code INTO q FROM public.logistics_plan_queue
|
|
35386
|
+
WHERE order_id = p_order_id ORDER BY updated_at DESC NULLS LAST LIMIT 1;
|
|
35387
|
+
IF FOUND AND q.status = 'geblokkeerd' THEN
|
|
35388
|
+
v_code := coalesce(q.reason_code, 'geblokkeerd'); v_tekst := q.reason;
|
|
35389
|
+
ELSE
|
|
35390
|
+
SELECT dd.result, dd.explanation, dd.input_snapshot INTO d
|
|
35391
|
+
FROM public.logistics_decisions dd
|
|
35392
|
+
WHERE dd.slot = 'beladingindeling'
|
|
35393
|
+
AND ((dd.subject_type = 'order' AND dd.subject_id = o.id::text)
|
|
35394
|
+
OR (dd.subject_type = 'buffer' AND o.buffer_id IS NOT NULL AND dd.subject_id = o.buffer_id::text)
|
|
35395
|
+
OR (o.order_number IS NOT NULL AND coalesce(dd.input_snapshot->'members', '[]'::jsonb) ? o.order_number))
|
|
35396
|
+
ORDER BY dd.created_at DESC LIMIT 1;
|
|
35397
|
+
IF FOUND AND coalesce((d.result->>'blocked')::boolean, false) THEN
|
|
35398
|
+
v_code := coalesce(d.result->>'reason_code', 'geblokkeerd'); v_tekst := d.explanation;
|
|
35399
|
+
v_soort := d.input_snapshot->>'soort';
|
|
35400
|
+
ELSIF q.status IN ('pending', 'running') THEN
|
|
35401
|
+
v_code := 'wacht_op_indeling'; v_tekst := 'De karindeling wordt gemaakt; dit duurt meestal enkele seconden.';
|
|
35402
|
+
ELSE
|
|
35403
|
+
v_code := 'onbekend';
|
|
35404
|
+
v_tekst := 'Er is nog geen karindeling en er is geen blokkade vastgelegd. De minuutronde probeert het opnieuw; blijft dit staan, meld het aan beheer.';
|
|
35405
|
+
END IF;
|
|
35406
|
+
END IF;
|
|
35407
|
+
IF v_code LIKE 'belading%' OR v_code = 'ladingdrager_niet_in_beheer' THEN v_actie := 'belading_aanpassen'; END IF;
|
|
35408
|
+
END IF;
|
|
35409
|
+
v_tekst := coalesce(nullif(btrim(v_tekst), ''), 'Geen indeling; de reden is niet bekend.');
|
|
35410
|
+
RETURN jsonb_build_object('code', v_code, 'soort', v_soort, 'tekst', v_tekst,
|
|
35411
|
+
'regels', public.logistics_tekst_regels(v_tekst),
|
|
35412
|
+
'actie', coalesce(v_actie, 'beheer'),
|
|
35413
|
+
'actieLabel', CASE WHEN v_actie IS NOT NULL THEN 'Belading aanpassen' ELSE 'Naar Engine-beheer' END,
|
|
35414
|
+
'actieUrl', CASE WHEN v_actie IS NOT NULL THEN c_beheer || '#gegevens-voor-karindeling' ELSE c_beheer END);
|
|
35415
|
+
END $$;
|
|
35416
|
+
|
|
35417
|
+
-- Coverage: per kar capaciteit uit de producten, één vulgraad; indelingVerouderd op orderniveau.
|
|
35418
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_plan_coverage(p_order_id uuid)
|
|
35419
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35420
|
+
DECLARE b jsonb; x jsonb; v_hoog boolean;
|
|
35421
|
+
BEGIN
|
|
35422
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_plan_coverage');
|
|
35423
|
+
b := public.logistics_order_plan_coverage_v165(p_order_id);
|
|
35424
|
+
x := public.logistics_order_external_state(p_order_id);
|
|
35425
|
+
IF jsonb_typeof(b->'carts') = 'array' THEN
|
|
35426
|
+
b := b || jsonb_build_object('carts', (
|
|
35427
|
+
SELECT coalesce(jsonb_agg(
|
|
35428
|
+
CASE WHEN c.id IS NULL THEN t.e || jsonb_build_object('additionalLayers', NULL, 'layersUsed', NULL, 'teHoog', false, 'blokkade', NULL,
|
|
35429
|
+
'capaciteitBron', NULL, 'vulgraadPct', NULL)
|
|
35430
|
+
ELSE public.logistics_cart_platen_verrijk(t.e || jsonb_build_object('occupancyPct', c.occupancy_pct)) END
|
|
35431
|
+
ORDER BY t.o), '[]'::jsonb)
|
|
35432
|
+
FROM jsonb_array_elements(b->'carts') WITH ORDINALITY t(e, o)
|
|
35433
|
+
LEFT JOIN logistics_active.order_carts c ON c.id::text = t.e->>'cartId'));
|
|
35434
|
+
END IF;
|
|
35435
|
+
IF x IS NOT NULL AND (x->>'full')::boolean THEN
|
|
35436
|
+
b := b || jsonb_build_object('state', 'afgehandeld_extern', 'label', 'Afgehandeld in Floriday',
|
|
35437
|
+
'reason', 'De order is in Floriday afgehandeld; de Engine plant en print er niets meer voor.');
|
|
35438
|
+
END IF;
|
|
35439
|
+
v_hoog := EXISTS (SELECT 1 FROM public.logistics_order_te_hoge_karren(ARRAY[p_order_id]));
|
|
35440
|
+
IF v_hoog AND b->>'state' IS DISTINCT FROM 'afgehandeld_extern' THEN
|
|
35441
|
+
b := b || jsonb_build_object('label', 'Ingedeeld — kar te hoog');
|
|
35442
|
+
END IF;
|
|
35443
|
+
b := b || jsonb_build_object('geenIndeling',
|
|
35444
|
+
CASE WHEN b->>'state' IN ('geen_indeling', 'deels') OR (v_hoog AND b->>'state' IS DISTINCT FROM 'afgehandeld_extern')
|
|
35445
|
+
THEN public.logistics_order_geen_indeling_core(p_order_id) END,
|
|
35446
|
+
'indelingVerouderd', public.logistics_order_indeling_verouderd_core(p_order_id));
|
|
35447
|
+
RETURN b || jsonb_build_object('externalFulfilled', x);
|
|
35448
|
+
END $$;
|
|
35449
|
+
|
|
35450
|
+
-- Vastzet-voorvertoning: meldt vastliggende karren en de mogelijke actie.
|
|
35451
|
+
DO $do$ BEGIN
|
|
35452
|
+
IF to_regprocedure('public.logistics_belading_vastzet_preview_v201(uuid,jsonb)') IS NULL THEN
|
|
35453
|
+
EXECUTE replace(pg_get_functiondef('public.logistics_belading_vastzet_preview(uuid,jsonb)'::regprocedure),
|
|
35454
|
+
'public.logistics_belading_vastzet_preview(', 'public.logistics_belading_vastzet_preview_v201(');
|
|
35455
|
+
END IF;
|
|
35456
|
+
END $do$;
|
|
35457
|
+
|
|
35458
|
+
CREATE OR REPLACE FUNCTION public.logistics_belading_vastzet_preview(p_order_item_id uuid, p_wijziging jsonb)
|
|
35459
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35460
|
+
DECLARE pv jsonb; v_order uuid; v_vast int; v_totaal int; v_tekst text;
|
|
35461
|
+
BEGIN
|
|
35462
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_belading_vastzet_preview');
|
|
35463
|
+
pv := public.logistics_belading_vastzet_preview_v201(p_order_item_id, p_wijziging);
|
|
35464
|
+
SELECT order_id INTO v_order FROM public.order_items WHERE id = p_order_item_id;
|
|
35465
|
+
SELECT count(DISTINCT u.cart_id), count(DISTINCT u.cart_id) FILTER (WHERE public.logistics_cart_vast_core(u.cart_id))
|
|
35466
|
+
INTO v_totaal, v_vast FROM public.logistics_order_unit_carts_core(ARRAY[v_order]) u;
|
|
35467
|
+
IF coalesce(v_vast, 0) > 0 THEN
|
|
35468
|
+
v_tekst := format('%s van %s kar(ren) zijn al geprint of in pick; de nieuwe belading geldt pas na herindelen. Herindelen verandert alleen de niet-geprinte karren.',
|
|
35469
|
+
v_vast, v_totaal);
|
|
35470
|
+
pv := pv || jsonb_build_object('tekst', (pv->>'tekst') || ' ' || v_tekst, 'bevestigingNodig', true);
|
|
35471
|
+
END IF;
|
|
35472
|
+
RETURN pv || jsonb_build_object('vastliggendeKarren', coalesce(v_vast, 0), 'karrenTotaal', coalesce(v_totaal, 0),
|
|
35473
|
+
'vastliggendTekst', v_tekst,
|
|
35474
|
+
'acties', CASE WHEN coalesce(v_vast, 0) > 0
|
|
35475
|
+
THEN jsonb_build_array(jsonb_build_object('actie', 'herindelen_niet_geprint', 'label', 'Niet-geprinte karren opnieuw indelen',
|
|
35476
|
+
'rpc', 'logistics_order_herindelen'))
|
|
35477
|
+
ELSE '[]'::jsonb END);
|
|
35478
|
+
END $$;
|
|
35479
|
+
|
|
35480
|
+
-- Herindelen van de niet-geprinte karren (vastliggende karren blijven staan).
|
|
35481
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_herindelen(p_order_id uuid)
|
|
35482
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35483
|
+
DECLARE v_vast int;
|
|
35484
|
+
BEGIN
|
|
35485
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_herindelen');
|
|
35486
|
+
IF auth.uid() IS NULL AND NOT public._scan_is_server() THEN RAISE EXCEPTION 'niet ingelogd'; END IF;
|
|
35487
|
+
IF NOT EXISTS (SELECT 1 FROM public.orders WHERE id = p_order_id) THEN RAISE EXCEPTION 'Order niet gevonden.'; END IF;
|
|
35488
|
+
SELECT count(DISTINCT u.cart_id) FILTER (WHERE public.logistics_cart_vast_core(u.cart_id)) INTO v_vast
|
|
35489
|
+
FROM public.logistics_order_unit_carts_core(ARRAY[p_order_id]) u;
|
|
35490
|
+
PERFORM public.logistics_plan_enqueue(p_order_id, 'belading gewijzigd: niet-geprinte karren opnieuw indelen');
|
|
35491
|
+
RETURN jsonb_build_object('ok', true, 'vastliggendeKarren', coalesce(v_vast, 0),
|
|
35492
|
+
'tekst', CASE WHEN coalesce(v_vast, 0) > 0 THEN format('Herindeling gestart; %s vastliggende kar(ren) blijven staan.', v_vast)
|
|
35493
|
+
ELSE 'Herindeling gestart.' END);
|
|
35494
|
+
END $$;
|
|
35495
|
+
|
|
35496
|
+
-- Productoordeel met de gekozen belading per regel (zelfde fysieke regel als Beheer).
|
|
35497
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_oordeel_belading(p_regels jsonb)
|
|
35498
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35499
|
+
DECLARE e jsonb; g record; c record; v_def text; v_code text; ids uuid[]; uit jsonb := '[]'::jsonb;
|
|
35500
|
+
ls int; fh numeric; ph numeric; cpl numeric; lpc numeric; ppc numeric; laag numeric; naam text;
|
|
35501
|
+
blok text[]; waar text[]; mist text[]; hmist text[]; v_pid uuid; v_oordeel text; v_tekst text;
|
|
35502
|
+
BEGIN
|
|
35503
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_oordeel_belading');
|
|
35504
|
+
IF p_regels IS NULL OR jsonb_typeof(p_regels) <> 'array' THEN RAISE EXCEPTION 'p_regels moet een lijst zijn.' USING ERRCODE = '22023'; END IF;
|
|
35505
|
+
IF jsonb_array_length(p_regels) > 1000 THEN
|
|
35506
|
+
RAISE EXCEPTION 'Maximaal 1000 regels per aanroep (ontvangen: %).', jsonb_array_length(p_regels) USING ERRCODE = '22023';
|
|
35507
|
+
END IF;
|
|
35508
|
+
SELECT array_agg(DISTINCT (x->>'product_id')::uuid) INTO ids FROM jsonb_array_elements(p_regels) x WHERE nullif(x->>'product_id', '') IS NOT NULL;
|
|
35509
|
+
CREATE TEMP TABLE IF NOT EXISTS _oordeel_g ON COMMIT DROP AS SELECT * FROM public.logistics_data_gereedheid(ARRAY[]::uuid[]) LIMIT 0;
|
|
35510
|
+
DELETE FROM _oordeel_g WHERE true;
|
|
35511
|
+
IF ids IS NOT NULL THEN INSERT INTO _oordeel_g SELECT * FROM public.logistics_data_gereedheid(ids); END IF;
|
|
35512
|
+
SELECT nullif(btrim(coalesce(s.settings->'karrenindeling'->'fields'->>'default_carrier_type', s.settings->'karrenindeling'->>'default_carrier_type')), '')
|
|
35513
|
+
INTO v_def FROM public.logistics_rule_configs s WHERE s.is_active ORDER BY s.updated_at DESC LIMIT 1;
|
|
35514
|
+
|
|
35515
|
+
FOR e IN SELECT x FROM jsonb_array_elements(p_regels) x LOOP
|
|
35516
|
+
blok := '{}'; waar := '{}'; mist := '{}'; hmist := '{}';
|
|
35517
|
+
v_pid := nullif(e->>'product_id', '')::uuid;
|
|
35518
|
+
SELECT * INTO g FROM _oordeel_g WHERE product_id = v_pid;
|
|
35519
|
+
v_code := coalesce(nullif(btrim(e->>'carrier_code'), ''), v_def);
|
|
35520
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm, t.max_crates_per_layer, t.layers_per_carrier INTO c
|
|
35521
|
+
FROM public.load_carrier_types t
|
|
35522
|
+
WHERE t.is_active AND (t.code = v_code OR (v_code IS NULL AND t.is_default))
|
|
35523
|
+
ORDER BY (t.code = v_code) DESC NULLS LAST LIMIT 1;
|
|
35524
|
+
naam := coalesce(c.name, c.code, 'de ladingdrager');
|
|
35525
|
+
ppc := nullif(e->>'plants_per_crate', '')::numeric;
|
|
35526
|
+
cpl := nullif(e->>'crates_per_layer', '')::numeric;
|
|
35527
|
+
lpc := nullif(e->>'layers_per_cart', '')::numeric;
|
|
35528
|
+
IF coalesce(ppc, 0) <= 0 THEN mist := mist || 'planten per fust'::text; END IF;
|
|
35529
|
+
IF coalesce(cpl, 0) <= 0 THEN mist := mist || 'fusten per laag'::text; END IF;
|
|
35530
|
+
IF coalesce(lpc, 0) <= 0 THEN mist := mist || 'lagen per kar'::text; END IF;
|
|
35531
|
+
IF v_code IS NOT NULL AND c.code IS NULL THEN blok := blok || format('ladingdrager %s staat niet in Beheer', v_code); END IF;
|
|
35532
|
+
IF g.product_id IS NULL THEN
|
|
35533
|
+
mist := mist || 'product onbekend'::text;
|
|
35534
|
+
ELSE
|
|
35535
|
+
fh := nullif(g.velden->'fust_height_mm'->>'waarde', '')::numeric / 10.0;
|
|
35536
|
+
ph := nullif(g.velden->'plant_height_cm'->>'waarde', '')::numeric;
|
|
35537
|
+
ls := public.logistics_max_fusten_per_laag(c.layer_length_cm, c.layer_width_cm,
|
|
35538
|
+
nullif(g.velden->'fust_length_mm'->>'waarde', '')::numeric / 10.0, nullif(g.velden->'fust_width_mm'->>'waarde', '')::numeric / 10.0);
|
|
35539
|
+
IF coalesce(lpc,0) > 0 AND coalesce(fh,0) > 0 AND coalesce(ph,0) > 0 AND coalesce(c.max_height_cm,0) > 0 THEN
|
|
35540
|
+
laag := greatest(fh, ph);
|
|
35541
|
+
IF lpc * laag > c.max_height_cm + 1e-9 THEN
|
|
35542
|
+
blok := blok || format('%s lagen × %s cm = %s cm, terwijl %s %s cm hoog is; er passen maximaal %s lagen',
|
|
35543
|
+
lpc, trim_scale(round(laag,1)), trim_scale(round(lpc*laag,1)), naam, trim_scale(round(c.max_height_cm::numeric,1)), floor(c.max_height_cm / laag));
|
|
35544
|
+
END IF;
|
|
35545
|
+
ELSE
|
|
35546
|
+
IF coalesce(fh,0) <= 0 THEN hmist := hmist || 'fusthoogte'::text; END IF;
|
|
35547
|
+
IF coalesce(ph,0) <= 0 THEN hmist := hmist || 'planthoogte'::text; END IF;
|
|
35548
|
+
IF coalesce(c.max_height_cm,0) <= 0 THEN hmist := hmist || ('hoogte van ' || naam); END IF;
|
|
35549
|
+
END IF;
|
|
35550
|
+
IF ls IS NOT NULL AND coalesce(cpl,0) > ls THEN
|
|
35551
|
+
blok := blok || format('%s fust per laag, maar op een laag van %s passen er maximaal %s', cpl, naam, ls);
|
|
35552
|
+
END IF;
|
|
35553
|
+
IF coalesce(c.max_crates_per_layer,0) > 0 AND coalesce(cpl,0) > c.max_crates_per_layer THEN
|
|
35554
|
+
blok := blok || format('%s fust per laag, maar %s staat maximaal %s fust per laag toe', cpl, naam, c.max_crates_per_layer);
|
|
35555
|
+
END IF;
|
|
35556
|
+
IF cardinality(blok) = 0 AND cardinality(hmist) > 0 AND coalesce(c.layers_per_carrier,0) > 0 AND coalesce(lpc,0) > c.layers_per_carrier THEN
|
|
35557
|
+
waar := waar || format('%s lagen opgegeven, standaard %s; niet te controleren omdat de %s ontbreekt', lpc, c.layers_per_carrier, array_to_string(hmist, ', '));
|
|
35558
|
+
END IF;
|
|
35559
|
+
IF 'weight' = ANY(coalesce(g.ontbrekend, '{}')) THEN waar := waar || 'gewicht per fust ontbreekt'::text; END IF;
|
|
35560
|
+
END IF;
|
|
35561
|
+
IF cardinality(blok) > 0 THEN
|
|
35562
|
+
v_oordeel := 'onmogelijk'; v_tekst := format('%s past niet op %s.', coalesce(g.product, 'Product'), naam);
|
|
35563
|
+
ELSIF cardinality(mist) > 0 THEN
|
|
35564
|
+
v_oordeel := 'mist_gegevens'; v_tekst := format('%s: %s ontbreekt.', coalesce(g.product, 'Product'), array_to_string(mist, ', '));
|
|
35565
|
+
ELSIF cardinality(waar) > 0 THEN
|
|
35566
|
+
v_oordeel := 'waarschuwing'; v_tekst := format('%s: belading mogelijk, met waarschuwing.', g.product);
|
|
35567
|
+
ELSE
|
|
35568
|
+
v_oordeel := 'compleet'; v_tekst := format('%s: belading past.', g.product);
|
|
35569
|
+
END IF;
|
|
35570
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', v_oordeel, 'tekst', v_tekst,
|
|
35571
|
+
'regels', to_jsonb(ARRAY(SELECT upper(left(z,1)) || substr(z,2) || '.' FROM unnest(blok || mist || waar) z))));
|
|
35572
|
+
END LOOP;
|
|
35573
|
+
RETURN uit;
|
|
35574
|
+
END $$;
|
|
35575
|
+
|
|
35576
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_capaciteit_core(uuid) TO authenticated, service_role;
|
|
35577
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_vast_core(uuid) TO service_role;
|
|
35578
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_indeling_verouderd_core(uuid) TO service_role;
|
|
35579
|
+
GRANT EXECUTE ON FUNCTION public.logistics_tekst_regels(text) TO authenticated, service_role;
|
|
35580
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_herindelen(uuid) TO authenticated, service_role;
|
|
35581
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_oordeel_belading(jsonb) TO authenticated, service_role;
|
|
35582
|
+
|
|
35583
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_204()
|
|
35584
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35585
|
+
SELECT 'capaciteit gemengde kar', to_regprocedure('public.logistics_cart_capaciteit_core(uuid)') IS NOT NULL, 'Capaciteit = hoogste lagen per kar van de producten'
|
|
35586
|
+
UNION ALL SELECT 'te hoog per kar', position('oi.order_id = u.order_id' IN pg_get_functiondef('public.logistics_order_te_hoge_karren(uuid[])'::regprocedure)) > 0, 'Alleen karren met eigen regels'
|
|
35587
|
+
UNION ALL SELECT 'indeling verouderd', position('indelingVerouderd' IN pg_get_functiondef('public.logistics_order_plan_coverage(uuid)'::regprocedure)) > 0, 'Coverage meldt verouderde indeling'
|
|
35588
|
+
UNION ALL SELECT 'vastzet vastliggend', position('vastliggendeKarren' IN pg_get_functiondef('public.logistics_belading_vastzet_preview(uuid,jsonb)'::regprocedure)) > 0, 'Voorvertoning meldt vastliggende karren'
|
|
35589
|
+
UNION ALL SELECT 'geenIndeling.regels', position('logistics_tekst_regels' IN pg_get_functiondef('public.logistics_order_geen_indeling_core(uuid)'::regprocedure)) > 0, 'Reden in korte zinnen'
|
|
35590
|
+
UNION ALL SELECT 'productoordeel belading', to_regprocedure('public.logistics_product_oordeel_belading(jsonb)') IS NOT NULL, 'Oordeel met gekozen belading (Verkoop)'
|
|
35591
|
+
UNION ALL SELECT 'guards 1.0.204', position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_order_herindelen(uuid)'::regprocedure)) > 0
|
|
35592
|
+
AND position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_product_oordeel_belading(jsonb)'::regprocedure)) > 0, 'Nieuwe functies controleren de aanroeper'
|
|
35593
|
+
$$;
|
|
35594
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_204() TO authenticated, service_role;
|
|
35595
|
+
-- 1.0.204: tekst_regels zonder lookbehind
|
|
35596
|
+
CREATE OR REPLACE FUNCTION public.logistics_tekst_regels(p_tekst text)
|
|
35597
|
+
RETURNS jsonb LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$
|
|
35598
|
+
SELECT coalesce(jsonb_agg(z || CASE WHEN z ~ '[.!?]$' THEN '' ELSE '.' END ORDER BY o), '[]'::jsonb)
|
|
35599
|
+
FROM (SELECT btrim(s) z, o FROM regexp_split_to_table(coalesce(p_tekst, ''), '[.;]\s+') WITH ORDINALITY t(s, o)) q
|
|
35600
|
+
WHERE z <> ''
|
|
35601
|
+
$$;
|
|
35602
|
+
|
|
35603
|
+
-- ===== 1.0.204 vervolg: menging per laag, printer verzendbrief =====
|
|
35604
|
+
-- 1.0.204 vervolg: menging per laag in de capaciteitsberekening; printer van de volgende verzendbrief.
|
|
35605
|
+
|
|
35606
|
+
CREATE OR REPLACE FUNCTION public.logistics_laag_menging_core()
|
|
35607
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
35608
|
+
DECLARE k jsonb; v_opt boolean; v_kpl int; v_bel int; v_een boolean := false;
|
|
35609
|
+
BEGIN
|
|
35610
|
+
SELECT coalesce(s.settings->'karrenindeling'->'fields', s.settings->'karrenindeling') INTO k
|
|
35611
|
+
FROM public.logistics_rule_configs s WHERE s.is_active ORDER BY s.updated_at DESC LIMIT 1;
|
|
35612
|
+
v_opt := coalesce((k->>'optimal_fill')::boolean, true);
|
|
35613
|
+
v_kpl := nullif(k->>'max_customers_per_layer', '')::numeric::int;
|
|
35614
|
+
IF to_regclass('public.cart_planning_settings') IS NOT NULL THEN
|
|
35615
|
+
EXECUTE 'SELECT max_beladingen_per_layer, coalesce(max_one_customer_per_layer, false) FROM public.cart_planning_settings LIMIT 1'
|
|
35616
|
+
INTO v_bel, v_een;
|
|
35617
|
+
END IF;
|
|
35618
|
+
v_bel := CASE WHEN NOT v_opt THEN 1 ELSE coalesce(v_bel, 2) END;
|
|
35619
|
+
IF NOT v_opt THEN RETURN jsonb_build_object('menging', 'per_regel', 'reden', 'optimale vulling staat uit'); END IF;
|
|
35620
|
+
IF v_bel > 0 AND v_bel < 999 THEN RETURN jsonb_build_object('menging', 'per_regel', 'reden', format('maximaal %s beladingen per laag', v_bel)); END IF;
|
|
35621
|
+
IF coalesce(v_een, false) THEN RETURN jsonb_build_object('menging', 'per_regel', 'reden', 'één klant per laag'); END IF;
|
|
35622
|
+
IF coalesce(v_kpl, 0) > 0 THEN RETURN jsonb_build_object('menging', 'per_regel', 'reden', format('maximaal %s klant(en) per laag', v_kpl)); END IF;
|
|
35623
|
+
RETURN jsonb_build_object('menging', 'vrij', 'reden', 'mengen per laag toegestaan');
|
|
35624
|
+
END $$;
|
|
35625
|
+
|
|
35626
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_capaciteit_core(p_cart_id uuid)
|
|
35627
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
35628
|
+
WITH m AS (SELECT public.logistics_laag_menging_core()->>'menging' = 'per_regel' hele),
|
|
35629
|
+
c AS (SELECT oc.cart_number, oc.total_layers_used, oc.max_layers FROM logistics_active.order_carts oc WHERE oc.id = p_cart_id),
|
|
35630
|
+
i AS (SELECT count(*) n, count(*) FILTER (WHERE coalesce(ci.crates_per_layer, 0) > 0) ncpl,
|
|
35631
|
+
sum(CASE WHEN m.hele THEN ceil(ci.crates::numeric / nullif(ci.crates_per_layer, 0) - 1e-9)
|
|
35632
|
+
ELSE ci.crates::numeric / nullif(ci.crates_per_layer, 0) END) lagen,
|
|
35633
|
+
max(nullif(ci.layers_per_cart, 0)) lpc
|
|
35634
|
+
FROM logistics_active.order_cart_items ci, m WHERE ci.cart_id = p_cart_id),
|
|
35635
|
+
v AS (SELECT c.cart_number,
|
|
35636
|
+
CASE WHEN i.n > 0 AND i.n = i.ncpl THEN round(i.lagen, 2) ELSE c.total_layers_used::numeric END lagen,
|
|
35637
|
+
coalesce(i.lpc::numeric, nullif(c.max_layers, 0)::numeric) cap,
|
|
35638
|
+
CASE WHEN i.lpc IS NOT NULL THEN 'product' WHEN coalesce(c.max_layers, 0) > 0 THEN 'ladingdrager' END bron
|
|
35639
|
+
FROM c, i)
|
|
35640
|
+
SELECT jsonb_build_object('layersUsed', v.lagen, 'maxLayers', v.cap, 'capaciteitBron', v.bron,
|
|
35641
|
+
'laagMenging', (SELECT CASE WHEN hele THEN 'per_regel' ELSE 'vrij' END FROM m),
|
|
35642
|
+
'vulgraadPct', CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END,
|
|
35643
|
+
'layerUtilizationPct', CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END)
|
|
35644
|
+
|| public.logistics_kar_blokkade(v.cart_number::text, v.lagen, v.cap)
|
|
35645
|
+
FROM v
|
|
35646
|
+
$$;
|
|
35647
|
+
|
|
35648
|
+
-- Welke printer krijgt de volgende verzendbrief (route "verzendbrief bij pakbon")?
|
|
35649
|
+
CREATE OR REPLACE FUNCTION public.logistics_shipping_note_printer(p_order_id uuid DEFAULT NULL)
|
|
35650
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35651
|
+
DECLARE slip record; v_plek uuid; v_wp text; r jsonb; v_naam text; v_pid uuid;
|
|
35652
|
+
BEGIN
|
|
35653
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_shipping_note_printer');
|
|
35654
|
+
IF to_regprocedure('public.printer_routering(text,uuid,text,uuid,text,uuid)') IS NULL THEN
|
|
35655
|
+
RETURN jsonb_build_object('printerId', NULL, 'printerNaam', NULL, 'regel', NULL,
|
|
35656
|
+
'reden', 'De printerregels van Layouts zijn niet geïnstalleerd; de printer is niet te bepalen.');
|
|
35657
|
+
END IF;
|
|
35658
|
+
SELECT pj.id, pj.payload INTO slip FROM public.print_jobs pj
|
|
35659
|
+
WHERE pj.documenttype::text = 'pakbon'
|
|
35660
|
+
AND (p_order_id IS NULL OR pj.payload->>'order_id' = p_order_id::text)
|
|
35661
|
+
ORDER BY pj.created_at DESC LIMIT 1;
|
|
35662
|
+
IF slip.id IS NOT NULL THEN
|
|
35663
|
+
BEGIN v_plek := nullif(coalesce(slip.payload->>'print_plek_id', slip.payload->>'printPlekId'), '')::uuid;
|
|
35664
|
+
EXCEPTION WHEN invalid_text_representation THEN v_plek := NULL; END;
|
|
35665
|
+
v_wp := nullif(btrim(coalesce(slip.payload->>'werkplek', slip.payload->>'computer_naam', '')), '');
|
|
35666
|
+
END IF;
|
|
35667
|
+
r := public.printer_routering('afleverbrief', v_plek, v_wp, NULL, NULL, NULL);
|
|
35668
|
+
v_pid := nullif(r->>'printer_id', '')::uuid;
|
|
35669
|
+
IF v_pid IS NOT NULL THEN
|
|
35670
|
+
SELECT coalesce(nullif(p.weergavenaam, ''), p.naam) INTO v_naam FROM public.printers p WHERE p.id = v_pid;
|
|
35671
|
+
END IF;
|
|
35672
|
+
RETURN jsonb_build_object(
|
|
35673
|
+
'printerId', v_pid, 'printerNaam', v_naam,
|
|
35674
|
+
'regel', CASE WHEN v_pid IS NULL THEN NULL ELSE jsonb_build_object('bron', r->>'bron', 'regelId', r->>'regel_id',
|
|
35675
|
+
'printPlekId', v_plek, 'werkplek', v_wp, 'pakbonJobId', slip.id) END,
|
|
35676
|
+
'reden', CASE WHEN v_pid IS NOT NULL THEN NULL
|
|
35677
|
+
WHEN slip.id IS NULL THEN 'Er is nog geen pakbon geprint; zonder printplek is de printer van de verzendbrief niet te bepalen.'
|
|
35678
|
+
ELSE 'Er is geen printerregel voor de verzendbrief op deze printplek. Stel die in bij Layouts → printers.' END,
|
|
35679
|
+
'overgeslagen', r->'overgeslagen');
|
|
35680
|
+
END $$;
|
|
35681
|
+
GRANT EXECUTE ON FUNCTION public.logistics_shipping_note_printer(uuid) TO authenticated, service_role;
|
|
35682
|
+
GRANT EXECUTE ON FUNCTION public.logistics_laag_menging_core() TO service_role;
|
|
35683
|
+
|
|
35684
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_204b()
|
|
35685
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35686
|
+
SELECT 'menging per laag', position('logistics_laag_menging_core' IN pg_get_functiondef('public.logistics_cart_capaciteit_core(uuid)'::regprocedure)) > 0, 'Capaciteit telt begonnen lagen per regel als menging beperkt is'
|
|
35687
|
+
UNION ALL SELECT 'printer verzendbrief', to_regprocedure('public.logistics_shipping_note_printer(uuid)') IS NOT NULL
|
|
35688
|
+
AND position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_shipping_note_printer(uuid)'::regprocedure)) > 0, 'Leesfunctie met eigen toegangscontrole'
|
|
35689
|
+
$$;
|
|
35690
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_204b() TO authenticated, service_role;
|
|
35691
|
+
|
|
35692
|
+
-- ===== 1.0.205: mengregel per laag via groepen, quarantaine overslaan =====
|
|
35693
|
+
-- 1.0.205: mengregel per laag via groepen; regels in quarantaine overal overslaan.
|
|
35694
|
+
|
|
35695
|
+
CREATE OR REPLACE FUNCTION public.logistics_laag_menging_core()
|
|
35696
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
35697
|
+
DECLARE k jsonb; v_opt boolean; v_kpl int; v_bel int; v_een boolean := false; v_kl int; v_b int; v_reden text[] := '{}';
|
|
35698
|
+
BEGIN
|
|
35699
|
+
SELECT coalesce(s.settings->'karrenindeling'->'fields', s.settings->'karrenindeling') INTO k
|
|
35700
|
+
FROM public.logistics_rule_configs s WHERE s.is_active ORDER BY s.updated_at DESC LIMIT 1;
|
|
35701
|
+
v_opt := coalesce((k->>'optimal_fill')::boolean, true);
|
|
35702
|
+
v_kpl := nullif(k->>'max_customers_per_layer', '')::numeric::int;
|
|
35703
|
+
IF to_regclass('public.cart_planning_settings') IS NOT NULL THEN
|
|
35704
|
+
EXECUTE 'SELECT max_beladingen_per_layer, coalesce(max_one_customer_per_layer, false) FROM public.cart_planning_settings LIMIT 1'
|
|
35705
|
+
INTO v_bel, v_een;
|
|
35706
|
+
END IF;
|
|
35707
|
+
IF NOT v_opt THEN
|
|
35708
|
+
RETURN jsonb_build_object('menging', 'per_regel', 'klantenPerLaag', NULL, 'beladingenPerLaag', NULL, 'reden', 'optimale vulling staat uit');
|
|
35709
|
+
END IF;
|
|
35710
|
+
v_b := CASE WHEN coalesce(v_bel, 2) > 0 AND coalesce(v_bel, 2) < 999 THEN coalesce(v_bel, 2) END;
|
|
35711
|
+
v_kl := CASE WHEN coalesce(v_een, false) THEN 1 WHEN coalesce(v_kpl, 0) > 0 THEN v_kpl END;
|
|
35712
|
+
IF v_kl IS NOT NULL THEN v_reden := v_reden || format('maximaal %s klant(en) per laag', v_kl); END IF;
|
|
35713
|
+
IF v_b IS NOT NULL THEN v_reden := v_reden || format('maximaal %s beladingen per laag binnen een klant', v_b); END IF;
|
|
35714
|
+
RETURN jsonb_build_object('menging', 'vrij', 'klantenPerLaag', v_kl, 'beladingenPerLaag', v_b,
|
|
35715
|
+
'reden', CASE WHEN cardinality(v_reden) = 0 THEN 'mengen per laag toegestaan' ELSE array_to_string(v_reden, '; ') END);
|
|
35716
|
+
END $$;
|
|
35717
|
+
|
|
35718
|
+
-- Lagen van een kar volgens de mengregels (zelfde als karLagen() in de planner).
|
|
35719
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_lagen_core(p_cart_id uuid)
|
|
35720
|
+
RETURNS numeric LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
35721
|
+
DECLARE m jsonb := public.logistics_laag_menging_core(); v_n int; v_m int; units numeric[] := '{}'; r record; v_tot numeric := 0;
|
|
35722
|
+
v_ontbreekt boolean;
|
|
35723
|
+
BEGIN
|
|
35724
|
+
SELECT bool_or(coalesce(ci.crates_per_layer, 0) <= 0) INTO v_ontbreekt
|
|
35725
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35726
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL;
|
|
35727
|
+
IF v_ontbreekt IS NULL OR v_ontbreekt THEN RETURN NULL; END IF;
|
|
35728
|
+
IF m->>'menging' = 'per_regel' THEN
|
|
35729
|
+
SELECT sum(ceil(ci.crates::numeric / ci.crates_per_layer - 1e-9)) INTO v_tot
|
|
35730
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35731
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL;
|
|
35732
|
+
RETURN round(v_tot, 2);
|
|
35733
|
+
END IF;
|
|
35734
|
+
v_n := nullif(m->>'klantenPerLaag', '')::int;
|
|
35735
|
+
v_m := nullif(m->>'beladingenPerLaag', '')::int;
|
|
35736
|
+
IF v_n IS NULL AND v_m IS NULL THEN
|
|
35737
|
+
SELECT sum(ci.crates::numeric / ci.crates_per_layer) INTO v_tot
|
|
35738
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35739
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL;
|
|
35740
|
+
RETURN round(v_tot, 2);
|
|
35741
|
+
END IF;
|
|
35742
|
+
IF v_m IS NOT NULL THEN
|
|
35743
|
+
FOR r IN
|
|
35744
|
+
SELECT sum(f) u FROM (
|
|
35745
|
+
SELECT x.f, x.klant, (row_number() OVER (PARTITION BY x.klant ORDER BY x.regel) - 1) / v_m grp FROM (
|
|
35746
|
+
SELECT ci.crates::numeric / ci.crates_per_layer f, coalesce(o.customer_id::text, oi.order_id::text, 'regel:' || ci.order_item_id::text) klant,
|
|
35747
|
+
ci.order_item_id::text regel
|
|
35748
|
+
FROM logistics_active.order_cart_items ci
|
|
35749
|
+
LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35750
|
+
LEFT JOIN public.orders o ON o.id = oi.order_id
|
|
35751
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL) x) y
|
|
35752
|
+
GROUP BY klant, grp
|
|
35753
|
+
LOOP units := units || r.u; END LOOP;
|
|
35754
|
+
ELSE
|
|
35755
|
+
FOR r IN
|
|
35756
|
+
SELECT sum(f) u FROM (
|
|
35757
|
+
SELECT z.f, (dense_rank() OVER (ORDER BY z.klant) - 1) / v_n grp FROM (
|
|
35758
|
+
SELECT ci.crates::numeric / ci.crates_per_layer f, coalesce(o.customer_id::text, oi.order_id::text, 'regel:' || ci.order_item_id::text) klant
|
|
35759
|
+
FROM logistics_active.order_cart_items ci
|
|
35760
|
+
LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35761
|
+
LEFT JOIN public.orders o ON o.id = oi.order_id
|
|
35762
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL) z) y
|
|
35763
|
+
GROUP BY grp
|
|
35764
|
+
LOOP units := units || r.u; END LOOP;
|
|
35765
|
+
END IF;
|
|
35766
|
+
IF cardinality(units) <= 1 THEN
|
|
35767
|
+
SELECT coalesce(sum(u), 0) INTO v_tot FROM unnest(units) u;
|
|
35768
|
+
ELSE
|
|
35769
|
+
SELECT sum(ceil(u - 1e-9)) INTO v_tot FROM unnest(units) u;
|
|
35770
|
+
END IF;
|
|
35771
|
+
RETURN round(v_tot, 2);
|
|
35772
|
+
END $$;
|
|
35773
|
+
|
|
35774
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_capaciteit_core(p_cart_id uuid)
|
|
35775
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
35776
|
+
WITH c AS (SELECT oc.cart_number, oc.total_layers_used, oc.max_layers FROM logistics_active.order_carts oc WHERE oc.id = p_cart_id),
|
|
35777
|
+
i AS (SELECT max(nullif(ci.layers_per_cart, 0)) lpc
|
|
35778
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
35779
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL),
|
|
35780
|
+
v AS (SELECT c.cart_number,
|
|
35781
|
+
coalesce(public.logistics_cart_lagen_core(p_cart_id), c.total_layers_used::numeric) lagen,
|
|
35782
|
+
coalesce(i.lpc::numeric, nullif(c.max_layers, 0)::numeric) cap,
|
|
35783
|
+
CASE WHEN i.lpc IS NOT NULL THEN 'product' WHEN coalesce(c.max_layers, 0) > 0 THEN 'ladingdrager' END bron
|
|
35784
|
+
FROM c, i)
|
|
35785
|
+
SELECT jsonb_build_object('layersUsed', v.lagen, 'maxLayers', v.cap, 'capaciteitBron', v.bron,
|
|
35786
|
+
'laagMenging', public.logistics_laag_menging_core(),
|
|
35787
|
+
'vulgraadPct', CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END,
|
|
35788
|
+
'layerUtilizationPct', CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END)
|
|
35789
|
+
|| public.logistics_kar_blokkade(v.cart_number::text, v.lagen, v.cap)
|
|
35790
|
+
FROM v
|
|
35791
|
+
$$;
|
|
35792
|
+
|
|
35793
|
+
-- Quarantaine: bestaande functies additief bijwerken (alleen als de kolom bestaat; idempotent).
|
|
35794
|
+
DO $do$
|
|
35795
|
+
DECLARE f record; d text; n text;
|
|
35796
|
+
BEGIN
|
|
35797
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'order_items' AND column_name = 'quarantined_at') THEN
|
|
35798
|
+
RAISE NOTICE 'order_items.quarantined_at bestaat niet; quarantainefilter overgeslagen.';
|
|
35799
|
+
RETURN;
|
|
35800
|
+
END IF;
|
|
35801
|
+
FOR f IN SELECT * FROM (VALUES
|
|
35802
|
+
('public.logistics_order_plan_coverage_v165(uuid)', 'JOIN public.order_items oi ON oi.id = oci.order_item_id', 'JOIN public.order_items oi ON oi.id = oci.order_item_id AND oi.quarantined_at IS NULL'),
|
|
35803
|
+
('public.logistics_order_unit_carts_core(uuid[])', 'JOIN public.order_items oi ON oi.id = ci.order_item_id', 'JOIN public.order_items oi ON oi.id = ci.order_item_id AND oi.quarantined_at IS NULL'),
|
|
35804
|
+
('public.logistics_order_te_hoge_karren(uuid[])', 'JOIN public.order_items oi ON oi.id = ci.order_item_id', 'JOIN public.order_items oi ON oi.id = ci.order_item_id AND oi.quarantined_at IS NULL'),
|
|
35805
|
+
('public.logistics_order_indeling_verouderd_core(uuid)', 'WHERE oi.order_id = p_order_id AND oi.packing_locked_at IS NOT NULL', 'WHERE oi.order_id = p_order_id AND oi.packing_locked_at IS NOT NULL AND oi.quarantined_at IS NULL'),
|
|
35806
|
+
('public.logistics_cart_slip_plan_v200(uuid)', 'WHERE ci.cart_id = d.id', 'WHERE ci.cart_id = d.id AND NOT EXISTS (SELECT 1 FROM public.order_items qi WHERE qi.id = ci.order_item_id AND qi.quarantined_at IS NOT NULL)')
|
|
35807
|
+
) t(fn, oud, nieuw) LOOP
|
|
35808
|
+
IF to_regprocedure(f.fn) IS NULL THEN RAISE NOTICE '% ontbreekt', f.fn; CONTINUE; END IF;
|
|
35809
|
+
d := pg_get_functiondef(f.fn::regprocedure);
|
|
35810
|
+
IF position(f.nieuw IN d) > 0 THEN CONTINUE; END IF;
|
|
35811
|
+
IF position(f.oud IN d) = 0 THEN RAISE NOTICE 'patroon niet gevonden in %', f.fn; CONTINUE; END IF;
|
|
35812
|
+
n := replace(d, f.oud, f.nieuw);
|
|
35813
|
+
EXECUTE n;
|
|
35814
|
+
END LOOP;
|
|
35815
|
+
END $do$;
|
|
35816
|
+
|
|
35817
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_lagen_core(uuid) TO authenticated, service_role;
|
|
35818
|
+
|
|
35819
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_205()
|
|
35820
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35821
|
+
SELECT 'mengregel groepen', position('logistics_cart_lagen_core' IN pg_get_functiondef('public.logistics_cart_capaciteit_core(uuid)'::regprocedure)) > 0, 'Ceil alleen tussen groepen die geen laag mogen delen'
|
|
35822
|
+
UNION ALL SELECT 'quarantaine dekking', position('quarantined_at IS NULL' IN pg_get_functiondef('public.logistics_order_plan_coverage_v165(uuid)'::regprocedure)) > 0, 'Dekking slaat regels in quarantaine over'
|
|
35823
|
+
UNION ALL SELECT 'quarantaine pakbonplan', position('quarantined_at IS NOT NULL' IN pg_get_functiondef('public.logistics_cart_slip_plan_v200(uuid)'::regprocedure)) > 0, 'Pakbonplan toont geen regels in quarantaine'
|
|
35824
|
+
UNION ALL SELECT 'quarantaine kar-nummering', position('quarantined_at IS NULL' IN pg_get_functiondef('public.logistics_order_unit_carts_core(uuid[])'::regprocedure)) > 0, 'Karren van een order via actieve regels'
|
|
35825
|
+
UNION ALL SELECT 'quarantaine te hoog', position('quarantined_at IS NULL' IN pg_get_functiondef('public.logistics_order_te_hoge_karren(uuid[])'::regprocedure)) > 0, 'Te hoog alleen op actieve regels'
|
|
35826
|
+
$$;
|
|
35827
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_205() TO authenticated, service_role;
|