@flowselections/logistiek-engine 1.0.195 → 1.0.200
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 +1042 -13
- package/dist-lib/components/BeheerPage.d.ts.map +1 -1
- package/dist-lib/components/BeheerPage.js +3 -1
- package/dist-lib/components/DataGereedheidCard.d.ts +47 -0
- package/dist-lib/components/DataGereedheidCard.d.ts.map +1 -0
- package/dist-lib/components/DataGereedheidCard.js +133 -0
- package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts.map +1 -1
- package/dist-lib/components/GeblokkeerdeOrdersCard.js +3 -1
- package/dist-lib/components/GeblokkeerdeStickersCard.d.ts.map +1 -1
- package/dist-lib/components/GeblokkeerdeStickersCard.js +11 -1
- package/dist-lib/components/LadingdragerVoorstellenCard.d.ts +4 -0
- package/dist-lib/components/LadingdragerVoorstellenCard.d.ts.map +1 -0
- package/dist-lib/components/LadingdragerVoorstellenCard.js +44 -0
- package/dist-lib/components/LadingdragersPage.d.ts.map +1 -1
- package/dist-lib/components/LadingdragersPage.js +2 -1
- package/dist-lib/components/StartlijstCard.d.ts +2 -0
- package/dist-lib/components/StartlijstCard.d.ts.map +1 -0
- package/dist-lib/components/StartlijstCard.js +54 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts.map +1 -1
- package/dist-lib/hooks/useGeblokkeerdeOrders.js +2 -0
- package/dist-lib/index.d.ts +3 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +3 -0
- package/dist-lib/integrations/supabase/types.d.ts +353 -122
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/beladingRegels.d.ts +22 -0
- package/dist-lib/lib/beladingRegels.d.ts.map +1 -1
- package/dist-lib/lib/beladingRegels.js +46 -4
- package/dist-lib/lib/dimensionData.server.js +15 -12
- package/dist-lib/lib/dimensionPlanner.d.ts +11 -0
- package/dist-lib/lib/dimensionPlanner.d.ts.map +1 -1
- package/dist-lib/lib/dimensionPlanner.js +30 -2
- package/dist-lib/lib/handlers/index.d.ts +1 -0
- package/dist-lib/lib/handlers/index.d.ts.map +1 -1
- package/dist-lib/lib/handlers/index.js +1 -0
- package/dist-lib/lib/handlers/logistics-plan-now.server.d.ts +18 -0
- package/dist-lib/lib/handlers/logistics-plan-now.server.d.ts.map +1 -0
- package/dist-lib/lib/handlers/logistics-plan-now.server.js +114 -0
- package/dist-lib/lib/handlers/logistics-tick.server.d.ts +5 -0
- package/dist-lib/lib/handlers/logistics-tick.server.d.ts.map +1 -1
- package/dist-lib/lib/handlers/logistics-tick.server.js +7 -0
- package/dist-lib/lib/invoerTeksten.d.ts +4 -0
- package/dist-lib/lib/invoerTeksten.d.ts.map +1 -0
- package/dist-lib/lib/invoerTeksten.js +19 -0
- package/dist-lib/lib/layoutPrint.server.d.ts +8 -0
- package/dist-lib/lib/layoutPrint.server.d.ts.map +1 -1
- package/dist-lib/lib/layoutPrint.server.js +32 -0
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts +4 -0
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +209 -12
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -1
- package/dist-lib/lib/ruleEngineSchema.js +14 -0
- package/dist-lib/lib/stickerQueue.server.d.ts +12 -0
- package/dist-lib/lib/stickerQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/stickerQueue.server.js +40 -2
- package/package.json +11 -1
|
@@ -13,6 +13,25 @@
|
|
|
13
13
|
-- Gegenereerd uit de database; niet met de hand bewerken.
|
|
14
14
|
-- ============================================================================
|
|
15
15
|
|
|
16
|
+
-- 1.0.196: vroege definitie van de toegangscontrole, zodat SQL-functies verderop
|
|
17
|
+
-- bij een eerste installatie (lege database) al kunnen verwijzen. Identiek aan de
|
|
18
|
+
-- definitie verderop; die blijft leidend.
|
|
19
|
+
CREATE OR REPLACE FUNCTION public.logistics_acc_guard(p_level text, p_fn text)
|
|
20
|
+
RETURNS void LANGUAGE plpgsql STABLE SET search_path TO 'public'
|
|
21
|
+
AS $function$
|
|
22
|
+
BEGIN
|
|
23
|
+
IF public.logistics_acc_is_server() THEN RETURN; END IF;
|
|
24
|
+
IF pg_trigger_depth() > 0 THEN RETURN; END IF;
|
|
25
|
+
IF NOT public.logistics_acc_direct(p_fn) THEN RETURN; END IF;
|
|
26
|
+
IF p_level = 'ingelogd' AND auth.uid() IS NOT NULL THEN RETURN; END IF;
|
|
27
|
+
IF p_level = 'beheer' AND auth.uid() IS NOT NULL AND public.logistics_is_beheer() THEN RETURN; END IF;
|
|
28
|
+
RAISE EXCEPTION '%', CASE p_level
|
|
29
|
+
WHEN 'server' THEN 'Geen toegang: ' || p_fn || ' is alleen voor de server.'
|
|
30
|
+
WHEN 'beheer' THEN 'Geen toegang: ' || p_fn || ' is alleen voor beheer.'
|
|
31
|
+
ELSE 'Geen toegang: log in om ' || p_fn || ' te gebruiken.' END
|
|
32
|
+
USING ERRCODE = '42501';
|
|
33
|
+
END $function$;
|
|
34
|
+
|
|
16
35
|
SET check_function_bodies = off;
|
|
17
36
|
|
|
18
37
|
DO $fs$ BEGIN
|
|
@@ -26902,7 +26921,7 @@ BEGIN
|
|
|
26902
26921
|
AND coalesce(o.order_source, '') <> 'floriday'
|
|
26903
26922
|
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
26904
26923
|
AND coalesce(o.status, '') <> 'geannuleerd'
|
|
26905
|
-
AND o.delivery_date >= current_date - 1
|
|
26924
|
+
AND public.logistics_order_date(o.delivery_date) >= current_date - 1
|
|
26906
26925
|
GROUP BY o.id, o.order_number, o.customer_id, oi.product_id
|
|
26907
26926
|
LIMIT greatest(1, p_limit)
|
|
26908
26927
|
LOOP
|
|
@@ -26989,14 +27008,12 @@ $function$;
|
|
|
26989
27008
|
-- 6. Pakbon van het pickstation: alleen de centrale beslisregel (geen layout uit payload of werkwijze).
|
|
26990
27009
|
REVOKE EXECUTE ON FUNCTION public.logistics_own_sticker_sync(integer) FROM PUBLIC, anon, authenticated;
|
|
26991
27010
|
GRANT EXECUTE ON FUNCTION public.logistics_own_sticker_sync(integer) TO service_role;
|
|
26992
|
-
|
|
26993
|
-
GRANT EXECUTE ON FUNCTION public.logistics_document_for_order(uuid, text) TO authenticated, service_role;
|
|
27011
|
+
-- 1.0.197: rechten van logistics_document_for_order staan direct na de definitie (verderop).
|
|
26994
27012
|
REVOKE EXECUTE ON FUNCTION public.logistics_document_selection_status() FROM PUBLIC, anon;
|
|
26995
27013
|
GRANT EXECUTE ON FUNCTION public.logistics_document_selection_status() TO authenticated, service_role;
|
|
26996
27014
|
|
|
26997
27015
|
-- Veiligheid: draaien met de rechten van de aanroeper.
|
|
26998
27016
|
ALTER FUNCTION public.logistics_document_selection_status() SECURITY INVOKER;
|
|
26999
|
-
ALTER FUNCTION public.logistics_document_for_order(uuid, text) SECURITY INVOKER;
|
|
27000
27017
|
|
|
27001
27018
|
-- ===== 1.0.176 reserveringen FO + pakbon centrale keuze =====
|
|
27002
27019
|
-- 1.0.176: reserveringen (Voorraad 1.0.93) en pakbon via centrale documentkeuze (Pickschermen 1.0.56).
|
|
@@ -27813,13 +27830,19 @@ BEGIN
|
|
|
27813
27830
|
'documenttype', v_type, 'breedte_mm', v_l.breedte_mm, 'hoogte_mm', v_l.hoogte_mm, 'reden', NULL) || v_extra;
|
|
27814
27831
|
END;
|
|
27815
27832
|
$function$;
|
|
27833
|
+
-- 1.0.197: rechten na de definitie (een nieuwe Shell kent de functie hiervoor nog niet).
|
|
27834
|
+
REVOKE EXECUTE ON FUNCTION public.logistics_document_for_order(uuid, text) FROM PUBLIC, anon;
|
|
27835
|
+
GRANT EXECUTE ON FUNCTION public.logistics_document_for_order(uuid, text) TO authenticated, service_role;
|
|
27836
|
+
ALTER FUNCTION public.logistics_document_for_order(uuid, text) SECURITY INVOKER;
|
|
27816
27837
|
|
|
27817
27838
|
|
|
27818
27839
|
-- ===== 1.0.178: fusten en land per kar, eigen traystickers =====
|
|
27819
27840
|
-- 1.0.178 A: fusten en land per kar in control_get_todays_carts (achteraan toegevoegd)
|
|
27820
27841
|
DO $m$ BEGIN
|
|
27821
|
-
IF
|
|
27822
|
-
|
|
27842
|
+
IF to_regprocedure('public.control_get_todays_carts()') IS NOT NULL THEN
|
|
27843
|
+
IF pg_get_function_result('public.control_get_todays_carts()'::regprocedure) NOT LIKE '%crates_on_cart%' THEN
|
|
27844
|
+
DROP FUNCTION public.control_get_todays_carts();
|
|
27845
|
+
END IF;
|
|
27823
27846
|
END IF;
|
|
27824
27847
|
END $m$;
|
|
27825
27848
|
|
|
@@ -28396,7 +28419,7 @@ BEGIN
|
|
|
28396
28419
|
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
28397
28420
|
AND coalesce(o.status, '') <> 'geannuleerd'
|
|
28398
28421
|
AND oi.quarantined_at IS NULL
|
|
28399
|
-
AND o.delivery_date >= current_date - 1
|
|
28422
|
+
AND public.logistics_order_date(o.delivery_date) >= current_date - 1
|
|
28400
28423
|
)
|
|
28401
28424
|
SELECT g.*,
|
|
28402
28425
|
(SELECT min(x.regelnaam) FROM regels x WHERE x.order_id = g.order_id AND coalesce(x.crates, 0) <= 0) AS onbekende_regel
|
|
@@ -28445,7 +28468,7 @@ BEGIN
|
|
|
28445
28468
|
SET status = 'niet_printen', reden = 'Fust hoort niet meer bij deze kar of order vervallen.', updated_at = now()
|
|
28446
28469
|
WHERE p.soort = 'eigen_traysticker' AND p.status IN ('wacht_op_moment', 'geblokkeerd', 'klaar')
|
|
28447
28470
|
AND NOT (p.bron_id = ANY (v_keep))
|
|
28448
|
-
AND p.order_id IN (SELECT o.id FROM public.orders o WHERE o.delivery_date >= current_date - 1);
|
|
28471
|
+
AND p.order_id IN (SELECT o.id FROM public.orders o WHERE public.logistics_order_date(o.delivery_date) >= current_date - 1);
|
|
28449
28472
|
GET DIAGNOSTICS n_uit = ROW_COUNT;
|
|
28450
28473
|
|
|
28451
28474
|
UPDATE public.logistics_sticker_prints p
|
|
@@ -28679,7 +28702,7 @@ BEGIN
|
|
|
28679
28702
|
FROM public.orders o
|
|
28680
28703
|
JOIN public.floriday_salesorders_cache s ON s.floriday_id = o.floriday_sales_order_id AND NOT coalesce(s.is_deleted,false)
|
|
28681
28704
|
CROSS JOIN LATERAL jsonb_array_elements(CASE WHEN jsonb_typeof(s.data->'additionalServices') = 'array' THEN s.data->'additionalServices' ELSE '[]'::jsonb END) e
|
|
28682
|
-
WHERE o.deleted_at IS NULL AND o.delivery_date >= current_date - 2
|
|
28705
|
+
WHERE o.deleted_at IS NULL AND public.logistics_order_date(o.delivery_date) >= current_date - 2
|
|
28683
28706
|
AND upper(coalesce(e->>'unit','')) = 'LABEL' AND (e->>'numberOfUnits') ~ '^\d+$'
|
|
28684
28707
|
AND nullif(btrim(coalesce(e->>'stickerId','')),'') IS NOT NULL
|
|
28685
28708
|
AND NOT EXISTS (SELECT 1 FROM public.floriday_customer_stickers_cache c WHERE c.floriday_id = e->>'stickerId')
|
|
@@ -28713,7 +28736,7 @@ BEGIN
|
|
|
28713
28736
|
SELECT o.id, o.order_number, nullif(btrim(o.floriday_sales_order_id),'') AS sales
|
|
28714
28737
|
FROM public.orders o
|
|
28715
28738
|
WHERE o.deleted_at IS NULL AND nullif(btrim(o.floriday_sales_order_id),'') IS NOT NULL
|
|
28716
|
-
AND o.delivery_date >= current_date - 2
|
|
28739
|
+
AND public.logistics_order_date(o.delivery_date) >= current_date - 2
|
|
28717
28740
|
AND EXISTS (SELECT 1 FROM logistics_active.order_carts oc WHERE oc.order_id = o.id)
|
|
28718
28741
|
ORDER BY o.delivery_date LIMIT greatest(p_limit,1)
|
|
28719
28742
|
LOOP
|
|
@@ -29987,6 +30010,8 @@ DO $fs$ DECLARE f text; BEGIN
|
|
|
29987
30010
|
'logistics_set_order_carrier(uuid,uuid)','logistics_carrier_status()','logistics_carrier_set_backfill(boolean)',
|
|
29988
30011
|
'logistics_carrier_preview_existing(integer)','logistics_carrier_promote_oud(uuid[],integer)',
|
|
29989
30012
|
'logistics_order_carrier_label(uuid)','logistics_install_check()','logistics_order_departure(uuid)','logistics_resolve_carrier_for_location_many(jsonb)'] LOOP
|
|
30013
|
+
-- 1.0.197: in een nieuwe Shell kan een functie hier nog ontbreken (verderop gedefinieerd, eigen rechten daar).
|
|
30014
|
+
CONTINUE WHEN to_regprocedure('public.' || f) IS NULL;
|
|
29990
30015
|
EXECUTE format('REVOKE ALL ON FUNCTION public.%s FROM PUBLIC, anon', f);
|
|
29991
30016
|
EXECUTE format('GRANT EXECUTE ON FUNCTION public.%s TO authenticated, service_role', f);
|
|
29992
30017
|
END LOOP;
|
|
@@ -30005,9 +30030,10 @@ END $fs$;
|
|
|
30005
30030
|
-- 1.0.184: karrenlijst toont de vervoerder uit orders.carrier_id (achteraan toegevoegd).
|
|
30006
30031
|
-- "Eigen vervoer" en "Afhalen" op carrier_kind / self_pickup, nooit op naam.
|
|
30007
30032
|
DO $m$ BEGIN
|
|
30008
|
-
IF to_regprocedure('public.control_get_todays_carts()') IS NOT NULL
|
|
30009
|
-
|
|
30010
|
-
|
|
30033
|
+
IF to_regprocedure('public.control_get_todays_carts()') IS NOT NULL THEN
|
|
30034
|
+
IF pg_get_function_result('public.control_get_todays_carts()'::regprocedure) NOT LIKE '%carrier_name%' THEN
|
|
30035
|
+
DROP FUNCTION public.control_get_todays_carts();
|
|
30036
|
+
END IF;
|
|
30011
30037
|
END IF;
|
|
30012
30038
|
END $m$;
|
|
30013
30039
|
|
|
@@ -33232,6 +33258,7 @@ BEGIN
|
|
|
33232
33258
|
AND (q.printed_at IS NOT NULL OR q.completed_at IS NOT NULL)) THEN RETURN true; END IF;
|
|
33233
33259
|
IF EXISTS (SELECT 1 FROM public.cart_control_items ci WHERE ci.order_number = v_number) THEN RETURN true; END IF;
|
|
33234
33260
|
IF public.logistics_order_print_actief(v_number) THEN RETURN true; END IF;
|
|
33261
|
+
IF public.logistics_order_print_actief(v_number) THEN RETURN true; END IF;
|
|
33235
33262
|
RETURN false;
|
|
33236
33263
|
END;
|
|
33237
33264
|
$function$
|
|
@@ -33295,6 +33322,7 @@ begin
|
|
|
33295
33322
|
and not exists (select 1 from public.pick_queue q
|
|
33296
33323
|
where q.reference = c.id::text and q.printed_at is not null)
|
|
33297
33324
|
and not public.logistics_order_print_actief(o.order_number)
|
|
33325
|
+
and not public.logistics_order_print_actief(o.order_number)
|
|
33298
33326
|
and public.logistics_cart_checkin_at(c.id) is not null
|
|
33299
33327
|
limit greatest(coalesce(p_limit, 50), 1)
|
|
33300
33328
|
loop
|
|
@@ -33329,6 +33357,7 @@ AS $function$
|
|
|
33329
33357
|
WHERE oc.order_id = p_order_id AND public.logistics_cart_is_frozen(oc.id)
|
|
33330
33358
|
)
|
|
33331
33359
|
OR public.logistics_order_print_actief((SELECT o.order_number FROM public.orders o WHERE o.id = p_order_id))
|
|
33360
|
+
OR public.logistics_order_print_actief((SELECT o.order_number FROM public.orders o WHERE o.id = p_order_id))
|
|
33332
33361
|
OR EXISTS (
|
|
33333
33362
|
SELECT 1 FROM logistics_active.order_carts oc
|
|
33334
33363
|
JOIN logistics_active.order_cart_items oci ON oci.cart_id = oc.id
|
|
@@ -33354,6 +33383,7 @@ AS $function$
|
|
|
33354
33383
|
OR public.logistics_cart_handled(COALESCE(po.order_number, p.peer_order_id::text), p.cart_number)
|
|
33355
33384
|
OR public.logistics_order_afgemeld(p.peer_order_id)
|
|
33356
33385
|
OR public.logistics_order_print_actief(po.order_number)
|
|
33386
|
+
OR public.logistics_order_print_actief(po.order_number)
|
|
33357
33387
|
OR public.logistics_cart_is_frozen(p.cart_id)
|
|
33358
33388
|
OR EXISTS (SELECT 1 FROM public.pick_queue q WHERE q.cancelled_at IS NULL
|
|
33359
33389
|
AND q.payload->>'cartId' = p.cart_id::text
|
|
@@ -33444,6 +33474,34 @@ BEGIN
|
|
|
33444
33474
|
END;
|
|
33445
33475
|
v_result := v_result || jsonb_build_object('instellingen_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
33446
33476
|
|
|
33477
|
+
-- 1.0.194: lichte ronde — pickwachtrij en laadtoestand in SQL, niet meer via HTTP.
|
|
33478
|
+
v_t := clock_timestamp();
|
|
33479
|
+
BEGIN
|
|
33480
|
+
PERFORM set_config('statement_timeout', '15000', true);
|
|
33481
|
+
v_result := v_result || jsonb_build_object('pickwachtrij', public.logistics_sync_pick_queue());
|
|
33482
|
+
EXCEPTION WHEN OTHERS THEN
|
|
33483
|
+
v_err := true; v_result := v_result || jsonb_build_object('pickwachtrij', left(SQLERRM, 200));
|
|
33484
|
+
END;
|
|
33485
|
+
v_result := v_result || jsonb_build_object('pickwachtrij_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
33486
|
+
|
|
33487
|
+
v_t := clock_timestamp();
|
|
33488
|
+
BEGIN
|
|
33489
|
+
PERFORM set_config('statement_timeout', '10000', true);
|
|
33490
|
+
v_result := v_result || jsonb_build_object('laadtoestand', public.logistics_refresh_plan_state_als_nodig());
|
|
33491
|
+
EXCEPTION WHEN OTHERS THEN
|
|
33492
|
+
v_err := true; v_result := v_result || jsonb_build_object('laadtoestand', left(SQLERRM, 200));
|
|
33493
|
+
END;
|
|
33494
|
+
v_result := v_result || jsonb_build_object('laadtoestand_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
33495
|
+
|
|
33496
|
+
v_t := clock_timestamp();
|
|
33497
|
+
BEGIN
|
|
33498
|
+
PERFORM set_config('statement_timeout', '10000', true);
|
|
33499
|
+
v_result := v_result || jsonb_build_object('instellingen', public.logistics_ensure_periodiek());
|
|
33500
|
+
EXCEPTION WHEN OTHERS THEN
|
|
33501
|
+
v_err := true; v_result := v_result || jsonb_build_object('instellingen', left(SQLERRM, 200));
|
|
33502
|
+
END;
|
|
33503
|
+
v_result := v_result || jsonb_build_object('instellingen_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
33504
|
+
|
|
33447
33505
|
BEGIN
|
|
33448
33506
|
INSERT INTO public.logistics_tick_runs(started_at, finished_at, duration_ms, has_error, steps)
|
|
33449
33507
|
VALUES (v_start, clock_timestamp(), (extract(epoch from clock_timestamp()-v_start)*1000)::int, v_err, v_result);
|
|
@@ -33553,6 +33611,7 @@ BEGIN
|
|
|
33553
33611
|
ORDER BY e.created_at DESC LIMIT 1), '') END;
|
|
33554
33612
|
RETURN NEXT;
|
|
33555
33613
|
RETURN QUERY SELECT * FROM public.logistics_install_check_194();
|
|
33614
|
+
RETURN QUERY SELECT * FROM public.logistics_install_check_196();
|
|
33556
33615
|
RETURN QUERY SELECT * FROM public.logistics_access_check();
|
|
33557
33616
|
RETURN QUERY SELECT * FROM public.logistics_overload_check();
|
|
33558
33617
|
RETURN QUERY SELECT * FROM public.logistics_check_190();
|
|
@@ -33572,3 +33631,973 @@ GRANT EXECUTE ON FUNCTION public.logistics_order_date(date) TO authenticated, se
|
|
|
33572
33631
|
GRANT EXECUTE ON FUNCTION public.logistics_print_status(uuid[]) TO authenticated, service_role;
|
|
33573
33632
|
GRANT EXECUTE ON FUNCTION public.logistics_kick_metingen(integer) TO authenticated, service_role;
|
|
33574
33633
|
GRANT EXECUTE ON FUNCTION public.logistics_install_check_194() TO authenticated, service_role;
|
|
33634
|
+
|
|
33635
|
+
-- ============================================================================
|
|
33636
|
+
-- logistiek-engine 1.0.196 — direct wekken, achterstand in één aanroep, gegevens
|
|
33637
|
+
-- voor karindeling, sticker opnieuw proberen, rebuffer-slot (additief, idempotent)
|
|
33638
|
+
-- ============================================================================
|
|
33639
|
+
-- 1.0.196 — direct wekken, achterstand in één aanroep, gegevens voor karindeling, sticker opnieuw, rebuffer-slot
|
|
33640
|
+
|
|
33641
|
+
CREATE OR REPLACE FUNCTION public.logistics_plan_now_gate(p_order_ids uuid[])
|
|
33642
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33643
|
+
DECLARE
|
|
33644
|
+
v_running boolean; v_last timestamptz;
|
|
33645
|
+
v_debounce int := public.logistics_plan_setting('kick_debounce_seconds', 5)::int;
|
|
33646
|
+
v_n int := coalesce(cardinality(p_order_ids), 0);
|
|
33647
|
+
BEGIN
|
|
33648
|
+
PERFORM public.logistics_acc_guard('server', 'logistics_plan_now_gate');
|
|
33649
|
+
IF v_n > 1000 THEN
|
|
33650
|
+
RAISE EXCEPTION 'Maximaal 1000 orders per aanroep (ontvangen: %).', v_n USING ERRCODE = '22023';
|
|
33651
|
+
END IF;
|
|
33652
|
+
SELECT EXISTS (SELECT 1 FROM public.logistics_plan_locks WHERE lock_key = 'tick:ronde' AND locked_until > now())
|
|
33653
|
+
INTO v_running;
|
|
33654
|
+
IF v_running THEN
|
|
33655
|
+
INSERT INTO public.logistics_plan_settings(key, value, updated_at)
|
|
33656
|
+
VALUES ('kick_pending', clock_timestamp()::text, now())
|
|
33657
|
+
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now();
|
|
33658
|
+
BEGIN INSERT INTO public.logistics_kick_log(skipped_reason) VALUES ('plan_now_vlag_gezet'); EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
33659
|
+
RETURN jsonb_build_object('actie', 'vlag_gezet', 'orders', v_n);
|
|
33660
|
+
END IF;
|
|
33661
|
+
SELECT NULLIF(value,'')::timestamptz INTO v_last FROM public.logistics_plan_settings WHERE key = 'last_kick_at';
|
|
33662
|
+
IF v_last IS NOT NULL AND v_last > now() - make_interval(secs => v_debounce) THEN
|
|
33663
|
+
-- Binnen de wachttijd: niet laten vallen, de eerstvolgende ronde pakt de vlag op.
|
|
33664
|
+
INSERT INTO public.logistics_plan_settings(key, value, updated_at)
|
|
33665
|
+
VALUES ('kick_pending', clock_timestamp()::text, now())
|
|
33666
|
+
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now();
|
|
33667
|
+
BEGIN INSERT INTO public.logistics_kick_log(skipped_reason) VALUES ('plan_now_debounce'); EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
33668
|
+
RETURN jsonb_build_object('actie', 'debounce', 'orders', v_n);
|
|
33669
|
+
END IF;
|
|
33670
|
+
INSERT INTO public.logistics_plan_settings(key, value, updated_at)
|
|
33671
|
+
VALUES ('last_kick_at', now()::text, now())
|
|
33672
|
+
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now();
|
|
33673
|
+
BEGIN INSERT INTO public.logistics_kick_log(skipped_reason) VALUES ('plan_now_start'); EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
33674
|
+
RETURN jsonb_build_object('actie', 'start', 'orders', v_n);
|
|
33675
|
+
END $$;
|
|
33676
|
+
GRANT EXECUTE ON FUNCTION public.logistics_plan_now_gate(uuid[]) TO service_role;
|
|
33677
|
+
|
|
33678
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_backlog_info_many(p_order_ids uuid[])
|
|
33679
|
+
RETURNS TABLE(order_id uuid, info jsonb, achterstand boolean, leverdatum date, dagen integer)
|
|
33680
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33681
|
+
BEGIN
|
|
33682
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_backlog_info_many');
|
|
33683
|
+
IF coalesce(cardinality(p_order_ids), 0) > 1000 THEN
|
|
33684
|
+
RAISE EXCEPTION 'Maximaal 1000 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
33685
|
+
END IF;
|
|
33686
|
+
RETURN QUERY
|
|
33687
|
+
WITH ids AS (SELECT DISTINCT u AS id FROM unnest(coalesce(p_order_ids, '{}'::uuid[])) u WHERE u IS NOT NULL),
|
|
33688
|
+
today AS (SELECT (now() AT TIME ZONE public.logistics_tz())::date AS d),
|
|
33689
|
+
hit AS (
|
|
33690
|
+
SELECT o.id, (o.delivery_date::text)::date AS ld
|
|
33691
|
+
FROM public.orders o JOIN ids ON ids.id = o.id, today
|
|
33692
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
33693
|
+
AND COALESCE(o.is_reservation, false) = false
|
|
33694
|
+
AND lower(coalesce(o.status, '')) = 'nog te picken'
|
|
33695
|
+
AND NULLIF(o.delivery_date::text, '') IS NOT NULL
|
|
33696
|
+
AND (o.delivery_date::text)::date < today.d
|
|
33697
|
+
AND NOT public.logistics_order_handled(o.id)
|
|
33698
|
+
AND NOT EXISTS (SELECT 1 FROM public.floriday_salesorders_cache fc
|
|
33699
|
+
WHERE o.floriday_sales_order_id IS NOT NULL AND fc.floriday_id = o.floriday_sales_order_id AND fc.controlled_at IS NOT NULL)
|
|
33700
|
+
)
|
|
33701
|
+
SELECT ids.id,
|
|
33702
|
+
CASE WHEN h.id IS NULL THEN NULL
|
|
33703
|
+
ELSE jsonb_build_object('achterstand', true, 'leverdatum', h.ld, 'dagen', t.d - h.ld) END,
|
|
33704
|
+
h.id IS NOT NULL, h.ld, CASE WHEN h.id IS NULL THEN NULL ELSE t.d - h.ld END
|
|
33705
|
+
FROM ids CROSS JOIN today t LEFT JOIN hit h ON h.id = ids.id;
|
|
33706
|
+
END $$;
|
|
33707
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_backlog_info_many(uuid[]) TO authenticated, service_role;
|
|
33708
|
+
|
|
33709
|
+
-- E4/E5: gegevens voor karindeling
|
|
33710
|
+
CREATE OR REPLACE FUNCTION public.logistics_data_gereedheid(p_product_ids uuid[] DEFAULT NULL)
|
|
33711
|
+
RETURNS TABLE(product_id uuid, product text, ladingdrager text, methode text, in_open_order boolean,
|
|
33712
|
+
ontbrekend text[], velden jsonb, voorstel jsonb, uitleg text)
|
|
33713
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33714
|
+
DECLARE v_methode text; v_carrier text; c record;
|
|
33715
|
+
BEGIN
|
|
33716
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_data_gereedheid');
|
|
33717
|
+
SELECT CASE WHEN coalesce(s.settings->'karrenindeling'->'fields'->>'cart_layout_method', s.settings->'karrenindeling'->>'cart_layout_method') = 'afmetingen'
|
|
33718
|
+
THEN 'afmetingen' ELSE 'belading' END,
|
|
33719
|
+
nullif(btrim(coalesce(s.settings->'karrenindeling'->'fields'->>'default_carrier_type', s.settings->'karrenindeling'->>'default_carrier_type')), '')
|
|
33720
|
+
INTO v_methode, v_carrier
|
|
33721
|
+
FROM public.logistics_rule_configs s WHERE s.is_active ORDER BY s.updated_at DESC LIMIT 1;
|
|
33722
|
+
v_methode := coalesce(v_methode, 'belading');
|
|
33723
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm INTO c
|
|
33724
|
+
FROM public.load_carrier_types t
|
|
33725
|
+
WHERE t.is_active AND (t.code = v_carrier OR (v_carrier IS NULL AND t.is_default))
|
|
33726
|
+
ORDER BY (t.code = v_carrier) DESC NULLS LAST LIMIT 1;
|
|
33727
|
+
|
|
33728
|
+
RETURN QUERY
|
|
33729
|
+
WITH open_p AS (
|
|
33730
|
+
SELECT DISTINCT oi.product_id FROM public.orders o JOIN public.order_items oi ON oi.order_id = o.id
|
|
33731
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.is_reservation,false) = false
|
|
33732
|
+
AND lower(coalesce(o.status,'')) = 'nog te picken' AND oi.product_id IS NOT NULL
|
|
33733
|
+
),
|
|
33734
|
+
p AS (
|
|
33735
|
+
SELECT pr.id, pr.product, pr.plants_per_crate, pr.crates_per_layer, pr.layers_per_cart,
|
|
33736
|
+
NULLIF(regexp_replace(coalesce(pr.weight::text,''), '[^0-9.,]', '', 'g'), '') AS weight_txt,
|
|
33737
|
+
pr.plant_height_cm, pr.fust_type_id, pr.floriday_packing_source,
|
|
33738
|
+
ft.length_mm, ft.width_mm, ft.height_mm,
|
|
33739
|
+
(op.product_id IS NOT NULL) AS in_open
|
|
33740
|
+
FROM public.products pr
|
|
33741
|
+
LEFT JOIN public.fust_types ft ON ft.id = pr.fust_type_id
|
|
33742
|
+
LEFT JOIN open_p op ON op.product_id = pr.id
|
|
33743
|
+
WHERE (p_product_ids IS NULL AND op.product_id IS NOT NULL) OR pr.id = ANY(p_product_ids)
|
|
33744
|
+
),
|
|
33745
|
+
m AS (
|
|
33746
|
+
SELECT p.*,
|
|
33747
|
+
array_remove(ARRAY[
|
|
33748
|
+
CASE WHEN coalesce(p.plants_per_crate,0) <= 0 THEN 'plants_per_crate' END,
|
|
33749
|
+
CASE WHEN v_methode = 'belading' AND coalesce(p.crates_per_layer,0) <= 0 THEN 'crates_per_layer' END,
|
|
33750
|
+
CASE WHEN v_methode = 'belading' AND coalesce(p.layers_per_cart,0) <= 0 THEN 'layers_per_cart' END,
|
|
33751
|
+
CASE WHEN v_methode = 'afmetingen' AND p.fust_type_id IS NULL THEN 'fust_type_id' END,
|
|
33752
|
+
CASE WHEN v_methode = 'afmetingen' AND coalesce(p.plant_height_cm,0) <= 0 THEN 'plant_height_cm' END,
|
|
33753
|
+
CASE WHEN p.weight_txt IS NULL THEN 'weight' END
|
|
33754
|
+
], NULL) AS mist,
|
|
33755
|
+
-- Fusten per laag uit fustmaat × laagmaat (beide oriëntaties, raster).
|
|
33756
|
+
CASE WHEN p.length_mm > 0 AND p.width_mm > 0 AND c.layer_length_cm > 0 AND c.layer_width_cm > 0 THEN
|
|
33757
|
+
greatest(floor(c.layer_length_cm*10 / p.length_mm) * floor(c.layer_width_cm*10 / p.width_mm),
|
|
33758
|
+
floor(c.layer_length_cm*10 / p.width_mm) * floor(c.layer_width_cm*10 / p.length_mm))::int END AS calc_cpl,
|
|
33759
|
+
-- Lagen per kar uit planthoogte + fusthoogte tegen hoogte ladingdrager.
|
|
33760
|
+
CASE WHEN coalesce(p.plant_height_cm,0) > 0 AND c.max_height_cm > 0 THEN
|
|
33761
|
+
floor(c.max_height_cm / (p.plant_height_cm + coalesce(p.height_mm,0)/10.0))::int END AS calc_lpc
|
|
33762
|
+
FROM p
|
|
33763
|
+
)
|
|
33764
|
+
SELECT m.id, m.product, c.code, v_methode, m.in_open, m.mist,
|
|
33765
|
+
jsonb_build_object(
|
|
33766
|
+
'plants_per_crate', jsonb_build_object('waarde', m.plants_per_crate, 'bron', CASE WHEN m.plants_per_crate > 0 THEN coalesce(m.floriday_packing_source, 'product') END),
|
|
33767
|
+
'crates_per_layer', jsonb_build_object('waarde', m.crates_per_layer, 'bron', CASE WHEN m.crates_per_layer > 0 THEN coalesce(m.floriday_packing_source, 'product') END),
|
|
33768
|
+
'layers_per_cart', jsonb_build_object('waarde', m.layers_per_cart, 'bron', CASE WHEN m.layers_per_cart > 0 THEN coalesce(m.floriday_packing_source, 'product') END),
|
|
33769
|
+
'weight', jsonb_build_object('waarde', m.weight_txt, 'bron', CASE WHEN m.weight_txt IS NOT NULL THEN 'product' END),
|
|
33770
|
+
'plant_height_cm', jsonb_build_object('waarde', m.plant_height_cm, 'bron', CASE WHEN m.plant_height_cm > 0 THEN 'product' END),
|
|
33771
|
+
'fust_type_id', jsonb_build_object('waarde', m.fust_type_id, 'bron', CASE WHEN m.fust_type_id IS NOT NULL THEN 'product' END)),
|
|
33772
|
+
jsonb_strip_nulls(jsonb_build_object(
|
|
33773
|
+
'crates_per_layer', CASE WHEN m.calc_cpl > 0 THEN jsonb_build_object('waarde', m.calc_cpl, 'bron', 'berekend',
|
|
33774
|
+
'berekening', format('fust %s×%s mm op laag %s×%s cm (%s)', m.length_mm, m.width_mm, c.layer_length_cm, c.layer_width_cm, c.name))
|
|
33775
|
+
ELSE (SELECT jsonb_build_object('waarde', x.v, 'bron', 'vergelijkbaar', 'berekening', format('meest gebruikt bij %s product(en) met dezelfde fust', x.n))
|
|
33776
|
+
FROM (SELECT p2.crates_per_layer v, count(*) n FROM public.products p2
|
|
33777
|
+
WHERE m.fust_type_id IS NOT NULL AND p2.fust_type_id = m.fust_type_id AND p2.crates_per_layer > 0 AND p2.id <> m.id
|
|
33778
|
+
GROUP BY 1 ORDER BY 2 DESC LIMIT 1) x) END,
|
|
33779
|
+
'layers_per_cart', CASE WHEN m.calc_lpc > 0 THEN jsonb_build_object('waarde', m.calc_lpc, 'bron', 'berekend',
|
|
33780
|
+
'berekening', format('hoogte %s cm / (plant %s cm + fust %s cm)', c.max_height_cm, m.plant_height_cm, round(coalesce(m.height_mm,0)/10.0,1)))
|
|
33781
|
+
ELSE (SELECT jsonb_build_object('waarde', x.v, 'bron', 'vergelijkbaar', 'berekening', format('meest gebruikt bij %s product(en) met dezelfde fust', x.n))
|
|
33782
|
+
FROM (SELECT p2.layers_per_cart v, count(*) n FROM public.products p2
|
|
33783
|
+
WHERE m.fust_type_id IS NOT NULL AND p2.fust_type_id = m.fust_type_id AND p2.layers_per_cart > 0 AND p2.id <> m.id
|
|
33784
|
+
GROUP BY 1 ORDER BY 2 DESC LIMIT 1) x) END)),
|
|
33785
|
+
CASE WHEN cardinality(m.mist) = 0 THEN 'Compleet.'
|
|
33786
|
+
ELSE format('Bij "%s" ontbreekt: %s. Vul dit in bij het product (Voorraad) of hier met "Invullen".', m.product,
|
|
33787
|
+
array_to_string(ARRAY(SELECT CASE f WHEN 'plants_per_crate' THEN 'planten per fust' WHEN 'crates_per_layer' THEN 'fusten per laag'
|
|
33788
|
+
WHEN 'layers_per_cart' THEN 'lagen per kar' WHEN 'fust_type_id' THEN 'fustsoort' WHEN 'plant_height_cm' THEN 'planthoogte'
|
|
33789
|
+
WHEN 'weight' THEN 'gewicht per fust' ELSE f END FROM unnest(m.mist) f), ', ')) END
|
|
33790
|
+
FROM m
|
|
33791
|
+
ORDER BY cardinality(m.mist) DESC, m.in_open DESC, m.product
|
|
33792
|
+
LIMIT 2000;
|
|
33793
|
+
END $$;
|
|
33794
|
+
GRANT EXECUTE ON FUNCTION public.logistics_data_gereedheid(uuid[]) TO authenticated, service_role;
|
|
33795
|
+
|
|
33796
|
+
CREATE OR REPLACE FUNCTION public.logistics_data_vul_in(p_product_id uuid, p_veld text, p_waarde numeric)
|
|
33797
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33798
|
+
BEGIN
|
|
33799
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_data_vul_in');
|
|
33800
|
+
IF p_waarde IS NULL OR p_waarde <= 0 THEN
|
|
33801
|
+
RAISE EXCEPTION 'Vul een getal groter dan 0 in.' USING ERRCODE = '22023';
|
|
33802
|
+
END IF;
|
|
33803
|
+
IF p_veld = 'plants_per_crate' THEN UPDATE public.products SET plants_per_crate = p_waarde, updated_at = now() WHERE id = p_product_id;
|
|
33804
|
+
ELSIF p_veld = 'crates_per_layer' THEN UPDATE public.products SET crates_per_layer = p_waarde, updated_at = now() WHERE id = p_product_id;
|
|
33805
|
+
ELSIF p_veld = 'layers_per_cart' THEN UPDATE public.products SET layers_per_cart = p_waarde, updated_at = now() WHERE id = p_product_id;
|
|
33806
|
+
ELSIF p_veld = 'plant_height_cm' THEN UPDATE public.products SET plant_height_cm = p_waarde, updated_at = now() WHERE id = p_product_id;
|
|
33807
|
+
ELSIF p_veld = 'weight' THEN UPDATE public.products SET weight = p_waarde, updated_at = now() WHERE id = p_product_id;
|
|
33808
|
+
ELSE RAISE EXCEPTION 'Dit veld kan hier niet worden ingevuld: %', p_veld USING ERRCODE = '22023';
|
|
33809
|
+
END IF;
|
|
33810
|
+
IF NOT FOUND THEN RAISE EXCEPTION 'Product niet gevonden.' USING ERRCODE = 'P0002'; END IF;
|
|
33811
|
+
RETURN jsonb_build_object('ok', true, 'productId', p_product_id, 'veld', p_veld, 'waarde', p_waarde);
|
|
33812
|
+
END $$;
|
|
33813
|
+
GRANT EXECUTE ON FUNCTION public.logistics_data_vul_in(uuid, text, numeric) TO authenticated, service_role;
|
|
33814
|
+
|
|
33815
|
+
-- 4: geweigerde sticker opnieuw proberen (status blijft binnen bestaande CHECK)
|
|
33816
|
+
CREATE OR REPLACE FUNCTION public.logistics_sticker_retry(p_id uuid)
|
|
33817
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33818
|
+
BEGIN
|
|
33819
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_sticker_retry');
|
|
33820
|
+
UPDATE public.logistics_sticker_prints
|
|
33821
|
+
SET status = 'klaar', reden = NULL, print_job_id = NULL, attempts = 0, next_attempt_at = NULL, updated_at = now()
|
|
33822
|
+
WHERE id = p_id AND status IN ('geblokkeerd', 'mislukt');
|
|
33823
|
+
IF NOT FOUND THEN
|
|
33824
|
+
RAISE EXCEPTION 'Deze sticker is niet geblokkeerd of mislukt; opnieuw proberen is niet nodig.' USING ERRCODE = '22023';
|
|
33825
|
+
END IF;
|
|
33826
|
+
RETURN jsonb_build_object('ok', true, 'id', p_id);
|
|
33827
|
+
END $$;
|
|
33828
|
+
GRANT EXECUTE ON FUNCTION public.logistics_sticker_retry(uuid) TO authenticated, service_role;
|
|
33829
|
+
|
|
33830
|
+
-- 6: rebuffer-instelling onder advisory lock (geen deadlock meer bij gelijktijdige aanroepen)
|
|
33831
|
+
CREATE OR REPLACE FUNCTION public.logistics_ensure_rebuffer_setting()
|
|
33832
|
+
RETURNS integer LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33833
|
+
DECLARE v_n integer := 0;
|
|
33834
|
+
BEGIN
|
|
33835
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_ensure_rebuffer_setting');
|
|
33836
|
+
-- 1.0.196: één tegelijk; bezet = overslaan zonder fout. Daarna rijen in vaste volgorde vergrendelen.
|
|
33837
|
+
IF NOT pg_try_advisory_xact_lock(hashtext('logistics_ensure_rebuffer_setting')) THEN
|
|
33838
|
+
RETURN 0;
|
|
33839
|
+
END IF;
|
|
33840
|
+
PERFORM 1 FROM public.logistics_rule_configs c
|
|
33841
|
+
WHERE NOT coalesce(c.settings->'order_verwerking'->'fields' ? 'rebuffer_on_change', false)
|
|
33842
|
+
AND NOT coalesce(c.settings->'order_verwerking' ? 'rebuffer_on_change', false)
|
|
33843
|
+
ORDER BY c.id FOR UPDATE SKIP LOCKED;
|
|
33844
|
+
UPDATE public.logistics_rule_configs c
|
|
33845
|
+
SET settings = jsonb_set(coalesce(c.settings, '{}'::jsonb), '{order_verwerking}',
|
|
33846
|
+
coalesce(c.settings->'order_verwerking', '{}'::jsonb)
|
|
33847
|
+
|| jsonb_build_object('fields', coalesce(c.settings->'order_verwerking'->'fields', '{}'::jsonb)
|
|
33848
|
+
|| jsonb_build_object('rebuffer_on_change', true)), true)
|
|
33849
|
+
WHERE c.id IS NOT NULL
|
|
33850
|
+
AND NOT coalesce(c.settings->'order_verwerking'->'fields' ? 'rebuffer_on_change', false)
|
|
33851
|
+
AND NOT coalesce(c.settings->'order_verwerking' ? 'rebuffer_on_change', false);
|
|
33852
|
+
GET DIAGNOSTICS v_n = ROW_COUNT;
|
|
33853
|
+
RETURN v_n;
|
|
33854
|
+
END $$;
|
|
33855
|
+
|
|
33856
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_196()
|
|
33857
|
+
RETURNS TABLE(controle text, ok boolean, toelichting text)
|
|
33858
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33859
|
+
BEGIN
|
|
33860
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_install_check_196');
|
|
33861
|
+
RETURN QUERY SELECT 'Engine: direct wekken (plan-now) – sleutel ingesteld'::text,
|
|
33862
|
+
EXISTS (SELECT 1 FROM public.module_runtime_config WHERE key = 'logistics_tick_apikey' AND nullif(btrim(value),'') IS NOT NULL),
|
|
33863
|
+
'module_runtime_config logistics_tick_apikey; zonder sleutel antwoordt de route 500.'::text;
|
|
33864
|
+
RETURN QUERY SELECT 'Engine: poort direct wekken aanwezig', to_regprocedure('public.logistics_plan_now_gate(uuid[])') IS NOT NULL, 'logistics_plan_now_gate';
|
|
33865
|
+
RETURN QUERY SELECT 'Engine: achterstand in één aanroep', to_regprocedure('public.logistics_order_backlog_info_many(uuid[])') IS NOT NULL, 'logistics_order_backlog_info_many';
|
|
33866
|
+
RETURN QUERY SELECT 'Engine: gegevens voor karindeling', to_regprocedure('public.logistics_data_gereedheid(uuid[])') IS NOT NULL, 'logistics_data_gereedheid';
|
|
33867
|
+
RETURN QUERY SELECT 'Engine: sticker opnieuw proberen', to_regprocedure('public.logistics_sticker_retry(uuid)') IS NOT NULL, 'logistics_sticker_retry';
|
|
33868
|
+
RETURN QUERY SELECT 'Engine: rebuffer-instelling onder slot',
|
|
33869
|
+
coalesce(pg_get_functiondef('public.logistics_ensure_rebuffer_setting()'::regprocedure) LIKE '%pg_try_advisory_xact_lock%', false),
|
|
33870
|
+
'voorkomt deadlock bij gelijktijdige aanroep';
|
|
33871
|
+
END $$;
|
|
33872
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_196() TO authenticated, service_role;
|
|
33873
|
+
DO $do$ DECLARE d text;
|
|
33874
|
+
BEGIN
|
|
33875
|
+
d := pg_get_functiondef('public.logistics_install_check()'::regprocedure);
|
|
33876
|
+
IF position('logistics_install_check_196' in d) = 0 THEN
|
|
33877
|
+
d := replace(d, $r$ RETURN QUERY SELECT * FROM public.logistics_access_check();$r$,
|
|
33878
|
+
$r$ RETURN QUERY SELECT * FROM public.logistics_install_check_196();
|
|
33879
|
+
RETURN QUERY SELECT * FROM public.logistics_access_check();$r$);
|
|
33880
|
+
EXECUTE d;
|
|
33881
|
+
END IF;
|
|
33882
|
+
EXCEPTION WHEN undefined_function THEN NULL;
|
|
33883
|
+
END $do$;
|
|
33884
|
+
|
|
33885
|
+
-- ===== 1.0.197 =====
|
|
33886
|
+
-- ============================================================================
|
|
33887
|
+
-- logistiek-engine 1.0.197 — unieke karnummering per buffer (incl. bevroren
|
|
33888
|
+
-- karren uit eerdere buffers), "van N" over alle karren, orderscherm telt via de
|
|
33889
|
+
-- buffer, fysieke beladingscontrole in de installatiecontrole (additief, idempotent)
|
|
33890
|
+
-- ============================================================================
|
|
33891
|
+
|
|
33892
|
+
-- Kern zonder guard en zonder SECURITY DEFINER: RLS van de aanroeper blijft gelden.
|
|
33893
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_unit_carts_core(p_order_ids uuid[])
|
|
33894
|
+
RETURNS TABLE(cart_id uuid, cart_number integer, buffer_id uuid, order_id uuid, display_seq integer, display_total integer)
|
|
33895
|
+
LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
33896
|
+
WITH ords AS (
|
|
33897
|
+
SELECT o.id, o.buffer_id FROM public.orders o WHERE o.id = ANY(coalesce(p_order_ids, '{}'::uuid[]))
|
|
33898
|
+
),
|
|
33899
|
+
bufs AS (SELECT DISTINCT b.buffer_id FROM ords b WHERE b.buffer_id IS NOT NULL),
|
|
33900
|
+
ords2 AS (
|
|
33901
|
+
SELECT o.id FROM ords o
|
|
33902
|
+
UNION
|
|
33903
|
+
SELECT o.id FROM public.orders o
|
|
33904
|
+
WHERE o.buffer_id IN (SELECT bb.buffer_id FROM bufs bb) AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
33905
|
+
),
|
|
33906
|
+
k AS (
|
|
33907
|
+
SELECT c.id FROM logistics_active.order_carts c WHERE c.order_id IN (SELECT x.id FROM ords2 x)
|
|
33908
|
+
UNION
|
|
33909
|
+
SELECT ci.cart_id FROM logistics_active.order_cart_items ci
|
|
33910
|
+
JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
33911
|
+
WHERE oi.order_id IN (SELECT x.id FROM ords2 x)
|
|
33912
|
+
UNION
|
|
33913
|
+
SELECT c.id FROM logistics_active.order_carts c
|
|
33914
|
+
WHERE c.order_id IS NULL AND c.buffer_id IN (SELECT bb.buffer_id FROM bufs bb)
|
|
33915
|
+
),
|
|
33916
|
+
base AS (
|
|
33917
|
+
SELECT c.id, c.cart_number, c.buffer_id, c.order_id, c.created_at,
|
|
33918
|
+
min(c.created_at) OVER (PARTITION BY coalesce(c.buffer_id, c.id)) AS grp_at
|
|
33919
|
+
FROM logistics_active.order_carts c WHERE c.id IN (SELECT k.id FROM k)
|
|
33920
|
+
),
|
|
33921
|
+
f AS (
|
|
33922
|
+
SELECT count(*)::int AS n, count(DISTINCT b.cart_number)::int AS nd,
|
|
33923
|
+
coalesce(max(b.cart_number), 0)::int AS mx,
|
|
33924
|
+
count(*) FILTER (WHERE b.cart_number IS NULL)::int AS leeg
|
|
33925
|
+
FROM base b
|
|
33926
|
+
)
|
|
33927
|
+
SELECT b.id, b.cart_number, b.buffer_id, b.order_id,
|
|
33928
|
+
CASE WHEN f.nd = f.n AND f.leeg = 0 THEN b.cart_number
|
|
33929
|
+
ELSE row_number() OVER (ORDER BY b.grp_at, coalesce(b.buffer_id, b.id), b.cart_number NULLS LAST, b.id)::int END,
|
|
33930
|
+
CASE WHEN f.nd = f.n AND f.leeg = 0 THEN greatest(f.n, f.mx) ELSE f.n END
|
|
33931
|
+
FROM base b CROSS JOIN f
|
|
33932
|
+
$$;
|
|
33933
|
+
|
|
33934
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_unit_carts(p_order_ids uuid[])
|
|
33935
|
+
RETURNS TABLE(cart_id uuid, cart_number integer, buffer_id uuid, order_id uuid, display_seq integer, display_total integer)
|
|
33936
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33937
|
+
BEGIN
|
|
33938
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_order_unit_carts');
|
|
33939
|
+
IF coalesce(cardinality(p_order_ids), 0) > 1000 THEN
|
|
33940
|
+
RAISE EXCEPTION 'Maximaal 1000 orders per aanroep (ontvangen: %).', cardinality(p_order_ids) USING ERRCODE = '22023';
|
|
33941
|
+
END IF;
|
|
33942
|
+
RETURN QUERY SELECT * FROM public.logistics_order_unit_carts_core(p_order_ids);
|
|
33943
|
+
END $$;
|
|
33944
|
+
GRANT EXECUTE ON FUNCTION public.logistics_order_unit_carts(uuid[]) TO authenticated, service_role;
|
|
33945
|
+
|
|
33946
|
+
-- Bestaande handtekening blijft; weergave nu uniek binnen de hele eenheid.
|
|
33947
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_fixed_numbering(p_cart_id uuid)
|
|
33948
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33949
|
+
DECLARE c record; v_ids uuid[]; u record; v_total int;
|
|
33950
|
+
BEGIN
|
|
33951
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_fixed_numbering');
|
|
33952
|
+
SELECT * INTO c FROM public.order_carts WHERE id = p_cart_id;
|
|
33953
|
+
IF NOT FOUND THEN RETURN NULL; END IF;
|
|
33954
|
+
IF c.archived_at IS NULL THEN
|
|
33955
|
+
SELECT array_agg(DISTINCT s.x) INTO v_ids FROM (
|
|
33956
|
+
SELECT c.order_id AS x
|
|
33957
|
+
UNION SELECT oi.order_id FROM public.order_cart_items ci JOIN public.order_items oi ON oi.id = ci.order_item_id WHERE ci.cart_id = p_cart_id
|
|
33958
|
+
UNION SELECT o.id FROM public.orders o WHERE c.buffer_id IS NOT NULL AND o.buffer_id = c.buffer_id AND o.deleted_at IS NULL
|
|
33959
|
+
) s WHERE s.x IS NOT NULL;
|
|
33960
|
+
IF v_ids IS NOT NULL THEN
|
|
33961
|
+
SELECT * INTO u FROM public.logistics_order_unit_carts_core(v_ids) z WHERE z.cart_id = p_cart_id;
|
|
33962
|
+
IF FOUND AND u.display_seq IS NOT NULL THEN
|
|
33963
|
+
RETURN jsonb_build_object('cartSeq', u.display_seq, 'cartIndex', u.display_seq, 'cartTotal', u.display_total,
|
|
33964
|
+
'cartLabel', 'Kar ' || u.display_seq || ' van ' || u.display_total, 'storedCartNumber', c.cart_number);
|
|
33965
|
+
END IF;
|
|
33966
|
+
END IF;
|
|
33967
|
+
END IF;
|
|
33968
|
+
-- Terugval (gearchiveerde kar of geen orders): oude berekening.
|
|
33969
|
+
SELECT greatest(coalesce(max(c2.total_carts), 0), count(*)::int, coalesce(c.cart_number, 0)) INTO v_total
|
|
33970
|
+
FROM public.order_carts c2
|
|
33971
|
+
WHERE (c.order_id IS NULL AND c.buffer_id IS NOT NULL AND c2.order_id IS NULL AND c2.buffer_id = c.buffer_id)
|
|
33972
|
+
OR (c.order_id IS NOT NULL AND c2.order_id = c.order_id)
|
|
33973
|
+
OR (c.order_id IS NULL AND c.buffer_id IS NULL AND c2.id = c.id);
|
|
33974
|
+
RETURN jsonb_build_object('cartSeq', c.cart_number, 'cartIndex', c.cart_number, 'cartTotal', v_total,
|
|
33975
|
+
'cartLabel', 'Kar ' || c.cart_number || ' van ' || v_total);
|
|
33976
|
+
END $$;
|
|
33977
|
+
|
|
33978
|
+
-- Orderscherm: tel alle karren van de eenheid (buffer + karren met goederen van de order).
|
|
33979
|
+
CREATE OR REPLACE FUNCTION public.logistics_live_cart_count(p_order_ref text)
|
|
33980
|
+
RETURNS integer LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
33981
|
+
SELECT COALESCE(
|
|
33982
|
+
NULLIF((SELECT count(*)::int FROM public.logistics_order_unit_carts_core(
|
|
33983
|
+
ARRAY(SELECT o.id FROM public.orders o WHERE o.order_number = p_order_ref AND o.deleted_at IS NULL))), 0),
|
|
33984
|
+
public.logistics_order_cart_count(p_order_ref),
|
|
33985
|
+
0);
|
|
33986
|
+
$$;
|
|
33987
|
+
|
|
33988
|
+
-- Controle: actieve pakbonnen met dezelfde naam (alleen melden, niets wijzigen).
|
|
33989
|
+
CREATE OR REPLACE FUNCTION public.logistics_dubbele_pakbonnamen()
|
|
33990
|
+
RETURNS TABLE(document_number text, aantal integer, karren text[])
|
|
33991
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
33992
|
+
BEGIN
|
|
33993
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_dubbele_pakbonnamen');
|
|
33994
|
+
RETURN QUERY
|
|
33995
|
+
SELECT q.document_number, count(*)::int, array_agg(q.reference ORDER BY q.reference)
|
|
33996
|
+
FROM public.pick_queue q
|
|
33997
|
+
WHERE q.cancelled_at IS NULL AND q.document_number LIKE 'PB-%-K%'
|
|
33998
|
+
GROUP BY q.document_number HAVING count(*) > 1;
|
|
33999
|
+
END $$;
|
|
34000
|
+
GRANT EXECUTE ON FUNCTION public.logistics_dubbele_pakbonnamen() TO authenticated, service_role;
|
|
34001
|
+
|
|
34002
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_197()
|
|
34003
|
+
RETURNS TABLE(controle text, ok boolean, toelichting text)
|
|
34004
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34005
|
+
DECLARE v_dub int;
|
|
34006
|
+
BEGIN
|
|
34007
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_install_check_197');
|
|
34008
|
+
RETURN QUERY SELECT 'Engine: karnummering per eenheid'::text,
|
|
34009
|
+
to_regprocedure('public.logistics_order_unit_carts(uuid[])') IS NOT NULL
|
|
34010
|
+
AND coalesce(pg_get_functiondef('public.logistics_cart_fixed_numbering(uuid)'::regprocedure) LIKE '%logistics_order_unit_carts_core%', false),
|
|
34011
|
+
'logistics_order_unit_carts + logistics_cart_fixed_numbering'::text;
|
|
34012
|
+
RETURN QUERY SELECT 'Engine: orderscherm telt karren via de buffer',
|
|
34013
|
+
coalesce(pg_get_functiondef('public.logistics_live_cart_count(text)'::regprocedure) LIKE '%logistics_order_unit_carts_core%', false),
|
|
34014
|
+
'logistics_live_cart_count';
|
|
34015
|
+
BEGIN
|
|
34016
|
+
SELECT count(*) INTO v_dub FROM public.logistics_dubbele_pakbonnamen();
|
|
34017
|
+
RETURN QUERY SELECT 'Engine: geen dubbele pakbonnamen', v_dub = 0,
|
|
34018
|
+
CASE WHEN v_dub = 0 THEN 'geen' ELSE v_dub || ' naam/namen dubbel; de eerstvolgende pakbonronde zet het unieke nummer' END;
|
|
34019
|
+
EXCEPTION WHEN undefined_table THEN
|
|
34020
|
+
RETURN QUERY SELECT 'Engine: geen dubbele pakbonnamen', true, 'pick_queue ontbreekt in deze Shell';
|
|
34021
|
+
END;
|
|
34022
|
+
END $$;
|
|
34023
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_197() TO authenticated, service_role;
|
|
34024
|
+
|
|
34025
|
+
DO $do$ DECLARE d text;
|
|
34026
|
+
BEGIN
|
|
34027
|
+
d := pg_get_functiondef('public.logistics_install_check()'::regprocedure);
|
|
34028
|
+
IF position('logistics_install_check_197' in d) = 0 THEN
|
|
34029
|
+
d := replace(d, $r$ RETURN QUERY SELECT * FROM public.logistics_access_check();$r$,
|
|
34030
|
+
$r$ RETURN QUERY SELECT * FROM public.logistics_install_check_197();
|
|
34031
|
+
RETURN QUERY SELECT * FROM public.logistics_access_check();$r$);
|
|
34032
|
+
EXECUTE d;
|
|
34033
|
+
END IF;
|
|
34034
|
+
EXCEPTION WHEN undefined_function THEN NULL;
|
|
34035
|
+
END $do$;
|
|
34036
|
+
|
|
34037
|
+
-- ============================================================================
|
|
34038
|
+
-- 1.0.198: maten hergebruiken uit Floricode/Floriday/Voorraad; niets stil invullen
|
|
34039
|
+
-- ============================================================================
|
|
34040
|
+
|
|
34041
|
+
-- Bronregistratie van overgenomen of bevestigde waarden (Engine-eigendom).
|
|
34042
|
+
CREATE TABLE IF NOT EXISTS public.logistics_gegevens_bron (
|
|
34043
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
34044
|
+
onderwerp text NOT NULL,
|
|
34045
|
+
sleutel text NOT NULL,
|
|
34046
|
+
veld text NOT NULL,
|
|
34047
|
+
waarde text,
|
|
34048
|
+
bron text NOT NULL,
|
|
34049
|
+
toelichting text,
|
|
34050
|
+
vastgelegd_door uuid,
|
|
34051
|
+
vastgelegd_op timestamptz NOT NULL DEFAULT now(),
|
|
34052
|
+
UNIQUE (onderwerp, sleutel, veld)
|
|
34053
|
+
);
|
|
34054
|
+
GRANT SELECT ON public.logistics_gegevens_bron TO authenticated;
|
|
34055
|
+
GRANT ALL ON public.logistics_gegevens_bron TO service_role;
|
|
34056
|
+
ALTER TABLE public.logistics_gegevens_bron ENABLE ROW LEVEL SECURITY;
|
|
34057
|
+
DO $do$ BEGIN
|
|
34058
|
+
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname = 'public' AND tablename = 'logistics_gegevens_bron' AND policyname = 'logistics_gegevens_bron_lezen') THEN
|
|
34059
|
+
CREATE POLICY logistics_gegevens_bron_lezen ON public.logistics_gegevens_bron FOR SELECT TO authenticated USING (true);
|
|
34060
|
+
END IF;
|
|
34061
|
+
END $do$;
|
|
34062
|
+
|
|
34063
|
+
-- Positief getal uit tekst, anders NULL. Nooit een standaardwaarde.
|
|
34064
|
+
CREATE OR REPLACE FUNCTION public.logistics_pos_num(p text)
|
|
34065
|
+
RETURNS numeric LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$
|
|
34066
|
+
SELECT CASE WHEN replace(btrim(coalesce(p, '')), ',', '.') ~ '^[0-9]+(\.[0-9]+)?$'
|
|
34067
|
+
THEN NULLIF(replace(btrim(p), ',', '.')::numeric, 0) END
|
|
34068
|
+
$$;
|
|
34069
|
+
GRANT EXECUTE ON FUNCTION public.logistics_pos_num(text) TO authenticated, service_role;
|
|
34070
|
+
|
|
34071
|
+
-- VBN-kenmerkwaarde in cm. Met Floricode: alleen een omschrijving "N cm" telt;
|
|
34072
|
+
-- een bereik of andere tekst = onbekend. Zonder Floricode-tabel: de code zelf (cm).
|
|
34073
|
+
CREATE OR REPLACE FUNCTION public.logistics_vbn_cm(p_feature text, p_code text)
|
|
34074
|
+
RETURNS numeric LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
34075
|
+
DECLARE v_desc text; v_found boolean := false;
|
|
34076
|
+
BEGIN
|
|
34077
|
+
IF p_code IS NULL OR btrim(p_code) = '' THEN RETURN NULL; END IF;
|
|
34078
|
+
IF to_regclass('public.floricode_records') IS NOT NULL THEN
|
|
34079
|
+
EXECUTE $q$SELECT r.data->>'description' FROM public.floricode_records r
|
|
34080
|
+
WHERE r.resource = 'FeatureValue' AND r.data->>'feature_type_id' = $1 AND r.data->>'code' = $2
|
|
34081
|
+
ORDER BY (r.data->>'expiry_date') IS NULL DESC LIMIT 1$q$
|
|
34082
|
+
INTO v_desc USING p_feature, p_code;
|
|
34083
|
+
v_found := v_desc IS NOT NULL;
|
|
34084
|
+
END IF;
|
|
34085
|
+
IF v_found THEN
|
|
34086
|
+
IF v_desc ~* '^\s*[0-9]+([.,][0-9]+)?\s*cm\s*$' THEN
|
|
34087
|
+
RETURN public.logistics_pos_num(regexp_replace(v_desc, '[^0-9.,]', '', 'g'));
|
|
34088
|
+
END IF;
|
|
34089
|
+
RETURN NULL;
|
|
34090
|
+
END IF;
|
|
34091
|
+
RETURN public.logistics_pos_num(p_code);
|
|
34092
|
+
END $$;
|
|
34093
|
+
GRANT EXECUTE ON FUNCTION public.logistics_vbn_cm(text, text) TO authenticated, service_role;
|
|
34094
|
+
|
|
34095
|
+
-- 1: eigen terugval voor fustmaten. Per veld: Floricode -> Floriday custom package -> handmatig -> onbekend.
|
|
34096
|
+
CREATE OR REPLACE FUNCTION public.logistics_fust_maten_terugval()
|
|
34097
|
+
RETURNS TABLE(fust_type_id uuid, fust_key text, vbn_code integer, name text,
|
|
34098
|
+
length_mm numeric, width_mm numeric, height_mm numeric,
|
|
34099
|
+
lengte_bron text, breedte_bron text, hoogte_bron text)
|
|
34100
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34101
|
+
#variable_conflict use_column
|
|
34102
|
+
DECLARE v_fc text; v_fd text;
|
|
34103
|
+
BEGIN
|
|
34104
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_fust_maten_terugval');
|
|
34105
|
+
IF to_regprocedure('public.floricode_packaging_types()') IS NOT NULL THEN
|
|
34106
|
+
v_fc := $q$SELECT DISTINCT ON (c.code::text)
|
|
34107
|
+
CASE WHEN c.code::text ~ '^[0-9]+$' THEN c.code::text::int END AS code,
|
|
34108
|
+
public.logistics_pos_num(c.length_mm::text) AS l, public.logistics_pos_num(c.width_mm::text) AS w,
|
|
34109
|
+
public.logistics_pos_num(c.height_mm::text) AS h
|
|
34110
|
+
FROM public.floricode_packaging_types() c ORDER BY c.code::text, c.expiry_date DESC NULLS FIRST$q$;
|
|
34111
|
+
ELSIF to_regclass('public.floricode_records') IS NOT NULL THEN
|
|
34112
|
+
v_fc := $q$SELECT DISTINCT ON (r.data->>'code')
|
|
34113
|
+
CASE WHEN (r.data->>'code') ~ '^[0-9]+$' THEN (r.data->>'code')::int END AS code,
|
|
34114
|
+
public.logistics_pos_num(r.data->>'length') AS l, public.logistics_pos_num(r.data->>'width') AS w,
|
|
34115
|
+
public.logistics_pos_num(r.data->>'height') AS h
|
|
34116
|
+
FROM public.floricode_records r WHERE r.resource = 'LoadCarrier'
|
|
34117
|
+
ORDER BY r.data->>'code', (r.data->>'expiry_date') DESC NULLS FIRST$q$;
|
|
34118
|
+
ELSE
|
|
34119
|
+
v_fc := $q$SELECT NULL::int AS code, NULL::numeric AS l, NULL::numeric AS w, NULL::numeric AS h WHERE false$q$;
|
|
34120
|
+
END IF;
|
|
34121
|
+
IF to_regclass('public.floriday_packings_cache') IS NOT NULL THEN
|
|
34122
|
+
v_fd := $q$SELECT DISTINCT ON (p.floriday_id) p.floriday_id AS id, p.data->>'customPackageId' AS id2,
|
|
34123
|
+
public.logistics_pos_num(coalesce(p.data->'dimension'->>'length', p.data->'dimensions'->>'length', p.data->>'lengthInMm', p.data->>'length')) AS l,
|
|
34124
|
+
public.logistics_pos_num(coalesce(p.data->'dimension'->>'width', p.data->'dimensions'->>'width', p.data->>'widthInMm', p.data->>'width')) AS w,
|
|
34125
|
+
public.logistics_pos_num(coalesce(p.data->'dimension'->>'height', p.data->'dimensions'->>'height', p.data->>'heightInMm', p.data->>'height')) AS h
|
|
34126
|
+
FROM public.floriday_packings_cache p WHERE coalesce(p.is_deleted, false) = false
|
|
34127
|
+
ORDER BY p.floriday_id, p.updated_at DESC NULLS LAST$q$;
|
|
34128
|
+
ELSE
|
|
34129
|
+
v_fd := $q$SELECT NULL::text AS id, NULL::text AS id2, NULL::numeric AS l, NULL::numeric AS w, NULL::numeric AS h WHERE false$q$;
|
|
34130
|
+
END IF;
|
|
34131
|
+
RETURN QUERY EXECUTE format($q$
|
|
34132
|
+
WITH fc AS (%s), fd AS (%s)
|
|
34133
|
+
SELECT f.id, f.fust_key, f.vbn_code, f.name,
|
|
34134
|
+
coalesce(fc.l, fdx.l, public.logistics_pos_num(f.length_mm::text)),
|
|
34135
|
+
coalesce(fc.w, fdx.w, public.logistics_pos_num(f.width_mm::text)),
|
|
34136
|
+
coalesce(fc.h, fdx.h, public.logistics_pos_num(f.height_mm::text)),
|
|
34137
|
+
CASE WHEN fc.l IS NOT NULL THEN 'floricode' WHEN fdx.l IS NOT NULL THEN 'floriday' WHEN public.logistics_pos_num(f.length_mm::text) IS NOT NULL THEN 'handmatig' ELSE 'onbekend' END,
|
|
34138
|
+
CASE WHEN fc.w IS NOT NULL THEN 'floricode' WHEN fdx.w IS NOT NULL THEN 'floriday' WHEN public.logistics_pos_num(f.width_mm::text) IS NOT NULL THEN 'handmatig' ELSE 'onbekend' END,
|
|
34139
|
+
CASE WHEN fc.h IS NOT NULL THEN 'floricode' WHEN fdx.h IS NOT NULL THEN 'floriday' WHEN public.logistics_pos_num(f.height_mm::text) IS NOT NULL THEN 'handmatig' ELSE 'onbekend' END
|
|
34140
|
+
FROM public.fust_types f
|
|
34141
|
+
LEFT JOIN fc ON fc.code = coalesce(f.vbn_code, CASE WHEN f.fust_key ~ '^vbn:[0-9]+$' THEN substr(f.fust_key, 5)::int END)
|
|
34142
|
+
LEFT JOIN LATERAL (SELECT fd.l, fd.w, fd.h FROM fd
|
|
34143
|
+
WHERE nullif(f.custom_package_id, '') IS NOT NULL AND (fd.id = f.custom_package_id OR fd.id2 = f.custom_package_id)
|
|
34144
|
+
LIMIT 1) fdx ON true
|
|
34145
|
+
$q$, v_fc, v_fd);
|
|
34146
|
+
END $$;
|
|
34147
|
+
GRANT EXECUTE ON FUNCTION public.logistics_fust_maten_terugval() TO authenticated, service_role;
|
|
34148
|
+
|
|
34149
|
+
-- 1: fustmaten. Voorraad (voorraad_fust_dimensions) als die bestaat, anders de eigen terugval.
|
|
34150
|
+
CREATE OR REPLACE FUNCTION public.logistics_fust_maten()
|
|
34151
|
+
RETURNS TABLE(fust_type_id uuid, fust_key text, vbn_code integer, name text,
|
|
34152
|
+
length_mm numeric, width_mm numeric, height_mm numeric,
|
|
34153
|
+
lengte_bron text, breedte_bron text, hoogte_bron text, pad text)
|
|
34154
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34155
|
+
#variable_conflict use_column
|
|
34156
|
+
DECLARE j jsonb; v_src text;
|
|
34157
|
+
BEGIN
|
|
34158
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_fust_maten');
|
|
34159
|
+
IF to_regprocedure('public.voorraad_fust_dimensions()') IS NOT NULL THEN
|
|
34160
|
+
FOR j IN EXECUTE 'SELECT to_jsonb(x) FROM public.voorraad_fust_dimensions() x' LOOP
|
|
34161
|
+
fust_type_id := (j->>'fust_type_id')::uuid;
|
|
34162
|
+
fust_key := j->>'fust_key';
|
|
34163
|
+
vbn_code := CASE WHEN (j->>'vbn_code') ~ '^[0-9]+$' THEN (j->>'vbn_code')::int END;
|
|
34164
|
+
name := j->>'name';
|
|
34165
|
+
length_mm := public.logistics_pos_num(j->>'length_mm');
|
|
34166
|
+
width_mm := public.logistics_pos_num(j->>'width_mm');
|
|
34167
|
+
height_mm := public.logistics_pos_num(j->>'height_mm');
|
|
34168
|
+
v_src := nullif(j->>'dimension_source', 'onbekend');
|
|
34169
|
+
lengte_bron := CASE WHEN length_mm IS NULL THEN 'onbekend' ELSE coalesce(j->>'length_source', j->>'lengte_bron', v_src, 'voorraad') END;
|
|
34170
|
+
breedte_bron := CASE WHEN width_mm IS NULL THEN 'onbekend' ELSE coalesce(j->>'width_source', j->>'breedte_bron', v_src, 'voorraad') END;
|
|
34171
|
+
hoogte_bron := CASE WHEN height_mm IS NULL THEN 'onbekend' ELSE coalesce(j->>'height_source', j->>'hoogte_bron', v_src, 'voorraad') END;
|
|
34172
|
+
pad := 'voorraad';
|
|
34173
|
+
RETURN NEXT;
|
|
34174
|
+
END LOOP;
|
|
34175
|
+
RETURN;
|
|
34176
|
+
END IF;
|
|
34177
|
+
RETURN QUERY SELECT t.fust_type_id, t.fust_key, t.vbn_code, t.name, t.length_mm, t.width_mm, t.height_mm,
|
|
34178
|
+
t.lengte_bron, t.breedte_bron, t.hoogte_bron, 'terugval'::text
|
|
34179
|
+
FROM public.logistics_fust_maten_terugval() t;
|
|
34180
|
+
END $$;
|
|
34181
|
+
GRANT EXECUTE ON FUNCTION public.logistics_fust_maten() TO authenticated, service_role;
|
|
34182
|
+
|
|
34183
|
+
-- 2: eigen terugval voor artikelkenmerken (S15, S02, fust) uit het Floriday-handelsitem.
|
|
34184
|
+
-- Leest nooit products.custom_fields.
|
|
34185
|
+
CREATE OR REPLACE FUNCTION public.logistics_artikel_vbn_terugval(p_product_id uuid)
|
|
34186
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34187
|
+
DECLARE v_ti text; v jsonb;
|
|
34188
|
+
BEGIN
|
|
34189
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_artikel_vbn_terugval');
|
|
34190
|
+
SELECT coalesce(nullif(p.floriday_trade_item_id, ''), nullif(p.trade_item_key, '')) INTO v_ti FROM public.products p WHERE p.id = p_product_id;
|
|
34191
|
+
IF v_ti IS NULL OR to_regclass('public.floriday_trade_items_cache') IS NULL THEN
|
|
34192
|
+
RETURN jsonb_build_object('bron', 'geen', 's02_cm', NULL, 's15_cm', NULL, 'vbn_package_code', NULL, 'custom_package_id', NULL);
|
|
34193
|
+
END IF;
|
|
34194
|
+
EXECUTE $q$
|
|
34195
|
+
SELECT jsonb_build_object(
|
|
34196
|
+
'bron', 'floriday_handelsitem',
|
|
34197
|
+
's15_cm', public.logistics_vbn_cm('S15', (SELECT x->>'vbnValueCode' FROM jsonb_array_elements(coalesce(c.data->'characteristics', '[]'::jsonb)) x WHERE x->>'vbnCode' = 'S15' LIMIT 1)),
|
|
34198
|
+
's02_cm', public.logistics_vbn_cm('S02', (SELECT x->>'vbnValueCode' FROM jsonb_array_elements(coalesce(c.data->'characteristics', '[]'::jsonb)) x WHERE x->>'vbnCode' = 'S02' LIMIT 1)),
|
|
34199
|
+
'vbn_package_code', (SELECT CASE WHEN (pc->'package'->>'vbnPackageCode') ~ '^[0-9]+$' THEN (pc->'package'->>'vbnPackageCode')::int END
|
|
34200
|
+
FROM jsonb_array_elements(coalesce(c.data->'packingConfigurations', '[]'::jsonb)) pc
|
|
34201
|
+
ORDER BY (pc->>'primary')::boolean DESC NULLS LAST LIMIT 1),
|
|
34202
|
+
'custom_package_id', (SELECT nullif(pc->'package'->>'customPackageId', '')
|
|
34203
|
+
FROM jsonb_array_elements(coalesce(c.data->'packingConfigurations', '[]'::jsonb)) pc
|
|
34204
|
+
ORDER BY (pc->>'primary')::boolean DESC NULLS LAST LIMIT 1))
|
|
34205
|
+
FROM public.floriday_trade_items_cache c
|
|
34206
|
+
WHERE (c.floriday_id = $1 OR c.data->>'tradeItemId' = $1) AND coalesce(c.is_deleted, false) = false
|
|
34207
|
+
LIMIT 1$q$ INTO v USING v_ti;
|
|
34208
|
+
RETURN coalesce(v, jsonb_build_object('bron', 'geen', 's02_cm', NULL, 's15_cm', NULL, 'vbn_package_code', NULL, 'custom_package_id', NULL));
|
|
34209
|
+
END $$;
|
|
34210
|
+
GRANT EXECUTE ON FUNCTION public.logistics_artikel_vbn_terugval(uuid) TO authenticated, service_role;
|
|
34211
|
+
|
|
34212
|
+
-- 2: artikelkenmerken. Voorraad (voorraad_article_vbn) als die bestaat, anders de eigen terugval.
|
|
34213
|
+
CREATE OR REPLACE FUNCTION public.logistics_artikel_vbn(p_product_id uuid)
|
|
34214
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34215
|
+
DECLARE j jsonb;
|
|
34216
|
+
BEGIN
|
|
34217
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_artikel_vbn');
|
|
34218
|
+
IF to_regprocedure('public.voorraad_article_vbn(uuid)') IS NOT NULL THEN
|
|
34219
|
+
EXECUTE 'SELECT to_jsonb(x) FROM public.voorraad_article_vbn($1) x LIMIT 1' INTO j USING p_product_id;
|
|
34220
|
+
IF j ? 'voorraad_article_vbn' AND jsonb_typeof(j->'voorraad_article_vbn') = 'object' THEN j := j->'voorraad_article_vbn'; END IF;
|
|
34221
|
+
j := coalesce(j, '{}'::jsonb);
|
|
34222
|
+
RETURN jsonb_build_object(
|
|
34223
|
+
'pad', 'voorraad',
|
|
34224
|
+
'bron', coalesce(j->>'bron', j->>'source', 'voorraad'),
|
|
34225
|
+
's15_cm', coalesce(public.logistics_pos_num(j->>'s15_cm'), public.logistics_vbn_cm('S15', j->'features'->>'S15')),
|
|
34226
|
+
's02_cm', coalesce(public.logistics_pos_num(j->>'s02_cm'),
|
|
34227
|
+
CASE WHEN j->>'s02_source' = 'handmatig' THEN public.logistics_pos_num(j->>'s02')
|
|
34228
|
+
ELSE public.logistics_vbn_cm('S02', coalesce(j->>'s02', j->'features'->>'S02')) END),
|
|
34229
|
+
'vbn_package_code', CASE WHEN coalesce(j->>'vbn_package_code', j->'fust'->>'vbn_code') ~ '^[0-9]+$' THEN coalesce(j->>'vbn_package_code', j->'fust'->>'vbn_code')::int END,
|
|
34230
|
+
'custom_package_id', nullif(coalesce(j->>'custom_package_id', j->'fust'->>'custom_package_id'), ''));
|
|
34231
|
+
END IF;
|
|
34232
|
+
RETURN public.logistics_artikel_vbn_terugval(p_product_id) || jsonb_build_object('pad', 'terugval');
|
|
34233
|
+
END $$;
|
|
34234
|
+
GRANT EXECUTE ON FUNCTION public.logistics_artikel_vbn(uuid) TO authenticated, service_role;
|
|
34235
|
+
|
|
34236
|
+
-- 1+2: maten per product in één bron. Fustkeuze: handmatig -> VBN-code (rij met de meeste maten) -> custom package.
|
|
34237
|
+
-- Maten per veld; ontbreekt een veld bij de gekozen rij, dan uit een andere rij met dezelfde fust_key.
|
|
34238
|
+
-- Planthoogte geldt altijd INCLUSIEF pot: handmatig -> S15 (transporthoogte) -> S02 (min. planthoogte incl. pot).
|
|
34239
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_maten(p_product_ids uuid[])
|
|
34240
|
+
RETURNS TABLE(product_id uuid, product_name text, plants_per_crate integer, fust_type_id uuid, fust_name text, fust_bron text,
|
|
34241
|
+
fust_length_mm numeric, fust_width_mm numeric, fust_height_mm numeric,
|
|
34242
|
+
lengte_bron text, breedte_bron text, hoogte_bron text,
|
|
34243
|
+
plant_height_cm numeric, height_source text, weight_kg numeric,
|
|
34244
|
+
pad_fust text, pad_artikel text, missing_reason text)
|
|
34245
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34246
|
+
#variable_conflict use_column
|
|
34247
|
+
BEGIN
|
|
34248
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_maten');
|
|
34249
|
+
IF p_product_ids IS NOT NULL AND cardinality(p_product_ids) > 2000 THEN
|
|
34250
|
+
RAISE EXCEPTION 'Maximaal 2000 producten per aanvraag.' USING ERRCODE = '22023';
|
|
34251
|
+
END IF;
|
|
34252
|
+
RETURN QUERY
|
|
34253
|
+
WITH fm AS (SELECT * FROM public.logistics_fust_maten()),
|
|
34254
|
+
pr AS (
|
|
34255
|
+
SELECT p.id, p.product, p.plants_per_crate, p.fust_type_id AS hand_fid, p.plant_height_cm AS hand_h, p.weight,
|
|
34256
|
+
public.logistics_artikel_vbn(p.id) AS a
|
|
34257
|
+
FROM public.products p
|
|
34258
|
+
WHERE p_product_ids IS NULL OR p.id = ANY(p_product_ids)
|
|
34259
|
+
),
|
|
34260
|
+
keuze AS (
|
|
34261
|
+
SELECT pr.*,
|
|
34262
|
+
(SELECT m.fust_type_id FROM fm m
|
|
34263
|
+
WHERE (pr.a->>'vbn_package_code') ~ '^[0-9]+$'
|
|
34264
|
+
AND (m.vbn_code = (pr.a->>'vbn_package_code')::int OR m.fust_key = 'vbn:' || (pr.a->>'vbn_package_code'))
|
|
34265
|
+
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
|
|
34266
|
+
LIMIT 1) AS vbn_fid,
|
|
34267
|
+
(SELECT f.id FROM public.fust_types f
|
|
34268
|
+
WHERE nullif(pr.a->>'custom_package_id', '') IS NOT NULL AND f.custom_package_id = pr.a->>'custom_package_id'
|
|
34269
|
+
ORDER BY f.created_at, f.id LIMIT 1) AS cp_fid
|
|
34270
|
+
FROM pr
|
|
34271
|
+
),
|
|
34272
|
+
k2 AS (
|
|
34273
|
+
SELECT k.*, coalesce(k.hand_fid, k.vbn_fid, k.cp_fid) AS fid,
|
|
34274
|
+
CASE WHEN k.hand_fid IS NOT NULL THEN 'handmatig' WHEN k.vbn_fid IS NOT NULL THEN 'vbn' WHEN k.cp_fid IS NOT NULL THEN 'floriday' END AS fbron
|
|
34275
|
+
FROM keuze k
|
|
34276
|
+
),
|
|
34277
|
+
maat AS (
|
|
34278
|
+
SELECT k.*, m.name AS mname, m.pad AS mpad,
|
|
34279
|
+
coalesce(m.length_mm, lx.length_mm) AS l, CASE WHEN m.length_mm IS NOT NULL THEN m.lengte_bron ELSE coalesce(lx.lengte_bron, 'onbekend') END AS lb,
|
|
34280
|
+
coalesce(m.width_mm, wx.width_mm) AS w, CASE WHEN m.width_mm IS NOT NULL THEN m.breedte_bron ELSE coalesce(wx.breedte_bron, 'onbekend') END AS wb,
|
|
34281
|
+
coalesce(m.height_mm, hx.height_mm) AS h, CASE WHEN m.height_mm IS NOT NULL THEN m.hoogte_bron ELSE coalesce(hx.hoogte_bron, 'onbekend') END AS hb
|
|
34282
|
+
FROM k2 k
|
|
34283
|
+
LEFT JOIN fm m ON m.fust_type_id = k.fid
|
|
34284
|
+
LEFT JOIN LATERAL (SELECT m2.length_mm, m2.lengte_bron FROM fm m2 WHERE m.fust_key IS NOT NULL AND m2.fust_key = m.fust_key AND m2.length_mm IS NOT NULL ORDER BY m2.fust_type_id LIMIT 1) lx ON true
|
|
34285
|
+
LEFT JOIN LATERAL (SELECT m2.width_mm, m2.breedte_bron FROM fm m2 WHERE m.fust_key IS NOT NULL AND m2.fust_key = m.fust_key AND m2.width_mm IS NOT NULL ORDER BY m2.fust_type_id LIMIT 1) wx ON true
|
|
34286
|
+
LEFT JOIN LATERAL (SELECT m2.height_mm, m2.hoogte_bron 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) hx ON true
|
|
34287
|
+
),
|
|
34288
|
+
hoogte AS (
|
|
34289
|
+
SELECT x.*,
|
|
34290
|
+
public.logistics_pos_num(x.hand_h::text) AS hh,
|
|
34291
|
+
public.logistics_pos_num(x.a->>'s15_cm') AS s15,
|
|
34292
|
+
public.logistics_pos_num(x.a->>'s02_cm') AS s02,
|
|
34293
|
+
(SELECT b.bron FROM public.logistics_gegevens_bron b
|
|
34294
|
+
WHERE b.onderwerp = 'product' AND b.sleutel = x.id::text AND b.veld = 'plant_height_cm'
|
|
34295
|
+
AND public.logistics_pos_num(b.waarde) = public.logistics_pos_num(x.hand_h::text) LIMIT 1) AS hand_bron
|
|
34296
|
+
FROM maat x
|
|
34297
|
+
)
|
|
34298
|
+
SELECT h.id, h.product, h.plants_per_crate::int, h.fid, h.mname, h.fbron,
|
|
34299
|
+
h.l, h.w, h.h, h.lb, h.wb, h.hb,
|
|
34300
|
+
coalesce(h.hh, h.s15, h.s02),
|
|
34301
|
+
CASE WHEN h.hh IS NOT NULL THEN coalesce(h.hand_bron, 'handmatig')
|
|
34302
|
+
WHEN h.s15 IS NOT NULL THEN 'floricode_s15'
|
|
34303
|
+
WHEN h.s02 IS NOT NULL THEN 'floricode_s02' END,
|
|
34304
|
+
public.logistics_pos_num(regexp_replace(coalesce(h.weight::text, ''), '[^0-9.,]', '', 'g')),
|
|
34305
|
+
coalesce(h.mpad, (SELECT fm.pad FROM fm LIMIT 1)), h.a->>'pad',
|
|
34306
|
+
CASE
|
|
34307
|
+
WHEN h.fid IS NULL AND h.a->>'vbn_package_code' IS NULL AND h.a->>'custom_package_id' IS NULL
|
|
34308
|
+
THEN format('Bij "%s" is geen fustsoort bekend: kies de fustsoort bij het product in Voorraad.', h.product)
|
|
34309
|
+
WHEN h.fid IS NULL
|
|
34310
|
+
THEN format('Bij "%s" bestaat de fustsoort (VBN %s) niet in Voorraad → Fusten.', h.product, coalesce(h.a->>'vbn_package_code', h.a->>'custom_package_id'))
|
|
34311
|
+
WHEN h.l IS NULL OR h.w IS NULL OR h.h IS NULL
|
|
34312
|
+
THEN format('Fust %s heeft geen volledige maten in Floricode, Floriday of Voorraad → Fusten (ontbreekt: %s).', coalesce(h.mname, 'onbekend'),
|
|
34313
|
+
array_to_string(array_remove(ARRAY[CASE WHEN h.l IS NULL THEN 'lengte' END, CASE WHEN h.w IS NULL THEN 'breedte' END, CASE WHEN h.h IS NULL THEN 'hoogte' END], NULL), ', '))
|
|
34314
|
+
WHEN coalesce(h.hh, h.s15, h.s02) IS NULL
|
|
34315
|
+
THEN format('Bij "%s" is de planthoogte inclusief pot onbekend (geen S15/S02 in Floricode of Floriday, niet handmatig ingevuld).', h.product)
|
|
34316
|
+
END
|
|
34317
|
+
FROM hoogte h;
|
|
34318
|
+
END $$;
|
|
34319
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_maten(uuid[]) TO authenticated, service_role;
|
|
34320
|
+
|
|
34321
|
+
-- Bestaande view blijft met dezelfde kolommen werken; de bron is nu logistics_product_maten.
|
|
34322
|
+
DO $fs$ BEGIN
|
|
34323
|
+
EXECUTE $v$CREATE OR REPLACE VIEW public.logistics_product_dimensions AS
|
|
34324
|
+
SELECT m.product_id, m.product_name, m.plants_per_crate, m.fust_type_id,
|
|
34325
|
+
CASE m.fust_bron WHEN 'vbn' THEN 'floriday' ELSE m.fust_bron END AS fust_source,
|
|
34326
|
+
m.fust_name, m.fust_length_mm, m.fust_width_mm, m.fust_height_mm,
|
|
34327
|
+
m.plant_height_cm, m.height_source,
|
|
34328
|
+
CASE WHEN m.missing_reason IS NULL THEN coalesce(nullif(m.fust_bron, 'vbn'), 'floriday') ELSE 'onbekend' END AS dimension_source,
|
|
34329
|
+
m.missing_reason
|
|
34330
|
+
FROM public.logistics_product_maten(NULL) m$v$;
|
|
34331
|
+
EXCEPTION WHEN undefined_table OR undefined_column OR undefined_function OR invalid_table_definition THEN
|
|
34332
|
+
RAISE NOTICE 'logistiek-engine: view logistics_product_dimensions niet vervangen: %', SQLERRM;
|
|
34333
|
+
END $fs$;
|
|
34334
|
+
|
|
34335
|
+
-- 3+E4: gegevens voor karindeling, nu met bronnen uit logistics_product_maten.
|
|
34336
|
+
-- Gewicht per fust alleen gevraagd als de gebruikte ladingdrager een kg-grens heeft.
|
|
34337
|
+
-- Lagen per kar: laaghoogte = max(fusthoogte, planthoogte inclusief pot).
|
|
34338
|
+
CREATE OR REPLACE FUNCTION public.logistics_data_gereedheid(p_product_ids uuid[] DEFAULT NULL)
|
|
34339
|
+
RETURNS TABLE(product_id uuid, product text, ladingdrager text, methode text, in_open_order boolean,
|
|
34340
|
+
ontbrekend text[], velden jsonb, voorstel jsonb, uitleg text)
|
|
34341
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34342
|
+
#variable_conflict use_column
|
|
34343
|
+
DECLARE v_methode text; v_carrier text; c record; v_ids uuid[];
|
|
34344
|
+
BEGIN
|
|
34345
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_data_gereedheid');
|
|
34346
|
+
SELECT CASE WHEN coalesce(s.settings->'karrenindeling'->'fields'->>'cart_layout_method', s.settings->'karrenindeling'->>'cart_layout_method') = 'afmetingen'
|
|
34347
|
+
THEN 'afmetingen' ELSE 'belading' END,
|
|
34348
|
+
nullif(btrim(coalesce(s.settings->'karrenindeling'->'fields'->>'default_carrier_type', s.settings->'karrenindeling'->>'default_carrier_type')), '')
|
|
34349
|
+
INTO v_methode, v_carrier
|
|
34350
|
+
FROM public.logistics_rule_configs s WHERE s.is_active ORDER BY s.updated_at DESC LIMIT 1;
|
|
34351
|
+
v_methode := coalesce(v_methode, 'belading');
|
|
34352
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm, t.max_weight_kg INTO c
|
|
34353
|
+
FROM public.load_carrier_types t
|
|
34354
|
+
WHERE t.is_active AND (t.code = v_carrier OR (v_carrier IS NULL AND t.is_default))
|
|
34355
|
+
ORDER BY (t.code = v_carrier) DESC NULLS LAST LIMIT 1;
|
|
34356
|
+
|
|
34357
|
+
SELECT array_agg(DISTINCT x) INTO v_ids FROM (
|
|
34358
|
+
SELECT oi.product_id AS x FROM public.orders o JOIN public.order_items oi ON oi.order_id = o.id
|
|
34359
|
+
WHERE p_product_ids IS NULL AND o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.is_reservation, false) = false
|
|
34360
|
+
AND lower(coalesce(o.status, '')) = 'nog te picken' AND oi.product_id IS NOT NULL
|
|
34361
|
+
UNION SELECT unnest(p_product_ids)) q WHERE x IS NOT NULL;
|
|
34362
|
+
IF v_ids IS NULL THEN RETURN; END IF;
|
|
34363
|
+
|
|
34364
|
+
RETURN QUERY
|
|
34365
|
+
WITH open_p AS (
|
|
34366
|
+
SELECT DISTINCT oi.product_id FROM public.orders o JOIN public.order_items oi ON oi.order_id = o.id
|
|
34367
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.is_reservation, false) = false
|
|
34368
|
+
AND lower(coalesce(o.status, '')) = 'nog te picken' AND oi.product_id = ANY(v_ids)
|
|
34369
|
+
),
|
|
34370
|
+
p AS (
|
|
34371
|
+
SELECT pr.id, pr.product, pr.plants_per_crate, pr.crates_per_layer, pr.layers_per_cart, pr.floriday_packing_source,
|
|
34372
|
+
mt.fust_type_id, mt.fust_name, mt.fust_bron, mt.fust_length_mm AS length_mm, mt.fust_width_mm AS width_mm, mt.fust_height_mm AS height_mm,
|
|
34373
|
+
mt.lengte_bron, mt.breedte_bron, mt.hoogte_bron, mt.plant_height_cm, mt.height_source, mt.weight_kg,
|
|
34374
|
+
(op.product_id IS NOT NULL) AS in_open
|
|
34375
|
+
FROM public.products pr
|
|
34376
|
+
JOIN public.logistics_product_maten(v_ids) mt ON mt.product_id = pr.id
|
|
34377
|
+
LEFT JOIN open_p op ON op.product_id = pr.id
|
|
34378
|
+
),
|
|
34379
|
+
m AS (
|
|
34380
|
+
SELECT p.*,
|
|
34381
|
+
array_remove(ARRAY[
|
|
34382
|
+
CASE WHEN coalesce(p.plants_per_crate, 0) <= 0 THEN 'plants_per_crate' END,
|
|
34383
|
+
CASE WHEN v_methode = 'belading' AND coalesce(p.crates_per_layer, 0) <= 0 THEN 'crates_per_layer' END,
|
|
34384
|
+
CASE WHEN v_methode = 'belading' AND coalesce(p.layers_per_cart, 0) <= 0 THEN 'layers_per_cart' END,
|
|
34385
|
+
CASE WHEN v_methode = 'afmetingen' AND p.fust_type_id IS NULL THEN 'fust_type_id' END,
|
|
34386
|
+
CASE WHEN v_methode = 'afmetingen' AND p.fust_type_id IS NOT NULL AND (p.length_mm IS NULL OR p.width_mm IS NULL OR p.height_mm IS NULL) THEN 'fust_maten' END,
|
|
34387
|
+
CASE WHEN v_methode = 'afmetingen' AND p.plant_height_cm IS NULL THEN 'plant_height_cm' END,
|
|
34388
|
+
CASE WHEN coalesce(c.max_weight_kg, 0) > 0 AND p.weight_kg IS NULL THEN 'weight' END
|
|
34389
|
+
], NULL) AS mist,
|
|
34390
|
+
CASE WHEN p.length_mm > 0 AND p.width_mm > 0 AND c.layer_length_cm > 0 AND c.layer_width_cm > 0 THEN
|
|
34391
|
+
greatest(floor(c.layer_length_cm * 10 / p.length_mm) * floor(c.layer_width_cm * 10 / p.width_mm),
|
|
34392
|
+
floor(c.layer_length_cm * 10 / p.width_mm) * floor(c.layer_width_cm * 10 / p.length_mm))::int END AS calc_cpl,
|
|
34393
|
+
CASE WHEN p.plant_height_cm > 0 AND c.max_height_cm > 0 THEN
|
|
34394
|
+
floor(c.max_height_cm / greatest(p.plant_height_cm, coalesce(p.height_mm, 0) / 10.0))::int END AS calc_lpc
|
|
34395
|
+
FROM p
|
|
34396
|
+
)
|
|
34397
|
+
SELECT m.id, m.product, c.code, v_methode, m.in_open, m.mist,
|
|
34398
|
+
jsonb_build_object(
|
|
34399
|
+
'plants_per_crate', jsonb_build_object('waarde', m.plants_per_crate, 'bron', CASE WHEN m.plants_per_crate > 0 THEN coalesce(m.floriday_packing_source, 'product') END),
|
|
34400
|
+
'crates_per_layer', jsonb_build_object('waarde', m.crates_per_layer, 'bron', CASE WHEN m.crates_per_layer > 0 THEN coalesce(m.floriday_packing_source, 'product') END),
|
|
34401
|
+
'layers_per_cart', jsonb_build_object('waarde', m.layers_per_cart, 'bron', CASE WHEN m.layers_per_cart > 0 THEN coalesce(m.floriday_packing_source, 'product') END),
|
|
34402
|
+
'weight', jsonb_build_object('waarde', m.weight_kg, 'bron', CASE WHEN m.weight_kg IS NOT NULL THEN 'product' END,
|
|
34403
|
+
'nodig', coalesce(c.max_weight_kg, 0) > 0, 'grens_kg', c.max_weight_kg),
|
|
34404
|
+
'plant_height_cm', jsonb_build_object('waarde', m.plant_height_cm, 'bron', m.height_source, 'inclusief_pot', true),
|
|
34405
|
+
'fust_type_id', jsonb_build_object('waarde', m.fust_type_id, 'bron', m.fust_bron, 'naam', m.fust_name),
|
|
34406
|
+
'fust_length_mm', jsonb_build_object('waarde', m.length_mm, 'bron', m.lengte_bron),
|
|
34407
|
+
'fust_width_mm', jsonb_build_object('waarde', m.width_mm, 'bron', m.breedte_bron),
|
|
34408
|
+
'fust_height_mm', jsonb_build_object('waarde', m.height_mm, 'bron', m.hoogte_bron)),
|
|
34409
|
+
jsonb_strip_nulls(jsonb_build_object(
|
|
34410
|
+
'crates_per_layer', CASE WHEN m.calc_cpl > 0 THEN jsonb_build_object('waarde', m.calc_cpl, 'bron', 'berekend',
|
|
34411
|
+
'berekening', format('fust %s×%s mm op laag %s×%s cm (%s)', m.length_mm, m.width_mm, c.layer_length_cm, c.layer_width_cm, c.name)) END,
|
|
34412
|
+
'layers_per_cart', CASE WHEN m.calc_lpc > 0 THEN jsonb_build_object('waarde', m.calc_lpc, 'bron', 'berekend',
|
|
34413
|
+
'berekening', format('hoogte %s cm / grootste van (plant incl. pot %s cm, fust %s cm)', c.max_height_cm, m.plant_height_cm, round(coalesce(m.height_mm, 0) / 10.0, 1))) END)),
|
|
34414
|
+
CASE WHEN cardinality(m.mist) = 0 THEN 'Compleet.'
|
|
34415
|
+
ELSE format('Bij "%s" ontbreekt: %s. Vul dit in bij het product (Voorraad) of hier met "Invullen".', m.product,
|
|
34416
|
+
array_to_string(ARRAY(SELECT CASE f WHEN 'plants_per_crate' THEN 'planten per fust' WHEN 'crates_per_layer' THEN 'fusten per laag'
|
|
34417
|
+
WHEN 'layers_per_cart' THEN 'lagen per kar' WHEN 'fust_type_id' THEN 'fustsoort' WHEN 'fust_maten' THEN 'fustmaten'
|
|
34418
|
+
WHEN 'plant_height_cm' THEN 'planthoogte inclusief pot'
|
|
34419
|
+
WHEN 'weight' THEN format('gewicht per fust (%s heeft een grens van %s kg)', c.name, c.max_weight_kg) ELSE f END FROM unnest(m.mist) f), ', ')) END
|
|
34420
|
+
FROM m
|
|
34421
|
+
ORDER BY cardinality(m.mist) DESC, m.in_open DESC, m.product
|
|
34422
|
+
LIMIT 2000;
|
|
34423
|
+
END $$;
|
|
34424
|
+
GRANT EXECUTE ON FUNCTION public.logistics_data_gereedheid(uuid[]) TO authenticated, service_role;
|
|
34425
|
+
|
|
34426
|
+
-- 5: "Alles overnemen uit Floricode/Floriday": alleen lege velden, bron vastgelegd.
|
|
34427
|
+
-- p_uitvoeren = false geeft alleen de voorvertoning.
|
|
34428
|
+
CREATE OR REPLACE FUNCTION public.logistics_data_overnemen(p_uitvoeren boolean)
|
|
34429
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34430
|
+
#variable_conflict use_column
|
|
34431
|
+
DECLARE v_lijst jsonb := '[]'::jsonb; r record; v_n int := 0; v_ids uuid[];
|
|
34432
|
+
BEGIN
|
|
34433
|
+
PERFORM public.logistics_acc_guard(CASE WHEN p_uitvoeren THEN 'beheer' ELSE 'ingelogd' END, 'logistics_data_overnemen');
|
|
34434
|
+
SELECT array_agg(DISTINCT oi.product_id) INTO v_ids FROM public.orders o JOIN public.order_items oi ON oi.order_id = o.id
|
|
34435
|
+
WHERE o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.is_reservation, false) = false
|
|
34436
|
+
AND lower(coalesce(o.status, '')) = 'nog te picken' AND oi.product_id IS NOT NULL;
|
|
34437
|
+
IF v_ids IS NULL THEN RETURN jsonb_build_object('uitgevoerd', false, 'velden', v_lijst, 'aantal', 0); END IF;
|
|
34438
|
+
FOR r IN
|
|
34439
|
+
SELECT m.*, p.fust_type_id AS hand_fid, p.plant_height_cm AS hand_h, f.length_mm AS f_l, f.width_mm AS f_w, f.height_mm AS f_h
|
|
34440
|
+
FROM public.logistics_product_maten(v_ids) m
|
|
34441
|
+
JOIN public.products p ON p.id = m.product_id
|
|
34442
|
+
LEFT JOIN public.fust_types f ON f.id = m.fust_type_id
|
|
34443
|
+
LOOP
|
|
34444
|
+
IF r.hand_h IS NULL AND r.height_source IN ('floricode_s15', 'floricode_s02') THEN
|
|
34445
|
+
v_lijst := v_lijst || jsonb_build_object('onderwerp', 'product', 'sleutel', r.product_id, 'naam', r.product_name, 'veld', 'plant_height_cm', 'waarde', r.plant_height_cm, 'bron', r.height_source);
|
|
34446
|
+
IF p_uitvoeren THEN
|
|
34447
|
+
UPDATE public.products SET plant_height_cm = r.plant_height_cm, updated_at = now() WHERE id = r.product_id AND plant_height_cm IS NULL;
|
|
34448
|
+
END IF;
|
|
34449
|
+
END IF;
|
|
34450
|
+
IF r.hand_fid IS NULL AND r.fust_type_id IS NOT NULL THEN
|
|
34451
|
+
v_lijst := v_lijst || jsonb_build_object('onderwerp', 'product', 'sleutel', r.product_id, 'naam', r.product_name, 'veld', 'fust_type_id', 'waarde', r.fust_type_id,
|
|
34452
|
+
'bron', CASE r.fust_bron WHEN 'vbn' THEN 'floriday_vbn' ELSE r.fust_bron END);
|
|
34453
|
+
IF p_uitvoeren THEN
|
|
34454
|
+
UPDATE public.products SET fust_type_id = r.fust_type_id, updated_at = now() WHERE id = r.product_id AND fust_type_id IS NULL;
|
|
34455
|
+
END IF;
|
|
34456
|
+
END IF;
|
|
34457
|
+
IF r.fust_type_id IS NOT NULL AND r.f_l IS NULL AND r.fust_length_mm IS NOT NULL AND r.lengte_bron IN ('floricode', 'floriday') THEN
|
|
34458
|
+
v_lijst := v_lijst || jsonb_build_object('onderwerp', 'fust', 'sleutel', r.fust_type_id, 'naam', r.fust_name, 'veld', 'length_mm', 'waarde', r.fust_length_mm, 'bron', r.lengte_bron);
|
|
34459
|
+
IF p_uitvoeren THEN UPDATE public.fust_types SET length_mm = round(r.fust_length_mm)::int, updated_at = now() WHERE id = r.fust_type_id AND length_mm IS NULL; END IF;
|
|
34460
|
+
END IF;
|
|
34461
|
+
IF r.fust_type_id IS NOT NULL AND r.f_w IS NULL AND r.fust_width_mm IS NOT NULL AND r.breedte_bron IN ('floricode', 'floriday') THEN
|
|
34462
|
+
v_lijst := v_lijst || jsonb_build_object('onderwerp', 'fust', 'sleutel', r.fust_type_id, 'naam', r.fust_name, 'veld', 'width_mm', 'waarde', r.fust_width_mm, 'bron', r.breedte_bron);
|
|
34463
|
+
IF p_uitvoeren THEN UPDATE public.fust_types SET width_mm = round(r.fust_width_mm)::int, updated_at = now() WHERE id = r.fust_type_id AND width_mm IS NULL; END IF;
|
|
34464
|
+
END IF;
|
|
34465
|
+
IF r.fust_type_id IS NOT NULL AND r.f_h IS NULL AND r.fust_height_mm IS NOT NULL AND r.hoogte_bron IN ('floricode', 'floriday') THEN
|
|
34466
|
+
v_lijst := v_lijst || jsonb_build_object('onderwerp', 'fust', 'sleutel', r.fust_type_id, 'naam', r.fust_name, 'veld', 'height_mm', 'waarde', r.fust_height_mm, 'bron', r.hoogte_bron);
|
|
34467
|
+
IF p_uitvoeren THEN UPDATE public.fust_types SET height_mm = round(r.fust_height_mm)::int, updated_at = now() WHERE id = r.fust_type_id AND height_mm IS NULL; END IF;
|
|
34468
|
+
END IF;
|
|
34469
|
+
END LOOP;
|
|
34470
|
+
-- Ontdubbelen (meerdere producten met hetzelfde fust).
|
|
34471
|
+
SELECT coalesce(jsonb_agg(DISTINCT e), '[]'::jsonb) INTO v_lijst FROM jsonb_array_elements(v_lijst) e;
|
|
34472
|
+
IF p_uitvoeren THEN
|
|
34473
|
+
INSERT INTO public.logistics_gegevens_bron(onderwerp, sleutel, veld, waarde, bron, toelichting, vastgelegd_door)
|
|
34474
|
+
SELECT e->>'onderwerp', e->>'sleutel', e->>'veld', e->>'waarde', e->>'bron', 'Overgenomen via de startlijst', auth.uid()
|
|
34475
|
+
FROM jsonb_array_elements(v_lijst) e
|
|
34476
|
+
ON CONFLICT (onderwerp, sleutel, veld) DO UPDATE SET waarde = EXCLUDED.waarde, bron = EXCLUDED.bron, toelichting = EXCLUDED.toelichting,
|
|
34477
|
+
vastgelegd_door = EXCLUDED.vastgelegd_door, vastgelegd_op = now();
|
|
34478
|
+
END IF;
|
|
34479
|
+
v_n := jsonb_array_length(v_lijst);
|
|
34480
|
+
RETURN jsonb_build_object('uitgevoerd', p_uitvoeren, 'aantal', v_n, 'velden', v_lijst,
|
|
34481
|
+
'per_bron', (SELECT coalesce(jsonb_object_agg(b, n), '{}'::jsonb) FROM (SELECT e->>'bron' b, count(*) n FROM jsonb_array_elements(v_lijst) e GROUP BY 1) q));
|
|
34482
|
+
END $$;
|
|
34483
|
+
GRANT EXECUTE ON FUNCTION public.logistics_data_overnemen(boolean) TO authenticated, service_role;
|
|
34484
|
+
|
|
34485
|
+
-- 4: algemene standaard-laagmaten per Floriday-ladingdragertype (vaste, klant-onafhankelijke referentie).
|
|
34486
|
+
-- Alleen lengte en breedte; hoogte en gewichtsgrens hebben geen algemene standaard en vult de beheerder zelf in.
|
|
34487
|
+
CREATE OR REPLACE FUNCTION public.logistics_ladingdrager_referentie()
|
|
34488
|
+
RETURNS TABLE(floriday_code text, lengte_cm integer, breedte_cm integer, bron text)
|
|
34489
|
+
LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$
|
|
34490
|
+
VALUES ('DANISH_TROLLEY', 135, 56, 'Standaard Deense container (CC), 1350×565 mm'),
|
|
34491
|
+
('DANISH_TROLLEY_NON_CC_RFID', 135, 56, 'Standaard Deense container, 1350×565 mm'),
|
|
34492
|
+
('DANISH_TROLLEY_WATER_TRAY', 135, 56, 'Standaard Deense container met waterbak, 1350×565 mm'),
|
|
34493
|
+
('AUCTION_TROLLEY', 135, 56, 'Standaard veilingstapelwagen, 1350×565 mm'),
|
|
34494
|
+
('EURO_PALLET', 120, 80, 'Europallet (EPAL), 1200×800 mm'),
|
|
34495
|
+
('HT_EURO_PALLET', 120, 80, 'Europallet (EPAL, HT), 1200×800 mm'),
|
|
34496
|
+
('BLOCK_PALLET', 120, 100, 'Blokpallet, 1200×1000 mm')
|
|
34497
|
+
$$;
|
|
34498
|
+
GRANT EXECUTE ON FUNCTION public.logistics_ladingdrager_referentie() TO authenticated, service_role;
|
|
34499
|
+
|
|
34500
|
+
CREATE OR REPLACE FUNCTION public.logistics_ladingdrager_voorstellen()
|
|
34501
|
+
RETURNS TABLE(code text, naam text, floriday_code text, veld text, huidig numeric, voorstel numeric, bron text, actie text)
|
|
34502
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34503
|
+
#variable_conflict use_column
|
|
34504
|
+
BEGIN
|
|
34505
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_ladingdrager_voorstellen');
|
|
34506
|
+
RETURN QUERY
|
|
34507
|
+
WITH k AS (
|
|
34508
|
+
SELECT DISTINCT ON (t.code) t.code, t.name, m.floriday_code, t.layer_length_cm, t.layer_width_cm, r.lengte_cm, r.breedte_cm, r.bron
|
|
34509
|
+
FROM public.load_carrier_types t
|
|
34510
|
+
JOIN public.logistics_floriday_carrier_map m ON m.carrier_code = t.code
|
|
34511
|
+
JOIN public.logistics_ladingdrager_referentie() r ON r.floriday_code = m.floriday_code
|
|
34512
|
+
WHERE t.is_active
|
|
34513
|
+
ORDER BY t.code, m.floriday_code
|
|
34514
|
+
)
|
|
34515
|
+
SELECT k.code, k.name, k.floriday_code, v.veld, v.huidig, v.voorstel, k.bron,
|
|
34516
|
+
CASE WHEN coalesce(v.huidig, 0) <= 0 THEN 'invullen' WHEN v.huidig = v.voorstel THEN 'gelijk' ELSE 'afwijkend' END
|
|
34517
|
+
FROM k CROSS JOIN LATERAL (VALUES ('layer_length_cm', k.layer_length_cm::numeric, k.lengte_cm::numeric),
|
|
34518
|
+
('layer_width_cm', k.layer_width_cm::numeric, k.breedte_cm::numeric)) v(veld, huidig, voorstel)
|
|
34519
|
+
ORDER BY k.code, v.veld;
|
|
34520
|
+
END $$;
|
|
34521
|
+
GRANT EXECUTE ON FUNCTION public.logistics_ladingdrager_voorstellen() TO authenticated, service_role;
|
|
34522
|
+
|
|
34523
|
+
-- Bevestigen per ladingdrager: schrijft alleen lege velden en legt de bron vast. Overschrijft nooit.
|
|
34524
|
+
CREATE OR REPLACE FUNCTION public.logistics_ladingdrager_voorstel_bevestigen(p_code text)
|
|
34525
|
+
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34526
|
+
#variable_conflict use_column
|
|
34527
|
+
DECLARE r record; v_n int := 0;
|
|
34528
|
+
BEGIN
|
|
34529
|
+
PERFORM public.logistics_acc_guard('beheer', 'logistics_ladingdrager_voorstel_bevestigen');
|
|
34530
|
+
FOR r IN SELECT * FROM public.logistics_ladingdrager_voorstellen() v WHERE v.code = p_code AND v.actie = 'invullen' LOOP
|
|
34531
|
+
IF r.veld = 'layer_length_cm' THEN
|
|
34532
|
+
UPDATE public.load_carrier_types SET layer_length_cm = r.voorstel::int, updated_at = now() WHERE code = p_code AND coalesce(layer_length_cm, 0) <= 0;
|
|
34533
|
+
ELSIF r.veld = 'layer_width_cm' THEN
|
|
34534
|
+
UPDATE public.load_carrier_types SET layer_width_cm = r.voorstel::int, updated_at = now() WHERE code = p_code AND coalesce(layer_width_cm, 0) <= 0;
|
|
34535
|
+
END IF;
|
|
34536
|
+
IF FOUND THEN
|
|
34537
|
+
v_n := v_n + 1;
|
|
34538
|
+
INSERT INTO public.logistics_gegevens_bron(onderwerp, sleutel, veld, waarde, bron, toelichting, vastgelegd_door)
|
|
34539
|
+
VALUES ('ladingdrager', p_code, r.veld, r.voorstel::text, 'standaard:' || r.floriday_code, r.bron, auth.uid())
|
|
34540
|
+
ON CONFLICT (onderwerp, sleutel, veld) DO UPDATE SET waarde = EXCLUDED.waarde, bron = EXCLUDED.bron, toelichting = EXCLUDED.toelichting,
|
|
34541
|
+
vastgelegd_door = EXCLUDED.vastgelegd_door, vastgelegd_op = now();
|
|
34542
|
+
END IF;
|
|
34543
|
+
END LOOP;
|
|
34544
|
+
RETURN jsonb_build_object('ok', true, 'code', p_code, 'ingevuld', v_n);
|
|
34545
|
+
END $$;
|
|
34546
|
+
GRANT EXECUTE ON FUNCTION public.logistics_ladingdrager_voorstel_bevestigen(text) TO authenticated, service_role;
|
|
34547
|
+
|
|
34548
|
+
-- 5: startlijst voor een nieuwe shell.
|
|
34549
|
+
CREATE OR REPLACE FUNCTION public.logistics_startlijst()
|
|
34550
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34551
|
+
DECLARE v_drag int; v_drag_mist int; v_werk boolean; v_prod int; v_prod_mist int;
|
|
34552
|
+
BEGIN
|
|
34553
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_startlijst');
|
|
34554
|
+
SELECT count(*), count(*) FILTER (WHERE coalesce(t.layer_length_cm, 0) <= 0 OR coalesce(t.layer_width_cm, 0) <= 0 OR coalesce(t.max_height_cm, 0) <= 0)
|
|
34555
|
+
INTO v_drag, v_drag_mist
|
|
34556
|
+
FROM public.load_carrier_types t
|
|
34557
|
+
WHERE t.is_active AND NOT EXISTS (SELECT 1 FROM public.logistics_floriday_carrier_map m WHERE m.carrier_code = t.code AND m.floriday_code = 'NONE');
|
|
34558
|
+
SELECT EXISTS (SELECT 1 FROM public.logistics_rule_configs s WHERE s.is_active AND s.settings ? 'karrenindeling') INTO v_werk;
|
|
34559
|
+
SELECT count(*), count(*) FILTER (WHERE cardinality(g.ontbrekend) > 0) INTO v_prod, v_prod_mist FROM public.logistics_data_gereedheid(NULL) g;
|
|
34560
|
+
RETURN jsonb_build_object(
|
|
34561
|
+
'ladingdragers', jsonb_build_object('klaar', v_drag > 0 AND v_drag_mist = 0, 'aantal', v_drag, 'onvolledig', v_drag_mist),
|
|
34562
|
+
'werkwijze', jsonb_build_object('klaar', v_werk),
|
|
34563
|
+
'gereedheid', jsonb_build_object('klaar', v_prod_mist = 0, 'producten', v_prod, 'onvolledig', v_prod_mist));
|
|
34564
|
+
END $$;
|
|
34565
|
+
GRANT EXECUTE ON FUNCTION public.logistics_startlijst() TO authenticated, service_role;
|
|
34566
|
+
|
|
34567
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_198()
|
|
34568
|
+
RETURNS TABLE(controle text, ok boolean, toelichting text)
|
|
34569
|
+
LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
34570
|
+
BEGIN
|
|
34571
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_install_check_198');
|
|
34572
|
+
RETURN QUERY SELECT 'Engine: fustmaten uit één bron'::text,
|
|
34573
|
+
to_regprocedure('public.logistics_fust_maten()') IS NOT NULL,
|
|
34574
|
+
CASE WHEN to_regprocedure('public.voorraad_fust_dimensions()') IS NOT NULL THEN 'via Voorraad (voorraad_fust_dimensions)'
|
|
34575
|
+
ELSE 'eigen terugval: Floricode → Floriday → handmatig' END;
|
|
34576
|
+
RETURN QUERY SELECT 'Engine: artikelkenmerken (S15/S02, fust)',
|
|
34577
|
+
to_regprocedure('public.logistics_artikel_vbn(uuid)') IS NOT NULL,
|
|
34578
|
+
CASE WHEN to_regprocedure('public.voorraad_article_vbn(uuid)') IS NOT NULL THEN 'via Voorraad (voorraad_article_vbn)'
|
|
34579
|
+
ELSE 'eigen terugval: Floriday-handelsitem' END;
|
|
34580
|
+
RETURN QUERY SELECT 'Engine: view logistics_product_dimensions gebruikt logistics_product_maten',
|
|
34581
|
+
coalesce(pg_get_viewdef('public.logistics_product_dimensions'::regclass) LIKE '%logistics_product_maten%', false), 'view';
|
|
34582
|
+
RETURN QUERY SELECT 'Engine: gereedheid vraagt gewicht alleen bij kg-grens',
|
|
34583
|
+
coalesce(pg_get_functiondef('public.logistics_data_gereedheid(uuid[])'::regprocedure) LIKE '%max_weight_kg%', false), 'logistics_data_gereedheid';
|
|
34584
|
+
RETURN QUERY SELECT 'Engine: startlijst en standaardmaten ladingdragers',
|
|
34585
|
+
to_regprocedure('public.logistics_startlijst()') IS NOT NULL AND to_regprocedure('public.logistics_ladingdrager_voorstel_bevestigen(text)') IS NOT NULL,
|
|
34586
|
+
'logistics_startlijst + logistics_ladingdrager_voorstel_bevestigen';
|
|
34587
|
+
RETURN QUERY SELECT 'Engine: bronregistratie', to_regclass('public.logistics_gegevens_bron') IS NOT NULL, 'logistics_gegevens_bron';
|
|
34588
|
+
EXCEPTION WHEN undefined_table OR undefined_function THEN
|
|
34589
|
+
RETURN QUERY SELECT 'Engine: maten 1.0.198'::text, false, SQLERRM;
|
|
34590
|
+
END $$;
|
|
34591
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_198() TO authenticated, service_role;
|
|
34592
|
+
|
|
34593
|
+
DO $do$ DECLARE d text;
|
|
34594
|
+
BEGIN
|
|
34595
|
+
d := pg_get_functiondef('public.logistics_install_check()'::regprocedure);
|
|
34596
|
+
IF position('logistics_install_check_198' in d) = 0 THEN
|
|
34597
|
+
d := replace(d, $r$ RETURN QUERY SELECT * FROM public.logistics_access_check();$r$,
|
|
34598
|
+
$r$ RETURN QUERY SELECT * FROM public.logistics_install_check_198();
|
|
34599
|
+
RETURN QUERY SELECT * FROM public.logistics_access_check();$r$);
|
|
34600
|
+
EXECUTE d;
|
|
34601
|
+
END IF;
|
|
34602
|
+
EXCEPTION WHEN undefined_function THEN NULL;
|
|
34603
|
+
END $do$;
|