@flowselections/logistiek-engine 1.0.219 → 1.0.224
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 +1325 -1
- package/dist-lib/integrations/supabase/types.d.ts +360 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
- package/dist-lib/lib/modulePrompts.js +59 -0
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/package.json +2 -2
|
@@ -37647,4 +37647,1328 @@ RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY D
|
|
|
37647
37647
|
AND position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_order_transport_group(jsonb)'::regprocedure)) > 0,
|
|
37648
37648
|
'Aanroeper wordt intern gecontroleerd'
|
|
37649
37649
|
$$;
|
|
37650
|
-
GRANT EXECUTE ON FUNCTION public.logistics_install_check_218() TO authenticated, service_role;
|
|
37650
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_218() TO authenticated, service_role;
|
|
37651
|
+
-- ===== 1.0.220 =====
|
|
37652
|
+
-- ===== 1.0.220 reden per verouderde kar, één buffertelling, eigen vervoer in Dagdetails =====
|
|
37653
|
+
|
|
37654
|
+
-- Kar gemaakt voor een eerdere gecombineerde order (de order zit nu in een andere buffer). Alleen melding.
|
|
37655
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_eerdere_buffer(p_cart_id uuid)
|
|
37656
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public'
|
|
37657
|
+
AS $function$
|
|
37658
|
+
WITH k AS (SELECT c.id, c.order_id, c.buffer_id FROM public.order_carts c WHERE c.id = p_cart_id),
|
|
37659
|
+
o AS (
|
|
37660
|
+
SELECT x.order_number, x.buffer_id FROM k
|
|
37661
|
+
JOIN public.order_cart_items ci ON ci.cart_id = k.id
|
|
37662
|
+
JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
37663
|
+
JOIN public.orders x ON x.id = oi.order_id
|
|
37664
|
+
WHERE x.deleted_at IS NULL
|
|
37665
|
+
UNION
|
|
37666
|
+
SELECT x.order_number, x.buffer_id FROM k JOIN public.orders x ON x.id = k.order_id WHERE x.deleted_at IS NULL
|
|
37667
|
+
),
|
|
37668
|
+
a AS (SELECT DISTINCT o.order_number FROM o, k
|
|
37669
|
+
WHERE o.buffer_id IS DISTINCT FROM k.buffer_id AND (o.buffer_id IS NOT NULL OR k.order_id IS NULL))
|
|
37670
|
+
SELECT CASE WHEN count(*) > 0 THEN jsonb_build_object('orders', jsonb_agg(order_number ORDER BY order_number),
|
|
37671
|
+
'tekst', 'Deze kar is ingedeeld voor een eerdere gecombineerde order; '
|
|
37672
|
+
|| string_agg(order_number, ', ' ORDER BY order_number)
|
|
37673
|
+
|| CASE WHEN count(*) > 1 THEN ' zitten' ELSE ' zit' END || ' nu in een andere gecombineerde order.') END
|
|
37674
|
+
FROM a
|
|
37675
|
+
$function$;
|
|
37676
|
+
|
|
37677
|
+
-- Alle redenen waarom een kar verouderd is, in gewone taal, in vaste volgorde (eerste = hoofdreden).
|
|
37678
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_verouderd_redenen(p_cart_id uuid)
|
|
37679
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SET search_path TO 'public'
|
|
37680
|
+
AS $function$
|
|
37681
|
+
DECLARE v_nr text; v_n int; v_live int; v_afw text[]; v_r jsonb; v_out jsonb := '[]'::jsonb;
|
|
37682
|
+
BEGIN
|
|
37683
|
+
IF p_cart_id IS NULL THEN RETURN v_out; END IF;
|
|
37684
|
+
SELECT coalesce(cart_number::text, '?') INTO v_nr FROM public.order_carts WHERE id = p_cart_id;
|
|
37685
|
+
IF NOT FOUND THEN RETURN v_out; END IF;
|
|
37686
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'order_items' AND column_name = 'quarantined_at') THEN
|
|
37687
|
+
SELECT count(*) INTO v_n FROM public.order_cart_items ci JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
37688
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NOT NULL;
|
|
37689
|
+
IF coalesce(v_n, 0) > 0 THEN
|
|
37690
|
+
v_out := v_out || jsonb_build_array(jsonb_build_object('code', 'quarantaine',
|
|
37691
|
+
'tekst', format('%s regel(s) op kar %s staan in quarantaine bij Verkoop.', v_n, v_nr),
|
|
37692
|
+
'extra', jsonb_build_object('regelsInQuarantaine', v_n),
|
|
37693
|
+
'blokkade', jsonb_build_object('code', 'kar_verouderd',
|
|
37694
|
+
'tekst', format('Kar %s heeft %s regel(s) die Verkoop in quarantaine heeft gezet. Deel de niet-geprinte karren opnieuw in.', v_nr, v_n))));
|
|
37695
|
+
END IF;
|
|
37696
|
+
SELECT count(*) INTO v_live FROM public.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
37697
|
+
WHERE ci.cart_id = p_cart_id AND coalesce(ci.crates, 0) > 0 AND oi.quarantined_at IS NULL;
|
|
37698
|
+
ELSE
|
|
37699
|
+
SELECT count(*) INTO v_live FROM public.order_cart_items ci WHERE ci.cart_id = p_cart_id AND coalesce(ci.crates, 0) > 0;
|
|
37700
|
+
END IF;
|
|
37701
|
+
IF coalesce(v_live, 0) = 0 THEN
|
|
37702
|
+
RETURN v_out || jsonb_build_array(jsonb_build_object('code', 'leeg',
|
|
37703
|
+
'tekst', format('Kar %s heeft geen regels meer.', v_nr),
|
|
37704
|
+
'blokkade', jsonb_build_object('code', 'kar_leeg',
|
|
37705
|
+
'tekst', format('Kar %s heeft geen regels meer. Deel de niet-geprinte karren opnieuw in.', v_nr))));
|
|
37706
|
+
END IF;
|
|
37707
|
+
v_afw := public.logistics_cart_aantal_afwijking_core(p_cart_id);
|
|
37708
|
+
IF coalesce(cardinality(v_afw), 0) > 0 THEN
|
|
37709
|
+
v_out := v_out || jsonb_build_array(jsonb_build_object('code', 'aantal',
|
|
37710
|
+
'tekst', format('De aantallen op de kar wijken af van de order (%s).', array_to_string(v_afw, ', ')),
|
|
37711
|
+
'extra', jsonb_build_object('producten', to_jsonb(v_afw)),
|
|
37712
|
+
'blokkade', jsonb_build_object('code', 'kar_verouderd',
|
|
37713
|
+
'tekst', format('Kar %s: de aantallen wijken af van de order (%s). Deel de niet-geprinte karren opnieuw in.', v_nr, array_to_string(v_afw, ', ')))));
|
|
37714
|
+
END IF;
|
|
37715
|
+
v_r := public.logistics_cart_vervoer_gemengd(p_cart_id);
|
|
37716
|
+
IF v_r IS NOT NULL THEN
|
|
37717
|
+
v_out := v_out || jsonb_build_array(jsonb_build_object('code', 'vervoer_gemengd', 'tekst', v_r->>'tekst', 'blokkade', NULL));
|
|
37718
|
+
END IF;
|
|
37719
|
+
v_r := public.logistics_cart_eerdere_buffer(p_cart_id);
|
|
37720
|
+
IF v_r IS NOT NULL THEN
|
|
37721
|
+
v_out := v_out || jsonb_build_array(jsonb_build_object('code', 'eerdere_buffer', 'tekst', v_r->>'tekst', 'blokkade', NULL));
|
|
37722
|
+
END IF;
|
|
37723
|
+
v_r := public.logistics_cart_regels_verouderd_core(p_cart_id);
|
|
37724
|
+
IF v_r IS NOT NULL THEN
|
|
37725
|
+
v_out := v_out || jsonb_build_array(jsonb_build_object('code', v_r->>'reden', 'tekst', v_r->>'tekst', 'blokkade', NULL));
|
|
37726
|
+
END IF;
|
|
37727
|
+
RETURN v_out;
|
|
37728
|
+
END $function$;
|
|
37729
|
+
|
|
37730
|
+
-- Hoofdreden blijft gelijk aan vóór 1.0.220 (zelfde volgorde: quarantaine, leeg, aantal,
|
|
37731
|
+
-- logistics_cart_vervoer_gemengd, regels); nieuw: eerdere buffer en de volledige lijst 'redenen'.
|
|
37732
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_verouderd_core(p_cart_id uuid)
|
|
37733
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SET search_path TO 'public'
|
|
37734
|
+
AS $function$
|
|
37735
|
+
DECLARE v_lijst jsonb; v_r jsonb;
|
|
37736
|
+
BEGIN
|
|
37737
|
+
IF p_cart_id IS NULL THEN RETURN NULL; END IF;
|
|
37738
|
+
v_lijst := public.logistics_cart_verouderd_redenen(p_cart_id);
|
|
37739
|
+
IF coalesce(jsonb_array_length(v_lijst), 0) = 0 THEN RETURN NULL; END IF;
|
|
37740
|
+
v_r := v_lijst->0;
|
|
37741
|
+
RETURN jsonb_build_object('verouderd', true, 'reden', v_r->>'code', 'tekst', v_r->>'tekst',
|
|
37742
|
+
'blokkade', v_r->'blokkade',
|
|
37743
|
+
'redenen', (SELECT jsonb_agg(e - 'extra' - 'blokkade') FROM jsonb_array_elements(v_lijst) e))
|
|
37744
|
+
|| coalesce(v_r->'extra', '{}'::jsonb);
|
|
37745
|
+
END $function$;
|
|
37746
|
+
|
|
37747
|
+
-- Kaartgegevens krijgen naast verouderdReden ook de volledige lijst verouderdRedenen.
|
|
37748
|
+
DO $fs$
|
|
37749
|
+
DECLARE v_def text;
|
|
37750
|
+
BEGIN
|
|
37751
|
+
v_def := pg_get_functiondef('public.logistics_cart_platen_verrijk'::regproc);
|
|
37752
|
+
IF position('verouderdRedenen' IN v_def) = 0 THEN
|
|
37753
|
+
IF position('''verouderdReden'', public.logistics_cart_verouderd_core(v_id)->>''tekst'')' IN v_def) = 0 THEN
|
|
37754
|
+
RAISE EXCEPTION 'logistics_cart_platen_verrijk: verwachte tekst niet gevonden; niet aangepast';
|
|
37755
|
+
END IF;
|
|
37756
|
+
v_def := replace(v_def, '''verouderdReden'', public.logistics_cart_verouderd_core(v_id)->>''tekst'')',
|
|
37757
|
+
'''verouderdReden'', public.logistics_cart_verouderd_core(v_id)->>''tekst'', ''verouderdRedenen'', public.logistics_cart_verouderd_core(v_id)->''redenen'')');
|
|
37758
|
+
EXECUTE v_def;
|
|
37759
|
+
END IF;
|
|
37760
|
+
END $fs$;
|
|
37761
|
+
|
|
37762
|
+
-- Eén bron voor de karren van een gecombineerde order: kop, karindeling en pickdocumenten.
|
|
37763
|
+
CREATE OR REPLACE FUNCTION public.logistics_buffer_carts(p_buffer_id uuid)
|
|
37764
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
37765
|
+
AS $function$
|
|
37766
|
+
DECLARE v_ids uuid[]; v_refs text[]; v_carts jsonb; v_types jsonb; v_dubbel jsonb;
|
|
37767
|
+
BEGIN
|
|
37768
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_buffer_carts');
|
|
37769
|
+
IF p_buffer_id IS NULL THEN RETURN NULL; END IF;
|
|
37770
|
+
SELECT array_agg(o.id ORDER BY o.order_number), array_agg(o.order_number ORDER BY o.order_number) INTO v_ids, v_refs
|
|
37771
|
+
FROM public.orders o
|
|
37772
|
+
WHERE o.buffer_id = p_buffer_id AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
37773
|
+
AND coalesce(o.status, '') <> 'geannuleerd';
|
|
37774
|
+
IF v_ids IS NULL THEN
|
|
37775
|
+
RETURN jsonb_build_object('bufferId', p_buffer_id, 'orders', '[]'::jsonb, 'karren', 0, 'ladingdragers', '[]'::jsonb,
|
|
37776
|
+
'carts', '[]'::jsonb, 'dubbeleDocumenten', '[]'::jsonb);
|
|
37777
|
+
END IF;
|
|
37778
|
+
WITH u AS (SELECT * FROM public.logistics_order_unit_carts_core(v_ids)),
|
|
37779
|
+
d AS (
|
|
37780
|
+
SELECT DISTINCT ON (q.reference) q.reference, q.id, q.document_number, q.printed_at
|
|
37781
|
+
FROM public.pick_queue q
|
|
37782
|
+
WHERE q.cancelled_at IS NULL AND q.reference IN (SELECT u.cart_id::text FROM u)
|
|
37783
|
+
ORDER BY q.reference, q.created_at DESC
|
|
37784
|
+
)
|
|
37785
|
+
SELECT coalesce(jsonb_agg(jsonb_build_object(
|
|
37786
|
+
'cartId', u.cart_id, 'seq', u.display_seq, 'total', u.display_total,
|
|
37787
|
+
'storedCartNumber', u.cart_number, 'cartBufferId', u.buffer_id, 'orderId', u.order_id,
|
|
37788
|
+
'carrierType', c.carrier_type,
|
|
37789
|
+
'ladingdrager', coalesce((SELECT coalesce(t.name, t.code) FROM public.load_carrier_types t WHERE t.code = c.carrier_type LIMIT 1), c.carrier_type),
|
|
37790
|
+
'verouderd', v.v IS NOT NULL, 'verouderdReden', v.v->>'tekst', 'verouderdRedenen', coalesce(v.v->'redenen', '[]'::jsonb),
|
|
37791
|
+
'pickDocument', CASE WHEN d.id IS NULL THEN NULL ELSE jsonb_build_object('id', d.id, 'documentNumber', d.document_number, 'printedAt', d.printed_at) END)
|
|
37792
|
+
ORDER BY u.display_seq), '[]'::jsonb)
|
|
37793
|
+
INTO v_carts
|
|
37794
|
+
FROM u JOIN public.order_carts c ON c.id = u.cart_id
|
|
37795
|
+
LEFT JOIN LATERAL (SELECT public.logistics_cart_verouderd_core(u.cart_id) AS v) v ON true
|
|
37796
|
+
LEFT JOIN d ON d.reference = u.cart_id::text;
|
|
37797
|
+
|
|
37798
|
+
SELECT coalesce(jsonb_agg(jsonb_build_object('ladingdrager', x->>'ladingdrager', 'aantal', n) ORDER BY n DESC, x->>'ladingdrager'), '[]'::jsonb)
|
|
37799
|
+
INTO v_types
|
|
37800
|
+
FROM (SELECT jsonb_build_object('ladingdrager', e->>'ladingdrager') x, count(*) n FROM jsonb_array_elements(v_carts) e GROUP BY 1) s;
|
|
37801
|
+
|
|
37802
|
+
-- Open pickdocumenten van deze orders met hetzelfde nummer (alleen melden, niets wijzigen).
|
|
37803
|
+
SELECT coalesce(jsonb_agg(jsonb_build_object('documentNumber', g.document_number, 'documenten', g.docs)), '[]'::jsonb)
|
|
37804
|
+
INTO v_dubbel
|
|
37805
|
+
FROM (SELECT q.document_number,
|
|
37806
|
+
jsonb_agg(jsonb_build_object('id', q.id, 'cartId', q.reference, 'aangemaakt', q.created_at,
|
|
37807
|
+
'hoortBijIndeling', EXISTS (SELECT 1 FROM jsonb_array_elements(v_carts) e WHERE e->>'cartId' = q.reference)) ORDER BY q.created_at) AS docs
|
|
37808
|
+
FROM public.pick_queue q
|
|
37809
|
+
WHERE q.cancelled_at IS NULL AND q.order_number = ANY(v_refs) AND q.document_number IS NOT NULL
|
|
37810
|
+
GROUP BY q.document_number HAVING count(DISTINCT q.reference) > 1) g;
|
|
37811
|
+
|
|
37812
|
+
RETURN jsonb_build_object('bufferId', p_buffer_id, 'orders', to_jsonb(v_refs),
|
|
37813
|
+
'karren', jsonb_array_length(v_carts), 'ladingdragers', v_types, 'carts', v_carts, 'dubbeleDocumenten', v_dubbel);
|
|
37814
|
+
END $function$;
|
|
37815
|
+
REVOKE ALL ON FUNCTION public.logistics_buffer_carts(uuid) FROM PUBLIC, anon;
|
|
37816
|
+
GRANT EXECUTE ON FUNCTION public.logistics_buffer_carts(uuid) TO authenticated, service_role;
|
|
37817
|
+
|
|
37818
|
+
-- buffer_cart_count telt exact dezelfde karren als logistics_buffer_carts (logistics_order_unit_carts_core).
|
|
37819
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_plan_coverage_list(p_order_ids uuid[])
|
|
37820
|
+
RETURNS TABLE(order_id uuid, order_number text, buffer_id uuid, state text, label text, progress_pct integer, reason text, cart_count integer, pick_row_count integer, pick_status text, picked_at timestamp with time zone, buffer_order_count integer, buffer_cart_count integer)
|
|
37821
|
+
LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
37822
|
+
AS $function$
|
|
37823
|
+
SELECT public.logistics_acc_guard('ingelogd', 'logistics_order_plan_coverage_list');
|
|
37824
|
+
WITH b AS (SELECT * FROM public.logistics_order_plan_coverage_list_v152(p_order_ids)),
|
|
37825
|
+
mem AS (
|
|
37826
|
+
SELECT DISTINCT b.buffer_id AS buf, o.id AS oid FROM b
|
|
37827
|
+
JOIN public.orders o ON o.buffer_id = b.buffer_id
|
|
37828
|
+
WHERE b.buffer_id IS NOT NULL AND o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.status,'') <> 'geannuleerd'
|
|
37829
|
+
),
|
|
37830
|
+
bc AS (
|
|
37831
|
+
SELECT m.buf, (SELECT count(*) FROM public.logistics_order_unit_carts_core(array_agg(m.oid)))::int AS n
|
|
37832
|
+
FROM mem m GROUP BY m.buf
|
|
37833
|
+
)
|
|
37834
|
+
SELECT b.order_id, b.order_number, b.buffer_id,
|
|
37835
|
+
CASE WHEN x.full_fulfilled THEN 'afgehandeld_extern' ELSE b.state END,
|
|
37836
|
+
CASE WHEN x.full_fulfilled THEN 'Afgehandeld in Floriday' ELSE b.label END,
|
|
37837
|
+
b.progress_pct,
|
|
37838
|
+
CASE WHEN x.full_fulfilled THEN 'De order is in Floriday afgehandeld; de Engine plant en print er niets meer voor.' ELSE b.reason END,
|
|
37839
|
+
b.cart_count, b.pick_row_count, b.pick_status, b.picked_at,
|
|
37840
|
+
CASE WHEN b.buffer_id IS NULL THEN 1 ELSE greatest((SELECT count(*) FROM mem WHERE mem.buf = b.buffer_id)::int, 1) END,
|
|
37841
|
+
CASE WHEN b.buffer_id IS NULL THEN b.cart_count ELSE coalesce((SELECT bc.n FROM bc WHERE bc.buf = b.buffer_id), 0) END
|
|
37842
|
+
FROM b LEFT JOIN public.logistics_external_fulfillment x ON x.order_id = b.order_id
|
|
37843
|
+
$function$;
|
|
37844
|
+
|
|
37845
|
+
-- Dagdag van een order: de pickdag, maar nooit later dan de leverdag. Een order waarvan de leverdag
|
|
37846
|
+
-- in het verleden is gezet (bijv. HO-2601467 op 28-10, gewijzigd op 29-10) blijft zo op zijn leverdag staan.
|
|
37847
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_dag(p_planned_start timestamptz, p_delivery_date text)
|
|
37848
|
+
RETURNS date LANGUAGE sql STABLE SET search_path TO 'public'
|
|
37849
|
+
AS $function$
|
|
37850
|
+
SELECT CASE
|
|
37851
|
+
WHEN p_delivery_date ~ '^\d{4}-\d{2}-\d{2}' AND p_planned_start IS NOT NULL
|
|
37852
|
+
THEN least((p_planned_start AT TIME ZONE public.logistics_tz())::date, left(p_delivery_date, 10)::date)
|
|
37853
|
+
WHEN p_planned_start IS NOT NULL THEN (p_planned_start AT TIME ZONE public.logistics_tz())::date
|
|
37854
|
+
WHEN p_delivery_date ~ '^\d{4}-\d{2}-\d{2}' THEN left(p_delivery_date, 10)::date
|
|
37855
|
+
END
|
|
37856
|
+
$function$;
|
|
37857
|
+
|
|
37858
|
+
CREATE OR REPLACE FUNCTION public.logistics_capacity_day_load(p_from date, p_to date, p_user uuid, p_settings jsonb)
|
|
37859
|
+
RETURNS TABLE(d date, carts integer, required numeric, zonder_kar integer)
|
|
37860
|
+
LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
37861
|
+
AS $function$
|
|
37862
|
+
WITH t0 AS (
|
|
37863
|
+
SELECT DISTINCT ON (t.order_ref) t.order_ref, t.planned_start
|
|
37864
|
+
FROM public.logistics_tasks t
|
|
37865
|
+
WHERE t.task_type = 'pick.execute' AND t.status NOT IN ('done','cancelled') AND NOT t.shadow
|
|
37866
|
+
AND t.planned_start IS NOT NULL AND (p_user IS NULL OR t.user_id = p_user)
|
|
37867
|
+
AND (t.planned_start AT TIME ZONE public.logistics_tz())::date >= p_from
|
|
37868
|
+
ORDER BY t.order_ref, t.planned_start
|
|
37869
|
+
),
|
|
37870
|
+
t AS (
|
|
37871
|
+
SELECT t0.order_ref, public.logistics_order_dag(t0.planned_start, o.delivery_date) AS d, o.id
|
|
37872
|
+
FROM t0 JOIN public.orders o ON o.order_number = t0.order_ref AND o.deleted_at IS NULL
|
|
37873
|
+
),
|
|
37874
|
+
o AS (SELECT t.d, t.order_ref, t.id FROM t WHERE t.d BETWEEN p_from AND p_to),
|
|
37875
|
+
k AS (
|
|
37876
|
+
SELECT DISTINCT ON (u.cart_id) u.cart_id, o.d
|
|
37877
|
+
FROM o, LATERAL public.logistics_order_unit_carts_core(ARRAY[o.id]) u
|
|
37878
|
+
ORDER BY u.cart_id, o.d
|
|
37879
|
+
),
|
|
37880
|
+
kc AS (
|
|
37881
|
+
SELECT k.d, count(*)::int AS carts,
|
|
37882
|
+
SUM(public.logistics_carrier_minutes(COALESCE(c.carrier_type, 'trolley'), p_settings)) AS mins
|
|
37883
|
+
FROM k JOIN public.order_carts c ON c.id = k.cart_id GROUP BY k.d
|
|
37884
|
+
),
|
|
37885
|
+
zk AS (
|
|
37886
|
+
SELECT o.d, count(*)::int AS n FROM o
|
|
37887
|
+
WHERE NOT EXISTS (SELECT 1 FROM public.logistics_order_unit_carts_core(ARRAY[o.id]) u)
|
|
37888
|
+
GROUP BY o.d
|
|
37889
|
+
),
|
|
37890
|
+
dd AS (SELECT DISTINCT o.d FROM o)
|
|
37891
|
+
SELECT dd.d, COALESCE(kc.carts, 0), COALESCE(NULLIF(kc.mins, 0), COALESCE(kc.carts, 0) * 15)::numeric, COALESCE(zk.n, 0)
|
|
37892
|
+
FROM dd LEFT JOIN kc ON kc.d = dd.d LEFT JOIN zk ON zk.d = dd.d
|
|
37893
|
+
ORDER BY dd.d;
|
|
37894
|
+
$function$;
|
|
37895
|
+
|
|
37896
|
+
-- Alle open orders van één dag (ook eigen vervoer, klant haalt op en orders zonder kar), met reden.
|
|
37897
|
+
CREATE OR REPLACE FUNCTION public.logistics_capacity_day_orders(p_date date)
|
|
37898
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
37899
|
+
AS $function$
|
|
37900
|
+
DECLARE v jsonb;
|
|
37901
|
+
BEGIN
|
|
37902
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_capacity_day_orders');
|
|
37903
|
+
IF p_date IS NULL THEN RETURN '[]'::jsonb; END IF;
|
|
37904
|
+
WITH t AS (
|
|
37905
|
+
SELECT DISTINCT ON (t.order_ref) t.order_ref, t.planned_start
|
|
37906
|
+
FROM public.logistics_tasks t
|
|
37907
|
+
WHERE t.task_type = 'pick.execute' AND t.status NOT IN ('done','cancelled') AND NOT t.shadow AND t.planned_start IS NOT NULL
|
|
37908
|
+
ORDER BY t.order_ref, t.planned_start
|
|
37909
|
+
),
|
|
37910
|
+
o AS (
|
|
37911
|
+
SELECT x.*, t.planned_start, public.logistics_order_dag(t.planned_start, x.delivery_date) AS dag
|
|
37912
|
+
FROM public.orders x LEFT JOIN t ON t.order_ref = x.order_number
|
|
37913
|
+
WHERE x.deleted_at IS NULL AND x.cancelled_at IS NULL
|
|
37914
|
+
AND lower(coalesce(x.status,'')) NOT IN ('cancelled','geannuleerd','deleted','verwijderd','afgehandeld','completed','delivered','geleverd')
|
|
37915
|
+
AND (t.order_ref IS NOT NULL OR x.delivery_date ~ '^\d{4}-\d{2}-\d{2}')
|
|
37916
|
+
),
|
|
37917
|
+
r AS (
|
|
37918
|
+
SELECT o.*, (SELECT count(*) FROM public.logistics_order_unit_carts_core(ARRAY[o.id]))::int AS karren,
|
|
37919
|
+
public.logistics_order_transport_group(to_jsonb(o)) AS grp
|
|
37920
|
+
FROM o WHERE o.dag = p_date
|
|
37921
|
+
)
|
|
37922
|
+
SELECT coalesce(jsonb_agg(jsonb_build_object(
|
|
37923
|
+
'orderId', r.id, 'orderNumber', r.order_number, 'bufferId', r.buffer_id,
|
|
37924
|
+
'deliveryDate', left(r.delivery_date, 10), 'pickStart', r.planned_start,
|
|
37925
|
+
'transportGroup', r.grp,
|
|
37926
|
+
'vervoer', CASE r.grp WHEN 'eigen_vervoer' THEN 'Eigen vervoer (wij leveren)' WHEN 'klant_haalt_op' THEN 'Klant haalt op' ELSE 'Vervoerder' END,
|
|
37927
|
+
'karren', r.karren, 'zonderKar', r.karren = 0,
|
|
37928
|
+
'reden', CASE WHEN r.karren > 0 THEN NULL
|
|
37929
|
+
WHEN r.planned_start IS NULL THEN 'Nog niet ingepland: er staat geen picktaak voor deze order.'
|
|
37930
|
+
ELSE 'Ingepland, maar zonder kar: de karindeling ontbreekt. De bewaking deelt hem opnieuw in.' END)
|
|
37931
|
+
ORDER BY r.buffer_id NULLS LAST, r.order_number), '[]'::jsonb)
|
|
37932
|
+
INTO v FROM r;
|
|
37933
|
+
RETURN v;
|
|
37934
|
+
END $function$;
|
|
37935
|
+
REVOKE ALL ON FUNCTION public.logistics_capacity_day_orders(date) FROM PUBLIC, anon;
|
|
37936
|
+
GRANT EXECUTE ON FUNCTION public.logistics_capacity_day_orders(date) TO authenticated, service_role;
|
|
37937
|
+
|
|
37938
|
+
-- Bewaking zonder kar: ook een open order waarvan de leverdag net in het verleden is gezet
|
|
37939
|
+
-- (max. 7 dagen terug en in de laatste 24 uur gewijzigd), zoals HO-2601467.
|
|
37940
|
+
CREATE OR REPLACE FUNCTION public.logistics_open_orders_zonder_kar()
|
|
37941
|
+
RETURNS TABLE(order_id uuid, order_number text, delivery_date text, laatste_reden text)
|
|
37942
|
+
LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
37943
|
+
AS $function$
|
|
37944
|
+
SELECT public.logistics_acc_guard('ingelogd', 'logistics_open_orders_zonder_kar');
|
|
37945
|
+
WITH lq AS (
|
|
37946
|
+
SELECT DISTINCT ON (q.order_id) q.order_id, q.status, q.reason_code, q.error
|
|
37947
|
+
FROM public.logistics_plan_queue q ORDER BY q.order_id, q.updated_at DESC
|
|
37948
|
+
)
|
|
37949
|
+
SELECT o.id, o.order_number, o.delivery_date, lq.error
|
|
37950
|
+
FROM public.orders o
|
|
37951
|
+
LEFT JOIN lq ON lq.order_id = o.id
|
|
37952
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
37953
|
+
AND lower(coalesce(o.status,'')) NOT IN ('cancelled','geannuleerd','deleted','verwijderd','afgehandeld','completed','delivered','geleverd')
|
|
37954
|
+
AND o.delivery_date ~ '^\d{4}-\d{2}-\d{2}'
|
|
37955
|
+
AND (left(o.delivery_date,10)::date >= public.logistics_local_today()
|
|
37956
|
+
OR (left(o.delivery_date,10)::date >= public.logistics_local_today() - 7 AND o.updated_at > now() - interval '24 hours'))
|
|
37957
|
+
AND EXISTS (SELECT 1 FROM public.order_items oi WHERE oi.order_id = o.id)
|
|
37958
|
+
AND NOT coalesce(public.logistics_order_buffer_excluded(o.id), false)
|
|
37959
|
+
AND NOT (coalesce(lq.status,'') IN ('geblokkeerd','pending','running'))
|
|
37960
|
+
AND NOT (coalesce(lq.status,'') = 'gearchiveerd'
|
|
37961
|
+
AND coalesce(lq.reason_code,'') IN ('belading_onwaarschijnlijk','belading_onvolledig','belading_onbekend','artikel_kiezen','ladingdrager_onbekend'))
|
|
37962
|
+
AND NOT EXISTS (SELECT 1 FROM logistics_active.order_carts c WHERE c.order_id = o.id)
|
|
37963
|
+
AND NOT EXISTS (SELECT 1 FROM public.order_items oi
|
|
37964
|
+
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
37965
|
+
JOIN logistics_active.order_carts c ON c.id = ci.cart_id
|
|
37966
|
+
WHERE oi.order_id = o.id);
|
|
37967
|
+
$function$;
|
|
37968
|
+
|
|
37969
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_220()
|
|
37970
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
37971
|
+
SELECT 'redenen per kar', position('logistics_cart_verouderd_redenen' IN pg_get_functiondef('public.logistics_cart_verouderd_core(uuid)'::regprocedure)) > 0,
|
|
37972
|
+
'Verouderde kar geeft alle redenen in gewone taal'
|
|
37973
|
+
UNION ALL SELECT 'kaart toont redenen', position('verouderdRedenen' IN pg_get_functiondef('public.logistics_cart_platen_verrijk'::regproc)) > 0,
|
|
37974
|
+
'Kaartgegevens bevatten verouderdRedenen'
|
|
37975
|
+
UNION ALL SELECT 'één buffertelling', position('logistics_order_unit_carts_core' IN pg_get_functiondef('public.logistics_order_plan_coverage_list(uuid[])'::regprocedure)) > 0
|
|
37976
|
+
AND to_regprocedure('public.logistics_buffer_carts(uuid)') IS NOT NULL,
|
|
37977
|
+
'Kop, karindeling en pickdocumenten uit dezelfde karren'
|
|
37978
|
+
UNION ALL SELECT 'dagdag niet na leverdag', position('logistics_order_dag' IN pg_get_functiondef('public.logistics_capacity_day_load(date,date,uuid,jsonb)'::regprocedure)) > 0,
|
|
37979
|
+
'Order staat op zijn pickdag, nooit later dan de leverdag'
|
|
37980
|
+
UNION ALL SELECT 'dagorders', to_regprocedure('public.logistics_capacity_day_orders(date)') IS NOT NULL,
|
|
37981
|
+
'Alle open orders van een dag, ook eigen vervoer en zonder kar'
|
|
37982
|
+
UNION ALL SELECT 'bewaking recente datumwijziging', position('interval ''24 hours''' IN pg_get_functiondef('public.logistics_open_orders_zonder_kar()'::regprocedure)) > 0,
|
|
37983
|
+
'Order met net in het verleden gezette leverdag wordt opnieuw ingedeeld'
|
|
37984
|
+
$$;
|
|
37985
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_220() TO authenticated, service_role;
|
|
37986
|
+
|
|
37987
|
+
-- ===== 1.0.221 bevroren verdelingen, karren uit eerdere buffer, status geannuleerd =====
|
|
37988
|
+
|
|
37989
|
+
-- ---------- 1+2. Bevroren verdeling ongeldig? (inactieve groep / niet-canonieke sleutel) ----------
|
|
37990
|
+
CREATE OR REPLACE FUNCTION public.logistics_allocation_stale_reden(p_order_item_id uuid)
|
|
37991
|
+
RETURNS text LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
37992
|
+
AS $function$
|
|
37993
|
+
DECLARE v_pid uuid; v_qty numeric; v_items text[]; v_groups uuid[]; v_err boolean; r record;
|
|
37994
|
+
BEGIN
|
|
37995
|
+
IF p_order_item_id IS NULL THEN RETURN NULL; END IF;
|
|
37996
|
+
SELECT oi.product_id, COALESCE(oi.quantity, 0)::numeric INTO v_pid, v_qty
|
|
37997
|
+
FROM public.order_items oi WHERE oi.id = p_order_item_id;
|
|
37998
|
+
IF v_pid IS NULL OR v_qty <= 0 THEN RETURN NULL; END IF;
|
|
37999
|
+
IF NOT EXISTS (SELECT 1 FROM public.logistics_reservation_allocations a
|
|
38000
|
+
WHERE a.order_item_id = p_order_item_id AND a.source IN ('item', 'group')) THEN
|
|
38001
|
+
RETURN NULL;
|
|
38002
|
+
END IF;
|
|
38003
|
+
SELECT array_agg(public.logistics_reserved_key(e.ref)) FILTER (WHERE e.kind = 'item'),
|
|
38004
|
+
array_agg(e.ref::uuid) FILTER (WHERE e.kind = 'group'),
|
|
38005
|
+
bool_or(e.kind = 'error')
|
|
38006
|
+
INTO v_items, v_groups, v_err
|
|
38007
|
+
FROM public.logistics_expand_line(v_pid, v_qty) e;
|
|
38008
|
+
IF COALESCE(v_err, false) THEN RETURN NULL; END IF;
|
|
38009
|
+
FOR r IN SELECT a.source, a.group_id, a.trade_item_key FROM public.logistics_reservation_allocations a
|
|
38010
|
+
WHERE a.order_item_id = p_order_item_id AND a.source IN ('item', 'group') LOOP
|
|
38011
|
+
IF r.source = 'group' THEN
|
|
38012
|
+
IF r.group_id IS NULL OR NOT EXISTS (SELECT 1 FROM public.product_groups g WHERE g.id = r.group_id AND g.is_active) THEN
|
|
38013
|
+
RETURN 'Verdeeld via een groep die niet meer actief is';
|
|
38014
|
+
END IF;
|
|
38015
|
+
IF NOT (r.group_id = ANY (COALESCE(v_groups, '{}'::uuid[]))) THEN
|
|
38016
|
+
RETURN 'Verdeeld via een groep die niet meer bij dit artikel hoort';
|
|
38017
|
+
END IF;
|
|
38018
|
+
IF NOT EXISTS (SELECT 1 FROM public.product_group_items pgi
|
|
38019
|
+
WHERE pgi.product_group_id = r.group_id
|
|
38020
|
+
AND public.logistics_reserved_key(public.resolve_group_member_stock_key(pgi.trade_item_id)) = r.trade_item_key) THEN
|
|
38021
|
+
RETURN 'Groepsregel wijst naar een voorraadregel die geen lid (meer) is';
|
|
38022
|
+
END IF;
|
|
38023
|
+
ELSE
|
|
38024
|
+
IF NOT (r.trade_item_key = ANY (COALESCE(v_items, '{}'::text[]))) THEN
|
|
38025
|
+
RETURN 'Sleutel is niet de canonieke voorraadregel van het artikel';
|
|
38026
|
+
END IF;
|
|
38027
|
+
END IF;
|
|
38028
|
+
END LOOP;
|
|
38029
|
+
RETURN NULL;
|
|
38030
|
+
END $function$;
|
|
38031
|
+
|
|
38032
|
+
CREATE OR REPLACE FUNCTION public.logistics_allocation_stale(p_order_item_id uuid)
|
|
38033
|
+
RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
38034
|
+
AS $function$ SELECT public.logistics_allocation_stale_reden(p_order_item_id) IS NOT NULL $function$;
|
|
38035
|
+
|
|
38036
|
+
REVOKE ALL ON FUNCTION public.logistics_allocation_stale_reden(uuid) FROM PUBLIC, anon, authenticated;
|
|
38037
|
+
REVOKE ALL ON FUNCTION public.logistics_allocation_stale(uuid) FROM PUBLIC, anon, authenticated;
|
|
38038
|
+
GRANT EXECUTE ON FUNCTION public.logistics_allocation_stale_reden(uuid) TO service_role;
|
|
38039
|
+
GRANT EXECUTE ON FUNCTION public.logistics_allocation_stale(uuid) TO service_role;
|
|
38040
|
+
|
|
38041
|
+
-- Bestaande (bevroren) verdeling alleen teruggeven als hij nog geldig is.
|
|
38042
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_line_allocation(p_order_item_id uuid)
|
|
38043
|
+
RETURNS TABLE(trade_item_key text, qty numeric, source text, group_id uuid, note text)
|
|
38044
|
+
LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38045
|
+
AS $function$
|
|
38046
|
+
DECLARE
|
|
38047
|
+
v_oi record; part record; member_rec record;
|
|
38048
|
+
v_key text; v_last text; v_rem numeric; v_av numeric; v_take numeric; v_err text;
|
|
38049
|
+
BEGIN
|
|
38050
|
+
PERFORM public.logistics_acc_guard('server', 'logistics_order_line_allocation');
|
|
38051
|
+
IF p_order_item_id IS NULL THEN RETURN; END IF;
|
|
38052
|
+
|
|
38053
|
+
IF EXISTS (SELECT 1 FROM public.logistics_double_group_lines(
|
|
38054
|
+
(SELECT oi.order_id FROM public.order_items oi WHERE oi.id = p_order_item_id)) d
|
|
38055
|
+
WHERE d.order_item_id = p_order_item_id) THEN
|
|
38056
|
+
RETURN;
|
|
38057
|
+
END IF;
|
|
38058
|
+
|
|
38059
|
+
IF EXISTS (SELECT 1 FROM public.logistics_reservation_allocations a WHERE a.order_item_id = p_order_item_id)
|
|
38060
|
+
AND NOT public.logistics_allocation_stale(p_order_item_id) THEN
|
|
38061
|
+
RETURN QUERY
|
|
38062
|
+
SELECT a.trade_item_key, a.qty, a.source, a.group_id, NULL::text
|
|
38063
|
+
FROM public.logistics_reservation_allocations a
|
|
38064
|
+
WHERE a.order_item_id = p_order_item_id
|
|
38065
|
+
ORDER BY a.source, a.trade_item_key;
|
|
38066
|
+
RETURN;
|
|
38067
|
+
END IF;
|
|
38068
|
+
|
|
38069
|
+
SELECT oi.id, oi.product_id, COALESCE(oi.quantity, 0)::numeric AS quantity
|
|
38070
|
+
INTO v_oi FROM public.order_items oi WHERE oi.id = p_order_item_id;
|
|
38071
|
+
IF v_oi.id IS NULL OR v_oi.product_id IS NULL OR v_oi.quantity <= 0 THEN RETURN; END IF;
|
|
38072
|
+
|
|
38073
|
+
SELECT string_agg(e.note, '; ') INTO v_err
|
|
38074
|
+
FROM public.logistics_expand_line(v_oi.product_id, v_oi.quantity) e WHERE e.kind = 'error';
|
|
38075
|
+
IF v_err IS NOT NULL THEN
|
|
38076
|
+
RETURN QUERY SELECT NULL::text, 0::numeric, 'error'::text, NULL::uuid, v_err;
|
|
38077
|
+
RETURN;
|
|
38078
|
+
END IF;
|
|
38079
|
+
|
|
38080
|
+
FOR part IN SELECT e.kind, e.ref, e.qty FROM public.logistics_expand_line(v_oi.product_id, v_oi.quantity) e LOOP
|
|
38081
|
+
IF part.kind = 'item' THEN
|
|
38082
|
+
v_key := public.logistics_reserved_key(part.ref);
|
|
38083
|
+
IF v_key IS NULL THEN
|
|
38084
|
+
RETURN QUERY SELECT part.ref, part.qty, 'error'::text, NULL::uuid, 'geen voorraadrij'::text;
|
|
38085
|
+
ELSE
|
|
38086
|
+
RETURN QUERY SELECT v_key, part.qty, 'item'::text, NULL::uuid, NULL::text;
|
|
38087
|
+
END IF;
|
|
38088
|
+
ELSE
|
|
38089
|
+
v_rem := part.qty;
|
|
38090
|
+
v_last := NULL;
|
|
38091
|
+
FOR member_rec IN
|
|
38092
|
+
SELECT public.resolve_group_member_stock_key(pgi.trade_item_id) AS raw_key
|
|
38093
|
+
FROM public.product_group_items pgi
|
|
38094
|
+
WHERE pgi.product_group_id = part.ref::uuid
|
|
38095
|
+
AND public.resolve_group_member_stock_key(pgi.trade_item_id) IS NOT NULL
|
|
38096
|
+
AND public.resolve_group_member_stock_key(pgi.trade_item_id) NOT LIKE 'group:%'
|
|
38097
|
+
ORDER BY pgi.sort_order ASC NULLS LAST, pgi.created_at ASC, pgi.id ASC
|
|
38098
|
+
LOOP
|
|
38099
|
+
v_key := public.logistics_reserved_key(member_rec.raw_key);
|
|
38100
|
+
IF v_key IS NULL THEN CONTINUE; END IF;
|
|
38101
|
+
v_last := v_key;
|
|
38102
|
+
IF v_rem <= 0 THEN CONTINUE; END IF;
|
|
38103
|
+
SELECT GREATEST(COALESCE(MAX(s.physical_stock), 0)
|
|
38104
|
+
- COALESCE((SELECT SUM(a.qty) FROM public.logistics_reservation_allocations a
|
|
38105
|
+
WHERE a.trade_item_key = v_key
|
|
38106
|
+
AND a.order_item_id <> p_order_item_id), 0), 0)
|
|
38107
|
+
INTO v_av
|
|
38108
|
+
FROM public.trade_item_stock s WHERE s.trade_item_key = v_key;
|
|
38109
|
+
IF COALESCE(v_av, 0) <= 0 THEN CONTINUE; END IF;
|
|
38110
|
+
v_take := LEAST(v_av, v_rem);
|
|
38111
|
+
RETURN QUERY SELECT v_key, v_take, 'group'::text, part.ref::uuid, NULL::text;
|
|
38112
|
+
v_rem := v_rem - v_take;
|
|
38113
|
+
END LOOP;
|
|
38114
|
+
IF v_rem > 0 THEN
|
|
38115
|
+
IF v_last IS NULL THEN
|
|
38116
|
+
RETURN QUERY SELECT ('group:' || part.ref)::text, v_rem, 'error'::text, part.ref::uuid, 'groep zonder lid met voorraadrij'::text;
|
|
38117
|
+
ELSE
|
|
38118
|
+
RETURN QUERY SELECT v_last, v_rem, 'group'::text, part.ref::uuid, NULL::text;
|
|
38119
|
+
END IF;
|
|
38120
|
+
END IF;
|
|
38121
|
+
END IF;
|
|
38122
|
+
END LOOP;
|
|
38123
|
+
END
|
|
38124
|
+
$function$;
|
|
38125
|
+
|
|
38126
|
+
-- Gerichte herberekening: een ongeldige bevroren verdeling telt niet als bevroren.
|
|
38127
|
+
DO $do$
|
|
38128
|
+
DECLARE d text; n text;
|
|
38129
|
+
BEGIN
|
|
38130
|
+
d := pg_get_functiondef('public.logistics_recompute_reserved_targeted(uuid)'::regprocedure);
|
|
38131
|
+
IF position('logistics_allocation_stale(o.order_item_id)' IN d) > 0 THEN RETURN; END IF;
|
|
38132
|
+
n := replace(d, 'AND public.logistics_allocation_frozen(o.order_id)',
|
|
38133
|
+
'AND public.logistics_allocation_frozen(o.order_id) AND NOT public.logistics_allocation_stale(o.order_item_id)');
|
|
38134
|
+
IF n = d THEN RAISE EXCEPTION '1.0.221: bevroren-stap in logistics_recompute_reserved_targeted niet gevonden'; END IF;
|
|
38135
|
+
EXECUTE n;
|
|
38136
|
+
END $do$;
|
|
38137
|
+
|
|
38138
|
+
-- Herstel: ongeldige bevroren verdelingen van open orders opnieuw maken (droog of uitvoeren).
|
|
38139
|
+
CREATE OR REPLACE FUNCTION public.logistics_reservation_repair_stale_core(p_uitvoeren boolean, p_order_item_ids uuid[])
|
|
38140
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38141
|
+
AS $function$
|
|
38142
|
+
DECLARE r record; v_old jsonb; v_new jsonb; v_regels jsonb := '[]'::jsonb; v_keys text[] := '{}'; v_n int := 0;
|
|
38143
|
+
BEGIN
|
|
38144
|
+
FOR r IN
|
|
38145
|
+
SELECT x.order_item_id, o.order_number, oi.quantity, oi.product_name AS artikel,
|
|
38146
|
+
public.logistics_allocation_stale_reden(x.order_item_id) AS reden
|
|
38147
|
+
FROM (SELECT DISTINCT a.order_item_id FROM public.logistics_reservation_allocations a
|
|
38148
|
+
WHERE a.source IN ('item', 'group')
|
|
38149
|
+
AND (p_order_item_ids IS NULL OR a.order_item_id = ANY (p_order_item_ids))) x
|
|
38150
|
+
JOIN public.order_items oi ON oi.id = x.order_item_id
|
|
38151
|
+
JOIN public.orders o ON o.id = oi.order_id
|
|
38152
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
38153
|
+
AND NOT public.logistics_order_is_shipped_status(o.status)
|
|
38154
|
+
AND NOT EXISTS (SELECT 1 FROM public.stock_mutation_log sml
|
|
38155
|
+
WHERE sml.order_item_id = x.order_item_id AND sml.mutation_type = 'consumption')
|
|
38156
|
+
ORDER BY o.order_number
|
|
38157
|
+
LOOP
|
|
38158
|
+
CONTINUE WHEN r.reden IS NULL;
|
|
38159
|
+
v_n := v_n + 1;
|
|
38160
|
+
SELECT jsonb_agg(jsonb_build_object('sleutel', a.trade_item_key, 'bron', a.source, 'groep', a.group_id, 'aantal', a.qty)
|
|
38161
|
+
ORDER BY a.source, a.trade_item_key)
|
|
38162
|
+
INTO v_old FROM public.logistics_reservation_allocations a WHERE a.order_item_id = r.order_item_id;
|
|
38163
|
+
SELECT jsonb_agg(jsonb_build_object('sleutel', n.trade_item_key, 'bron', n.source, 'groep', n.group_id, 'aantal', n.qty, 'melding', n.note))
|
|
38164
|
+
INTO v_new FROM public.logistics_order_line_allocation(r.order_item_id) n;
|
|
38165
|
+
v_regels := v_regels || jsonb_build_object('order', r.order_number, 'artikel', r.artikel, 'orderRegel', r.order_item_id,
|
|
38166
|
+
'besteld', r.quantity, 'reden', r.reden, 'nu', COALESCE(v_old, '[]'::jsonb), 'nieuw', COALESCE(v_new, '[]'::jsonb));
|
|
38167
|
+
v_keys := v_keys
|
|
38168
|
+
|| ARRAY(SELECT e->>'sleutel' FROM jsonb_array_elements(COALESCE(v_old, '[]'::jsonb)) e WHERE e->>'sleutel' IS NOT NULL)
|
|
38169
|
+
|| ARRAY(SELECT e->>'sleutel' FROM jsonb_array_elements(COALESCE(v_new, '[]'::jsonb)) e WHERE e->>'sleutel' IS NOT NULL);
|
|
38170
|
+
IF p_uitvoeren THEN
|
|
38171
|
+
DELETE FROM public.logistics_reservation_allocations WHERE order_item_id = r.order_item_id;
|
|
38172
|
+
INSERT INTO public.logistics_reservation_allocations (order_item_id, trade_item_key, qty, source, group_id, line_qty)
|
|
38173
|
+
SELECT r.order_item_id, e->>'sleutel', (e->>'aantal')::numeric, e->>'bron', NULLIF(e->>'groep', '')::uuid, r.quantity
|
|
38174
|
+
FROM jsonb_array_elements(COALESCE(v_new, '[]'::jsonb)) e
|
|
38175
|
+
WHERE e->>'sleutel' IS NOT NULL;
|
|
38176
|
+
END IF;
|
|
38177
|
+
END LOOP;
|
|
38178
|
+
RETURN jsonb_build_object('uitgevoerd', p_uitvoeren, 'aantalRegels', v_n,
|
|
38179
|
+
'sleutels', (SELECT COALESCE(jsonb_agg(DISTINCT k ORDER BY k), '[]'::jsonb) FROM unnest(v_keys) k),
|
|
38180
|
+
'regels', v_regels);
|
|
38181
|
+
END $function$;
|
|
38182
|
+
REVOKE ALL ON FUNCTION public.logistics_reservation_repair_stale_core(boolean, uuid[]) FROM PUBLIC, anon, authenticated;
|
|
38183
|
+
GRANT EXECUTE ON FUNCTION public.logistics_reservation_repair_stale_core(boolean, uuid[]) TO service_role;
|
|
38184
|
+
|
|
38185
|
+
CREATE OR REPLACE FUNCTION public.logistics_reservation_repair_stale(p_uitvoeren boolean DEFAULT false)
|
|
38186
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38187
|
+
AS $function$
|
|
38188
|
+
BEGIN
|
|
38189
|
+
IF NOT (public.logistics_acc_is_server() OR public.logistics_is_beheer()) THEN
|
|
38190
|
+
RAISE EXCEPTION 'Geen toegang: alleen beheer of de server mag verdelingen herstellen.' USING ERRCODE = '42501';
|
|
38191
|
+
END IF;
|
|
38192
|
+
RETURN public.logistics_reservation_repair_stale_core(COALESCE(p_uitvoeren, false), NULL);
|
|
38193
|
+
END $function$;
|
|
38194
|
+
REVOKE ALL ON FUNCTION public.logistics_reservation_repair_stale(boolean) FROM PUBLIC, anon;
|
|
38195
|
+
GRANT EXECUTE ON FUNCTION public.logistics_reservation_repair_stale(boolean) TO authenticated, service_role;
|
|
38196
|
+
|
|
38197
|
+
-- Groep op inactief: regels die via die groep verdeeld zijn direct opnieuw maken (nooit blokkeren).
|
|
38198
|
+
CREATE OR REPLACE FUNCTION public.logistics_group_inactive_repair_trg()
|
|
38199
|
+
RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38200
|
+
AS $function$
|
|
38201
|
+
DECLARE v_ids uuid[];
|
|
38202
|
+
BEGIN
|
|
38203
|
+
IF COALESCE(OLD.is_active, false) AND NOT COALESCE(NEW.is_active, false) THEN
|
|
38204
|
+
SELECT array_agg(DISTINCT a.order_item_id) INTO v_ids
|
|
38205
|
+
FROM public.logistics_reservation_allocations a WHERE a.group_id = NEW.id;
|
|
38206
|
+
IF v_ids IS NOT NULL THEN
|
|
38207
|
+
BEGIN
|
|
38208
|
+
PERFORM public.logistics_reservation_repair_stale_core(true, v_ids);
|
|
38209
|
+
EXCEPTION WHEN OTHERS THEN
|
|
38210
|
+
RAISE WARNING 'Verdelingen van groep % niet direct hersteld: %', NEW.id, SQLERRM;
|
|
38211
|
+
END;
|
|
38212
|
+
END IF;
|
|
38213
|
+
END IF;
|
|
38214
|
+
RETURN NULL;
|
|
38215
|
+
END $function$;
|
|
38216
|
+
DROP TRIGGER IF EXISTS trg_logistics_group_inactive_repair ON public.product_groups;
|
|
38217
|
+
CREATE TRIGGER trg_logistics_group_inactive_repair AFTER UPDATE OF is_active ON public.product_groups
|
|
38218
|
+
FOR EACH ROW EXECUTE FUNCTION public.logistics_group_inactive_repair_trg();
|
|
38219
|
+
|
|
38220
|
+
-- ---------- 6. cancelled_at gevuld => status geannuleerd ----------
|
|
38221
|
+
INSERT INTO public.pick_document_statuses (code, name, color, sort_order, is_open, is_terminal, active)
|
|
38222
|
+
VALUES ('cancelled', 'Geannuleerd', '#ef4444', 90, false, true, true)
|
|
38223
|
+
ON CONFLICT (code) DO NOTHING;
|
|
38224
|
+
|
|
38225
|
+
CREATE OR REPLACE FUNCTION public.logistics_pick_queue_cancel_status_trg()
|
|
38226
|
+
RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38227
|
+
AS $function$
|
|
38228
|
+
DECLARE v_id uuid;
|
|
38229
|
+
BEGIN
|
|
38230
|
+
IF NEW.cancelled_at IS NULL THEN RETURN NEW; END IF;
|
|
38231
|
+
SELECT s.id INTO v_id FROM public.pick_document_statuses s WHERE s.code = 'cancelled';
|
|
38232
|
+
IF v_id IS NULL THEN
|
|
38233
|
+
RAISE EXCEPTION 'Pickdocumentstatus "cancelled" (Geannuleerd) ontbreekt; annuleren kan de status niet zetten.';
|
|
38234
|
+
END IF;
|
|
38235
|
+
IF NEW.status_id IS DISTINCT FROM v_id THEN NEW.status_id := v_id; END IF;
|
|
38236
|
+
RETURN NEW;
|
|
38237
|
+
END $function$;
|
|
38238
|
+
DROP TRIGGER IF EXISTS trg_logistics_pick_queue_cancel_status ON public.pick_queue;
|
|
38239
|
+
CREATE TRIGGER trg_logistics_pick_queue_cancel_status BEFORE INSERT OR UPDATE OF cancelled_at, status_id ON public.pick_queue
|
|
38240
|
+
FOR EACH ROW EXECUTE FUNCTION public.logistics_pick_queue_cancel_status_trg();
|
|
38241
|
+
|
|
38242
|
+
CREATE OR REPLACE FUNCTION public.logistics_pick_queue_fix_cancelled_status(p_uitvoeren boolean DEFAULT false)
|
|
38243
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38244
|
+
AS $function$
|
|
38245
|
+
DECLARE v_id uuid; v_list jsonb; v_n int := 0;
|
|
38246
|
+
BEGIN
|
|
38247
|
+
IF NOT (public.logistics_acc_is_server() OR public.logistics_is_beheer()) THEN
|
|
38248
|
+
RAISE EXCEPTION 'Geen toegang: alleen beheer of de server mag pickdocumenten rechtzetten.' USING ERRCODE = '42501';
|
|
38249
|
+
END IF;
|
|
38250
|
+
SELECT s.id INTO v_id FROM public.pick_document_statuses s WHERE s.code = 'cancelled';
|
|
38251
|
+
IF v_id IS NULL THEN RAISE EXCEPTION 'Pickdocumentstatus "cancelled" ontbreekt.'; END IF;
|
|
38252
|
+
SELECT jsonb_agg(jsonb_build_object('id', q.id, 'document', q.document_number, 'order', q.order_number,
|
|
38253
|
+
'statusNu', s.name, 'geannuleerdOp', q.cancelled_at) ORDER BY q.document_number, q.created_at)
|
|
38254
|
+
INTO v_list
|
|
38255
|
+
FROM public.pick_queue q LEFT JOIN public.pick_document_statuses s ON s.id = q.status_id
|
|
38256
|
+
WHERE q.cancelled_at IS NOT NULL AND q.status_id IS DISTINCT FROM v_id;
|
|
38257
|
+
IF p_uitvoeren THEN
|
|
38258
|
+
UPDATE public.pick_queue SET status_id = v_id WHERE cancelled_at IS NOT NULL AND status_id IS DISTINCT FROM v_id;
|
|
38259
|
+
GET DIAGNOSTICS v_n = ROW_COUNT;
|
|
38260
|
+
END IF;
|
|
38261
|
+
RETURN jsonb_build_object('uitgevoerd', COALESCE(p_uitvoeren, false), 'aantal', COALESCE(jsonb_array_length(v_list), 0),
|
|
38262
|
+
'rechtgezet', v_n, 'documenten', COALESCE(v_list, '[]'::jsonb));
|
|
38263
|
+
END $function$;
|
|
38264
|
+
REVOKE ALL ON FUNCTION public.logistics_pick_queue_fix_cancelled_status(boolean) FROM PUBLIC, anon;
|
|
38265
|
+
GRANT EXECUTE ON FUNCTION public.logistics_pick_queue_fix_cancelled_status(boolean) TO authenticated, service_role;
|
|
38266
|
+
|
|
38267
|
+
-- ---------- 5. Karren uit een eerdere buffer ----------
|
|
38268
|
+
CREATE OR REPLACE FUNCTION public.logistics_stale_buffer_carts(p_buffer uuid DEFAULT NULL)
|
|
38269
|
+
RETURNS TABLE(cart_id uuid, karnummer integer, oude_buffer uuid, orders text, nieuwe_buffer text,
|
|
38270
|
+
actieve_order boolean, geprint boolean, gescand boolean, afgerond boolean, besluit text)
|
|
38271
|
+
LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
38272
|
+
AS $function$
|
|
38273
|
+
WITH k AS (
|
|
38274
|
+
SELECT c.id, c.cart_number, c.buffer_id, c.order_id FROM public.order_carts c
|
|
38275
|
+
WHERE c.archived_at IS NULL AND c.buffer_id IS NOT NULL
|
|
38276
|
+
AND (p_buffer IS NULL OR c.buffer_id = p_buffer)
|
|
38277
|
+
AND NOT EXISTS (SELECT 1 FROM public.orders o WHERE o.buffer_id = c.buffer_id AND o.deleted_at IS NULL)
|
|
38278
|
+
), ko AS (
|
|
38279
|
+
SELECT k.id AS cart_id, o.order_number, o.buffer_id, o.deleted_at, o.cancelled_at, o.status FROM k
|
|
38280
|
+
JOIN public.order_cart_items ci ON ci.cart_id = k.id
|
|
38281
|
+
JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
38282
|
+
JOIN public.orders o ON o.id = oi.order_id
|
|
38283
|
+
UNION
|
|
38284
|
+
SELECT k.id, o.order_number, o.buffer_id, o.deleted_at, o.cancelled_at, o.status FROM k JOIN public.orders o ON o.id = k.order_id
|
|
38285
|
+
), f AS (
|
|
38286
|
+
SELECT k.*,
|
|
38287
|
+
(SELECT string_agg(DISTINCT ko.order_number, ', ') FROM ko WHERE ko.cart_id = k.id) AS orders,
|
|
38288
|
+
(SELECT string_agg(DISTINCT COALESCE(ko.buffer_id::text, 'geen'), ', ') FROM ko WHERE ko.cart_id = k.id) AS nieuwe_buffer,
|
|
38289
|
+
EXISTS (SELECT 1 FROM ko WHERE ko.cart_id = k.id AND ko.deleted_at IS NULL AND ko.cancelled_at IS NULL
|
|
38290
|
+
AND NOT public.logistics_order_is_shipped_status(ko.status)) AS actief,
|
|
38291
|
+
EXISTS (SELECT 1 FROM public.pick_queue q WHERE (q.reference = k.id::text OR q.payload->>'cartId' = k.id::text)
|
|
38292
|
+
AND (q.printed_at IS NOT NULL OR COALESCE(q.print_count, 0) > 0)) AS geprint,
|
|
38293
|
+
EXISTS (SELECT 1 FROM public.logistics_control_scan s WHERE s.cart_id = k.id
|
|
38294
|
+
AND s.approved_at IS NOT NULL AND s.status <> 'geannuleerd') AS gescand,
|
|
38295
|
+
EXISTS (SELECT 1 FROM public.pick_queue q WHERE (q.reference = k.id::text OR q.payload->>'cartId' = k.id::text)
|
|
38296
|
+
AND q.completed_at IS NOT NULL) AS afgerond
|
|
38297
|
+
FROM k
|
|
38298
|
+
)
|
|
38299
|
+
SELECT f.id, f.cart_number, f.buffer_id, f.orders, f.nieuwe_buffer, f.actief, f.geprint, f.gescand, f.afgerond,
|
|
38300
|
+
CASE WHEN f.actief THEN 'actieve order, niet gearchiveerd'
|
|
38301
|
+
WHEN f.gescand OR f.afgerond THEN 'gescand of afgerond, niet gearchiveerd'
|
|
38302
|
+
WHEN f.geprint THEN 'geprint, niet gearchiveerd'
|
|
38303
|
+
ELSE 'archiveren' END
|
|
38304
|
+
FROM f ORDER BY f.buffer_id, f.cart_number;
|
|
38305
|
+
$function$;
|
|
38306
|
+
REVOKE ALL ON FUNCTION public.logistics_stale_buffer_carts(uuid) FROM PUBLIC, anon, authenticated;
|
|
38307
|
+
GRANT EXECUTE ON FUNCTION public.logistics_stale_buffer_carts(uuid) TO service_role;
|
|
38308
|
+
|
|
38309
|
+
CREATE OR REPLACE FUNCTION public.logistics_archive_stale_buffer_carts_core(p_uitvoeren boolean, p_buffer uuid)
|
|
38310
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38311
|
+
AS $function$
|
|
38312
|
+
DECLARE v_list jsonb; v_ids uuid[]; v_n int := 0;
|
|
38313
|
+
v_reden constant text := 'Kar hoorde bij een eerdere gecombineerde order; de order is opnieuw ingedeeld in een andere buffer.';
|
|
38314
|
+
BEGIN
|
|
38315
|
+
SELECT jsonb_agg(to_jsonb(s)), array_agg(s.cart_id) FILTER (WHERE s.besluit = 'archiveren')
|
|
38316
|
+
INTO v_list, v_ids FROM public.logistics_stale_buffer_carts(p_buffer) s;
|
|
38317
|
+
IF p_uitvoeren AND v_ids IS NOT NULL THEN
|
|
38318
|
+
UPDATE public.pick_queue q
|
|
38319
|
+
SET cancelled_at = now(),
|
|
38320
|
+
payload = COALESCE(q.payload, '{}'::jsonb) || jsonb_build_object('cancelReason', v_reden, 'cancelledBy', 'karplan')
|
|
38321
|
+
WHERE q.cancelled_at IS NULL AND q.completed_at IS NULL
|
|
38322
|
+
AND (q.reference = ANY (SELECT x::text FROM unnest(v_ids) x) OR q.payload->>'cartId' = ANY (SELECT x::text FROM unnest(v_ids) x));
|
|
38323
|
+
INSERT INTO public.logistics_cart_archive_log (cart_id, action, reason, actor, snapshot)
|
|
38324
|
+
SELECT c.id, 'archive', v_reden, NULL, to_jsonb(c) FROM public.order_carts c WHERE c.id = ANY (v_ids) AND c.archived_at IS NULL;
|
|
38325
|
+
UPDATE public.order_carts SET archived_at = now(), archived_reason = v_reden
|
|
38326
|
+
WHERE id = ANY (v_ids) AND archived_at IS NULL;
|
|
38327
|
+
GET DIAGNOSTICS v_n = ROW_COUNT;
|
|
38328
|
+
END IF;
|
|
38329
|
+
RETURN jsonb_build_object('uitgevoerd', COALESCE(p_uitvoeren, false), 'gearchiveerd', v_n, 'karren', COALESCE(v_list, '[]'::jsonb));
|
|
38330
|
+
END $function$;
|
|
38331
|
+
REVOKE ALL ON FUNCTION public.logistics_archive_stale_buffer_carts_core(boolean, uuid) FROM PUBLIC, anon, authenticated;
|
|
38332
|
+
GRANT EXECUTE ON FUNCTION public.logistics_archive_stale_buffer_carts_core(boolean, uuid) TO service_role;
|
|
38333
|
+
|
|
38334
|
+
CREATE OR REPLACE FUNCTION public.logistics_archive_stale_buffer_carts(p_uitvoeren boolean DEFAULT false)
|
|
38335
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38336
|
+
AS $function$
|
|
38337
|
+
BEGIN
|
|
38338
|
+
IF NOT (public.logistics_acc_is_server() OR public.logistics_is_beheer()) THEN
|
|
38339
|
+
RAISE EXCEPTION 'Geen toegang: alleen beheer of de server mag karren archiveren.' USING ERRCODE = '42501';
|
|
38340
|
+
END IF;
|
|
38341
|
+
RETURN public.logistics_archive_stale_buffer_carts_core(COALESCE(p_uitvoeren, false), NULL);
|
|
38342
|
+
END $function$;
|
|
38343
|
+
REVOKE ALL ON FUNCTION public.logistics_archive_stale_buffer_carts(boolean) FROM PUBLIC, anon;
|
|
38344
|
+
GRANT EXECUTE ON FUNCTION public.logistics_archive_stale_buffer_carts(boolean) TO authenticated, service_role;
|
|
38345
|
+
|
|
38346
|
+
-- Herindelen: na wijziging van buffer of na leeghalen van karren de oude buffer opruimen.
|
|
38347
|
+
CREATE OR REPLACE FUNCTION public.logistics_orders_old_buffer_trg()
|
|
38348
|
+
RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38349
|
+
AS $function$
|
|
38350
|
+
BEGIN
|
|
38351
|
+
IF OLD.buffer_id IS NOT NULL AND NEW.buffer_id IS DISTINCT FROM OLD.buffer_id THEN
|
|
38352
|
+
PERFORM public.logistics_archive_stale_buffer_carts_core(true, OLD.buffer_id);
|
|
38353
|
+
END IF;
|
|
38354
|
+
RETURN NULL;
|
|
38355
|
+
END $function$;
|
|
38356
|
+
DROP TRIGGER IF EXISTS trg_logistics_orders_old_buffer ON public.orders;
|
|
38357
|
+
CREATE TRIGGER trg_logistics_orders_old_buffer AFTER UPDATE OF buffer_id ON public.orders
|
|
38358
|
+
FOR EACH ROW EXECUTE FUNCTION public.logistics_orders_old_buffer_trg();
|
|
38359
|
+
|
|
38360
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_items_old_buffer_trg()
|
|
38361
|
+
RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
38362
|
+
AS $function$
|
|
38363
|
+
DECLARE b uuid;
|
|
38364
|
+
BEGIN
|
|
38365
|
+
FOR b IN SELECT DISTINCT c.buffer_id FROM old_rows r JOIN public.order_carts c ON c.id = r.cart_id
|
|
38366
|
+
WHERE c.buffer_id IS NOT NULL AND c.archived_at IS NULL
|
|
38367
|
+
AND NOT EXISTS (SELECT 1 FROM public.orders o WHERE o.buffer_id = c.buffer_id AND o.deleted_at IS NULL) LOOP
|
|
38368
|
+
PERFORM public.logistics_archive_stale_buffer_carts_core(true, b);
|
|
38369
|
+
END LOOP;
|
|
38370
|
+
RETURN NULL;
|
|
38371
|
+
END $function$;
|
|
38372
|
+
DROP TRIGGER IF EXISTS trg_logistics_cart_items_old_buffer ON public.order_cart_items;
|
|
38373
|
+
CREATE TRIGGER trg_logistics_cart_items_old_buffer AFTER DELETE ON public.order_cart_items
|
|
38374
|
+
REFERENCING OLD TABLE AS old_rows FOR EACH STATEMENT EXECUTE FUNCTION public.logistics_cart_items_old_buffer_trg();
|
|
38375
|
+
|
|
38376
|
+
-- ---------- Install-check ----------
|
|
38377
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_221()
|
|
38378
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
38379
|
+
SELECT 'status geannuleerd bestaat', EXISTS (SELECT 1 FROM public.pick_document_statuses WHERE code = 'cancelled'),
|
|
38380
|
+
'Pickdocumentstatus cancelled (Geannuleerd) is aanwezig'
|
|
38381
|
+
UNION ALL SELECT 'geannuleerd => status', EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_logistics_pick_queue_cancel_status' AND NOT tgisinternal),
|
|
38382
|
+
'cancelled_at gevuld zet altijd status Geannuleerd'
|
|
38383
|
+
UNION ALL SELECT 'bevroren verdeling gecontroleerd', position('logistics_allocation_stale' IN pg_get_functiondef('public.logistics_order_line_allocation(uuid)'::regprocedure)) > 0
|
|
38384
|
+
AND position('logistics_allocation_stale' IN pg_get_functiondef('public.logistics_recompute_reserved_targeted(uuid)'::regprocedure)) > 0,
|
|
38385
|
+
'Ongeldige bevroren verdeling (inactieve groep, niet-canonieke sleutel) wordt opnieuw gemaakt'
|
|
38386
|
+
UNION ALL SELECT 'groep inactief herstelt verdeling', EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_logistics_group_inactive_repair'),
|
|
38387
|
+
'Groep op inactief maakt verdelingen via die groep opnieuw'
|
|
38388
|
+
UNION ALL SELECT 'karren eerdere buffer', EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_logistics_orders_old_buffer')
|
|
38389
|
+
AND EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_logistics_cart_items_old_buffer'),
|
|
38390
|
+
'Ongeprinte karren zonder actieve order uit een eerdere buffer worden gearchiveerd'
|
|
38391
|
+
$$;
|
|
38392
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_221() TO authenticated, service_role;
|
|
38393
|
+
|
|
38394
|
+
REVOKE ALL ON FUNCTION public.logistics_group_inactive_repair_trg() FROM PUBLIC, anon, authenticated;
|
|
38395
|
+
REVOKE ALL ON FUNCTION public.logistics_pick_queue_cancel_status_trg() FROM PUBLIC, anon, authenticated;
|
|
38396
|
+
REVOKE ALL ON FUNCTION public.logistics_orders_old_buffer_trg() FROM PUBLIC, anon, authenticated;
|
|
38397
|
+
REVOKE ALL ON FUNCTION public.logistics_cart_items_old_buffer_trg() FROM PUBLIC, anon, authenticated;
|
|
38398
|
+
REVOKE ALL ON FUNCTION public.logistics_install_check_221() FROM PUBLIC, anon;
|
|
38399
|
+
|
|
38400
|
+
|
|
38401
|
+
-- ===== 1.0.222 = Pickvoortgang per order (alleen lezen) =====
|
|
38402
|
+
-- 1.0.222 Pickvoortgang per order (alleen lezen).
|
|
38403
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_pick_progress(p_order_ids uuid[])
|
|
38404
|
+
RETURNS TABLE(order_uuid uuid, carts_total integer, carts_printed integer, carts_scanned integer,
|
|
38405
|
+
first_printed_at timestamptz, last_scanned_at timestamptz, pick_date date,
|
|
38406
|
+
blocked boolean, blocked_reason_plain text, carts_archived boolean)
|
|
38407
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
38408
|
+
AS $function$
|
|
38409
|
+
BEGIN
|
|
38410
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_pick_progress');
|
|
38411
|
+
IF cardinality(p_order_ids) > 500 THEN
|
|
38412
|
+
RAISE EXCEPTION 'Maximaal 500 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
38413
|
+
END IF;
|
|
38414
|
+
IF p_order_ids IS NULL OR cardinality(p_order_ids) = 0 THEN RETURN; END IF;
|
|
38415
|
+
|
|
38416
|
+
RETURN QUERY
|
|
38417
|
+
WITH ids AS (
|
|
38418
|
+
SELECT DISTINCT o.id, o.order_number FROM public.orders o
|
|
38419
|
+
WHERE o.id = ANY (p_order_ids) AND o.deleted_at IS NULL
|
|
38420
|
+
),
|
|
38421
|
+
-- Actieve karren: eigen kar of kar met een regel van de order (gedeelde kar telt bij elke order).
|
|
38422
|
+
act AS (
|
|
38423
|
+
SELECT i.id AS oid, c.id AS cid FROM ids i JOIN logistics_active.order_carts c ON c.order_id = i.id
|
|
38424
|
+
UNION
|
|
38425
|
+
SELECT i.id, ci.cart_id FROM ids i
|
|
38426
|
+
JOIN logistics_active.order_items oi ON oi.order_id = i.id
|
|
38427
|
+
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
38428
|
+
JOIN logistics_active.order_carts c2 ON c2.id = ci.cart_id
|
|
38429
|
+
),
|
|
38430
|
+
-- Geprinte, niet-geannuleerde pickdocumenten van de order, per kar.
|
|
38431
|
+
doc AS (
|
|
38432
|
+
SELECT i.id AS oid, x.cid, q.printed_at
|
|
38433
|
+
FROM ids i
|
|
38434
|
+
JOIN public.pick_queue q
|
|
38435
|
+
ON q.cancelled_at IS NULL AND q.printed_at IS NOT NULL
|
|
38436
|
+
AND (q.payload->>'orderId' = i.id::text
|
|
38437
|
+
OR (jsonb_typeof(q.payload->'orderIds') = 'array' AND q.payload->'orderIds' ? i.id::text))
|
|
38438
|
+
CROSS JOIN LATERAL (
|
|
38439
|
+
SELECT public.logistics_try_uuid(q.payload->>'cartId') AS cid
|
|
38440
|
+
UNION SELECT public.logistics_try_uuid(u) FROM jsonb_array_elements_text(CASE WHEN jsonb_typeof(q.printed_cart_ids) = 'array' THEN q.printed_cart_ids ELSE '[]'::jsonb END) u
|
|
38441
|
+
) x
|
|
38442
|
+
WHERE x.cid IS NOT NULL
|
|
38443
|
+
),
|
|
38444
|
+
-- Goedgekeurde, niet-geannuleerde scans (zelfde regel als logistics_cart_scanned).
|
|
38445
|
+
scan AS (
|
|
38446
|
+
SELECT i.id AS oid, s.cart_id AS cid, s.approved_at
|
|
38447
|
+
FROM ids i JOIN public.logistics_control_scan s
|
|
38448
|
+
ON s.approved_at IS NOT NULL AND s.status <> 'geannuleerd' AND s.cart_id IS NOT NULL
|
|
38449
|
+
AND (s.order_id = i.id OR s.cart_id IN (SELECT a.cid FROM act a WHERE a.oid = i.id)
|
|
38450
|
+
OR s.cart_id IN (SELECT d.cid FROM doc d WHERE d.oid = i.id))
|
|
38451
|
+
),
|
|
38452
|
+
mode AS (
|
|
38453
|
+
SELECT i.id AS oid, EXISTS (SELECT 1 FROM act a WHERE a.oid = i.id) AS heeft_actief FROM ids i
|
|
38454
|
+
),
|
|
38455
|
+
karren AS (
|
|
38456
|
+
SELECT a.oid, a.cid FROM act a
|
|
38457
|
+
UNION
|
|
38458
|
+
SELECT m.oid, d.cid FROM mode m JOIN doc d ON d.oid = m.oid WHERE NOT m.heeft_actief
|
|
38459
|
+
UNION
|
|
38460
|
+
SELECT m.oid, s.cid FROM mode m JOIN scan s ON s.oid = m.oid WHERE NOT m.heeft_actief
|
|
38461
|
+
),
|
|
38462
|
+
telling AS (
|
|
38463
|
+
SELECT k.oid,
|
|
38464
|
+
count(DISTINCT k.cid)::int AS tot,
|
|
38465
|
+
count(DISTINCT k.cid) FILTER (WHERE EXISTS (SELECT 1 FROM doc d WHERE d.oid = k.oid AND d.cid = k.cid))::int AS pr,
|
|
38466
|
+
count(DISTINCT k.cid) FILTER (WHERE EXISTS (SELECT 1 FROM scan s WHERE s.oid = k.oid AND s.cid = k.cid))::int AS sc,
|
|
38467
|
+
min(d1.printed_at) AS first_pr,
|
|
38468
|
+
max(s1.approved_at) AS last_sc
|
|
38469
|
+
FROM karren k
|
|
38470
|
+
LEFT JOIN doc d1 ON d1.oid = k.oid AND d1.cid = k.cid
|
|
38471
|
+
LEFT JOIN scan s1 ON s1.oid = k.oid AND s1.cid = k.cid
|
|
38472
|
+
GROUP BY k.oid
|
|
38473
|
+
),
|
|
38474
|
+
blok AS (
|
|
38475
|
+
SELECT DISTINCT ON (q.order_id) q.order_id AS oid, q.reason
|
|
38476
|
+
FROM public.logistics_plan_queue q JOIN ids i ON i.id = q.order_id
|
|
38477
|
+
WHERE q.status = 'geblokkeerd'
|
|
38478
|
+
ORDER BY q.order_id, q.updated_at DESC
|
|
38479
|
+
),
|
|
38480
|
+
kand AS MATERIALIZED (
|
|
38481
|
+
SELECT a.oid, a.cid FROM act a
|
|
38482
|
+
WHERE NOT EXISTS (SELECT 1 FROM scan s WHERE s.cid = a.cid) -- gescande kar is afgerond
|
|
38483
|
+
AND NOT EXISTS (SELECT 1 FROM blok b WHERE b.oid = a.oid) -- blokkade gaat al voor
|
|
38484
|
+
),
|
|
38485
|
+
oud AS (
|
|
38486
|
+
SELECT DISTINCT ON (k.oid) k.oid, v.j->>'tekst' AS tekst
|
|
38487
|
+
FROM kand k CROSS JOIN LATERAL (SELECT public.logistics_cart_verouderd_core(k.cid) AS j) v
|
|
38488
|
+
WHERE coalesce((v.j->>'verouderd')::boolean, false)
|
|
38489
|
+
ORDER BY k.oid, k.cid
|
|
38490
|
+
),
|
|
38491
|
+
taak AS (
|
|
38492
|
+
SELECT DISTINCT ON (i.id) i.id AS oid,
|
|
38493
|
+
((coalesce(t.planned_start, t.created_at) AT TIME ZONE public.logistics_tz())::date) AS dag
|
|
38494
|
+
FROM ids i JOIN public.logistics_tasks t
|
|
38495
|
+
ON t.task_type = 'pick.execute' AND t.shadow IS NOT TRUE AND t.status NOT IN ('cancelled','superseded')
|
|
38496
|
+
AND (t.payload->>'orderId' = i.id::text OR (nullif(t.payload->>'orderId','') IS NULL AND t.order_ref = i.order_number))
|
|
38497
|
+
ORDER BY i.id, t.created_at DESC
|
|
38498
|
+
)
|
|
38499
|
+
SELECT i.id,
|
|
38500
|
+
coalesce(t.tot, 0), coalesce(t.pr, 0), coalesce(t.sc, 0),
|
|
38501
|
+
t.first_pr, t.last_sc,
|
|
38502
|
+
coalesce(pd.pick_date, tk.dag),
|
|
38503
|
+
(b.oid IS NOT NULL OR o.oid IS NOT NULL),
|
|
38504
|
+
CASE
|
|
38505
|
+
WHEN b.oid IS NOT NULL AND coalesce(t.tot, 0) = 0 THEN 'Geen kar: ' || coalesce(nullif(b.reason, ''), 'order is geblokkeerd')
|
|
38506
|
+
WHEN b.oid IS NOT NULL THEN 'Geblokkeerd: ' || coalesce(nullif(b.reason, ''), 'order is geblokkeerd')
|
|
38507
|
+
WHEN o.oid IS NOT NULL THEN 'Kar verouderd: opnieuw indelen' || coalesce(' — ' || nullif(o.tekst, ''), '')
|
|
38508
|
+
END,
|
|
38509
|
+
(NOT m.heeft_actief AND coalesce(t.tot, 0) > 0)
|
|
38510
|
+
FROM ids i
|
|
38511
|
+
JOIN mode m ON m.oid = i.id
|
|
38512
|
+
LEFT JOIN telling t ON t.oid = i.id
|
|
38513
|
+
LEFT JOIN blok b ON b.oid = i.id
|
|
38514
|
+
LEFT JOIN oud o ON o.oid = i.id
|
|
38515
|
+
LEFT JOIN taak tk ON tk.oid = i.id
|
|
38516
|
+
LEFT JOIN public.logistics_order_pick_day pd ON pd.order_id = i.id;
|
|
38517
|
+
END $function$;
|
|
38518
|
+
|
|
38519
|
+
REVOKE ALL ON FUNCTION public.logistics_order_pick_progress(uuid[]) FROM PUBLIC, anon;
|
|
38520
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_pick_progress(uuid[]) TO authenticated, service_role;
|
|
38521
|
+
|
|
38522
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_222()
|
|
38523
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
38524
|
+
SELECT 'pickvoortgang per order',
|
|
38525
|
+
to_regprocedure('public.logistics_order_pick_progress(uuid[])') IS NOT NULL,
|
|
38526
|
+
'Leesfunctie logistics_order_pick_progress (max 500 orders) is aanwezig'
|
|
38527
|
+
$$;
|
|
38528
|
+
REVOKE ALL ON FUNCTION public.logistics_install_check_222() FROM PUBLIC, anon;
|
|
38529
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_222() TO service_role;
|
|
38530
|
+
|
|
38531
|
+
-- ===== 1.0.223 = Snelle pickvoortgang: set-gebaseerde verouderd-controle (alleen lezen) =====
|
|
38532
|
+
-- bron: migratie 1.0.223
|
|
38533
|
+
CREATE OR REPLACE FUNCTION public.logistics_carts_verouderd_set(p_cart_ids uuid[])
|
|
38534
|
+
RETURNS TABLE(cart_id uuid, redenen jsonb)
|
|
38535
|
+
LANGUAGE sql STABLE SET search_path TO 'public'
|
|
38536
|
+
AS $function$
|
|
38537
|
+
WITH c AS (
|
|
38538
|
+
SELECT oc.id, coalesce(oc.cart_number::text, '?') nr, oc.order_id, oc.buffer_id, oc.carrier_type, oc.total_layers_used
|
|
38539
|
+
FROM public.order_carts oc WHERE oc.id = ANY (p_cart_ids)
|
|
38540
|
+
),
|
|
38541
|
+
ln AS MATERIALIZED (
|
|
38542
|
+
SELECT ci.id ci_id, ci.cart_id cid, ci.order_item_id, ci.crates, ci.crates_per_layer, ci.product_id,
|
|
38543
|
+
oi.id oi_id, oi.quarantined_at, oi.load_carrier_type, oi.product_id oi_pid
|
|
38544
|
+
FROM public.order_cart_items ci JOIN c ON c.id = ci.cart_id
|
|
38545
|
+
LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
38546
|
+
),
|
|
38547
|
+
agg AS (
|
|
38548
|
+
SELECT ln.cid,
|
|
38549
|
+
count(*) FILTER (WHERE ln.oi_id IS NOT NULL AND ln.quarantined_at IS NOT NULL) qn,
|
|
38550
|
+
count(*) FILTER (WHERE coalesce(ln.crates, 0) > 0 AND ln.quarantined_at IS NULL) live,
|
|
38551
|
+
sum(ln.crates::numeric / nullif(ln.crates_per_layer, 0)) lagen_som
|
|
38552
|
+
FROM ln GROUP BY ln.cid
|
|
38553
|
+
),
|
|
38554
|
+
basis AS (
|
|
38555
|
+
SELECT c.*, coalesce(g.qn, 0) qn, coalesce(g.live, 0) live, g.lagen_som
|
|
38556
|
+
FROM c LEFT JOIN agg g ON g.cid = c.id
|
|
38557
|
+
),
|
|
38558
|
+
items AS (SELECT DISTINCT ln.order_item_id FROM ln WHERE ln.order_item_id IS NOT NULL),
|
|
38559
|
+
s AS (
|
|
38560
|
+
SELECT oi.id, coalesce(oi.product_name, 'regel') naam, oi.quantity q, sum(ci.crates) fust,
|
|
38561
|
+
max(ci.plants_per_crate) ppc, count(DISTINCT ci.product_id) nprod,
|
|
38562
|
+
bool_or(ci.components IS NOT NULL AND ci.components::text NOT IN ('null','[]','{}')) comp
|
|
38563
|
+
FROM items r JOIN public.order_items oi ON oi.id = r.order_item_id
|
|
38564
|
+
JOIN public.order_cart_items ci ON ci.order_item_id = oi.id
|
|
38565
|
+
JOIN public.order_carts oc ON oc.id = ci.cart_id AND oc.archived_at IS NULL
|
|
38566
|
+
WHERE oi.quarantined_at IS NULL
|
|
38567
|
+
GROUP BY oi.id, oi.product_name, oi.quantity
|
|
38568
|
+
),
|
|
38569
|
+
afw AS (
|
|
38570
|
+
SELECT x.cid, array_agg(s.naam ORDER BY s.naam) namen
|
|
38571
|
+
FROM (SELECT DISTINCT ln.cid, ln.order_item_id FROM ln WHERE ln.order_item_id IS NOT NULL) x
|
|
38572
|
+
JOIN s ON s.id = x.order_item_id
|
|
38573
|
+
WHERE NOT s.comp AND s.nprod <= 1 AND s.q IS NOT NULL AND s.q > 0
|
|
38574
|
+
AND s.fust <> s.q AND s.fust <> ceil(s.q::numeric / greatest(coalesce(s.ppc, 1), 1))
|
|
38575
|
+
GROUP BY x.cid
|
|
38576
|
+
),
|
|
38577
|
+
vo AS (
|
|
38578
|
+
SELECT DISTINCT c.id cid, x.id, x.order_number, public.logistics_order_transport_group(to_jsonb(x)) g
|
|
38579
|
+
FROM c JOIN public.orders x
|
|
38580
|
+
ON x.deleted_at IS NULL AND (x.id = c.order_id OR (c.buffer_id IS NOT NULL AND x.buffer_id = c.buffer_id))
|
|
38581
|
+
),
|
|
38582
|
+
verv AS (
|
|
38583
|
+
SELECT vo.cid, 'Op deze kar staan verschillende soorten vertrek (' ||
|
|
38584
|
+
string_agg(vo.order_number || ': ' || CASE vo.g WHEN 'eigen_vervoer' THEN 'eigen vervoer' WHEN 'klant_haalt_op' THEN 'klant haalt op' ELSE 'vervoerder' END, ', ' ORDER BY vo.order_number)
|
|
38585
|
+
|| '); die worden niet samen gebufferd.' tekst
|
|
38586
|
+
FROM vo GROUP BY vo.cid HAVING count(DISTINCT vo.g) > 1
|
|
38587
|
+
),
|
|
38588
|
+
eo AS (
|
|
38589
|
+
SELECT ln.cid, x.order_number, x.buffer_id FROM ln
|
|
38590
|
+
JOIN public.order_items oi ON oi.id = ln.order_item_id
|
|
38591
|
+
JOIN public.orders x ON x.id = oi.order_id
|
|
38592
|
+
WHERE x.deleted_at IS NULL
|
|
38593
|
+
UNION
|
|
38594
|
+
SELECT c.id, x.order_number, x.buffer_id FROM c JOIN public.orders x ON x.id = c.order_id WHERE x.deleted_at IS NULL
|
|
38595
|
+
),
|
|
38596
|
+
ea AS (
|
|
38597
|
+
SELECT DISTINCT eo.cid, eo.order_number FROM eo JOIN c ON c.id = eo.cid
|
|
38598
|
+
WHERE eo.buffer_id IS DISTINCT FROM c.buffer_id AND (eo.buffer_id IS NOT NULL OR c.order_id IS NULL)
|
|
38599
|
+
),
|
|
38600
|
+
eerd AS (
|
|
38601
|
+
SELECT ea.cid, 'Deze kar is ingedeeld voor een eerdere gecombineerde order; '
|
|
38602
|
+
|| string_agg(ea.order_number, ', ' ORDER BY ea.order_number)
|
|
38603
|
+
|| CASE WHEN count(*) > 1 THEN ' zitten' ELSE ' zit' END || ' nu in een andere gecombineerde order.' tekst
|
|
38604
|
+
FROM ea GROUP BY ea.cid
|
|
38605
|
+
),
|
|
38606
|
+
-- Ladingdrager: de keuze hangt alleen af van (regelcode, product); elke combinatie één keer laten kiezen.
|
|
38607
|
+
reg AS (
|
|
38608
|
+
SELECT ln.cid, ln.load_carrier_type rc, coalesce(ln.product_id, ln.oi_pid) pid
|
|
38609
|
+
FROM ln JOIN c ON c.id = ln.cid
|
|
38610
|
+
WHERE coalesce(ln.crates, 0) > 0
|
|
38611
|
+
AND NOT (nullif(c.carrier_type, '') IS NULL OR c.carrier_type IN ('loose', 'none', 'NONE'))
|
|
38612
|
+
),
|
|
38613
|
+
regu AS (
|
|
38614
|
+
SELECT u.rc, u.pid, row_number() OVER (ORDER BY u.rc NULLS FIRST, u.pid NULLS FIRST)::text sleutel
|
|
38615
|
+
FROM (SELECT DISTINCT reg.rc, reg.pid FROM reg) u
|
|
38616
|
+
),
|
|
38617
|
+
kies AS MATERIALIZED (
|
|
38618
|
+
SELECT kv.key, kv.value
|
|
38619
|
+
FROM (SELECT public.logistics_ladingdrager_kies(jsonb_agg(jsonb_build_object('key', regu.sleutel, 'regel_code', regu.rc, 'product_id', regu.pid))) k
|
|
38620
|
+
FROM regu GROUP BY (regu.sleutel::bigint - 1) / 2000) b
|
|
38621
|
+
CROSS JOIN LATERAL jsonb_each(b.k) kv
|
|
38622
|
+
),
|
|
38623
|
+
codes AS (
|
|
38624
|
+
SELECT reg.cid, min(kies.value->>'code') eerste,
|
|
38625
|
+
array_agg(DISTINCT kies.value->>'code') lijst
|
|
38626
|
+
FROM reg
|
|
38627
|
+
JOIN regu ON regu.rc IS NOT DISTINCT FROM reg.rc AND regu.pid IS NOT DISTINCT FROM reg.pid
|
|
38628
|
+
JOIN kies ON kies.key = regu.sleutel
|
|
38629
|
+
WHERE kies.value->>'code' IS NOT NULL AND kies.value->>'bron' <> 'werkwijze'
|
|
38630
|
+
GROUP BY reg.cid
|
|
38631
|
+
),
|
|
38632
|
+
-- Hoogte: zelfde afleiding als logistics_product_maten (fusthoogte + planthoogte), artikelgegevens één keer per product.
|
|
38633
|
+
pids AS (SELECT DISTINCT ln.product_id FROM ln WHERE ln.product_id IS NOT NULL),
|
|
38634
|
+
fm AS MATERIALIZED (SELECT * FROM public.logistics_fust_maten() WHERE EXISTS (SELECT 1 FROM pids)),
|
|
38635
|
+
pr AS MATERIALIZED (
|
|
38636
|
+
SELECT p.id, p.fust_type_id AS hand_fid, p.plant_height_cm AS hand_h, public.logistics_artikel_vbn(p.id) AS a
|
|
38637
|
+
FROM public.products p JOIN pids ON pids.product_id = p.id
|
|
38638
|
+
),
|
|
38639
|
+
k2 AS (
|
|
38640
|
+
SELECT pr.id, pr.hand_h, pr.a,
|
|
38641
|
+
coalesce(pr.hand_fid,
|
|
38642
|
+
(SELECT m.fust_type_id FROM fm m
|
|
38643
|
+
WHERE (pr.a->>'vbn_package_code') ~ '^[0-9]+$'
|
|
38644
|
+
AND (m.vbn_code = (pr.a->>'vbn_package_code')::int OR m.fust_key = 'vbn:' || (pr.a->>'vbn_package_code'))
|
|
38645
|
+
ORDER BY ((m.length_mm IS NOT NULL)::int + (m.width_mm IS NOT NULL)::int + (m.height_mm IS NOT NULL)::int) DESC, m.fust_type_id
|
|
38646
|
+
LIMIT 1),
|
|
38647
|
+
(SELECT f.id FROM public.fust_types f
|
|
38648
|
+
WHERE nullif(pr.a->>'custom_package_id', '') IS NOT NULL AND f.custom_package_id = pr.a->>'custom_package_id'
|
|
38649
|
+
ORDER BY f.created_at, f.id LIMIT 1)) AS fid
|
|
38650
|
+
FROM pr
|
|
38651
|
+
),
|
|
38652
|
+
maten AS MATERIALIZED (
|
|
38653
|
+
SELECT x.product_id, greatest(coalesce(x.fh / 10.0, 0), coalesce(x.ph, 0)) lh FROM (
|
|
38654
|
+
SELECT k.id product_id,
|
|
38655
|
+
coalesce(m.height_mm, (SELECT m2.height_mm FROM fm m2 WHERE m.fust_key IS NOT NULL AND m2.fust_key = m.fust_key AND m2.height_mm IS NOT NULL ORDER BY m2.fust_type_id LIMIT 1)) fh,
|
|
38656
|
+
coalesce(public.logistics_pos_num(k.hand_h::text), public.logistics_pos_num(k.a->>'s15_cm'), public.logistics_pos_num(k.a->>'s02_cm')) ph
|
|
38657
|
+
FROM k2 k LEFT JOIN fm m ON m.fust_type_id = k.fid) x
|
|
38658
|
+
WHERE x.fh IS NOT NULL AND x.ph IS NOT NULL
|
|
38659
|
+
),
|
|
38660
|
+
lhc AS (
|
|
38661
|
+
SELECT x.cid, max(m.lh) lh FROM (SELECT DISTINCT ln.cid, ln.product_id FROM ln WHERE ln.product_id IS NOT NULL) x
|
|
38662
|
+
JOIN maten m ON m.product_id = x.product_id GROUP BY x.cid
|
|
38663
|
+
),
|
|
38664
|
+
hoog AS (
|
|
38665
|
+
SELECT b.id cid,
|
|
38666
|
+
(SELECT t.max_height_cm FROM public.load_carrier_types t WHERE t.code = b.carrier_type ORDER BY t.is_active DESC LIMIT 1) vmax,
|
|
38667
|
+
l.lh, coalesce(b.total_layers_used, b.lagen_som) lagen
|
|
38668
|
+
FROM basis b LEFT JOIN lhc l ON l.cid = b.id
|
|
38669
|
+
),
|
|
38670
|
+
regels AS (
|
|
38671
|
+
SELECT c.id cid,
|
|
38672
|
+
CASE
|
|
38673
|
+
WHEN nullif(c.carrier_type, '') IS NULL OR c.carrier_type IN ('loose', 'none', 'NONE') THEN
|
|
38674
|
+
jsonb_build_object('code', 'geen_ladingdrager', 'tekst', 'Kar staat zonder ladingdrager; een product zonder ladingdrager kan niet op een kar.')
|
|
38675
|
+
WHEN cd.cid IS NOT NULL AND NOT (c.carrier_type = ANY (cd.lijst)) THEN
|
|
38676
|
+
jsonb_build_object('code', 'andere_ladingdrager', 'tekst',
|
|
38677
|
+
format('Volgens het artikel hoort deze kar op %s, niet op %s.',
|
|
38678
|
+
coalesce((SELECT coalesce(t.name, t.code) FROM public.load_carrier_types t WHERE t.code = cd.eerste LIMIT 1), cd.eerste),
|
|
38679
|
+
coalesce((SELECT coalesce(t.name, t.code) FROM public.load_carrier_types t WHERE t.code = c.carrier_type LIMIT 1), c.carrier_type)))
|
|
38680
|
+
WHEN h.vmax IS NOT NULL AND h.vmax > 0 AND h.lh IS NOT NULL AND h.lh > 0 AND h.lagen IS NOT NULL
|
|
38681
|
+
AND ceil(h.lagen - 0.001) > floor(h.vmax * (1 + public.logistics_laag_tolerantie()) / h.lh) THEN
|
|
38682
|
+
jsonb_build_object('code', 'te_veel_lagen', 'tekst',
|
|
38683
|
+
format('%s lagen van %s cm passen niet in %s cm; maximaal %s lagen.', trim_scale(round(h.lagen, 1)), trim_scale(round(h.lh, 1)), h.vmax,
|
|
38684
|
+
floor(h.vmax * (1 + public.logistics_laag_tolerantie()) / h.lh)))
|
|
38685
|
+
END r
|
|
38686
|
+
FROM c LEFT JOIN codes cd ON cd.cid = c.id JOIN hoog h ON h.cid = c.id
|
|
38687
|
+
),
|
|
38688
|
+
alles AS (
|
|
38689
|
+
SELECT b.id,
|
|
38690
|
+
CASE WHEN b.qn > 0 THEN jsonb_build_array(jsonb_build_object('code', 'quarantaine',
|
|
38691
|
+
'tekst', format('%s regel(s) op kar %s staan in quarantaine bij Verkoop.', b.qn, b.nr))) ELSE '[]'::jsonb END
|
|
38692
|
+
|| CASE WHEN b.live = 0 THEN jsonb_build_array(jsonb_build_object('code', 'leeg', 'tekst', format('Kar %s heeft geen regels meer.', b.nr)))
|
|
38693
|
+
ELSE
|
|
38694
|
+
CASE WHEN coalesce(cardinality(a.namen), 0) > 0 THEN jsonb_build_array(jsonb_build_object('code', 'aantal',
|
|
38695
|
+
'tekst', format('De aantallen op de kar wijken af van de order (%s).', array_to_string(a.namen, ', ')))) ELSE '[]'::jsonb END
|
|
38696
|
+
|| CASE WHEN v.cid IS NOT NULL THEN jsonb_build_array(jsonb_build_object('code', 'vervoer_gemengd', 'tekst', v.tekst)) ELSE '[]'::jsonb END
|
|
38697
|
+
|| CASE WHEN e.cid IS NOT NULL THEN jsonb_build_array(jsonb_build_object('code', 'eerdere_buffer', 'tekst', e.tekst)) ELSE '[]'::jsonb END
|
|
38698
|
+
|| CASE WHEN r.r IS NOT NULL THEN jsonb_build_array(r.r) ELSE '[]'::jsonb END
|
|
38699
|
+
END AS lijst
|
|
38700
|
+
FROM basis b
|
|
38701
|
+
LEFT JOIN afw a ON a.cid = b.id
|
|
38702
|
+
LEFT JOIN verv v ON v.cid = b.id
|
|
38703
|
+
LEFT JOIN eerd e ON e.cid = b.id
|
|
38704
|
+
LEFT JOIN regels r ON r.cid = b.id
|
|
38705
|
+
)
|
|
38706
|
+
SELECT alles.id, alles.lijst FROM alles WHERE jsonb_array_length(alles.lijst) > 0
|
|
38707
|
+
$function$;
|
|
38708
|
+
REVOKE ALL ON FUNCTION public.logistics_carts_verouderd_set(uuid[]) FROM PUBLIC, anon, authenticated;
|
|
38709
|
+
GRANT EXECUTE ON FUNCTION public.logistics_carts_verouderd_set(uuid[]) TO service_role;
|
|
38710
|
+
|
|
38711
|
+
-- 1.0.223 Pickvoortgang: set-gebaseerde verouderd-beoordeling.
|
|
38712
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_pick_progress(p_order_ids uuid[])
|
|
38713
|
+
RETURNS TABLE(order_uuid uuid, carts_total integer, carts_printed integer, carts_scanned integer,
|
|
38714
|
+
first_printed_at timestamptz, last_scanned_at timestamptz, pick_date date,
|
|
38715
|
+
blocked boolean, blocked_reason_plain text, carts_archived boolean)
|
|
38716
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
38717
|
+
AS $function$
|
|
38718
|
+
BEGIN
|
|
38719
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_pick_progress');
|
|
38720
|
+
IF cardinality(p_order_ids) > 500 THEN
|
|
38721
|
+
RAISE EXCEPTION 'Maximaal 500 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
38722
|
+
END IF;
|
|
38723
|
+
IF p_order_ids IS NULL OR cardinality(p_order_ids) = 0 THEN RETURN; END IF;
|
|
38724
|
+
|
|
38725
|
+
RETURN QUERY
|
|
38726
|
+
WITH ids AS (
|
|
38727
|
+
SELECT DISTINCT o.id, o.order_number FROM public.orders o
|
|
38728
|
+
WHERE o.id = ANY (p_order_ids) AND o.deleted_at IS NULL
|
|
38729
|
+
),
|
|
38730
|
+
act AS (
|
|
38731
|
+
SELECT i.id AS oid, c.id AS cid FROM ids i JOIN logistics_active.order_carts c ON c.order_id = i.id
|
|
38732
|
+
UNION
|
|
38733
|
+
SELECT i.id, ci.cart_id FROM ids i
|
|
38734
|
+
JOIN logistics_active.order_items oi ON oi.order_id = i.id
|
|
38735
|
+
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
38736
|
+
JOIN logistics_active.order_carts c2 ON c2.id = ci.cart_id
|
|
38737
|
+
),
|
|
38738
|
+
doc AS (
|
|
38739
|
+
SELECT i.id AS oid, x.cid, q.printed_at
|
|
38740
|
+
FROM ids i
|
|
38741
|
+
JOIN public.pick_queue q
|
|
38742
|
+
ON q.cancelled_at IS NULL AND q.printed_at IS NOT NULL
|
|
38743
|
+
AND (q.payload->>'orderId' = i.id::text
|
|
38744
|
+
OR (jsonb_typeof(q.payload->'orderIds') = 'array' AND q.payload->'orderIds' ? i.id::text))
|
|
38745
|
+
CROSS JOIN LATERAL (
|
|
38746
|
+
SELECT public.logistics_try_uuid(q.payload->>'cartId') AS cid
|
|
38747
|
+
UNION SELECT public.logistics_try_uuid(u) FROM jsonb_array_elements_text(CASE WHEN jsonb_typeof(q.printed_cart_ids) = 'array' THEN q.printed_cart_ids ELSE '[]'::jsonb END) u
|
|
38748
|
+
) x
|
|
38749
|
+
WHERE x.cid IS NOT NULL
|
|
38750
|
+
),
|
|
38751
|
+
scan AS (
|
|
38752
|
+
SELECT i.id AS oid, s.cart_id AS cid, s.approved_at
|
|
38753
|
+
FROM ids i JOIN public.logistics_control_scan s
|
|
38754
|
+
ON s.approved_at IS NOT NULL AND s.status <> 'geannuleerd' AND s.cart_id IS NOT NULL
|
|
38755
|
+
AND (s.order_id = i.id OR s.cart_id IN (SELECT a.cid FROM act a WHERE a.oid = i.id)
|
|
38756
|
+
OR s.cart_id IN (SELECT d.cid FROM doc d WHERE d.oid = i.id))
|
|
38757
|
+
),
|
|
38758
|
+
mode AS (
|
|
38759
|
+
SELECT i.id AS oid, EXISTS (SELECT 1 FROM act a WHERE a.oid = i.id) AS heeft_actief FROM ids i
|
|
38760
|
+
),
|
|
38761
|
+
karren AS (
|
|
38762
|
+
SELECT a.oid, a.cid FROM act a
|
|
38763
|
+
UNION
|
|
38764
|
+
SELECT m.oid, d.cid FROM mode m JOIN doc d ON d.oid = m.oid WHERE NOT m.heeft_actief
|
|
38765
|
+
UNION
|
|
38766
|
+
SELECT m.oid, s.cid FROM mode m JOIN scan s ON s.oid = m.oid WHERE NOT m.heeft_actief
|
|
38767
|
+
),
|
|
38768
|
+
telling AS (
|
|
38769
|
+
SELECT k.oid,
|
|
38770
|
+
count(DISTINCT k.cid)::int AS tot,
|
|
38771
|
+
count(DISTINCT k.cid) FILTER (WHERE EXISTS (SELECT 1 FROM doc d WHERE d.oid = k.oid AND d.cid = k.cid))::int AS pr,
|
|
38772
|
+
count(DISTINCT k.cid) FILTER (WHERE EXISTS (SELECT 1 FROM scan s WHERE s.oid = k.oid AND s.cid = k.cid))::int AS sc,
|
|
38773
|
+
min(d1.printed_at) AS first_pr,
|
|
38774
|
+
max(s1.approved_at) AS last_sc
|
|
38775
|
+
FROM karren k
|
|
38776
|
+
LEFT JOIN doc d1 ON d1.oid = k.oid AND d1.cid = k.cid
|
|
38777
|
+
LEFT JOIN scan s1 ON s1.oid = k.oid AND s1.cid = k.cid
|
|
38778
|
+
GROUP BY k.oid
|
|
38779
|
+
),
|
|
38780
|
+
blok AS (
|
|
38781
|
+
SELECT DISTINCT ON (q.order_id) q.order_id AS oid, q.reason
|
|
38782
|
+
FROM public.logistics_plan_queue q JOIN ids i ON i.id = q.order_id
|
|
38783
|
+
WHERE q.status = 'geblokkeerd'
|
|
38784
|
+
ORDER BY q.order_id, q.updated_at DESC
|
|
38785
|
+
),
|
|
38786
|
+
kand AS MATERIALIZED (
|
|
38787
|
+
SELECT a.oid, a.cid FROM act a
|
|
38788
|
+
WHERE NOT EXISTS (SELECT 1 FROM scan s WHERE s.cid = a.cid)
|
|
38789
|
+
AND NOT EXISTS (SELECT 1 FROM blok b WHERE b.oid = a.oid)
|
|
38790
|
+
),
|
|
38791
|
+
oud AS (
|
|
38792
|
+
SELECT DISTINCT ON (k.oid) k.oid, v.redenen->0->>'tekst' AS tekst
|
|
38793
|
+
FROM kand k
|
|
38794
|
+
JOIN public.logistics_carts_verouderd_set((SELECT array_agg(DISTINCT k2.cid) FROM kand k2)) v ON v.cart_id = k.cid
|
|
38795
|
+
ORDER BY k.oid, k.cid
|
|
38796
|
+
),
|
|
38797
|
+
taak AS (
|
|
38798
|
+
SELECT DISTINCT ON (i.id) i.id AS oid,
|
|
38799
|
+
((coalesce(t.planned_start, t.created_at) AT TIME ZONE public.logistics_tz())::date) AS dag
|
|
38800
|
+
FROM ids i JOIN public.logistics_tasks t
|
|
38801
|
+
ON t.task_type = 'pick.execute' AND t.shadow IS NOT TRUE AND t.status NOT IN ('cancelled','superseded')
|
|
38802
|
+
AND (t.payload->>'orderId' = i.id::text OR (nullif(t.payload->>'orderId','') IS NULL AND t.order_ref = i.order_number))
|
|
38803
|
+
ORDER BY i.id, t.created_at DESC
|
|
38804
|
+
)
|
|
38805
|
+
SELECT i.id,
|
|
38806
|
+
coalesce(t.tot, 0), coalesce(t.pr, 0), coalesce(t.sc, 0),
|
|
38807
|
+
t.first_pr, t.last_sc,
|
|
38808
|
+
coalesce(pd.pick_date, tk.dag),
|
|
38809
|
+
(b.oid IS NOT NULL OR o.oid IS NOT NULL),
|
|
38810
|
+
CASE
|
|
38811
|
+
WHEN b.oid IS NOT NULL AND coalesce(t.tot, 0) = 0 THEN 'Geen kar: ' || coalesce(nullif(b.reason, ''), 'order is geblokkeerd')
|
|
38812
|
+
WHEN b.oid IS NOT NULL THEN 'Geblokkeerd: ' || coalesce(nullif(b.reason, ''), 'order is geblokkeerd')
|
|
38813
|
+
WHEN o.oid IS NOT NULL THEN 'Kar verouderd: opnieuw indelen' || coalesce(' — ' || nullif(o.tekst, ''), '')
|
|
38814
|
+
END,
|
|
38815
|
+
(NOT m.heeft_actief AND coalesce(t.tot, 0) > 0)
|
|
38816
|
+
FROM ids i
|
|
38817
|
+
JOIN mode m ON m.oid = i.id
|
|
38818
|
+
LEFT JOIN telling t ON t.oid = i.id
|
|
38819
|
+
LEFT JOIN blok b ON b.oid = i.id
|
|
38820
|
+
LEFT JOIN oud o ON o.oid = i.id
|
|
38821
|
+
LEFT JOIN taak tk ON tk.oid = i.id
|
|
38822
|
+
LEFT JOIN public.logistics_order_pick_day pd ON pd.order_id = i.id;
|
|
38823
|
+
END $function$;
|
|
38824
|
+
-- bron: migratie 1.0.223
|
|
38825
|
+
CREATE INDEX IF NOT EXISTS logistics_control_scan_order_idx ON public.logistics_control_scan (order_id) WHERE order_id IS NOT NULL;
|
|
38826
|
+
CREATE INDEX IF NOT EXISTS pick_queue_printed_order_idx ON public.pick_queue ((payload->>'orderId')) WHERE cancelled_at IS NULL AND printed_at IS NOT NULL;
|
|
38827
|
+
CREATE INDEX IF NOT EXISTS pick_queue_printed_orderids_gin ON public.pick_queue USING gin ((payload->'orderIds')) WHERE cancelled_at IS NULL AND printed_at IS NOT NULL;
|
|
38828
|
+
CREATE INDEX IF NOT EXISTS logistics_tasks_pick_order_idx ON public.logistics_tasks ((payload->>'orderId')) WHERE task_type = 'pick.execute';
|
|
38829
|
+
CREATE INDEX IF NOT EXISTS logistics_tasks_pick_ref_idx ON public.logistics_tasks (order_ref) WHERE task_type = 'pick.execute';
|
|
38830
|
+
|
|
38831
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_pick_progress(p_order_ids uuid[])
|
|
38832
|
+
RETURNS TABLE(order_uuid uuid, carts_total integer, carts_printed integer, carts_scanned integer,
|
|
38833
|
+
first_printed_at timestamptz, last_scanned_at timestamptz, pick_date date,
|
|
38834
|
+
blocked boolean, blocked_reason_plain text, carts_archived boolean)
|
|
38835
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
38836
|
+
AS $function$
|
|
38837
|
+
BEGIN
|
|
38838
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_pick_progress');
|
|
38839
|
+
IF cardinality(p_order_ids) > 500 THEN
|
|
38840
|
+
RAISE EXCEPTION 'Maximaal 500 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
38841
|
+
END IF;
|
|
38842
|
+
IF p_order_ids IS NULL OR cardinality(p_order_ids) = 0 THEN RETURN; END IF;
|
|
38843
|
+
|
|
38844
|
+
-- 1.0.223: zelfde regels als 1.0.222, set-gebaseerd en via indexen.
|
|
38845
|
+
RETURN QUERY
|
|
38846
|
+
WITH ids AS MATERIALIZED (
|
|
38847
|
+
SELECT DISTINCT o.id, o.order_number FROM public.orders o
|
|
38848
|
+
WHERE o.id = ANY (p_order_ids) AND o.deleted_at IS NULL
|
|
38849
|
+
),
|
|
38850
|
+
-- Actieve karren; regels volgens logistics_active.order_items (geen quarantaine, niet extern afgehandeld), hier set-gebaseerd.
|
|
38851
|
+
act AS MATERIALIZED (
|
|
38852
|
+
SELECT i.id AS oid, c.id AS cid FROM ids i JOIN public.order_carts c ON c.order_id = i.id AND c.archived_at IS NULL
|
|
38853
|
+
UNION
|
|
38854
|
+
SELECT i.id, ci.cart_id FROM ids i
|
|
38855
|
+
JOIN public.order_items oi ON oi.order_id = i.id AND oi.quarantined_at IS NULL
|
|
38856
|
+
JOIN public.order_cart_items ci ON ci.order_item_id = oi.id
|
|
38857
|
+
JOIN public.order_carts c2 ON c2.id = ci.cart_id AND c2.archived_at IS NULL
|
|
38858
|
+
WHERE NOT EXISTS (SELECT 1 FROM public.logistics_external_fulfillment x
|
|
38859
|
+
WHERE x.order_id = oi.order_id
|
|
38860
|
+
AND (x.full_fulfilled OR lower(btrim(coalesce(oi.source_line_key, ''))) = ANY (x.sales_order_ids)))
|
|
38861
|
+
),
|
|
38862
|
+
dq AS (
|
|
38863
|
+
SELECT i.id AS oid, q.id AS qid FROM ids i JOIN public.pick_queue q
|
|
38864
|
+
ON q.cancelled_at IS NULL AND q.printed_at IS NOT NULL AND q.payload->>'orderId' = i.id::text
|
|
38865
|
+
UNION
|
|
38866
|
+
SELECT i.id, q.id FROM ids i JOIN public.pick_queue q
|
|
38867
|
+
ON q.cancelled_at IS NULL AND q.printed_at IS NOT NULL
|
|
38868
|
+
AND jsonb_typeof(q.payload->'orderIds') = 'array' AND q.payload->'orderIds' ? i.id::text
|
|
38869
|
+
),
|
|
38870
|
+
doc AS MATERIALIZED (
|
|
38871
|
+
SELECT dq.oid, x.cid, q.printed_at
|
|
38872
|
+
FROM dq JOIN public.pick_queue q ON q.id = dq.qid
|
|
38873
|
+
CROSS JOIN LATERAL (
|
|
38874
|
+
SELECT public.logistics_try_uuid(q.payload->>'cartId') AS cid
|
|
38875
|
+
UNION SELECT public.logistics_try_uuid(u) FROM jsonb_array_elements_text(CASE WHEN jsonb_typeof(q.printed_cart_ids) = 'array' THEN q.printed_cart_ids ELSE '[]'::jsonb END) u
|
|
38876
|
+
) x
|
|
38877
|
+
WHERE x.cid IS NOT NULL
|
|
38878
|
+
),
|
|
38879
|
+
docs AS (SELECT doc.oid, doc.cid, min(doc.printed_at) AS pa FROM doc GROUP BY doc.oid, doc.cid),
|
|
38880
|
+
scan AS MATERIALIZED (
|
|
38881
|
+
SELECT i.id AS oid, s.id AS sid, s.cart_id AS cid, s.approved_at FROM ids i JOIN public.logistics_control_scan s
|
|
38882
|
+
ON s.order_id = i.id AND s.approved_at IS NOT NULL AND s.status <> 'geannuleerd' AND s.cart_id IS NOT NULL
|
|
38883
|
+
UNION
|
|
38884
|
+
SELECT a.oid, s.id, s.cart_id, s.approved_at FROM act a JOIN public.logistics_control_scan s
|
|
38885
|
+
ON s.cart_id = a.cid AND s.approved_at IS NOT NULL AND s.status <> 'geannuleerd'
|
|
38886
|
+
UNION
|
|
38887
|
+
SELECT d.oid, s.id, s.cart_id, s.approved_at FROM (SELECT DISTINCT doc.oid, doc.cid FROM doc) d JOIN public.logistics_control_scan s
|
|
38888
|
+
ON s.cart_id = d.cid AND s.approved_at IS NOT NULL AND s.status <> 'geannuleerd'
|
|
38889
|
+
),
|
|
38890
|
+
scans AS (SELECT scan.oid, scan.cid, max(scan.approved_at) AS sa FROM scan GROUP BY scan.oid, scan.cid),
|
|
38891
|
+
mode AS (
|
|
38892
|
+
SELECT i.id AS oid, (a.oid IS NOT NULL) AS heeft_actief
|
|
38893
|
+
FROM ids i LEFT JOIN (SELECT DISTINCT act.oid FROM act) a ON a.oid = i.id
|
|
38894
|
+
),
|
|
38895
|
+
karren AS (
|
|
38896
|
+
SELECT a.oid, a.cid FROM act a
|
|
38897
|
+
UNION
|
|
38898
|
+
SELECT m.oid, d.cid FROM mode m JOIN docs d ON d.oid = m.oid WHERE NOT m.heeft_actief
|
|
38899
|
+
UNION
|
|
38900
|
+
SELECT m.oid, s.cid FROM mode m JOIN scans s ON s.oid = m.oid WHERE NOT m.heeft_actief
|
|
38901
|
+
),
|
|
38902
|
+
telling AS (
|
|
38903
|
+
SELECT k.oid, count(*)::int AS tot, count(d.cid)::int AS pr, count(s.cid)::int AS sc,
|
|
38904
|
+
min(d.pa) AS first_pr, max(s.sa) AS last_sc
|
|
38905
|
+
FROM karren k
|
|
38906
|
+
LEFT JOIN docs d ON d.oid = k.oid AND d.cid = k.cid
|
|
38907
|
+
LEFT JOIN scans s ON s.oid = k.oid AND s.cid = k.cid
|
|
38908
|
+
GROUP BY k.oid
|
|
38909
|
+
),
|
|
38910
|
+
blok AS (
|
|
38911
|
+
SELECT DISTINCT ON (q.order_id) q.order_id AS oid, q.reason
|
|
38912
|
+
FROM public.logistics_plan_queue q JOIN ids i ON i.id = q.order_id
|
|
38913
|
+
WHERE q.status = 'geblokkeerd'
|
|
38914
|
+
ORDER BY q.order_id, q.updated_at DESC
|
|
38915
|
+
),
|
|
38916
|
+
kand AS MATERIALIZED (
|
|
38917
|
+
SELECT a.oid, a.cid FROM act a
|
|
38918
|
+
WHERE NOT EXISTS (SELECT 1 FROM scan s WHERE s.cid = a.cid)
|
|
38919
|
+
AND NOT EXISTS (SELECT 1 FROM blok b WHERE b.oid = a.oid)
|
|
38920
|
+
),
|
|
38921
|
+
oud AS (
|
|
38922
|
+
SELECT DISTINCT ON (k.oid) k.oid, v.redenen->0->>'tekst' AS tekst
|
|
38923
|
+
FROM kand k
|
|
38924
|
+
JOIN public.logistics_carts_verouderd_set((SELECT array_agg(DISTINCT k2.cid) FROM kand k2)) v ON v.cart_id = k.cid
|
|
38925
|
+
ORDER BY k.oid, k.cid
|
|
38926
|
+
),
|
|
38927
|
+
tk0 AS (
|
|
38928
|
+
SELECT i.id AS oid, t.created_at, t.planned_start FROM ids i JOIN public.logistics_tasks t
|
|
38929
|
+
ON t.task_type = 'pick.execute' AND t.payload->>'orderId' = i.id::text
|
|
38930
|
+
AND t.shadow IS NOT TRUE AND t.status NOT IN ('cancelled','superseded')
|
|
38931
|
+
UNION ALL
|
|
38932
|
+
SELECT i.id, t.created_at, t.planned_start FROM ids i JOIN public.logistics_tasks t
|
|
38933
|
+
ON t.task_type = 'pick.execute' AND t.order_ref = i.order_number AND nullif(t.payload->>'orderId','') IS NULL
|
|
38934
|
+
AND t.shadow IS NOT TRUE AND t.status NOT IN ('cancelled','superseded')
|
|
38935
|
+
),
|
|
38936
|
+
taak AS (
|
|
38937
|
+
SELECT DISTINCT ON (tk0.oid) tk0.oid,
|
|
38938
|
+
((coalesce(tk0.planned_start, tk0.created_at) AT TIME ZONE public.logistics_tz())::date) AS dag
|
|
38939
|
+
FROM tk0 ORDER BY tk0.oid, tk0.created_at DESC
|
|
38940
|
+
)
|
|
38941
|
+
SELECT i.id,
|
|
38942
|
+
coalesce(t.tot, 0), coalesce(t.pr, 0), coalesce(t.sc, 0),
|
|
38943
|
+
t.first_pr, t.last_sc,
|
|
38944
|
+
coalesce(pd.pick_date, tk.dag),
|
|
38945
|
+
(b.oid IS NOT NULL OR o.oid IS NOT NULL),
|
|
38946
|
+
CASE
|
|
38947
|
+
WHEN b.oid IS NOT NULL AND coalesce(t.tot, 0) = 0 THEN 'Geen kar: ' || coalesce(nullif(b.reason, ''), 'order is geblokkeerd')
|
|
38948
|
+
WHEN b.oid IS NOT NULL THEN 'Geblokkeerd: ' || coalesce(nullif(b.reason, ''), 'order is geblokkeerd')
|
|
38949
|
+
WHEN o.oid IS NOT NULL THEN 'Kar verouderd: opnieuw indelen' || coalesce(' — ' || nullif(o.tekst, ''), '')
|
|
38950
|
+
END,
|
|
38951
|
+
(NOT m.heeft_actief AND coalesce(t.tot, 0) > 0)
|
|
38952
|
+
FROM ids i
|
|
38953
|
+
JOIN mode m ON m.oid = i.id
|
|
38954
|
+
LEFT JOIN telling t ON t.oid = i.id
|
|
38955
|
+
LEFT JOIN blok b ON b.oid = i.id
|
|
38956
|
+
LEFT JOIN oud o ON o.oid = i.id
|
|
38957
|
+
LEFT JOIN taak tk ON tk.oid = i.id
|
|
38958
|
+
LEFT JOIN public.logistics_order_pick_day pd ON pd.order_id = i.id;
|
|
38959
|
+
END $function$;
|
|
38960
|
+
-- bron: migratie 1.0.223
|
|
38961
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_223()
|
|
38962
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
38963
|
+
SELECT 'set-gebaseerde verouderd-controle',
|
|
38964
|
+
to_regprocedure('public.logistics_carts_verouderd_set(uuid[])') IS NOT NULL,
|
|
38965
|
+
'logistics_carts_verouderd_set is aanwezig (gebruikt door logistics_order_pick_progress)'
|
|
38966
|
+
UNION ALL
|
|
38967
|
+
SELECT 'indexen pickvoortgang',
|
|
38968
|
+
(SELECT count(*) FROM pg_indexes WHERE schemaname = 'public' AND indexname IN
|
|
38969
|
+
('logistics_control_scan_order_idx','pick_queue_printed_order_idx','pick_queue_printed_orderids_gin',
|
|
38970
|
+
'logistics_tasks_pick_order_idx','logistics_tasks_pick_ref_idx')) = 5,
|
|
38971
|
+
'Vijf indexen voor documenten, scans en picktaken per order zijn aanwezig'
|
|
38972
|
+
$$;
|
|
38973
|
+
REVOKE ALL ON FUNCTION public.logistics_install_check_223() FROM PUBLIC, anon, authenticated;
|
|
38974
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_223() TO service_role;
|