@flowselections/logistiek-engine 1.0.206 → 1.0.209
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 +765 -1
- package/dist-lib/integrations/supabase/types.d.ts +258 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/hoofdverpakking.d.ts +7 -0
- package/dist-lib/lib/hoofdverpakking.d.ts.map +1 -0
- package/dist-lib/lib/hoofdverpakking.js +19 -0
- package/dist-lib/lib/loadCarrierPlanner.d.ts +13 -1
- package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanner.js +68 -8
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +23 -2
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/package.json +1 -1
|
@@ -35824,4 +35824,768 @@ RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY D
|
|
|
35824
35824
|
UNION ALL SELECT 'quarantaine kar-nummering', position('quarantined_at IS NULL' IN pg_get_functiondef('public.logistics_order_unit_carts_core(uuid[])'::regprocedure)) > 0, 'Karren van een order via actieve regels'
|
|
35825
35825
|
UNION ALL SELECT 'quarantaine te hoog', position('quarantined_at IS NULL' IN pg_get_functiondef('public.logistics_order_te_hoge_karren(uuid[])'::regprocedure)) > 0, 'Te hoog alleen op actieve regels'
|
|
35826
35826
|
$$;
|
|
35827
|
-
GRANT EXECUTE ON FUNCTION public.logistics_install_check_205() TO authenticated, service_role;
|
|
35827
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_205() TO authenticated, service_role;
|
|
35828
|
+
-- ============================================================================
|
|
35829
|
+
-- 1.0.207 productoordeel belading zonder tijdelijke tabel (0A000-herstel)
|
|
35830
|
+
-- ============================================================================
|
|
35831
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_oordeel_belading(p_regels jsonb)
|
|
35832
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35833
|
+
DECLARE e jsonb; gj jsonb; gmap jsonb := '{}'::jsonb; c record; v_code text; v_eigen text; ids uuid[]; uit jsonb := '[]'::jsonb;
|
|
35834
|
+
ls int; fh numeric; ph numeric; cpl numeric; lpc numeric; ppc numeric; laag numeric; naam text; v_prod text;
|
|
35835
|
+
blok text[]; waar text[]; mist text[]; hmist text[]; v_pid uuid; v_oordeel text; v_tekst text; v_heeft_kol boolean;
|
|
35836
|
+
BEGIN
|
|
35837
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_oordeel_belading');
|
|
35838
|
+
IF p_regels IS NULL OR jsonb_typeof(p_regels) <> 'array' THEN RAISE EXCEPTION 'p_regels moet een lijst zijn.' USING ERRCODE = '22023'; END IF;
|
|
35839
|
+
IF jsonb_array_length(p_regels) > 1000 THEN
|
|
35840
|
+
RAISE EXCEPTION 'Maximaal 1000 regels per aanroep (ontvangen: %).', jsonb_array_length(p_regels) USING ERRCODE = '22023';
|
|
35841
|
+
END IF;
|
|
35842
|
+
SELECT array_agg(DISTINCT (x->>'product_id')::uuid) INTO ids FROM jsonb_array_elements(p_regels) x
|
|
35843
|
+
WHERE nullif(btrim(x->>'product_id'), '') ~* '^[0-9a-f-]{36}$';
|
|
35844
|
+
IF ids IS NOT NULL THEN
|
|
35845
|
+
SELECT coalesce(jsonb_object_agg(g.product_id::text, to_jsonb(g)), '{}'::jsonb) INTO gmap
|
|
35846
|
+
FROM public.logistics_data_gereedheid(ids) g;
|
|
35847
|
+
END IF;
|
|
35848
|
+
-- Eigen ladingdrager van het product, alleen als die kolom in deze Shell bestaat; geen standaard.
|
|
35849
|
+
SELECT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = to_regclass('public.products') AND attname = 'load_carrier_type' AND NOT attisdropped) INTO v_heeft_kol;
|
|
35850
|
+
|
|
35851
|
+
FOR e IN SELECT x FROM jsonb_array_elements(p_regels) x LOOP
|
|
35852
|
+
blok := '{}'; waar := '{}'; mist := '{}'; hmist := '{}'; c := NULL; v_eigen := NULL;
|
|
35853
|
+
v_pid := CASE WHEN nullif(btrim(e->>'product_id'), '') ~* '^[0-9a-f-]{36}$' THEN (e->>'product_id')::uuid END;
|
|
35854
|
+
gj := CASE WHEN v_pid IS NULL THEN NULL ELSE gmap->(v_pid::text) END;
|
|
35855
|
+
IF gj IS NULL THEN
|
|
35856
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', 'mist_gegevens', 'tekst', 'product onbekend',
|
|
35857
|
+
'regels', jsonb_build_array('Product onbekend.')));
|
|
35858
|
+
CONTINUE;
|
|
35859
|
+
END IF;
|
|
35860
|
+
v_prod := coalesce(gj->>'product', 'Product');
|
|
35861
|
+
v_code := nullif(btrim(e->>'carrier_code'), '');
|
|
35862
|
+
IF v_code IS NULL AND v_heeft_kol THEN
|
|
35863
|
+
EXECUTE 'SELECT nullif(btrim(load_carrier_type::text), '''') FROM public.products WHERE id = $1' INTO v_eigen USING v_pid;
|
|
35864
|
+
v_code := v_eigen;
|
|
35865
|
+
END IF;
|
|
35866
|
+
IF v_code IS NOT NULL THEN
|
|
35867
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm, t.max_crates_per_layer, t.layers_per_carrier INTO c
|
|
35868
|
+
FROM public.load_carrier_types t WHERE t.is_active AND t.code = v_code LIMIT 1;
|
|
35869
|
+
END IF;
|
|
35870
|
+
naam := coalesce(c.name, c.code, v_code, 'de ladingdrager');
|
|
35871
|
+
ppc := nullif(e->>'plants_per_crate', '')::numeric;
|
|
35872
|
+
cpl := nullif(e->>'crates_per_layer', '')::numeric;
|
|
35873
|
+
lpc := nullif(e->>'layers_per_cart', '')::numeric;
|
|
35874
|
+
IF coalesce(ppc, 0) <= 0 THEN mist := mist || 'planten per fust'::text; END IF;
|
|
35875
|
+
IF coalesce(cpl, 0) <= 0 THEN mist := mist || 'fusten per laag'::text; END IF;
|
|
35876
|
+
IF coalesce(lpc, 0) <= 0 THEN mist := mist || 'lagen per kar'::text; END IF;
|
|
35877
|
+
IF v_code IS NULL THEN
|
|
35878
|
+
mist := mist || 'ladingdrager'::text;
|
|
35879
|
+
ELSIF c.code IS NULL THEN
|
|
35880
|
+
blok := blok || format('ladingdrager %s staat niet in Beheer', v_code);
|
|
35881
|
+
ELSE
|
|
35882
|
+
fh := nullif(gj->'velden'->'fust_height_mm'->>'waarde', '')::numeric / 10.0;
|
|
35883
|
+
ph := nullif(gj->'velden'->'plant_height_cm'->>'waarde', '')::numeric;
|
|
35884
|
+
ls := public.logistics_max_fusten_per_laag(c.layer_length_cm, c.layer_width_cm,
|
|
35885
|
+
nullif(gj->'velden'->'fust_length_mm'->>'waarde', '')::numeric / 10.0, nullif(gj->'velden'->'fust_width_mm'->>'waarde', '')::numeric / 10.0);
|
|
35886
|
+
IF coalesce(lpc,0) > 0 AND coalesce(fh,0) > 0 AND coalesce(ph,0) > 0 AND coalesce(c.max_height_cm,0) > 0 THEN
|
|
35887
|
+
laag := greatest(fh, ph);
|
|
35888
|
+
IF lpc * laag > c.max_height_cm + 1e-9 THEN
|
|
35889
|
+
blok := blok || format('%s lagen × %s cm = %s cm, terwijl %s %s cm hoog is; er passen maximaal %s lagen',
|
|
35890
|
+
lpc, trim_scale(round(laag,1)), trim_scale(round(lpc*laag,1)), naam, trim_scale(round(c.max_height_cm::numeric,1)), floor(c.max_height_cm / laag));
|
|
35891
|
+
END IF;
|
|
35892
|
+
ELSE
|
|
35893
|
+
IF coalesce(fh,0) <= 0 THEN hmist := hmist || 'fusthoogte'::text; END IF;
|
|
35894
|
+
IF coalesce(ph,0) <= 0 THEN hmist := hmist || 'planthoogte'::text; END IF;
|
|
35895
|
+
IF coalesce(c.max_height_cm,0) <= 0 THEN hmist := hmist || ('hoogte van ' || naam); END IF;
|
|
35896
|
+
END IF;
|
|
35897
|
+
IF ls IS NOT NULL AND coalesce(cpl,0) > ls THEN
|
|
35898
|
+
blok := blok || format('%s fust per laag, maar op een laag van %s passen er maximaal %s', cpl, naam, ls);
|
|
35899
|
+
END IF;
|
|
35900
|
+
IF coalesce(c.max_crates_per_layer,0) > 0 AND coalesce(cpl,0) > c.max_crates_per_layer THEN
|
|
35901
|
+
blok := blok || format('%s fust per laag, maar %s staat maximaal %s fust per laag toe', cpl, naam, c.max_crates_per_layer);
|
|
35902
|
+
END IF;
|
|
35903
|
+
IF cardinality(blok) = 0 AND cardinality(hmist) > 0 AND coalesce(c.layers_per_carrier,0) > 0 AND coalesce(lpc,0) > c.layers_per_carrier THEN
|
|
35904
|
+
waar := waar || format('%s lagen opgegeven, standaard %s; niet te controleren omdat de %s ontbreekt', lpc, c.layers_per_carrier, array_to_string(hmist, ', '));
|
|
35905
|
+
END IF;
|
|
35906
|
+
END IF;
|
|
35907
|
+
IF coalesce(gj->'ontbrekend', '[]'::jsonb) ? 'weight' THEN waar := waar || 'gewicht per fust ontbreekt'::text; END IF;
|
|
35908
|
+
IF cardinality(blok) > 0 THEN
|
|
35909
|
+
v_oordeel := 'onmogelijk'; v_tekst := format('%s past niet op %s.', v_prod, naam);
|
|
35910
|
+
ELSIF cardinality(mist) > 0 THEN
|
|
35911
|
+
v_oordeel := 'mist_gegevens'; v_tekst := format('%s: %s ontbreekt.', v_prod, array_to_string(mist, ', '));
|
|
35912
|
+
ELSIF cardinality(waar) > 0 THEN
|
|
35913
|
+
v_oordeel := 'waarschuwing'; v_tekst := format('%s: belading mogelijk, met waarschuwing.', v_prod);
|
|
35914
|
+
ELSE
|
|
35915
|
+
v_oordeel := 'compleet'; v_tekst := format('%s: belading past.', v_prod);
|
|
35916
|
+
END IF;
|
|
35917
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', v_oordeel, 'tekst', v_tekst,
|
|
35918
|
+
'regels', to_jsonb(ARRAY(SELECT upper(left(z,1)) || substr(z,2) || '.' FROM unnest(blok || mist || waar) z))));
|
|
35919
|
+
END LOOP;
|
|
35920
|
+
RETURN uit;
|
|
35921
|
+
END $$;
|
|
35922
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_oordeel_belading(jsonb) TO authenticated, service_role;
|
|
35923
|
+
|
|
35924
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_207()
|
|
35925
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35926
|
+
DECLARE v_ok boolean := true; v_fout text := 'aanroep zonder fout'; v_cnt int;
|
|
35927
|
+
BEGIN
|
|
35928
|
+
SELECT count(*) INTO v_cnt FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
35929
|
+
WHERE n.nspname = 'public' AND p.proname LIKE 'logistics%' AND p.provolatile <> 'v' AND p.prosrc ~* 'create\s+temp';
|
|
35930
|
+
punt := 'geen tijdelijke tabel in niet-volatiele functie'; ok := v_cnt = 0; uitleg := format('%s functie(s) met CREATE TEMP', v_cnt); RETURN NEXT;
|
|
35931
|
+
BEGIN
|
|
35932
|
+
PERFORM public.logistics_product_oordeel_belading('[{"product_id":""}]'::jsonb);
|
|
35933
|
+
EXCEPTION WHEN SQLSTATE '0A000' THEN v_ok := false; v_fout := SQLERRM;
|
|
35934
|
+
WHEN OTHERS THEN v_fout := 'aanroep geweigerd door toegangscontrole of andere fout: ' || SQLERRM;
|
|
35935
|
+
END;
|
|
35936
|
+
punt := 'productoordeel belading aanroepbaar'; ok := v_ok; uitleg := v_fout; RETURN NEXT;
|
|
35937
|
+
END $$;
|
|
35938
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_207() TO authenticated, service_role;
|
|
35939
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_oordeel_belading(p_regels jsonb)
|
|
35940
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
35941
|
+
DECLARE e jsonb; gj jsonb; gmap jsonb := '{}'::jsonb; c record; v_code text; v_eigen text; ids uuid[]; uit jsonb := '[]'::jsonb;
|
|
35942
|
+
ls int; fh numeric; ph numeric; cpl numeric; lpc numeric; ppc numeric; laag numeric; naam text; v_prod text;
|
|
35943
|
+
blok text[]; waar text[]; mist text[]; hmist text[]; v_pid uuid; v_oordeel text; v_tekst text; v_heeft_kol boolean;
|
|
35944
|
+
BEGIN
|
|
35945
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_oordeel_belading');
|
|
35946
|
+
IF p_regels IS NULL OR jsonb_typeof(p_regels) <> 'array' THEN RAISE EXCEPTION 'p_regels moet een lijst zijn.' USING ERRCODE = '22023'; END IF;
|
|
35947
|
+
IF jsonb_array_length(p_regels) > 1000 THEN
|
|
35948
|
+
RAISE EXCEPTION 'Maximaal 1000 regels per aanroep (ontvangen: %).', jsonb_array_length(p_regels) USING ERRCODE = '22023';
|
|
35949
|
+
END IF;
|
|
35950
|
+
SELECT array_agg(DISTINCT (x->>'product_id')::uuid) INTO ids FROM jsonb_array_elements(p_regels) x
|
|
35951
|
+
WHERE nullif(btrim(x->>'product_id'), '') ~* '^[0-9a-f-]{36}$';
|
|
35952
|
+
IF ids IS NOT NULL THEN
|
|
35953
|
+
SELECT coalesce(jsonb_object_agg(g.product_id::text, to_jsonb(g)), '{}'::jsonb) INTO gmap
|
|
35954
|
+
FROM public.logistics_data_gereedheid(ids) g;
|
|
35955
|
+
END IF;
|
|
35956
|
+
SELECT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = to_regclass('public.products') AND attname = 'load_carrier_type' AND NOT attisdropped) INTO v_heeft_kol;
|
|
35957
|
+
|
|
35958
|
+
FOR e IN SELECT x FROM jsonb_array_elements(p_regels) x LOOP
|
|
35959
|
+
blok := '{}'; waar := '{}'; mist := '{}'; hmist := '{}'; v_eigen := NULL;
|
|
35960
|
+
v_pid := CASE WHEN nullif(btrim(e->>'product_id'), '') ~* '^[0-9a-f-]{36}$' THEN (e->>'product_id')::uuid END;
|
|
35961
|
+
gj := CASE WHEN v_pid IS NULL THEN NULL ELSE gmap->(v_pid::text) END;
|
|
35962
|
+
IF gj IS NULL THEN
|
|
35963
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', 'mist_gegevens', 'tekst', 'product onbekend',
|
|
35964
|
+
'regels', jsonb_build_array('Product onbekend.')));
|
|
35965
|
+
CONTINUE;
|
|
35966
|
+
END IF;
|
|
35967
|
+
v_prod := coalesce(gj->>'product', 'Product');
|
|
35968
|
+
v_code := nullif(btrim(e->>'carrier_code'), '');
|
|
35969
|
+
IF v_code IS NULL AND v_heeft_kol THEN
|
|
35970
|
+
EXECUTE 'SELECT nullif(btrim(load_carrier_type::text), '''') FROM public.products WHERE id = $1' INTO v_eigen USING v_pid;
|
|
35971
|
+
v_code := v_eigen;
|
|
35972
|
+
END IF;
|
|
35973
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm, t.max_crates_per_layer, t.layers_per_carrier INTO c
|
|
35974
|
+
FROM public.load_carrier_types t WHERE t.is_active AND t.code = v_code LIMIT 1;
|
|
35975
|
+
naam := coalesce(c.name, c.code, v_code, 'de ladingdrager');
|
|
35976
|
+
ppc := nullif(e->>'plants_per_crate', '')::numeric;
|
|
35977
|
+
cpl := nullif(e->>'crates_per_layer', '')::numeric;
|
|
35978
|
+
lpc := nullif(e->>'layers_per_cart', '')::numeric;
|
|
35979
|
+
IF coalesce(ppc, 0) <= 0 THEN mist := mist || 'planten per fust'::text; END IF;
|
|
35980
|
+
IF coalesce(cpl, 0) <= 0 THEN mist := mist || 'fusten per laag'::text; END IF;
|
|
35981
|
+
IF coalesce(lpc, 0) <= 0 THEN mist := mist || 'lagen per kar'::text; END IF;
|
|
35982
|
+
IF v_code IS NULL THEN
|
|
35983
|
+
mist := mist || 'ladingdrager'::text;
|
|
35984
|
+
ELSIF c.code IS NULL THEN
|
|
35985
|
+
blok := blok || format('ladingdrager %s staat niet in Beheer', v_code);
|
|
35986
|
+
ELSE
|
|
35987
|
+
fh := nullif(gj->'velden'->'fust_height_mm'->>'waarde', '')::numeric / 10.0;
|
|
35988
|
+
ph := nullif(gj->'velden'->'plant_height_cm'->>'waarde', '')::numeric;
|
|
35989
|
+
ls := public.logistics_max_fusten_per_laag(c.layer_length_cm, c.layer_width_cm,
|
|
35990
|
+
nullif(gj->'velden'->'fust_length_mm'->>'waarde', '')::numeric / 10.0, nullif(gj->'velden'->'fust_width_mm'->>'waarde', '')::numeric / 10.0);
|
|
35991
|
+
IF coalesce(lpc,0) > 0 AND coalesce(fh,0) > 0 AND coalesce(ph,0) > 0 AND coalesce(c.max_height_cm,0) > 0 THEN
|
|
35992
|
+
laag := greatest(fh, ph);
|
|
35993
|
+
IF lpc * laag > c.max_height_cm + 1e-9 THEN
|
|
35994
|
+
blok := blok || format('%s lagen × %s cm = %s cm, terwijl %s %s cm hoog is; er passen maximaal %s lagen',
|
|
35995
|
+
lpc, trim_scale(round(laag,1)), trim_scale(round(lpc*laag,1)), naam, trim_scale(round(c.max_height_cm::numeric,1)), floor(c.max_height_cm / laag));
|
|
35996
|
+
END IF;
|
|
35997
|
+
ELSE
|
|
35998
|
+
IF coalesce(fh,0) <= 0 THEN hmist := hmist || 'fusthoogte'::text; END IF;
|
|
35999
|
+
IF coalesce(ph,0) <= 0 THEN hmist := hmist || 'planthoogte'::text; END IF;
|
|
36000
|
+
IF coalesce(c.max_height_cm,0) <= 0 THEN hmist := hmist || ('hoogte van ' || naam); END IF;
|
|
36001
|
+
END IF;
|
|
36002
|
+
IF ls IS NOT NULL AND coalesce(cpl,0) > ls THEN
|
|
36003
|
+
blok := blok || format('%s fust per laag, maar op een laag van %s passen er maximaal %s', cpl, naam, ls);
|
|
36004
|
+
END IF;
|
|
36005
|
+
IF coalesce(c.max_crates_per_layer,0) > 0 AND coalesce(cpl,0) > c.max_crates_per_layer THEN
|
|
36006
|
+
blok := blok || format('%s fust per laag, maar %s staat maximaal %s fust per laag toe', cpl, naam, c.max_crates_per_layer);
|
|
36007
|
+
END IF;
|
|
36008
|
+
IF cardinality(blok) = 0 AND cardinality(hmist) > 0 AND coalesce(c.layers_per_carrier,0) > 0 AND coalesce(lpc,0) > c.layers_per_carrier THEN
|
|
36009
|
+
waar := waar || format('%s lagen opgegeven, standaard %s; niet te controleren omdat de %s ontbreekt', lpc, c.layers_per_carrier, array_to_string(hmist, ', '));
|
|
36010
|
+
END IF;
|
|
36011
|
+
END IF;
|
|
36012
|
+
IF coalesce(gj->'ontbrekend', '[]'::jsonb) ? 'weight' THEN waar := waar || 'gewicht per fust ontbreekt'::text; END IF;
|
|
36013
|
+
IF cardinality(blok) > 0 THEN
|
|
36014
|
+
v_oordeel := 'onmogelijk'; v_tekst := format('%s past niet op %s.', v_prod, naam);
|
|
36015
|
+
ELSIF cardinality(mist) > 0 THEN
|
|
36016
|
+
v_oordeel := 'mist_gegevens'; v_tekst := format('%s: %s ontbreekt.', v_prod, array_to_string(mist, ', '));
|
|
36017
|
+
ELSIF cardinality(waar) > 0 THEN
|
|
36018
|
+
v_oordeel := 'waarschuwing'; v_tekst := format('%s: belading mogelijk, met waarschuwing.', v_prod);
|
|
36019
|
+
ELSE
|
|
36020
|
+
v_oordeel := 'compleet'; v_tekst := format('%s: belading past.', v_prod);
|
|
36021
|
+
END IF;
|
|
36022
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', v_oordeel, 'tekst', v_tekst,
|
|
36023
|
+
'regels', to_jsonb(ARRAY(SELECT upper(left(z,1)) || substr(z,2) || '.' FROM unnest(blok || mist || waar) z))));
|
|
36024
|
+
END LOOP;
|
|
36025
|
+
RETURN uit;
|
|
36026
|
+
END $$;
|
|
36027
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_oordeel_belading(jsonb) TO authenticated, service_role;
|
|
36028
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_207()
|
|
36029
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36030
|
+
DECLARE v_ok boolean := true; v_fout text := 'aanroep zonder fout'; v_cnt int; v_namen text;
|
|
36031
|
+
BEGIN
|
|
36032
|
+
SELECT count(*), string_agg(p.proname, ', ') INTO v_cnt, v_namen FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
36033
|
+
WHERE n.nspname = 'public' AND p.proname LIKE 'logistics%' AND p.proname NOT LIKE 'logistics_install_check%'
|
|
36034
|
+
AND p.provolatile <> 'v' AND p.prosrc ~* 'create\s+temp';
|
|
36035
|
+
punt := 'geen tijdelijke tabel in niet-volatiele functie'; ok := v_cnt = 0;
|
|
36036
|
+
uitleg := CASE WHEN v_cnt = 0 THEN 'geen' ELSE v_namen END; RETURN NEXT;
|
|
36037
|
+
BEGIN
|
|
36038
|
+
PERFORM public.logistics_product_oordeel_belading('[{"product_id":""}]'::jsonb);
|
|
36039
|
+
EXCEPTION WHEN SQLSTATE '0A000' THEN v_ok := false; v_fout := SQLERRM;
|
|
36040
|
+
WHEN OTHERS THEN v_fout := 'aanroep geweigerd door toegangscontrole of andere fout: ' || SQLERRM;
|
|
36041
|
+
END;
|
|
36042
|
+
punt := 'productoordeel belading aanroepbaar'; ok := v_ok; uitleg := v_fout; RETURN NEXT;
|
|
36043
|
+
END $$;
|
|
36044
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_207() TO authenticated, service_role;
|
|
36045
|
+
|
|
36046
|
+
-- =====================================================================
|
|
36047
|
+
-- 1.0.208 — Floriday-vulgraad per kar, karTekst, ladingdrager uit hoofdverpakking,
|
|
36048
|
+
-- oordeel fysiek vóór mist_gegevens, snellere pickwachtrij, verouderde karren (quarantaine).
|
|
36049
|
+
-- Additief en idempotent; geen REVOKE/DROP.
|
|
36050
|
+
-- =====================================================================
|
|
36051
|
+
|
|
36052
|
+
DO $do$
|
|
36053
|
+
BEGIN
|
|
36054
|
+
IF to_regclass('public.logistics_floriday_carrier_map') IS NULL THEN RETURN; END IF;
|
|
36055
|
+
IF NOT EXISTS (
|
|
36056
|
+
SELECT 1 FROM pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
36057
|
+
WHERE i.indrelid = 'public.logistics_floriday_carrier_map'::regclass AND i.indisunique
|
|
36058
|
+
AND i.indnatts = 1 AND a.attname = 'floriday_code') THEN
|
|
36059
|
+
BEGIN
|
|
36060
|
+
CREATE UNIQUE INDEX IF NOT EXISTS logistics_floriday_carrier_map_code_uq ON public.logistics_floriday_carrier_map (floriday_code);
|
|
36061
|
+
EXCEPTION WHEN unique_violation THEN
|
|
36062
|
+
RAISE NOTICE 'logistiek-engine: dubbele Floriday-codes in de vertaaltabel; install_check meldt welke.';
|
|
36063
|
+
END;
|
|
36064
|
+
END IF;
|
|
36065
|
+
END $do$;
|
|
36066
|
+
|
|
36067
|
+
DO $do$
|
|
36068
|
+
BEGIN
|
|
36069
|
+
IF to_regclass('public.logistics_floriday_carrier_map') IS NULL THEN RETURN; END IF;
|
|
36070
|
+
INSERT INTO public.logistics_floriday_carrier_map (floriday_code, carrier_code)
|
|
36071
|
+
SELECT v.f, v.c FROM (VALUES
|
|
36072
|
+
('DANISH_TROLLEY','danish_container'), ('DANISH_TROLLEY_NON_CC_RFID','danish_container'),
|
|
36073
|
+
('DANISH_TROLLEY_WATER_TRAY','danish_container'), ('ONE_THIRD_DANISH_TROLLEY','danish_container'),
|
|
36074
|
+
('AUCTION_TROLLEY','trolley'),
|
|
36075
|
+
('EURO_TROLLEY','euro_rolcontainer'), ('WATERING_CONTAINER','euro_rolcontainer'),
|
|
36076
|
+
('EURO_PALLET','euro_pallet'), ('HT_EURO_PALLET','euro_pallet'),
|
|
36077
|
+
('PALLET','pallet'), ('BLOCK_PALLET','pallet'), ('IFCO_PALLET','pallet'),
|
|
36078
|
+
('CHEP_PALLET_BLUE','pallet'), ('CHEP_PALLET_RED','pallet'),
|
|
36079
|
+
('NONE','loose')) v(f, c)
|
|
36080
|
+
WHERE NOT EXISTS (SELECT 1 FROM public.logistics_floriday_carrier_map m WHERE upper(m.floriday_code) = v.f);
|
|
36081
|
+
END $do$;
|
|
36082
|
+
|
|
36083
|
+
CREATE OR REPLACE FUNCTION public.logistics_ladingdrager_resolve(p_code text)
|
|
36084
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36085
|
+
DECLARE v text := nullif(btrim(p_code), ''); n int; m text;
|
|
36086
|
+
BEGIN
|
|
36087
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_ladingdrager_resolve');
|
|
36088
|
+
IF v IS NULL OR upper(v) = 'NONE' THEN
|
|
36089
|
+
RETURN jsonb_build_object('code', NULL, 'invoer', v, 'bron', NULL, 'fout', 'ladingdrager ontbreekt');
|
|
36090
|
+
END IF;
|
|
36091
|
+
IF EXISTS (SELECT 1 FROM public.load_carrier_types t WHERE t.is_active AND t.code = v) THEN
|
|
36092
|
+
RETURN jsonb_build_object('code', v, 'invoer', v, 'bron', 'beheer', 'fout', NULL);
|
|
36093
|
+
END IF;
|
|
36094
|
+
IF to_regclass('public.logistics_floriday_carrier_map') IS NULL THEN
|
|
36095
|
+
RETURN jsonb_build_object('code', NULL, 'invoer', v, 'bron', NULL, 'fout', format('ladingdrager %s onbekend in Beheer', v));
|
|
36096
|
+
END IF;
|
|
36097
|
+
SELECT count(DISTINCT c.carrier_code), min(c.carrier_code) INTO n, m
|
|
36098
|
+
FROM public.logistics_floriday_carrier_map c WHERE upper(c.floriday_code) = upper(v);
|
|
36099
|
+
IF coalesce(n, 0) = 0 THEN
|
|
36100
|
+
RETURN jsonb_build_object('code', NULL, 'invoer', v, 'bron', NULL, 'fout', format('ladingdrager %s onbekend in Beheer', v));
|
|
36101
|
+
ELSIF n > 1 THEN
|
|
36102
|
+
RETURN jsonb_build_object('code', NULL, 'invoer', v, 'bron', 'floriday', 'fout', format('ladingdrager niet eenduidig (%s)', v));
|
|
36103
|
+
ELSIF m = 'loose' THEN
|
|
36104
|
+
RETURN jsonb_build_object('code', NULL, 'invoer', v, 'bron', 'floriday', 'fout', 'ladingdrager ontbreekt');
|
|
36105
|
+
ELSIF NOT EXISTS (SELECT 1 FROM public.load_carrier_types t WHERE t.is_active AND t.code = m) THEN
|
|
36106
|
+
RETURN jsonb_build_object('code', NULL, 'invoer', v, 'bron', 'floriday', 'fout', format('ladingdrager %s onbekend in Beheer', v));
|
|
36107
|
+
END IF;
|
|
36108
|
+
RETURN jsonb_build_object('code', m, 'invoer', v, 'bron', 'floriday', 'fout', NULL);
|
|
36109
|
+
END $$;
|
|
36110
|
+
GRANT EXECUTE ON FUNCTION public.logistics_ladingdrager_resolve(text) TO authenticated, service_role;
|
|
36111
|
+
|
|
36112
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_hoofdverpakking(p_product_id uuid)
|
|
36113
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36114
|
+
DECLARE v_lc text; v_found boolean := false; v_heeft_lc boolean;
|
|
36115
|
+
BEGIN
|
|
36116
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_hoofdverpakking');
|
|
36117
|
+
IF to_regclass('public.product_packings') IS NULL THEN RETURN NULL; END IF;
|
|
36118
|
+
SELECT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'public.product_packings'::regclass AND attname = 'load_carrier' AND NOT attisdropped) INTO v_heeft_lc;
|
|
36119
|
+
IF v_heeft_lc THEN
|
|
36120
|
+
EXECUTE 'SELECT true, nullif(btrim(load_carrier::text), '''') FROM public.product_packings WHERE product_id = $1 AND is_primary
|
|
36121
|
+
ORDER BY sort_order NULLS LAST, created_at LIMIT 1' INTO v_found, v_lc USING p_product_id;
|
|
36122
|
+
ELSE
|
|
36123
|
+
EXECUTE 'SELECT true FROM public.product_packings WHERE product_id = $1 AND is_primary LIMIT 1' INTO v_found USING p_product_id;
|
|
36124
|
+
END IF;
|
|
36125
|
+
RETURN jsonb_build_object('aanwezig', coalesce(v_found, false), 'ladingdrager', v_lc);
|
|
36126
|
+
END $$;
|
|
36127
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_hoofdverpakking(uuid) TO authenticated, service_role;
|
|
36128
|
+
|
|
36129
|
+
CREATE OR REPLACE FUNCTION public.logistics_max_fusten_per_laag_alle(p_fust_l numeric, p_fust_b numeric)
|
|
36130
|
+
RETURNS integer LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
36131
|
+
SELECT max(public.logistics_max_fusten_per_laag(t.layer_length_cm, t.layer_width_cm, p_fust_l, p_fust_b))
|
|
36132
|
+
FROM public.load_carrier_types t
|
|
36133
|
+
WHERE t.is_active AND coalesce(t.layer_length_cm, 0) > 0 AND coalesce(t.layer_width_cm, 0) > 0
|
|
36134
|
+
$$;
|
|
36135
|
+
GRANT EXECUTE ON FUNCTION public.logistics_max_fusten_per_laag_alle(numeric, numeric) TO authenticated, service_role;
|
|
36136
|
+
|
|
36137
|
+
CREATE OR REPLACE FUNCTION public.logistics_product_oordeel_belading(p_regels jsonb)
|
|
36138
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36139
|
+
DECLARE e jsonb; gj jsonb; gmap jsonb := '{}'::jsonb; c record; rc jsonb; hv jsonb; v_code text; v_eigen text; ids uuid[]; uit jsonb := '[]'::jsonb;
|
|
36140
|
+
ls int; fh numeric; ph numeric; cpl numeric; lpc numeric; ppc numeric; laag numeric; naam text; v_prod text; fl numeric; fb numeric;
|
|
36141
|
+
blok text[]; waar text[]; mist text[]; hmist text[]; v_pid uuid; v_oordeel text; v_tekst text; v_heeft_kol boolean; v_cfout text;
|
|
36142
|
+
BEGIN
|
|
36143
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_product_oordeel_belading');
|
|
36144
|
+
IF p_regels IS NULL OR jsonb_typeof(p_regels) <> 'array' THEN RAISE EXCEPTION 'p_regels moet een lijst zijn.' USING ERRCODE = '22023'; END IF;
|
|
36145
|
+
IF jsonb_array_length(p_regels) > 1000 THEN
|
|
36146
|
+
RAISE EXCEPTION 'Maximaal 1000 regels per aanroep (ontvangen: %).', jsonb_array_length(p_regels) USING ERRCODE = '22023';
|
|
36147
|
+
END IF;
|
|
36148
|
+
SELECT array_agg(DISTINCT (x->>'product_id')::uuid) INTO ids FROM jsonb_array_elements(p_regels) x
|
|
36149
|
+
WHERE nullif(btrim(x->>'product_id'), '') ~* '^[0-9a-f-]{36}$';
|
|
36150
|
+
IF ids IS NOT NULL THEN
|
|
36151
|
+
SELECT coalesce(jsonb_object_agg(g.product_id::text, to_jsonb(g)), '{}'::jsonb) INTO gmap
|
|
36152
|
+
FROM public.logistics_data_gereedheid(ids) g;
|
|
36153
|
+
END IF;
|
|
36154
|
+
SELECT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = to_regclass('public.products') AND attname = 'load_carrier_type' AND NOT attisdropped) INTO v_heeft_kol;
|
|
36155
|
+
|
|
36156
|
+
FOR e IN SELECT x FROM jsonb_array_elements(p_regels) x LOOP
|
|
36157
|
+
blok := '{}'; waar := '{}'; mist := '{}'; hmist := '{}'; v_eigen := NULL; c := NULL; v_cfout := NULL;
|
|
36158
|
+
v_pid := CASE WHEN nullif(btrim(e->>'product_id'), '') ~* '^[0-9a-f-]{36}$' THEN (e->>'product_id')::uuid END;
|
|
36159
|
+
gj := CASE WHEN v_pid IS NULL THEN NULL ELSE gmap->(v_pid::text) END;
|
|
36160
|
+
IF gj IS NULL THEN
|
|
36161
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', 'mist_gegevens', 'tekst', 'product onbekend',
|
|
36162
|
+
'regels', jsonb_build_array('Product onbekend.')));
|
|
36163
|
+
CONTINUE;
|
|
36164
|
+
END IF;
|
|
36165
|
+
v_prod := coalesce(gj->>'product', 'Product');
|
|
36166
|
+
hv := public.logistics_product_hoofdverpakking(v_pid);
|
|
36167
|
+
v_code := nullif(btrim(e->>'carrier_code'), '');
|
|
36168
|
+
IF v_code IS NULL THEN v_code := nullif(hv->>'ladingdrager', ''); END IF;
|
|
36169
|
+
IF v_code IS NULL AND v_heeft_kol THEN
|
|
36170
|
+
EXECUTE 'SELECT nullif(btrim(load_carrier_type::text), '''') FROM public.products WHERE id = $1' INTO v_eigen USING v_pid;
|
|
36171
|
+
v_code := v_eigen;
|
|
36172
|
+
END IF;
|
|
36173
|
+
rc := public.logistics_ladingdrager_resolve(v_code);
|
|
36174
|
+
v_cfout := rc->>'fout';
|
|
36175
|
+
IF rc->>'code' IS NOT NULL THEN
|
|
36176
|
+
SELECT t.code, t.name, t.layer_length_cm, t.layer_width_cm, t.max_height_cm, t.max_crates_per_layer, t.layers_per_carrier INTO c
|
|
36177
|
+
FROM public.load_carrier_types t WHERE t.is_active AND t.code = rc->>'code' LIMIT 1;
|
|
36178
|
+
END IF;
|
|
36179
|
+
naam := coalesce(c.name, c.code, 'de ladingdrager');
|
|
36180
|
+
ppc := nullif(e->>'plants_per_crate', '')::numeric;
|
|
36181
|
+
cpl := nullif(e->>'crates_per_layer', '')::numeric;
|
|
36182
|
+
lpc := nullif(e->>'layers_per_cart', '')::numeric;
|
|
36183
|
+
fh := nullif(gj->'velden'->'fust_height_mm'->>'waarde', '')::numeric / 10.0;
|
|
36184
|
+
ph := nullif(gj->'velden'->'plant_height_cm'->>'waarde', '')::numeric;
|
|
36185
|
+
fl := nullif(gj->'velden'->'fust_length_mm'->>'waarde', '')::numeric / 10.0;
|
|
36186
|
+
fb := nullif(gj->'velden'->'fust_width_mm'->>'waarde', '')::numeric / 10.0;
|
|
36187
|
+
IF hv IS NOT NULL AND NOT coalesce((hv->>'aanwezig')::boolean, false) THEN mist := mist || 'belading niet ingesteld'::text; END IF;
|
|
36188
|
+
IF coalesce(ppc, 0) <= 0 THEN mist := mist || 'planten per fust'::text; END IF;
|
|
36189
|
+
IF coalesce(cpl, 0) <= 0 THEN mist := mist || 'fusten per laag'::text; END IF;
|
|
36190
|
+
IF coalesce(lpc, 0) <= 0 THEN mist := mist || 'lagen per kar'::text; END IF;
|
|
36191
|
+
|
|
36192
|
+
IF c.code IS NULL THEN
|
|
36193
|
+
mist := mist || coalesce(v_cfout, 'ladingdrager ontbreekt');
|
|
36194
|
+
ls := public.logistics_max_fusten_per_laag_alle(fl, fb);
|
|
36195
|
+
IF ls IS NOT NULL AND coalesce(cpl,0) > ls THEN
|
|
36196
|
+
blok := blok || format('%s fust per laag, maar op geen enkele ladingdrager in Beheer passen er meer dan %s', cpl, ls);
|
|
36197
|
+
END IF;
|
|
36198
|
+
ELSE
|
|
36199
|
+
ls := public.logistics_max_fusten_per_laag(c.layer_length_cm, c.layer_width_cm, fl, fb);
|
|
36200
|
+
IF coalesce(lpc,0) > 0 AND coalesce(fh,0) > 0 AND coalesce(ph,0) > 0 AND coalesce(c.max_height_cm,0) > 0 THEN
|
|
36201
|
+
laag := greatest(fh, ph);
|
|
36202
|
+
IF lpc * laag > c.max_height_cm + 1e-9 THEN
|
|
36203
|
+
blok := blok || format('%s lagen × %s cm = %s cm, terwijl %s %s cm hoog is; er passen maximaal %s lagen',
|
|
36204
|
+
lpc, trim_scale(round(laag,1)), trim_scale(round(lpc*laag,1)), naam, trim_scale(round(c.max_height_cm::numeric,1)), floor(c.max_height_cm / laag));
|
|
36205
|
+
END IF;
|
|
36206
|
+
ELSE
|
|
36207
|
+
IF coalesce(fh,0) <= 0 THEN hmist := hmist || 'fusthoogte'::text; END IF;
|
|
36208
|
+
IF coalesce(ph,0) <= 0 THEN hmist := hmist || 'planthoogte'::text; END IF;
|
|
36209
|
+
IF coalesce(c.max_height_cm,0) <= 0 THEN hmist := hmist || ('hoogte van ' || naam); END IF;
|
|
36210
|
+
END IF;
|
|
36211
|
+
IF ls IS NOT NULL AND coalesce(cpl,0) > ls THEN
|
|
36212
|
+
blok := blok || format('%s fust per laag, maar op een laag van %s passen er maximaal %s', cpl, naam, ls);
|
|
36213
|
+
END IF;
|
|
36214
|
+
IF coalesce(c.max_crates_per_layer,0) > 0 AND coalesce(cpl,0) > c.max_crates_per_layer THEN
|
|
36215
|
+
blok := blok || format('%s fust per laag, maar %s staat maximaal %s fust per laag toe', cpl, naam, c.max_crates_per_layer);
|
|
36216
|
+
END IF;
|
|
36217
|
+
IF cardinality(blok) = 0 AND cardinality(hmist) > 0 AND coalesce(c.layers_per_carrier,0) > 0 AND coalesce(lpc,0) > c.layers_per_carrier THEN
|
|
36218
|
+
waar := waar || format('%s lagen opgegeven, standaard %s; niet te controleren omdat de %s ontbreekt', lpc, c.layers_per_carrier, array_to_string(hmist, ', '));
|
|
36219
|
+
END IF;
|
|
36220
|
+
END IF;
|
|
36221
|
+
IF coalesce(gj->'ontbrekend', '[]'::jsonb) ? 'weight' THEN waar := waar || 'gewicht per fust ontbreekt'::text; END IF;
|
|
36222
|
+
IF cardinality(blok) > 0 THEN
|
|
36223
|
+
v_oordeel := 'onmogelijk'; v_tekst := format('%s past niet op %s.', v_prod, CASE WHEN c.code IS NULL THEN 'een ladingdrager' ELSE naam END);
|
|
36224
|
+
ELSIF cardinality(mist) > 0 THEN
|
|
36225
|
+
v_oordeel := 'mist_gegevens'; v_tekst := format('%s: %s.', v_prod, array_to_string(mist, ', '));
|
|
36226
|
+
ELSIF cardinality(waar) > 0 THEN
|
|
36227
|
+
v_oordeel := 'waarschuwing'; v_tekst := format('%s: belading mogelijk, met waarschuwing.', v_prod);
|
|
36228
|
+
ELSE
|
|
36229
|
+
v_oordeel := 'compleet'; v_tekst := format('%s: belading past.', v_prod);
|
|
36230
|
+
END IF;
|
|
36231
|
+
uit := uit || jsonb_build_array(jsonb_build_object('product_id', v_pid, 'oordeel', v_oordeel, 'tekst', v_tekst,
|
|
36232
|
+
'ladingdrager', rc->>'code', 'ladingdragerInvoer', rc->>'invoer', 'ladingdragerBron', rc->>'bron',
|
|
36233
|
+
'regels', to_jsonb(ARRAY(SELECT upper(left(z,1)) || substr(z,2) || '.' FROM unnest(blok || mist || waar) z))));
|
|
36234
|
+
END LOOP;
|
|
36235
|
+
RETURN uit;
|
|
36236
|
+
END $$;
|
|
36237
|
+
GRANT EXECUTE ON FUNCTION public.logistics_product_oordeel_belading(jsonb) TO authenticated, service_role;
|
|
36238
|
+
|
|
36239
|
+
DO $do$
|
|
36240
|
+
DECLARE d text; n text;
|
|
36241
|
+
BEGIN
|
|
36242
|
+
IF to_regprocedure('public.logistics_product_oordeel_many(uuid[])') IS NULL THEN RETURN; END IF;
|
|
36243
|
+
d := pg_get_functiondef('public.logistics_product_oordeel_many(uuid[])'::regprocedure);
|
|
36244
|
+
IF position('belading niet ingesteld' IN d) > 0 THEN RETURN; END IF;
|
|
36245
|
+
n := replace(d,
|
|
36246
|
+
$a$ mist := array_remove(coalesce(r.ontbrekend, '{}'), 'weight');$a$,
|
|
36247
|
+
$a$ mist := array_remove(coalesce(r.ontbrekend, '{}'), 'weight');
|
|
36248
|
+
IF public.logistics_product_hoofdverpakking(r.product_id) IS NOT NULL
|
|
36249
|
+
AND NOT coalesce((public.logistics_product_hoofdverpakking(r.product_id)->>'aanwezig')::boolean, false) THEN
|
|
36250
|
+
mist := mist || 'belading niet ingesteld'::text;
|
|
36251
|
+
END IF;$a$);
|
|
36252
|
+
n := replace(n,
|
|
36253
|
+
$a$ oordeel := 'mist_gegevens'; tekst := r.uitleg;$a$,
|
|
36254
|
+
$a$ oordeel := 'mist_gegevens';
|
|
36255
|
+
tekst := CASE WHEN 'belading niet ingesteld' = ANY(mist) THEN format('%s: belading niet ingesteld.', r.product) ELSE r.uitleg END;$a$);
|
|
36256
|
+
IF n = d THEN RAISE NOTICE 'logistiek-engine: patroon oordeel_many niet gevonden'; RETURN; END IF;
|
|
36257
|
+
EXECUTE n;
|
|
36258
|
+
END $do$;
|
|
36259
|
+
|
|
36260
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_vulgraad_core(p_cart_id uuid)
|
|
36261
|
+
RETURNS numeric LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
36262
|
+
DECLARE m jsonb := public.logistics_laag_menging_core(); v_n int; v_m int; v_tot numeric; v_ontbreekt boolean; v_groepen int;
|
|
36263
|
+
BEGIN
|
|
36264
|
+
SELECT bool_or(coalesce(ci.crates_per_layer, 0) <= 0 OR coalesce(ci.layers_per_cart, 0) <= 0) INTO v_ontbreekt
|
|
36265
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
36266
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL;
|
|
36267
|
+
IF v_ontbreekt IS NULL OR v_ontbreekt THEN RETURN NULL; END IF;
|
|
36268
|
+
IF m->>'menging' = 'per_regel' THEN
|
|
36269
|
+
SELECT sum(ceil(ci.crates::numeric / ci.crates_per_layer - 1e-9) / ci.layers_per_cart) INTO v_tot
|
|
36270
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
36271
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL;
|
|
36272
|
+
RETURN v_tot;
|
|
36273
|
+
END IF;
|
|
36274
|
+
v_n := nullif(m->>'klantenPerLaag', '')::int;
|
|
36275
|
+
v_m := nullif(m->>'beladingenPerLaag', '')::int;
|
|
36276
|
+
WITH r AS (
|
|
36277
|
+
SELECT ci.crates::numeric / ci.crates_per_layer f, ci.layers_per_cart::numeric lpc,
|
|
36278
|
+
coalesce(o.customer_id::text, oi.order_id::text, 'regel:' || ci.order_item_id::text) klant, ci.order_item_id::text regel
|
|
36279
|
+
FROM logistics_active.order_cart_items ci
|
|
36280
|
+
LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
36281
|
+
LEFT JOIN public.orders o ON o.id = oi.order_id
|
|
36282
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL),
|
|
36283
|
+
g AS (
|
|
36284
|
+
SELECT r.*, CASE
|
|
36285
|
+
WHEN v_n IS NULL AND v_m IS NULL THEN '1'
|
|
36286
|
+
WHEN v_m IS NOT NULL THEN r.klant || ':' || ((row_number() OVER (PARTITION BY r.klant ORDER BY r.regel) - 1) / v_m)
|
|
36287
|
+
ELSE ((dense_rank() OVER (ORDER BY r.klant) - 1) / v_n)::text END grp
|
|
36288
|
+
FROM r),
|
|
36289
|
+
u AS (SELECT grp, sum(f) lagen, sum(f / lpc) vul, min(lpc) minl FROM g GROUP BY grp)
|
|
36290
|
+
SELECT count(*), CASE WHEN count(*) <= 1 THEN sum(vul) ELSE sum(ceil(lagen - 1e-9) / minl) END INTO v_groepen, v_tot FROM u;
|
|
36291
|
+
RETURN v_tot;
|
|
36292
|
+
END $$;
|
|
36293
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_vulgraad_core(uuid) TO authenticated, service_role;
|
|
36294
|
+
|
|
36295
|
+
CREATE OR REPLACE FUNCTION public.logistics_kar_blokkade_vul(p_kar text, p_vul numeric)
|
|
36296
|
+
RETURNS jsonb LANGUAGE sql IMMUTABLE SET search_path TO 'public' AS $$
|
|
36297
|
+
SELECT CASE WHEN p_vul IS NOT NULL AND p_vul > 1.001
|
|
36298
|
+
THEN jsonb_build_object('teHoog', true, 'blokkade', jsonb_build_object('code', 'kar_te_hoog',
|
|
36299
|
+
'tekst', format('Kar %s is voor %s %% gevuld, meer dan 100 %%. Deel de order opnieuw in of pas de belading aan.',
|
|
36300
|
+
coalesce(nullif(btrim(p_kar), ''), '?'), round(100 * p_vul)::int)))
|
|
36301
|
+
ELSE jsonb_build_object('teHoog', false, 'blokkade', NULL) END
|
|
36302
|
+
$$;
|
|
36303
|
+
GRANT EXECUTE ON FUNCTION public.logistics_kar_blokkade_vul(text, numeric) TO authenticated, service_role;
|
|
36304
|
+
|
|
36305
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_capaciteit_core(p_cart_id uuid)
|
|
36306
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
36307
|
+
WITH c AS (SELECT oc.cart_number, oc.total_layers_used, oc.max_layers FROM logistics_active.order_carts oc WHERE oc.id = p_cart_id),
|
|
36308
|
+
i AS (SELECT max(nullif(ci.layers_per_cart, 0)) lpc
|
|
36309
|
+
FROM logistics_active.order_cart_items ci LEFT JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
36310
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NULL),
|
|
36311
|
+
v AS (SELECT c.cart_number,
|
|
36312
|
+
coalesce(public.logistics_cart_lagen_core(p_cart_id), c.total_layers_used::numeric) lagen,
|
|
36313
|
+
coalesce(i.lpc::numeric, nullif(c.max_layers, 0)::numeric) cap,
|
|
36314
|
+
public.logistics_cart_vulgraad_core(p_cart_id) vul,
|
|
36315
|
+
CASE WHEN i.lpc IS NOT NULL THEN 'product' WHEN coalesce(c.max_layers, 0) > 0 THEN 'ladingdrager' END bron
|
|
36316
|
+
FROM c, i)
|
|
36317
|
+
SELECT jsonb_build_object('layersUsed', v.lagen, 'maxLayers', v.cap, 'capaciteitBron', v.bron,
|
|
36318
|
+
'laagMenging', public.logistics_laag_menging_core(),
|
|
36319
|
+
'vulgraad', round(v.vul, 4),
|
|
36320
|
+
'vulgraadPct', coalesce(round(100 * v.vul), CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END),
|
|
36321
|
+
'layerUtilizationPct', coalesce(round(100 * v.vul), CASE WHEN coalesce(v.cap, 0) > 0 AND v.lagen IS NOT NULL THEN round(100 * v.lagen / v.cap) END))
|
|
36322
|
+
|| CASE WHEN v.vul IS NOT NULL THEN public.logistics_kar_blokkade_vul(v.cart_number::text, v.vul)
|
|
36323
|
+
ELSE public.logistics_kar_blokkade(v.cart_number::text, v.lagen, v.cap) END
|
|
36324
|
+
FROM v
|
|
36325
|
+
$$;
|
|
36326
|
+
|
|
36327
|
+
CREATE OR REPLACE FUNCTION public.logistics_kar_tekst(p_carrier_code text, p_lagen numeric, p_pct numeric)
|
|
36328
|
+
RETURNS text LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36329
|
+
SELECT CASE WHEN p_lagen IS NULL THEN NULL ELSE
|
|
36330
|
+
replace(trim_scale(round(p_lagen, 1))::text, '.', ',') || ' lagen · '
|
|
36331
|
+
|| coalesce((SELECT nullif(btrim(t.name), '') FROM public.load_carrier_types t WHERE t.code = p_carrier_code ORDER BY t.is_active DESC LIMIT 1), 'Ladingdrager')
|
|
36332
|
+
|| CASE WHEN coalesce(public.logistics_extra_platen(p_lagen), 0) = 0 THEN ''
|
|
36333
|
+
WHEN public.logistics_extra_platen(p_lagen) = 1 THEN ' + 1 plaat'
|
|
36334
|
+
ELSE ' + ' || public.logistics_extra_platen(p_lagen) || ' platen' END
|
|
36335
|
+
|| CASE WHEN p_pct IS NULL THEN '' ELSE ' · ' || round(p_pct)::int || ' %' END END
|
|
36336
|
+
$$;
|
|
36337
|
+
GRANT EXECUTE ON FUNCTION public.logistics_kar_tekst(text, numeric, numeric) TO authenticated, service_role;
|
|
36338
|
+
|
|
36339
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_platen_verrijk(p_cart jsonb)
|
|
36340
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36341
|
+
DECLARE v_id uuid; k jsonb; c jsonb := p_cart; v_l numeric; v_pct numeric;
|
|
36342
|
+
BEGIN
|
|
36343
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_platen_verrijk');
|
|
36344
|
+
BEGIN v_id := nullif(coalesce(p_cart->>'cartId', p_cart->>'cart_id'), '')::uuid; EXCEPTION WHEN invalid_text_representation THEN v_id := NULL; END;
|
|
36345
|
+
IF v_id IS NOT NULL THEN k := public.logistics_cart_capaciteit_core(v_id); END IF;
|
|
36346
|
+
IF k IS NOT NULL THEN
|
|
36347
|
+
c := c || jsonb_build_object('layersUsed', k->'layersUsed', 'maxLayers', k->'maxLayers', 'capaciteitBron', k->'capaciteitBron',
|
|
36348
|
+
'vulgraadPct', k->'vulgraadPct', 'layerUtilizationPct', k->'layerUtilizationPct');
|
|
36349
|
+
END IF;
|
|
36350
|
+
v_l := nullif(c->>'layersUsed', '')::numeric;
|
|
36351
|
+
v_pct := coalesce(nullif(c->>'vulgraadPct', '')::numeric, nullif(c->>'layerUtilizationPct', '')::numeric, nullif(c->>'occupancyPct', '')::numeric);
|
|
36352
|
+
RETURN c || jsonb_build_object(
|
|
36353
|
+
'additionalLayers', public.logistics_extra_platen(v_l),
|
|
36354
|
+
'ladingdragerTekst', public.logistics_ladingdrager_tekst(c->>'carrierType', v_l, v_pct),
|
|
36355
|
+
'karTekst', public.logistics_kar_tekst(c->>'carrierType', v_l, v_pct))
|
|
36356
|
+
|| CASE WHEN k IS NOT NULL THEN jsonb_build_object('teHoog', coalesce(k->'teHoog', 'false'::jsonb), 'blokkade', k->'blokkade')
|
|
36357
|
+
ELSE public.logistics_kar_blokkade(coalesce(c->>'cartNumber', c->>'cart_number', c->>'seq'), v_l, nullif(c->>'maxLayers', '')::numeric) END;
|
|
36358
|
+
END $$;
|
|
36359
|
+
|
|
36360
|
+
DO $do$
|
|
36361
|
+
DECLARE d text; n text;
|
|
36362
|
+
BEGIN
|
|
36363
|
+
d := pg_get_functiondef('public.logistics_product_oordeel_belading(jsonb)'::regprocedure);
|
|
36364
|
+
IF position('c := NULL;' IN d) = 0 THEN RETURN; END IF;
|
|
36365
|
+
n := replace(d, 'v_eigen := NULL; c := NULL; v_cfout := NULL;',
|
|
36366
|
+
'v_eigen := NULL; v_cfout := NULL;
|
|
36367
|
+
SELECT NULL::text AS code, NULL::text AS name, NULL::numeric AS layer_length_cm, NULL::numeric AS layer_width_cm,
|
|
36368
|
+
NULL::numeric AS max_height_cm, NULL::integer AS max_crates_per_layer, NULL::integer AS layers_per_carrier INTO c;');
|
|
36369
|
+
EXECUTE n;
|
|
36370
|
+
END $do$;
|
|
36371
|
+
|
|
36372
|
+
CREATE OR REPLACE FUNCTION public.logistics_pick_cart_breakdown_fast(_order_id uuid)
|
|
36373
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $function$
|
|
36374
|
+
DECLARE
|
|
36375
|
+
v_orders uuid[]; v_ref text; v_status jsonb;
|
|
36376
|
+
v_ready boolean := false; v_released boolean := false;
|
|
36377
|
+
v_total integer := 0; v_full integer := 0; v_partial integer := 0;
|
|
36378
|
+
v_shared integer := 0; v_crates integer := 0;
|
|
36379
|
+
BEGIN
|
|
36380
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_pick_cart_breakdown_fast');
|
|
36381
|
+
v_orders := public.pick_buffer_order_ids(_order_id);
|
|
36382
|
+
IF v_orders IS NULL OR cardinality(v_orders) = 0 THEN v_orders := ARRAY[_order_id]; END IF;
|
|
36383
|
+
SELECT o.order_number INTO v_ref FROM public.orders o WHERE o.id = _order_id;
|
|
36384
|
+
-- 1.0.208: alleen de kern; planState (logistics_plan_state_for) wordt hier niet gebruikt.
|
|
36385
|
+
v_status := public.logistics_cart_plan_status_core(v_ref);
|
|
36386
|
+
v_ready := COALESCE((v_status->>'ready')::boolean, false);
|
|
36387
|
+
v_released := COALESCE((v_status->>'released')::boolean, false);
|
|
36388
|
+
IF v_ready THEN
|
|
36389
|
+
v_total := COALESCE((v_status->>'cartTotal')::integer, (v_status->>'totalCarts')::integer, 0);
|
|
36390
|
+
SELECT
|
|
36391
|
+
count(*) FILTER (WHERE COALESCE((c->>'isFullCart')::boolean, false)),
|
|
36392
|
+
count(*) FILTER (WHERE NOT COALESCE((c->>'isFullCart')::boolean, false)),
|
|
36393
|
+
count(*) FILTER (WHERE COALESCE((c->>'isShared')::boolean, false))
|
|
36394
|
+
INTO v_full, v_partial, v_shared
|
|
36395
|
+
FROM jsonb_array_elements(COALESCE(v_status->'carts', '[]'::jsonb)) c;
|
|
36396
|
+
IF v_total = 0 THEN v_total := v_full + v_partial; END IF;
|
|
36397
|
+
IF v_total > 0 AND v_full + v_partial <> v_total THEN
|
|
36398
|
+
v_partial := GREATEST(v_total - v_full, 0);
|
|
36399
|
+
END IF;
|
|
36400
|
+
END IF;
|
|
36401
|
+
SELECT COALESCE(sum(ci.crates), 0)::integer INTO v_crates
|
|
36402
|
+
FROM public.order_cart_items ci
|
|
36403
|
+
JOIN logistics_active.order_items oi ON oi.id = ci.order_item_id
|
|
36404
|
+
WHERE oi.order_id = ANY(v_orders);
|
|
36405
|
+
RETURN jsonb_build_object(
|
|
36406
|
+
'totalCarts', COALESCE(v_total, 0), 'fullCarts', COALESCE(v_full, 0), 'partialCarts', COALESCE(v_partial, 0),
|
|
36407
|
+
'sharedCarts', COALESCE(v_shared, 0), 'crates', COALESCE(v_crates, 0),
|
|
36408
|
+
'cartPlanReady', v_ready, 'cartPlanReleased', v_released, 'cartPlanReason', v_status->>'reason'
|
|
36409
|
+
) || public.logistics_pick_mode();
|
|
36410
|
+
END; $function$;
|
|
36411
|
+
GRANT EXECUTE ON FUNCTION public.logistics_pick_cart_breakdown_fast(uuid) TO authenticated, service_role;
|
|
36412
|
+
|
|
36413
|
+
DO $do$
|
|
36414
|
+
DECLARE d text; n text;
|
|
36415
|
+
BEGIN
|
|
36416
|
+
-- Kern
|
|
36417
|
+
d := pg_get_functiondef('public.logistics_sync_pick_queue_core()'::regprocedure);
|
|
36418
|
+
IF position('v_kand uuid[]' IN d) = 0 THEN
|
|
36419
|
+
n := replace(d, 'v_wait timestamptz; v_reason text; v_ok boolean;',
|
|
36420
|
+
'v_wait timestamptz; v_reason text; v_ok boolean; v_kand uuid[]; v_rel uuid[];');
|
|
36421
|
+
n := replace(n, E' SELECT min(d) INTO v_pickday FROM (',
|
|
36422
|
+
E' -- 1.0.208: controles per order één keer voor alle orders samen.\n'
|
|
36423
|
+
|| E' SELECT coalesce(array_agg(ord.id), ''{}'') INTO v_kand FROM public.orders ord\n'
|
|
36424
|
+
|| E' WHERE ord.order_number IS NOT NULL\n'
|
|
36425
|
+
|| E' AND EXISTS (SELECT 1 FROM public.logistics_tasks lt WHERE lt.order_ref = ord.order_number AND lt.task_type = ''pick.execute''\n'
|
|
36426
|
+
|| E' AND lt.status NOT IN (''done'',''cancelled'',''superseded'',''skipped''))\n'
|
|
36427
|
+
|| E' AND public.logistics_order_is_topick(ord.id, ord.order_number)\n'
|
|
36428
|
+
|| E' AND NOT public.logistics_order_handled(ord.id);\n'
|
|
36429
|
+
|| E' SELECT coalesce(array_agg(ord.id), ''{}'') INTO v_rel FROM public.orders ord\n'
|
|
36430
|
+
|| E' WHERE ord.id = ANY(v_kand) AND public.logistics_order_released(ord.order_number);\n'
|
|
36431
|
+
|| E' SELECT min(d) INTO v_pickday FROM (');
|
|
36432
|
+
n := regexp_replace(n, 'public\.logistics_order_is_topick\(ord\.id, ord\.order_number\)\s+AND NOT public\.logistics_order_handled\(ord\.id\)\s+AND public\.logistics_order_released\(ord\.order_number\)',
|
|
36433
|
+
'ord.id = ANY(v_rel)', 'g');
|
|
36434
|
+
n := regexp_replace(n, 'public\.logistics_order_is_topick\(ord\.id, ord\.order_number\)\s+AND NOT public\.logistics_order_handled\(ord\.id\)\s+AND \(v_forced IS NOT NULL OR public\.logistics_order_released\(ord\.order_number\)\)',
|
|
36435
|
+
'ord.id = ANY(v_kand) AND (v_forced IS NOT NULL OR ord.id = ANY(v_rel))', 'g');
|
|
36436
|
+
-- de eerste vervanging hierboven mag de nieuwe v_kand-berekening niet raken: die heeft geen released-regel erachter.
|
|
36437
|
+
n := replace(n, 'v_breakdown := public.pick_cart_breakdown(r_unit.lead_id);', 'v_breakdown := public.logistics_pick_cart_breakdown_fast(r_unit.lead_id);');
|
|
36438
|
+
EXECUTE n;
|
|
36439
|
+
END IF;
|
|
36440
|
+
|
|
36441
|
+
-- Achterstand
|
|
36442
|
+
d := pg_get_functiondef('public.logistics_sync_pick_queue_backlog()'::regprocedure);
|
|
36443
|
+
IF position('v_bl uuid[]' IN d) = 0 THEN
|
|
36444
|
+
n := replace(d, 'v_ins integer := 0; v_upd integer := 0; v_orders integer := 0;',
|
|
36445
|
+
'v_ins integer := 0; v_upd integer := 0; v_orders integer := 0; v_bl uuid[];');
|
|
36446
|
+
n := replace(n, E' FOR r_unit IN\n WITH k AS (',
|
|
36447
|
+
E' -- 1.0.208: achterstand in één keer voor alle orders (zelfde regel als logistics_order_is_backlog).\n'
|
|
36448
|
+
|| E' SELECT coalesce(array_agg(b.order_id), ''{}'') INTO v_bl\n'
|
|
36449
|
+
|| E' FROM public.logistics_order_backlog_info_many(ARRAY(SELECT o.id FROM public.orders o WHERE o.order_number IS NOT NULL)) b\n'
|
|
36450
|
+
|| E' JOIN public.orders o ON o.id = b.order_id\n'
|
|
36451
|
+
|| E' WHERE b.info IS NOT NULL AND (b.info->>''dagen'')::int <= v_max AND public.logistics_order_released(o.order_number);\n'
|
|
36452
|
+
|| E' FOR r_unit IN\n WITH k AS (');
|
|
36453
|
+
n := replace(n, 'public.logistics_order_is_backlog(o.id)', 'o.id = ANY(v_bl)');
|
|
36454
|
+
n := replace(n, 'v_breakdown := public.pick_cart_breakdown(r_unit.lead_id);', 'v_breakdown := public.logistics_pick_cart_breakdown_fast(r_unit.lead_id);');
|
|
36455
|
+
EXECUTE n;
|
|
36456
|
+
END IF;
|
|
36457
|
+
END $do$;
|
|
36458
|
+
|
|
36459
|
+
DO $do$
|
|
36460
|
+
DECLARE d text; n text;
|
|
36461
|
+
BEGIN
|
|
36462
|
+
d := pg_get_functiondef('public.logistics_cart_plan_status_core_v152(text)'::regprocedure);
|
|
36463
|
+
n := replace(d, 'public.logistics_cart_plan_status_core_v152(', 'public.logistics_cart_plan_status_slim(');
|
|
36464
|
+
n := replace(n, '''logistics_cart_plan_status_core_v152''', '''logistics_cart_plan_status_slim''');
|
|
36465
|
+
n := replace(n, 'public.logistics_cart_json_fixed(c)',
|
|
36466
|
+
'c || coalesce(public.logistics_cart_fixed_numbering(nullif(c->>''cartId'', '''')::uuid), ''{}''::jsonb)');
|
|
36467
|
+
IF position('logistics_cart_json_fixed' IN n) > 0 THEN RAISE EXCEPTION 'vervanging json_fixed mislukt'; END IF;
|
|
36468
|
+
EXECUTE n;
|
|
36469
|
+
|
|
36470
|
+
d := pg_get_functiondef('public.logistics_pick_cart_breakdown_fast(uuid)'::regprocedure);
|
|
36471
|
+
IF position('logistics_cart_plan_status_slim' IN d) = 0 THEN
|
|
36472
|
+
EXECUTE replace(d, 'v_status := public.logistics_cart_plan_status_core(v_ref);', 'v_status := public.logistics_cart_plan_status_slim(v_ref);');
|
|
36473
|
+
END IF;
|
|
36474
|
+
END $do$;
|
|
36475
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_plan_status_slim(text) TO service_role;
|
|
36476
|
+
|
|
36477
|
+
DO $do$
|
|
36478
|
+
DECLARE d text; n text; v_extra text := ' || jsonb_build_object(''cartCount'', 1, ''perCart'', true, ''pickMode'', ''cart'', ''cartPlanReady'', true)';
|
|
36479
|
+
BEGIN
|
|
36480
|
+
d := pg_get_functiondef('public.logistics_sync_pick_queue_backlog()'::regprocedure);
|
|
36481
|
+
IF position('''cartPlanReady'', true)' IN d) = 0 THEN
|
|
36482
|
+
n := replace(d, E'COALESCE(q.payload, ''{}''::jsonb) || v_payload);', E'COALESCE(q.payload, ''{}''::jsonb) || v_payload' || v_extra || ');');
|
|
36483
|
+
IF n = d THEN RAISE EXCEPTION 'patroon achterstand niet gevonden'; END IF;
|
|
36484
|
+
EXECUTE n;
|
|
36485
|
+
END IF;
|
|
36486
|
+
d := pg_get_functiondef('public.logistics_sync_pick_queue_core()'::regprocedure);
|
|
36487
|
+
IF position('''cartPlanReady'', true)' IN d) = 0 THEN
|
|
36488
|
+
n := replace(d, E'COALESCE(v_wait, v_due, q.due_at), COALESCE(q.payload, ''{}''::jsonb) || v_cart_payload);',
|
|
36489
|
+
E'COALESCE(v_wait, v_due, q.due_at), COALESCE(q.payload, ''{}''::jsonb) || v_cart_payload' || v_extra || ');');
|
|
36490
|
+
IF n = d THEN RAISE EXCEPTION 'patroon kern niet gevonden'; END IF;
|
|
36491
|
+
EXECUTE n;
|
|
36492
|
+
END IF;
|
|
36493
|
+
END $do$;
|
|
36494
|
+
|
|
36495
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_verouderd_core(p_cart_id uuid)
|
|
36496
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SET search_path TO 'public' AS $$
|
|
36497
|
+
DECLARE v_nr text; v_n int;
|
|
36498
|
+
BEGIN
|
|
36499
|
+
IF p_cart_id IS NULL THEN RETURN NULL; END IF;
|
|
36500
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'order_items' AND column_name = 'quarantined_at') THEN
|
|
36501
|
+
RETURN NULL;
|
|
36502
|
+
END IF;
|
|
36503
|
+
SELECT count(*) INTO v_n FROM public.order_cart_items ci JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
36504
|
+
WHERE ci.cart_id = p_cart_id AND oi.quarantined_at IS NOT NULL;
|
|
36505
|
+
IF coalesce(v_n, 0) = 0 THEN RETURN NULL; END IF;
|
|
36506
|
+
SELECT cart_number::text INTO v_nr FROM public.order_carts WHERE id = p_cart_id;
|
|
36507
|
+
RETURN jsonb_build_object('verouderd', true, 'regelsInQuarantaine', v_n,
|
|
36508
|
+
'blokkade', jsonb_build_object('code', 'kar_verouderd',
|
|
36509
|
+
'tekst', format('Kar %s heeft %s regel(s) die Verkoop in quarantaine heeft gezet. Deel de niet-geprinte karren opnieuw in.', coalesce(v_nr, '?'), v_n)));
|
|
36510
|
+
END $$;
|
|
36511
|
+
GRANT EXECUTE ON FUNCTION public.logistics_cart_verouderd_core(uuid) TO service_role;
|
|
36512
|
+
|
|
36513
|
+
CREATE OR REPLACE FUNCTION public.logistics_cart_te_hoog(p_cart_id uuid)
|
|
36514
|
+
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36515
|
+
DECLARE k jsonb; v jsonb;
|
|
36516
|
+
BEGIN
|
|
36517
|
+
PERFORM public.logistics_acc_guard('ingelogd', 'logistics_cart_te_hoog');
|
|
36518
|
+
k := public.logistics_cart_capaciteit_core(p_cart_id);
|
|
36519
|
+
IF k IS NOT NULL AND coalesce((k->>'teHoog')::boolean, false) THEN
|
|
36520
|
+
RETURN jsonb_build_object('teHoog', true, 'blokkade', k->'blokkade');
|
|
36521
|
+
END IF;
|
|
36522
|
+
-- 1.0.208: verouderde kar (regels in quarantaine) krijgt ook geen stickers/verzendbrief/pakbon.
|
|
36523
|
+
v := public.logistics_cart_verouderd_core(p_cart_id);
|
|
36524
|
+
IF v IS NOT NULL THEN
|
|
36525
|
+
RETURN jsonb_build_object('teHoog', false, 'indelingVerouderd', true, 'blokkade', v->'blokkade');
|
|
36526
|
+
END IF;
|
|
36527
|
+
RETURN jsonb_build_object('teHoog', false, 'blokkade', NULL);
|
|
36528
|
+
END $$;
|
|
36529
|
+
|
|
36530
|
+
DO $do$
|
|
36531
|
+
DECLARE d text; n text;
|
|
36532
|
+
BEGIN
|
|
36533
|
+
d := pg_get_functiondef('public.logistics_cart_platen_verrijk(jsonb)'::regprocedure);
|
|
36534
|
+
IF position('logistics_cart_verouderd_core' IN d) = 0 THEN
|
|
36535
|
+
n := replace(d,
|
|
36536
|
+
$a$ || CASE WHEN k IS NOT NULL THEN jsonb_build_object('teHoog', coalesce(k->'teHoog', 'false'::jsonb), 'blokkade', k->'blokkade')$a$,
|
|
36537
|
+
$a$ || CASE WHEN v_id IS NOT NULL AND public.logistics_cart_verouderd_core(v_id) IS NOT NULL
|
|
36538
|
+
AND NOT coalesce((k->>'teHoog')::boolean, false)
|
|
36539
|
+
THEN jsonb_build_object('teHoog', false, 'indelingVerouderd', true, 'blokkade', public.logistics_cart_verouderd_core(v_id)->'blokkade')
|
|
36540
|
+
WHEN k IS NOT NULL THEN jsonb_build_object('teHoog', coalesce(k->'teHoog', 'false'::jsonb), 'blokkade', k->'blokkade')$a$);
|
|
36541
|
+
IF n = d THEN RAISE EXCEPTION 'patroon platen_verrijk niet gevonden'; END IF;
|
|
36542
|
+
EXECUTE n;
|
|
36543
|
+
END IF;
|
|
36544
|
+
END $do$;
|
|
36545
|
+
|
|
36546
|
+
CREATE OR REPLACE FUNCTION public.logistics_order_indeling_verouderd_core(p_order_id uuid)
|
|
36547
|
+
RETURNS jsonb LANGUAGE sql STABLE SET search_path TO 'public' AS $$
|
|
36548
|
+
WITH a AS (
|
|
36549
|
+
SELECT oi.id, coalesce(oi.product_name, 'regel') naam, ci.cart_id,
|
|
36550
|
+
(oi.plants_per_crate IS DISTINCT FROM ci.plants_per_crate
|
|
36551
|
+
OR oi.crates_per_layer IS DISTINCT FROM ci.crates_per_layer
|
|
36552
|
+
OR oi.layers_per_cart IS DISTINCT FROM ci.layers_per_cart) afwijkend
|
|
36553
|
+
FROM public.order_items oi
|
|
36554
|
+
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
36555
|
+
WHERE oi.order_id = p_order_id AND oi.packing_locked_at IS NOT NULL AND oi.quarantined_at IS NULL),
|
|
36556
|
+
q AS (
|
|
36557
|
+
SELECT DISTINCT ci.cart_id, coalesce(oi.product_name, 'regel') naam
|
|
36558
|
+
FROM public.order_items oi
|
|
36559
|
+
JOIN public.order_cart_items ci ON ci.order_item_id = oi.id
|
|
36560
|
+
JOIN logistics_active.order_carts c ON c.id = ci.cart_id
|
|
36561
|
+
WHERE oi.order_id = p_order_id AND oi.quarantined_at IS NOT NULL)
|
|
36562
|
+
SELECT CASE
|
|
36563
|
+
WHEN EXISTS (SELECT 1 FROM q) THEN jsonb_build_object(
|
|
36564
|
+
'verouderd', true, 'blokkeert', true, 'reden', 'quarantaine',
|
|
36565
|
+
'producten', (SELECT to_jsonb(array_agg(DISTINCT naam)) FROM q),
|
|
36566
|
+
'karren', (SELECT to_jsonb(array_agg(DISTINCT cart_id)) FROM q),
|
|
36567
|
+
'vastliggendeKarren', (SELECT count(DISTINCT q2.cart_id) FROM q q2 WHERE public.logistics_cart_vast_core(q2.cart_id)),
|
|
36568
|
+
'tekst', 'Er staan regels op de karren die Verkoop in quarantaine heeft gezet. Deel de niet-geprinte karren opnieuw in.')
|
|
36569
|
+
WHEN (SELECT bool_or(afwijkend) FROM a) THEN jsonb_build_object(
|
|
36570
|
+
'verouderd', true, 'blokkeert', false, 'reden', 'belading',
|
|
36571
|
+
'producten', (SELECT to_jsonb(array_agg(DISTINCT naam) FILTER (WHERE afwijkend)) FROM a),
|
|
36572
|
+
'vastliggendeKarren', (SELECT count(DISTINCT a2.cart_id) FROM a a2 WHERE public.logistics_cart_vast_core(a2.cart_id)),
|
|
36573
|
+
'tekst', 'De belading is gewijzigd, maar de karindeling is nog oud. Deel de niet-geprinte karren opnieuw in.')
|
|
36574
|
+
ELSE NULL END
|
|
36575
|
+
$$;
|
|
36576
|
+
|
|
36577
|
+
CREATE OR REPLACE FUNCTION public.logistics_install_check_208()
|
|
36578
|
+
RETURNS TABLE(punt text, ok boolean, uitleg text) LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $$
|
|
36579
|
+
SELECT 'vulgraad per kar', to_regprocedure('public.logistics_cart_vulgraad_core(uuid)') IS NOT NULL, 'Vulgraad = som per regel van lagen ÷ lagen per kar (Floriday)'
|
|
36580
|
+
UNION ALL SELECT 'karTekst', to_regprocedure('public.logistics_kar_tekst(text,numeric,numeric)') IS NOT NULL, 'Tekst per kar: lagen · ladingdrager + platen · %'
|
|
36581
|
+
UNION ALL SELECT 'ladingdrager-vertaling', to_regprocedure('public.logistics_ladingdrager_resolve(text)') IS NOT NULL, 'Floriday- en Beheer-codes'
|
|
36582
|
+
UNION ALL SELECT 'vertaling eenduidig', NOT EXISTS (SELECT 1 FROM public.logistics_floriday_carrier_map GROUP BY floriday_code HAVING count(*) > 1), 'Elke Floriday-code naar precies één Beheer-type'
|
|
36583
|
+
UNION ALL SELECT 'hoofdverpakking', to_regprocedure('public.logistics_product_hoofdverpakking(uuid)') IS NOT NULL, 'Ladingdrager uit hoofdverpakking'
|
|
36584
|
+
UNION ALL SELECT 'pickwachtrij set-based', position('v_kand' IN pg_get_functiondef('public.logistics_sync_pick_queue_core()'::regprocedure)) > 0
|
|
36585
|
+
AND position('v_bl' IN pg_get_functiondef('public.logistics_sync_pick_queue_backlog()'::regprocedure)) > 0, 'Controles één keer voor alle orders'
|
|
36586
|
+
UNION ALL SELECT 'verouderde kar', to_regprocedure('public.logistics_cart_verouderd_core(uuid)') IS NOT NULL
|
|
36587
|
+
AND position('logistics_cart_verouderd_core' IN pg_get_functiondef('public.logistics_cart_te_hoog(uuid)'::regprocedure)) > 0, 'Kar met quarantaineregels krijgt geen documenten'
|
|
36588
|
+
UNION ALL SELECT 'guards 1.0.208', position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_ladingdrager_resolve(text)'::regprocedure)) > 0
|
|
36589
|
+
AND position('logistics_acc_guard' IN pg_get_functiondef('public.logistics_product_hoofdverpakking(uuid)'::regprocedure)) > 0, 'Nieuwe functies controleren de aanroeper'
|
|
36590
|
+
$$;
|
|
36591
|
+
GRANT EXECUTE ON FUNCTION public.logistics_install_check_208() TO authenticated, service_role;
|