@flowselections/floriday-voorraad 1.0.110 → 1.0.115

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.
Files changed (44) hide show
  1. package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
  2. package/dist-lib/components/voorraad/ArtikelWizard.js +63 -7
  3. package/dist-lib/components/voorraad/FustenPage.d.ts.map +1 -1
  4. package/dist-lib/components/voorraad/FustenPage.js +10 -6
  5. package/dist-lib/components/voorraad/PriceStatusBadge.d.ts.map +1 -1
  6. package/dist-lib/components/voorraad/PriceStatusBadge.js +6 -1
  7. package/dist-lib/components/voorraad/PublishProgressCard.d.ts +5 -0
  8. package/dist-lib/components/voorraad/PublishProgressCard.d.ts.map +1 -1
  9. package/dist-lib/components/voorraad/PublishProgressCard.js +16 -1
  10. package/dist-lib/components/voorraad/VoorraadPage.d.ts +13 -0
  11. package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
  12. package/dist-lib/components/voorraad/VoorraadPage.js +36 -54
  13. package/dist-lib/hooks/useNoPriceProducts.d.ts +10 -0
  14. package/dist-lib/hooks/useNoPriceProducts.d.ts.map +1 -0
  15. package/dist-lib/hooks/useNoPriceProducts.js +56 -0
  16. package/dist-lib/hooks/useStockPushJobs.d.ts.map +1 -1
  17. package/dist-lib/hooks/useStockPushJobs.js +6 -1
  18. package/dist-lib/hooks/useStockSyncHealth.d.ts.map +1 -1
  19. package/dist-lib/hooks/useStockSyncHealth.js +2 -9
  20. package/dist-lib/hooks/useVoorraadData.d.ts.map +1 -1
  21. package/dist-lib/hooks/useVoorraadData.js +45 -24
  22. package/dist-lib/integrations/supabase/types.d.ts +818 -122
  23. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  24. package/dist-lib/integrations/supabase/types.js +1 -0
  25. package/dist-lib/lib/__tests__/fust-dimensions.test.d.ts +2 -0
  26. package/dist-lib/lib/__tests__/fust-dimensions.test.d.ts.map +1 -0
  27. package/dist-lib/lib/__tests__/fust-dimensions.test.js +27 -0
  28. package/dist-lib/lib/__tests__/publish-114.test.d.ts +2 -0
  29. package/dist-lib/lib/__tests__/publish-114.test.d.ts.map +1 -0
  30. package/dist-lib/lib/__tests__/publish-114.test.js +31 -0
  31. package/dist-lib/lib/__tests__/request-guard.test.d.ts +2 -0
  32. package/dist-lib/lib/__tests__/request-guard.test.d.ts.map +1 -0
  33. package/dist-lib/lib/__tests__/request-guard.test.js +50 -0
  34. package/dist-lib/lib/fusten.d.ts +14 -3
  35. package/dist-lib/lib/fusten.d.ts.map +1 -1
  36. package/dist-lib/lib/fusten.js +38 -7
  37. package/dist-lib/lib/publish-errors.d.ts +6 -1
  38. package/dist-lib/lib/publish-errors.d.ts.map +1 -1
  39. package/dist-lib/lib/publish-errors.js +22 -2
  40. package/dist-lib/lib/request-guard.d.ts +46 -0
  41. package/dist-lib/lib/request-guard.d.ts.map +1 -0
  42. package/dist-lib/lib/request-guard.js +100 -0
  43. package/package.json +1 -1
  44. package/sql/floriday-voorraad-schema.sql +186 -27
@@ -1,4 +1,4 @@
1
- -- @flowselections/floriday-voorraad 1.0.109 – volledig schema (idempotent, geen gegevens).
1
+ -- @flowselections/floriday-voorraad 1.0.112 – volledig schema (idempotent, geen gegevens).
2
2
  -- Gegenereerd uit de database met scripts/generate-voorraad-schema.py. Niet met de hand wijzigen.
3
3
  -- Volgorde 20. Ontbrekende tabellen van andere modules worden overgeslagen met een NOTICE; draai opnieuw na die module.
4
4
  -- De statuscontrole van floriday_continuous_stock_queue is van Voorraad en wordt hier opnieuw gemaakt.
@@ -209,6 +209,7 @@ ALTER TABLE public.fust_types ADD COLUMN IF NOT EXISTS length_mm integer;
209
209
  ALTER TABLE public.fust_types ADD COLUMN IF NOT EXISTS width_mm integer;
210
210
  ALTER TABLE public.fust_types ADD COLUMN IF NOT EXISTS height_mm integer;
211
211
  ALTER TABLE public.fust_types ADD COLUMN IF NOT EXISTS capacity_units integer;
212
+ ALTER TABLE public.fust_types ADD COLUMN IF NOT EXISTS merged_into uuid;
212
213
 
213
214
  -- inventory_recompute_limits
214
215
  CREATE TABLE IF NOT EXISTS public.inventory_recompute_limits ();
@@ -4076,9 +4077,10 @@ CREATE OR REPLACE FUNCTION public.fust_types_duplicate_guard()
4076
4077
  SET search_path TO 'public'
4077
4078
  AS $function$
4078
4079
  BEGIN
4079
- IF EXISTS (SELECT 1 FROM public.fust_types f
4080
+ IF NEW.merged_into IS NULL AND EXISTS (SELECT 1 FROM public.fust_types f
4080
4081
  WHERE f.fust_key = NEW.fust_key
4081
4082
  AND f.connection_id IS NOT DISTINCT FROM NEW.connection_id
4083
+ AND f.merged_into IS NULL
4082
4084
  AND f.id <> NEW.id) THEN
4083
4085
  RAISE EXCEPTION 'Dit fusttype bestaat al (fustcode %).', NEW.fust_key USING ERRCODE = '23505';
4084
4086
  END IF;
@@ -7739,6 +7741,92 @@ END $function$
7739
7741
  REVOKE ALL ON FUNCTION voorraad_alert_floriday_not_updated(text,numeric,uuid,uuid) FROM PUBLIC;
7740
7742
  REVOKE ALL ON FUNCTION voorraad_alert_floriday_not_updated(text,numeric,uuid,uuid) FROM anon;
7741
7743
  GRANT EXECUTE ON FUNCTION voorraad_alert_floriday_not_updated(text,numeric,uuid,uuid) TO service_role;
7744
+ CREATE OR REPLACE FUNCTION public.voorraad_article_vbn(p_product_id uuid)
7745
+ RETURNS jsonb
7746
+ LANGUAGE plpgsql
7747
+ STABLE SECURITY DEFINER
7748
+ SET search_path TO 'public'
7749
+ AS $function$
7750
+ -- Leesfunctie voor de Engine: VBN-kenmerken en gekozen fust van één artikel, live gelezen, met bron.
7751
+ -- Volgorde: handmatige afwijking op products (plant_height_cm, fust_type_id) → lokale wizardgegevens
7752
+ -- (custom_fields.floriday_payload, als niet gekoppeld of nog niet doorgegeven) → Floriday-cache → lokale wizardgegevens.
7753
+ DECLARE
7754
+ v_p record; v_pl jsonb; v_cache jsonb; v_dirty boolean; v_src text;
7755
+ v_feat jsonb := '{}'::jsonb; v_vbn text; v_pack jsonb; v_fust_code text; v_fust_custom text;
7756
+ v_s02 text; v_s02_src text; v_fust jsonb; v_fust_src text; v_ft uuid;
7757
+ BEGIN
7758
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_article_vbn');
7759
+ SELECT id, custom_fields, floriday_trade_item_id, plant_height_cm, fust_type_id INTO v_p
7760
+ FROM public.products WHERE id = p_product_id;
7761
+ IF NOT FOUND THEN RETURN jsonb_build_object('ok', false, 'reason', 'Artikel niet gevonden'); END IF;
7762
+
7763
+ v_pl := v_p.custom_fields->'floriday_payload';
7764
+ v_dirty := COALESCE((v_p.custom_fields->'floriday_sync'->>'dirty')::boolean, false);
7765
+ IF v_p.floriday_trade_item_id IS NOT NULL THEN
7766
+ SELECT c.data INTO v_cache FROM public.floriday_trade_items_cache c
7767
+ WHERE c.floriday_id = v_p.floriday_trade_item_id::text AND COALESCE(c.is_deleted,false) = false
7768
+ ORDER BY (c.connection_id IS NOT DISTINCT FROM (SELECT s.connection_id FROM public.get_stock_context() s)) DESC, c.fetched_at DESC NULLS LAST LIMIT 1;
7769
+ END IF;
7770
+
7771
+ IF v_pl IS NOT NULL AND (v_cache IS NULL OR v_dirty) THEN
7772
+ v_src := 'wizard';
7773
+ v_vbn := v_pl->>'vbnCode';
7774
+ v_feat := COALESCE(v_pl->'features', '{}'::jsonb);
7775
+ SELECT e INTO v_pack FROM jsonb_array_elements(COALESCE(v_pl->'packingConfigurations','[]')) e
7776
+ ORDER BY (COALESCE((e->>'isPrimary')::boolean,(e->>'primary')::boolean,false)) DESC LIMIT 1;
7777
+ IF v_pack IS NOT NULL THEN
7778
+ IF upper(COALESCE(v_pack->>'source','VBN')) = 'VBN' THEN v_fust_code := v_pack->>'packagingType';
7779
+ ELSE v_fust_custom := v_pack->>'packagingType'; END IF;
7780
+ END IF;
7781
+ ELSIF v_cache IS NOT NULL THEN
7782
+ v_src := 'floriday';
7783
+ v_vbn := COALESCE(v_cache->>'vbnProductCode', v_cache->>'vbnCode');
7784
+ SELECT COALESCE(jsonb_object_agg(e->>'vbnCode', e->>'vbnValueCode'), '{}'::jsonb) INTO v_feat
7785
+ FROM jsonb_array_elements(CASE WHEN jsonb_typeof(v_cache->'characteristics')='array' THEN v_cache->'characteristics' ELSE '[]' END) e
7786
+ WHERE e->>'vbnCode' IS NOT NULL;
7787
+ SELECT e INTO v_pack FROM jsonb_array_elements(CASE WHEN jsonb_typeof(v_cache->'packingConfigurations')='array' THEN v_cache->'packingConfigurations' ELSE '[]' END) e
7788
+ ORDER BY (COALESCE((e->>'primary')::boolean,(e->>'isPrimary')::boolean,false)) DESC LIMIT 1;
7789
+ IF v_pack IS NOT NULL THEN
7790
+ v_fust_code := v_pack->'package'->>'vbnPackageCode';
7791
+ v_fust_custom := v_pack->'package'->>'customPackageId';
7792
+ END IF;
7793
+ ELSE
7794
+ v_src := 'onbekend';
7795
+ END IF;
7796
+
7797
+ -- S02 (planthoogte inclusief pot)
7798
+ IF v_p.plant_height_cm IS NOT NULL THEN v_s02 := v_p.plant_height_cm::text; v_s02_src := 'handmatig';
7799
+ ELSIF v_feat ? 'S02' THEN v_s02 := v_feat->>'S02'; v_s02_src := v_src;
7800
+ END IF;
7801
+
7802
+ -- Fust
7803
+ IF v_p.fust_type_id IS NOT NULL THEN v_ft := v_p.fust_type_id; v_fust_src := 'handmatig';
7804
+ ELSIF v_fust_code IS NOT NULL OR v_fust_custom IS NOT NULL THEN
7805
+ SELECT f.id INTO v_ft FROM public.fust_types f
7806
+ WHERE f.connection_id IS NULL
7807
+ AND ((v_fust_code IS NOT NULL AND f.fust_key = 'vbn:' || v_fust_code)
7808
+ OR (v_fust_custom IS NOT NULL AND f.custom_package_id = v_fust_custom))
7809
+ ORDER BY f.created_at, f.id LIMIT 1;
7810
+ v_fust_src := v_src;
7811
+ END IF;
7812
+ IF v_ft IS NOT NULL THEN
7813
+ SELECT to_jsonb(d) INTO v_fust FROM public.voorraad_fust_dimensions() d WHERE d.fust_type_id = v_ft;
7814
+ END IF;
7815
+ IF v_fust IS NULL AND (v_fust_code IS NOT NULL OR v_fust_custom IS NOT NULL) THEN
7816
+ v_fust := jsonb_build_object('vbn_code', v_fust_code, 'custom_package_id', v_fust_custom, 'fust_type_id', NULL);
7817
+ END IF;
7818
+
7819
+ RETURN jsonb_build_object(
7820
+ 'ok', true, 'product_id', v_p.id, 'source', v_src, 'vbn_code', v_vbn,
7821
+ 'features', v_feat,
7822
+ 's02', v_s02, 's02_source', v_s02_src,
7823
+ 'fust', v_fust, 'fust_source', v_fust_src);
7824
+ END $function$
7825
+ ;
7826
+ REVOKE ALL ON FUNCTION voorraad_article_vbn(uuid) FROM PUBLIC;
7827
+ REVOKE ALL ON FUNCTION voorraad_article_vbn(uuid) FROM anon;
7828
+ GRANT EXECUTE ON FUNCTION voorraad_article_vbn(uuid) TO authenticated;
7829
+ GRANT EXECUTE ON FUNCTION voorraad_article_vbn(uuid) TO service_role;
7742
7830
  CREATE OR REPLACE FUNCTION public.voorraad_can_write()
7743
7831
  RETURNS boolean
7744
7832
  LANGUAGE sql
@@ -7977,6 +8065,66 @@ REVOKE ALL ON FUNCTION voorraad_correctie_1098(boolean) FROM PUBLIC;
7977
8065
  REVOKE ALL ON FUNCTION voorraad_correctie_1098(boolean) FROM anon;
7978
8066
  GRANT EXECUTE ON FUNCTION voorraad_correctie_1098(boolean) TO authenticated;
7979
8067
  GRANT EXECUTE ON FUNCTION voorraad_correctie_1098(boolean) TO service_role;
8068
+ CREATE OR REPLACE FUNCTION public.voorraad_correctie_1112(p_uitvoeren boolean DEFAULT false)
8069
+ RETURNS jsonb
8070
+ LANGUAGE plpgsql
8071
+ SECURITY DEFINER
8072
+ SET search_path TO 'public'
8073
+ AS $function$
8074
+ -- Samenvoegen dubbele fusttypen (zelfde fust_key, connection_id NULL, niet samengevoegd).
8075
+ -- Per fust_key: bewaar de rij met de meeste mutaties; maten aanvullen; minimum = hoogste;
8076
+ -- mutaties overzetten op id; voorraad optellen; andere rij in_use=false, stock 0, merged_into = bewaarde rij. Nooit verwijderen.
8077
+ DECLARE v jsonb; v_keep record; v_oth record; v_moved int; v_total int := 0;
8078
+ BEGIN
8079
+ PERFORM public.voorraad_vereis('server', 'voorraad_correctie_1112');
8080
+ WITH m AS (
8081
+ SELECT f.*, (SELECT count(*) FROM public.fust_stock_mutations x WHERE x.fust_type_id = f.id) AS muts,
8082
+ count(*) OVER (PARTITION BY f.fust_key) AS n
8083
+ FROM public.fust_types f WHERE f.connection_id IS NULL AND f.merged_into IS NULL
8084
+ ), q AS (
8085
+ SELECT m.*, row_number() OVER (PARTITION BY fust_key ORDER BY muts DESC, created_at, id) AS rn FROM m WHERE n > 1
8086
+ )
8087
+ SELECT COALESCE(jsonb_agg(jsonb_build_object(
8088
+ 'fust_key', k.fust_key, 'naam', btrim(k.name),
8089
+ 'bewaren', jsonb_build_object('id', k.id, 'mutaties', k.muts, 'voorraad', k.stock),
8090
+ 'samenvoegen', (SELECT jsonb_agg(jsonb_build_object('id', q2.id, 'mutaties', q2.muts, 'voorraad', q2.stock)) FROM q q2 WHERE q2.fust_key = k.fust_key AND q2.rn > 1),
8091
+ 'na_samenvoegen', jsonb_build_object(
8092
+ 'voorraad', (SELECT sum(q3.stock) FROM q q3 WHERE q3.fust_key = k.fust_key),
8093
+ 'mutaties', (SELECT sum(q4.muts) FROM q q4 WHERE q4.fust_key = k.fust_key))
8094
+ ) ORDER BY k.name), '[]'::jsonb) INTO v
8095
+ FROM q k WHERE k.rn = 1;
8096
+
8097
+ IF p_uitvoeren THEN
8098
+ FOR v_keep IN SELECT (e->'bewaren'->>'id')::uuid AS keep_id, e->'samenvoegen' AS others FROM jsonb_array_elements(v) e LOOP
8099
+ PERFORM 1 FROM public.fust_types f WHERE f.id = v_keep.keep_id FOR UPDATE;
8100
+ FOR v_oth IN SELECT f.* FROM public.fust_types f
8101
+ WHERE f.id IN (SELECT (x->>'id')::uuid FROM jsonb_array_elements(v_keep.others) x)
8102
+ ORDER BY f.id FOR UPDATE LOOP
8103
+ UPDATE public.fust_stock_mutations SET fust_type_id = v_keep.keep_id WHERE fust_type_id = v_oth.id;
8104
+ GET DIAGNOSTICS v_moved = ROW_COUNT; v_total := v_total + v_moved;
8105
+ UPDATE public.fust_types k SET
8106
+ stock = k.stock + v_oth.stock,
8107
+ minimum_stock = GREATEST(k.minimum_stock, v_oth.minimum_stock),
8108
+ length_mm = COALESCE(k.length_mm, v_oth.length_mm),
8109
+ width_mm = COALESCE(k.width_mm, v_oth.width_mm),
8110
+ height_mm = COALESCE(k.height_mm, v_oth.height_mm),
8111
+ notes = COALESCE(k.notes, v_oth.notes)
8112
+ WHERE k.id = v_keep.keep_id;
8113
+ UPDATE public.fust_types SET stock = 0, in_use = false, used_by_count = 0, merged_into = v_keep.keep_id
8114
+ WHERE id = v_oth.id;
8115
+ END LOOP;
8116
+ END LOOP;
8117
+ END IF;
8118
+
8119
+ INSERT INTO public.voorraad_correcties(correctie, uitgevoerd_door, proef, aantallen, hash_ok)
8120
+ VALUES ('voorraad_correctie_1112', COALESCE(auth.uid()::text, session_user::text), NOT p_uitvoeren,
8121
+ jsonb_build_object('fusttypen', jsonb_array_length(v), 'mutaties_overgezet', v_total), true);
8122
+ RETURN jsonb_build_object('ok', true, 'proef', NOT p_uitvoeren, 'fusten', v, 'mutaties_overgezet', v_total);
8123
+ END $function$
8124
+ ;
8125
+ REVOKE ALL ON FUNCTION voorraad_correctie_1112(boolean) FROM PUBLIC;
8126
+ REVOKE ALL ON FUNCTION voorraad_correctie_1112(boolean) FROM anon;
8127
+ GRANT EXECUTE ON FUNCTION voorraad_correctie_1112(boolean) TO service_role;
7980
8128
  CREATE OR REPLACE FUNCTION public.voorraad_correctie_status(p_correctie text DEFAULT '1098'::text)
7981
8129
  RETURNS jsonb
7982
8130
  LANGUAGE plpgsql
@@ -8061,33 +8209,42 @@ CREATE OR REPLACE FUNCTION public.voorraad_fust_dimensions()
8061
8209
  STABLE SECURITY DEFINER
8062
8210
  SET search_path TO 'public'
8063
8211
  AS $function$
8064
- -- Leesfunctie voor de Engine: fustcode en maten per fusttype.
8065
- -- Maten: eerst Floricode (floricode_packaging_types, eigenaar Floriday-auth), anders handmatig ingevoerd, anders leeg (nooit standaardwaarden).
8212
+ -- Leesfunctie voor de Engine. Maten: Floricode → Floriday custom package (floriday_packings_cache) → handmatig → leeg (nooit standaardwaarden).
8066
8213
  DECLARE v_fc boolean := to_regprocedure('public.floricode_packaging_types()') IS NOT NULL;
8067
8214
  BEGIN
8068
8215
  PERFORM public.voorraad_vereis('ingelogd', 'voorraad_fust_dimensions');
8069
- IF v_fc THEN
8070
- RETURN QUERY
8071
- WITH fc AS (SELECT DISTINCT ON (c.code) c.code, c.name, c.length_mm, c.width_mm, c.height_mm
8072
- FROM public.floricode_packaging_types() c ORDER BY c.code, c.expiry_date DESC NULLS FIRST)
8073
- SELECT f.id, f.fust_key, f.vbn_code, f.name, fc.name,
8074
- COALESCE(fc.length_mm, f.length_mm::numeric), COALESCE(fc.width_mm, f.width_mm::numeric), COALESCE(fc.height_mm, f.height_mm::numeric),
8075
- CASE WHEN fc.length_mm IS NOT NULL OR fc.width_mm IS NOT NULL OR fc.height_mm IS NOT NULL THEN 'floricode'
8076
- WHEN f.length_mm IS NOT NULL OR f.width_mm IS NOT NULL OR f.height_mm IS NOT NULL THEN 'handmatig'
8077
- ELSE 'onbekend' END
8078
- FROM public.fust_types f
8079
- LEFT JOIN fc ON f.vbn_code IS NOT NULL AND fc.code = f.vbn_code::text
8080
- WHERE f.connection_id IS NULL
8081
- ORDER BY f.name;
8082
- ELSE
8083
- RETURN QUERY
8084
- SELECT f.id, f.fust_key, f.vbn_code, f.name, NULL::text,
8085
- f.length_mm::numeric, f.width_mm::numeric, f.height_mm::numeric,
8086
- CASE WHEN f.length_mm IS NOT NULL OR f.width_mm IS NOT NULL OR f.height_mm IS NOT NULL THEN 'handmatig' ELSE 'onbekend' END
8087
- FROM public.fust_types f
8088
- WHERE f.connection_id IS NULL
8089
- ORDER BY f.name;
8090
- END IF;
8216
+ RETURN QUERY
8217
+ WITH fc AS (
8218
+ SELECT * FROM (SELECT NULL::text code, NULL::text name, NULL::numeric length_mm, NULL::numeric width_mm, NULL::numeric height_mm) z WHERE false
8219
+ ), fcr AS (
8220
+ SELECT x.code, x.name, x.length_mm, x.width_mm, x.height_mm FROM fc x
8221
+ ), cp AS (
8222
+ SELECT DISTINCT ON (p.floriday_id) p.floriday_id,
8223
+ NULLIF(COALESCE(p.data->'dimensions'->>'length', p.data->'dimension'->>'length', p.data->>'lengthMm', p.data->>'length'),'')::numeric AS l,
8224
+ NULLIF(COALESCE(p.data->'dimensions'->>'width', p.data->'dimension'->>'width', p.data->>'widthMm', p.data->>'width'),'')::numeric AS w,
8225
+ NULLIF(COALESCE(p.data->'dimensions'->>'height', p.data->'dimension'->>'height', p.data->>'heightMm', p.data->>'height'),'')::numeric AS h
8226
+ FROM public.floriday_packings_cache p
8227
+ WHERE COALESCE(p.is_deleted,false) = false
8228
+ ORDER BY p.floriday_id, p.updated_at DESC NULLS LAST
8229
+ )
8230
+ SELECT f.id, f.fust_key, f.vbn_code, f.name, d.fc_name,
8231
+ COALESCE(d.fl, cp.l, f.length_mm::numeric),
8232
+ COALESCE(d.fw, cp.w, f.width_mm::numeric),
8233
+ COALESCE(d.fh, cp.h, f.height_mm::numeric),
8234
+ CASE WHEN d.fl IS NOT NULL OR d.fw IS NOT NULL OR d.fh IS NOT NULL THEN 'floricode'
8235
+ WHEN cp.l IS NOT NULL OR cp.w IS NOT NULL OR cp.h IS NOT NULL THEN 'floriday'
8236
+ WHEN f.length_mm IS NOT NULL OR f.width_mm IS NOT NULL OR f.height_mm IS NOT NULL THEN 'handmatig'
8237
+ ELSE 'onbekend' END
8238
+ FROM public.fust_types f
8239
+ LEFT JOIN LATERAL (
8240
+ SELECT c.name AS fc_name, c.length_mm AS fl, c.width_mm AS fw, c.height_mm AS fh
8241
+ FROM public.floricode_packaging_types() c
8242
+ WHERE v_fc AND f.vbn_code IS NOT NULL AND c.code = f.vbn_code::text
8243
+ ORDER BY c.expiry_date DESC NULLS FIRST LIMIT 1
8244
+ ) d ON v_fc
8245
+ LEFT JOIN cp ON f.custom_package_id IS NOT NULL AND cp.floriday_id = f.custom_package_id
8246
+ WHERE f.connection_id IS NULL
8247
+ ORDER BY f.name;
8091
8248
  END $function$
8092
8249
  ;
8093
8250
  REVOKE ALL ON FUNCTION voorraad_fust_dimensions() FROM PUBLIC;
@@ -8211,7 +8368,7 @@ CREATE OR REPLACE FUNCTION public.voorraad_install_check()
8211
8368
  STABLE SECURITY DEFINER
8212
8369
  SET search_path TO 'public'
8213
8370
  AS $function$
8214
- DECLARE v_f text[] := ARRAY['voorraad_reverse_order_mutations','voorraad_withdraw_stock_row','ensure_voorraad_local_context','get_stock_context','voorraad_stock_context_status','voorraad_fcsq_local_guard','_floriday_queue_cleanup_batch','_migrate_rewrite_stock_key','_stock_import_caller','apply_fust_stock_mutation','apply_stock_consumption','apply_stock_reservation','autolink_product_to_floriday','backfill_open_order_reservations','calculate_floriday_desired_stock','calculate_structure_available','canonicalize_trade_item_stock_key','check_product_structure','claim_floriday_base_supply','claim_floriday_stock_queue','cleanup_floriday_stock_queue','cleanup_voorraad_module_history','complete_floriday_base_supply','complete_floriday_stock_queue','complete_floriday_stock_queue_outcome','consume_bom_for_production','consume_order_item','drain_inventory_recompute_queue','enqueue_floriday_continuous_stock','enqueue_floriday_continuous_stock_after_warehouse_preference','enqueue_structure_recompute','ensure_inventory_recompute_drain','ensure_trade_item_stock_row','ensure_trade_item_stock_row_key','fcsq_block_disabled','fcsq_fallback_supersede','fcsq_wake_base_supply','find_trade_item_key','floriday_adopt_connection','floriday_autoheal_connections','floriday_capture_stock_snapshot','floriday_cleanup_stock_queue_v2','floriday_compact_stock_snapshots','floriday_default_owner','floriday_desired_stock_regression_check','floriday_ensure_inventory_settings','floriday_erp_leading_preview','floriday_fill_publish_horizon','floriday_follow_apply','floriday_ingest_sales_orders','floriday_leading_summary','floriday_make_erp_leading','floriday_norm_offer_forms','floriday_orphan_settings_count','floriday_publish_horizon_weeks','floriday_queue_erp_guard','floriday_queue_first_positive','floriday_recompute_inventory','floriday_relink_products','floriday_requeue_dead_letters','floriday_settings_change_recompute','floriday_settings_change_recompute_stmt','floriday_stock_change_recompute','floriday_stock_queue_supersede','floriday_takeover_apply','floriday_takeover_fetch_state','floriday_takeover_store_forms','floriday_takeover_undo','fust_negative_stock_report','fust_types_duplicate_guard','get_active_floriday_context','get_group_allocation_keys','get_group_head_key','get_product_stock','get_product_structure_totals','get_product_structure_totals_batch','inventory_inline_budget_ok','merge_products','normalize_order_source','process_inventory_recompute_queue','produce_designed_product','product_active_group_id','product_id_from_ref','product_is_set','product_label','product_member_group_ids','product_own_available','product_packings_derive','product_packings_replace','product_packings_sync_from_floriday','product_primary_pieces','product_set_depth_above','product_set_depth_below','product_structure_ancestors','product_structure_max_depth','product_structure_path','product_tray_stickers_touch','product_type','promote_trade_item_key','recompute_all_reserved_stock','recompute_order_status','recompute_reserved_for_order','recompute_reserved_stock','requeue_skipped_stock_rows','reset_stalled_floriday_stock_queue','resolve_group_allocation','resolve_group_member_stock_key','resolve_product_id_for_item','resolve_stock_trade_item_key','reverse_production','run_floriday_base_supply_process','run_floriday_continuous_stock_sync','run_floriday_follow','run_floriday_stock_queue_process','run_floriday_stock_reconcile','run_logistics_tasks_dispatch','self_heal_floriday_links','set_module_runtime_config_updated_at','set_product_bom_tenant','set_product_stock','set_updated_at_order_fust_bookings','stock_import_cleanup','stock_import_create','stock_import_process_chunk','stock_import_stop','stock_import_undo_chunk','sync_order_item_fusten','sync_products_quantity_from_stock','touch_fust_types_updated_at','trade_item_drafts_readonly','trade_item_prices_touch_updated_at','trade_item_stock_duplicates','trg_cart_numbers_sync_order_status_fn','trg_cart_session_consume_fn','trg_check_product_structure','trg_floriday_cache_relink_fn','trg_floriday_trade_items_autolink_fn','trg_order_items_autolink_fn','trg_order_items_fusten','trg_order_items_reserve_fn','trg_orders_cancel_release_fn','trg_orders_consume_on_complete_fn','trg_orders_default_phase_fn','trg_orders_external_fulfilled_fn','trg_orders_recompute_reserved_fn','trg_pgi_assign_sort_order','trg_pgi_order_taken_check','trg_process_recompute_on_commit','trg_product_packings_derive_fn','trg_products_autolink_fn','trg_products_floriday_link_enqueue','trg_products_seed_stock_fn','trg_requeue_no_warehouse_cache','trg_requeue_no_warehouse_connection','trg_requeue_no_warehouse_item_pref','trg_requeue_skipped_no_price','trg_stock_structure_recompute_ins','trg_stock_structure_recompute_upd','trg_structure_change_recompute','trg_trade_item_drafts_autolink_fn','trg_trade_item_stock_auto_bom','trg_trade_item_stock_auto_bom_reverse','trg_trade_item_stock_log_change','trg_trade_item_stock_reserve_fn','trg_trade_item_stock_zero_watch','trg_trade_items_cache_autolink_fn','update_updated_at_column','voorraad_alert_floriday_not_updated','voorraad_can_write','voorraad_cleanup_old_rows','voorraad_consume_external_fulfilled','voorraad_correctie_1098','voorraad_correctie_status','voorraad_external_fulfilled_ids','voorraad_floriday_leads_key','voorraad_fust_dimensions','voorraad_hook_base_url','voorraad_hook_on','voorraad_hook_post','voorraad_hook_switch_jobs','voorraad_install_check','voorraad_is_server','voorraad_mark_floriday_sold_before_switch','voorraad_production_enabled','voorraad_schema_ddl','voorraad_touch_updated_at','voorraad_vereis','voorraad_week_is_past'];
8371
+ DECLARE v_f text[] := ARRAY['voorraad_article_vbn','voorraad_correctie_1112','voorraad_reverse_order_mutations','voorraad_withdraw_stock_row','ensure_voorraad_local_context','get_stock_context','voorraad_stock_context_status','voorraad_fcsq_local_guard','_floriday_queue_cleanup_batch','_migrate_rewrite_stock_key','_stock_import_caller','apply_fust_stock_mutation','apply_stock_consumption','apply_stock_reservation','autolink_product_to_floriday','backfill_open_order_reservations','calculate_floriday_desired_stock','calculate_structure_available','canonicalize_trade_item_stock_key','check_product_structure','claim_floriday_base_supply','claim_floriday_stock_queue','cleanup_floriday_stock_queue','cleanup_voorraad_module_history','complete_floriday_base_supply','complete_floriday_stock_queue','complete_floriday_stock_queue_outcome','consume_bom_for_production','consume_order_item','drain_inventory_recompute_queue','enqueue_floriday_continuous_stock','enqueue_floriday_continuous_stock_after_warehouse_preference','enqueue_structure_recompute','ensure_inventory_recompute_drain','ensure_trade_item_stock_row','ensure_trade_item_stock_row_key','fcsq_block_disabled','fcsq_fallback_supersede','fcsq_wake_base_supply','find_trade_item_key','floriday_adopt_connection','floriday_autoheal_connections','floriday_capture_stock_snapshot','floriday_cleanup_stock_queue_v2','floriday_compact_stock_snapshots','floriday_default_owner','floriday_desired_stock_regression_check','floriday_ensure_inventory_settings','floriday_erp_leading_preview','floriday_fill_publish_horizon','floriday_follow_apply','floriday_ingest_sales_orders','floriday_leading_summary','floriday_make_erp_leading','floriday_norm_offer_forms','floriday_orphan_settings_count','floriday_publish_horizon_weeks','floriday_queue_erp_guard','floriday_queue_first_positive','floriday_recompute_inventory','floriday_relink_products','floriday_requeue_dead_letters','floriday_settings_change_recompute','floriday_settings_change_recompute_stmt','floriday_stock_change_recompute','floriday_stock_queue_supersede','floriday_takeover_apply','floriday_takeover_fetch_state','floriday_takeover_store_forms','floriday_takeover_undo','fust_negative_stock_report','fust_types_duplicate_guard','get_active_floriday_context','get_group_allocation_keys','get_group_head_key','get_product_stock','get_product_structure_totals','get_product_structure_totals_batch','inventory_inline_budget_ok','merge_products','normalize_order_source','process_inventory_recompute_queue','produce_designed_product','product_active_group_id','product_id_from_ref','product_is_set','product_label','product_member_group_ids','product_own_available','product_packings_derive','product_packings_replace','product_packings_sync_from_floriday','product_primary_pieces','product_set_depth_above','product_set_depth_below','product_structure_ancestors','product_structure_max_depth','product_structure_path','product_tray_stickers_touch','product_type','promote_trade_item_key','recompute_all_reserved_stock','recompute_order_status','recompute_reserved_for_order','recompute_reserved_stock','requeue_skipped_stock_rows','reset_stalled_floriday_stock_queue','resolve_group_allocation','resolve_group_member_stock_key','resolve_product_id_for_item','resolve_stock_trade_item_key','reverse_production','run_floriday_base_supply_process','run_floriday_continuous_stock_sync','run_floriday_follow','run_floriday_stock_queue_process','run_floriday_stock_reconcile','run_logistics_tasks_dispatch','self_heal_floriday_links','set_module_runtime_config_updated_at','set_product_bom_tenant','set_product_stock','set_updated_at_order_fust_bookings','stock_import_cleanup','stock_import_create','stock_import_process_chunk','stock_import_stop','stock_import_undo_chunk','sync_order_item_fusten','sync_products_quantity_from_stock','touch_fust_types_updated_at','trade_item_drafts_readonly','trade_item_prices_touch_updated_at','trade_item_stock_duplicates','trg_cart_numbers_sync_order_status_fn','trg_cart_session_consume_fn','trg_check_product_structure','trg_floriday_cache_relink_fn','trg_floriday_trade_items_autolink_fn','trg_order_items_autolink_fn','trg_order_items_fusten','trg_order_items_reserve_fn','trg_orders_cancel_release_fn','trg_orders_consume_on_complete_fn','trg_orders_default_phase_fn','trg_orders_external_fulfilled_fn','trg_orders_recompute_reserved_fn','trg_pgi_assign_sort_order','trg_pgi_order_taken_check','trg_process_recompute_on_commit','trg_product_packings_derive_fn','trg_products_autolink_fn','trg_products_floriday_link_enqueue','trg_products_seed_stock_fn','trg_requeue_no_warehouse_cache','trg_requeue_no_warehouse_connection','trg_requeue_no_warehouse_item_pref','trg_requeue_skipped_no_price','trg_stock_structure_recompute_ins','trg_stock_structure_recompute_upd','trg_structure_change_recompute','trg_trade_item_drafts_autolink_fn','trg_trade_item_stock_auto_bom','trg_trade_item_stock_auto_bom_reverse','trg_trade_item_stock_log_change','trg_trade_item_stock_reserve_fn','trg_trade_item_stock_zero_watch','trg_trade_items_cache_autolink_fn','update_updated_at_column','voorraad_alert_floriday_not_updated','voorraad_can_write','voorraad_cleanup_old_rows','voorraad_consume_external_fulfilled','voorraad_correctie_1098','voorraad_correctie_status','voorraad_external_fulfilled_ids','voorraad_floriday_leads_key','voorraad_fust_dimensions','voorraad_hook_base_url','voorraad_hook_on','voorraad_hook_post','voorraad_hook_switch_jobs','voorraad_install_check','voorraad_is_server','voorraad_mark_floriday_sold_before_switch','voorraad_production_enabled','voorraad_schema_ddl','voorraad_touch_updated_at','voorraad_vereis','voorraad_week_is_past'];
8215
8372
  v_t text[] := ARRAY['aa0_fcsq_local_context_guard@floriday_continuous_stock_queue','aa_fcsq_erp_leading_guard@floriday_continuous_stock_queue','aa_fis_norm_offer_forms@floriday_inventory_settings','aa_pgi_assign_sort_order@product_group_items','fcsq_block_disabled@floriday_continuous_stock_queue','fcsq_wake_base_supply_ins@floriday_continuous_stock_queue','fcsq_wake_base_supply_upd@floriday_continuous_stock_queue','fust_stock_mutations_apply@fust_stock_mutations','fust_types_duplicate_guard@fust_types','fust_types_touch@fust_types','product_packings_derive_trg@product_packings','product_packings_updated_at@product_packings','set_product_bom_tenant_trigger@product_bom_items','trade_item_prices_set_updated_at@trade_item_prices','trg_cart_numbers_sync_order_status@cart_numbers','trg_cart_session_consume@cart_control_sessions','trg_check_product_structure@product_bom_items','trg_check_product_structure@product_group_items','trg_check_product_structure@product_groups','trg_fcs_queue_updated_at@floriday_continuous_stock_queue','trg_fcsq_fallback_supersede@floriday_continuous_stock_queue','trg_fcsq_supersede@floriday_continuous_stock_queue','trg_floriday_cache_relink@floriday_trade_items_cache','trg_floriday_ensure_inventory_settings@products','trg_floriday_gate_stock_queue@floriday_continuous_stock_queue','trg_floriday_settings_change_recompute_ins@floriday_inventory_settings','trg_floriday_settings_change_recompute_upd@floriday_inventory_settings','trg_floriday_stock_change_recompute@trade_item_stock','trg_floriday_takeover_runs_updated_at@floriday_takeover_runs','trg_floriday_trade_items_autolink@floriday_trade_items_cache','trg_fust_types_requeue_blocked@fust_types','trg_module_runtime_config_updated_at@module_runtime_config','trg_order_fust_bookings_updated_at@order_fust_bookings','trg_order_items_autolink@order_items','trg_order_items_fusten_aiud@order_items','trg_order_items_reserve@order_items','trg_orders_cancel_release@orders','trg_orders_consume_on_complete@orders','trg_orders_default_phase@orders','trg_orders_external_fulfilled@orders','trg_orders_recompute_reserved@orders','trg_prevent_duplicate_product_draft@trade_item_drafts','trg_product_tray_stickers_touch@product_tray_stickers','trg_products_autolink@products','trg_products_floriday_link_enqueue@products','trg_products_seed_stock@products','trg_requeue_no_warehouse_cache@floriday_trade_items_cache','trg_requeue_no_warehouse_connection@floriday_connections','trg_requeue_no_warehouse_item_pref@trade_item_warehouse_preferences','trg_requeue_skipped_no_price@products','trg_stock_mutation_alert@stock_mutation_log','trg_stock_structure_recompute_ins@trade_item_stock','trg_stock_structure_recompute_upd@trade_item_stock','trg_structure_change_recompute@product_bom_items','trg_structure_change_recompute@product_group_items','trg_structure_change_recompute@product_groups','trg_sync_layer_stock_from_trade_stock@trade_item_stock','trg_sync_products_quantity_from_stock_del@trade_item_stock','trg_sync_products_quantity_from_stock_iu@trade_item_stock','trg_trade_item_drafts_autolink@trade_item_drafts','trg_trade_item_drafts_readonly@trade_item_drafts','trg_trade_item_stock_canonical_key@trade_item_stock','trg_trade_item_stock_publish@trade_item_stock','trg_trade_item_stock_reserve@trade_item_stock','trg_trade_item_stock_updated_at@trade_item_stock','trg_trade_item_stock_zero_watch@trade_item_stock','trg_trade_item_supply_lines_touch@trade_item_supply_lines','trg_trade_item_warehouse_preference_enqueue_stock@trade_item_warehouse_preferences','trg_trade_items_cache_autolink@floriday_trade_items_cache','trg_voorraad_buffer_state_updated_at@voorraad_buffer_state','trg_voorraad_event_log_updated_at@voorraad_logistics_event_log','update_trade_item_drafts_updated_at@trade_item_drafts','update_trade_item_warehouse_preferences_updated_at@trade_item_warehouse_preferences','update_voorraad_custom_fields_updated_at@voorraad_custom_fields','update_voorraad_publish_jobs_updated_at@voorraad_publish_jobs','update_voorraad_publish_learnings_updated_at@voorraad_publish_learnings','update_voorraad_publish_steps_updated_at@voorraad_publish_steps','voorraad_hook_switch_jobs@module_runtime_config','zz_fcsq_first_positive@floriday_continuous_stock_queue'];
8216
8373
  v_p text[] := ARRAY['Authenticated can add learnings@voorraad_publish_learnings','Authenticated can delete voorraad custom fields@voorraad_custom_fields','Authenticated can insert vbn required characteristics@floriday_vbn_required_characteristics','Authenticated can insert voorraad custom fields@voorraad_custom_fields','Authenticated can read continuous stock cache@floriday_continuous_stock_cache','Authenticated can read learnings@voorraad_publish_learnings','Authenticated can read vbn required characteristics@floriday_vbn_required_characteristics','Authenticated can read voorraad custom fields@voorraad_custom_fields','Authenticated can update learnings@voorraad_publish_learnings','Authenticated can update vbn required characteristics@floriday_vbn_required_characteristics','Authenticated can update voorraad custom fields@voorraad_custom_fields','Authenticated delete trade_item_warehouse_preferences@trade_item_warehouse_preferences','Authenticated insert trade_item_warehouse_preferences@trade_item_warehouse_preferences','Authenticated select trade_item_warehouse_preferences@trade_item_warehouse_preferences','Authenticated update trade_item_warehouse_preferences@trade_item_warehouse_preferences','Eigen momentopnamen lezen@inventory_stock_snapshots','Eigen voorraadinstellingen beheren@floriday_inventory_settings','Eigenaar leest importporties@stock_import_chunks','Eigenaar leest importregels@stock_import_rows','Fust mutations delete@fust_stock_mutations','Fust mutations insert@fust_stock_mutations','Fust mutations read@fust_stock_mutations','Fust mutations update@fust_stock_mutations','Fust types delete@fust_types','Fust types insert@fust_types','Fust types read@fust_types','Fust types update@fust_types','Ingelogde gebruikers kunnen bufferstatus lezen@voorraad_buffer_state','Ingelogde gebruikers kunnen de eventlog lezen@voorraad_logistics_event_log','Ingelogde gebruikers kunnen fustboekingen lezen@order_fust_bookings','Ingelogde gebruikers lezen drempels@inventory_recompute_limits','Ingelogde gebruikers lezen opruimlogboek@structure_cleanup_log','Ingelogde gebruikers lezen opruimruns@floriday_queue_cleanup_runs','Ingelogden beheren traystickers@product_tray_stickers','Ingelogden lezen herberekenwachtrij@inventory_recompute_queue','Ingelogden lezen voorraadmeldingen@stock_integrity_alerts','Ingelogden markeren voorraadmeldingen als gezien@stock_integrity_alerts','Own queue rows select@floriday_continuous_stock_queue','Owner delete trade_item_drafts@trade_item_drafts','Owner insert trade_item_drafts@trade_item_drafts','Owner select trade_item_drafts@trade_item_drafts','Owner update trade_item_drafts@trade_item_drafts','Signed-in users read reconcile runs@floriday_reconcile_runs','Stock delete@trade_item_stock','Stock insert@trade_item_stock','Stock read@trade_item_stock','Stock update@trade_item_stock','Synchronisatieposities lezen@floriday_sync_cursors','Users can insert own publish attempts@voorraad_publish_attempts','Users can read own publish attempts@voorraad_publish_attempts','Users can read own stock mutations@stock_mutation_log','Users manage own import runs@stock_import_runs','Users manage own supply lines@trade_item_supply_lines','Users manage own trade item prices@trade_item_prices','Users manage their own publish jobs@voorraad_publish_jobs','Users manage their own publish steps@voorraad_publish_steps','Verwerkte orders lezen@floriday_sales_order_ingest','Voorraadschrijvers lezen overnameregels@floriday_takeover_items','Voorraadschrijvers lezen overnames@floriday_takeover_runs','authenticated can insert merge log@product_merge_log','authenticated can read merge log@product_merge_log','service role only@voorraad_media_upload_failures','product_packings_read@product_packings','product_packings_write@product_packings'];
8217
8374
  v_open text[] := ARRAY['voorraad_is_server','voorraad_vereis'];
@@ -8767,6 +8924,7 @@ DO $g$ BEGIN IF to_regclass('public.products') IS NULL THEN RAISE NOTICE 'Voorra
8767
8924
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'floriday_takeover_items_run_id_fkey' AND conrelid = 'public.floriday_takeover_items'::regclass) THEN ALTER TABLE public.floriday_takeover_items ADD CONSTRAINT floriday_takeover_items_run_id_fkey FOREIGN KEY (run_id) REFERENCES floriday_takeover_runs(id) ON DELETE CASCADE; END IF; END $c$;
8768
8925
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'floriday_vbn_required_characteristics_updated_by_fkey' AND conrelid = 'public.floriday_vbn_required_characteristics'::regclass) THEN ALTER TABLE public.floriday_vbn_required_characteristics ADD CONSTRAINT floriday_vbn_required_characteristics_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES auth.users(id) ON DELETE SET NULL; END IF; END $c$;
8769
8926
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fust_stock_mutations_fust_type_id_fkey' AND conrelid = 'public.fust_stock_mutations'::regclass) THEN ALTER TABLE public.fust_stock_mutations ADD CONSTRAINT fust_stock_mutations_fust_type_id_fkey FOREIGN KEY (fust_type_id) REFERENCES fust_types(id) ON DELETE CASCADE; END IF; END $c$;
8927
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fust_types_merged_into_fkey' AND conrelid = 'public.fust_types'::regclass) THEN ALTER TABLE public.fust_types ADD CONSTRAINT fust_types_merged_into_fkey FOREIGN KEY (merged_into) REFERENCES fust_types(id); END IF; END $c$;
8770
8928
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'order_fust_bookings_fust_type_id_fkey' AND conrelid = 'public.order_fust_bookings'::regclass) THEN ALTER TABLE public.order_fust_bookings ADD CONSTRAINT order_fust_bookings_fust_type_id_fkey FOREIGN KEY (fust_type_id) REFERENCES fust_types(id) ON DELETE CASCADE; END IF; END $c$;
8771
8929
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'product_packings_fust_type_id_fkey' AND conrelid = 'public.product_packings'::regclass) THEN ALTER TABLE public.product_packings ADD CONSTRAINT product_packings_fust_type_id_fkey FOREIGN KEY (fust_type_id) REFERENCES fust_types(id) ON DELETE SET NULL; END IF; END $c$;
8772
8930
  DO $g$ BEGIN IF to_regclass('public.products') IS NULL THEN RAISE NOTICE 'Voorraad: products (core) ontbreekt, controles overgeslagen; draai de schema-update opnieuw na die module'; ELSE EXECUTE $q$DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'product_packings_product_id_fkey' AND conrelid = 'public.product_packings'::regclass) THEN ALTER TABLE public.product_packings ADD CONSTRAINT product_packings_product_id_fkey FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE; END IF; END $c$$q$; END IF; END $g$;
@@ -8810,6 +8968,7 @@ CREATE INDEX IF NOT EXISTS stock_integrity_alerts_open_idx ON public.stock_integ
8810
8968
  CREATE INDEX IF NOT EXISTS trade_item_prices_lookup ON public.trade_item_prices USING btree (trade_item_key, price_group_id);
8811
8969
  CREATE INDEX IF NOT EXISTS trade_item_stock_trade_item_key_idx ON public.trade_item_stock USING btree (trade_item_key);
8812
8970
  CREATE UNIQUE INDEX IF NOT EXISTS fcsq_one_open_per_week ON public.floriday_continuous_stock_queue USING btree (connection_id, trade_item_id, COALESCE(target_year, '-1'::integer), COALESCE(target_week, '-1'::integer)) WHERE (status = ANY (ARRAY['pending'::text, 'needs_base_supply'::text, 'skipped_no_price'::text, 'failed'::text]));
8971
+ CREATE UNIQUE INDEX IF NOT EXISTS fust_types_fust_key_active_uidx ON public.fust_types USING btree (fust_key) WHERE ((connection_id IS NULL) AND (merged_into IS NULL));
8813
8972
  CREATE UNIQUE INDEX IF NOT EXISTS fust_types_user_key_global_idx ON public.fust_types USING btree (user_id, fust_key) WHERE (connection_id IS NULL);
8814
8973
  CREATE UNIQUE INDEX IF NOT EXISTS product_packings_one_primary ON public.product_packings USING btree (product_id) WHERE is_primary;
8815
8974
  CREATE UNIQUE INDEX IF NOT EXISTS stock_import_runs_one_active ON public.stock_import_runs USING btree (COALESCE(connection_id, '00000000-0000-0000-0000-000000000000'::uuid)) WHERE (status = ANY (ARRAY['ontvangen'::text, 'bezig'::text, 'gestopt'::text]));