@flowselections/floriday-voorraad 1.0.147 → 1.0.150

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 (52) hide show
  1. package/dist-lib/components/voorraad/EditArtikelPage.d.ts.map +1 -1
  2. package/dist-lib/components/voorraad/EditArtikelPage.js +13 -20
  3. package/dist-lib/components/voorraad/OrderHistoryCard.d.ts +3 -1
  4. package/dist-lib/components/voorraad/OrderHistoryCard.d.ts.map +1 -1
  5. package/dist-lib/components/voorraad/OrderHistoryCard.js +7 -3
  6. package/dist-lib/components/voorraad/ProductCustomFieldsCard.d.ts +5 -1
  7. package/dist-lib/components/voorraad/ProductCustomFieldsCard.d.ts.map +1 -1
  8. package/dist-lib/components/voorraad/ProductCustomFieldsCard.js +9 -6
  9. package/dist-lib/components/voorraad/ProductSalePriceField.d.ts.map +1 -1
  10. package/dist-lib/components/voorraad/ProductSalePriceField.js +2 -0
  11. package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts +3 -1
  12. package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts.map +1 -1
  13. package/dist-lib/components/voorraad/StockMutationHistoryCard.js +16 -10
  14. package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts +3 -0
  15. package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts.map +1 -0
  16. package/dist-lib/components/voorraad/VoorraadBeheerCard.js +44 -0
  17. package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts +2 -1
  18. package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts.map +1 -1
  19. package/dist-lib/components/voorraad/artikel/ArtikelPagina.js +60 -10
  20. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts.map +1 -1
  21. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.js +5 -4
  22. package/dist-lib/hooks/useVoorraadCustomFields.d.ts +2 -1
  23. package/dist-lib/hooks/useVoorraadCustomFields.d.ts.map +1 -1
  24. package/dist-lib/hooks/useVoorraadCustomFields.js +8 -4
  25. package/dist-lib/index.d.ts.map +1 -1
  26. package/dist-lib/index.js +2 -0
  27. package/dist-lib/integrations/supabase/types.d.ts +283 -0
  28. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  29. package/dist-lib/lib/artikel-gewijzigd.d.ts +4 -0
  30. package/dist-lib/lib/artikel-gewijzigd.d.ts.map +1 -0
  31. package/dist-lib/lib/artikel-gewijzigd.js +7 -0
  32. package/dist-lib/lib/artikel-pagina.d.ts +14 -3
  33. package/dist-lib/lib/artikel-pagina.d.ts.map +1 -1
  34. package/dist-lib/lib/artikel-pagina.js +5 -1
  35. package/dist-lib/lib/floriday-versie-ronde.d.ts +59 -0
  36. package/dist-lib/lib/floriday-versie-ronde.d.ts.map +1 -0
  37. package/dist-lib/lib/floriday-versie-ronde.functions.d.ts +10 -0
  38. package/dist-lib/lib/floriday-versie-ronde.functions.d.ts.map +1 -0
  39. package/dist-lib/lib/floriday-versie-ronde.functions.js +22 -0
  40. package/dist-lib/lib/floriday-versie-ronde.js +106 -0
  41. package/dist-lib/lib/voorraad-lijst.d.ts +3 -2
  42. package/dist-lib/lib/voorraad-lijst.d.ts.map +1 -1
  43. package/dist-lib/lib/voorraad-lijst.js +6 -2
  44. package/dist-lib/server-hooks/floriday-stock-reconcile.d.ts.map +1 -1
  45. package/dist-lib/server-hooks/floriday-stock-reconcile.js +5 -0
  46. package/dist-lib/server-hooks/floriday-versieronde.d.ts +2 -0
  47. package/dist-lib/server-hooks/floriday-versieronde.d.ts.map +1 -0
  48. package/dist-lib/server-hooks/floriday-versieronde.js +29 -0
  49. package/dist-lib/server-hooks/guard.js +1 -1
  50. package/package.json +1 -1
  51. package/sql/AGENTS.md +2 -0
  52. package/sql/floriday-voorraad-schema.sql +638 -18
@@ -1,5 +1,5 @@
1
- -- @flowselections/floriday-voorraad 1.0.146 – volledig schema (idempotent, geen gegevens).
2
- -- Laatste migratie: 20261103225325_855bad38-f69b-4701-85b7-2d35ee33c08f.sql
1
+ -- @flowselections/floriday-voorraad 1.0.148 – volledig schema (idempotent, geen gegevens).
2
+ -- Laatste migratie: 20261104132044_b849caf0-1e96-4514-99da-94e4074d56b0.sql
3
3
  -- Gegenereerd uit de database met scripts/generate-voorraad-schema.py. Niet met de hand wijzigen.
4
4
  -- Volgorde 20. Ontbrekende tabellen van andere modules worden overgeslagen met een NOTICE; draai opnieuw na die module.
5
5
  -- De statuscontrole van floriday_continuous_stock_queue is van Voorraad en wordt hier opnieuw gemaakt.
@@ -579,12 +579,81 @@ ALTER TABLE public.voorraad_defaults_state ADD COLUMN IF NOT EXISTS versie integ
579
579
  ALTER TABLE public.voorraad_defaults_state ADD COLUMN IF NOT EXISTS toegepast_at timestamp with time zone DEFAULT now() NOT NULL;
580
580
  ALTER TABLE public.voorraad_defaults_state ADD COLUMN IF NOT EXISTS resultaat jsonb DEFAULT '{}'::jsonb NOT NULL;
581
581
 
582
+ -- voorraad_floriday_alias
583
+ CREATE TABLE IF NOT EXISTS public.voorraad_floriday_alias ();
584
+ ALTER TABLE public.voorraad_floriday_alias ADD COLUMN IF NOT EXISTS floriday_id text NOT NULL;
585
+ ALTER TABLE public.voorraad_floriday_alias ADD COLUMN IF NOT EXISTS product_id uuid NOT NULL;
586
+ ALTER TABLE public.voorraad_floriday_alias ADD COLUMN IF NOT EXISTS bron text NOT NULL;
587
+ ALTER TABLE public.voorraad_floriday_alias ADD COLUMN IF NOT EXISTS created_at timestamp with time zone DEFAULT now() NOT NULL;
588
+
582
589
  -- voorraad_floriday_artikel_wachtrij
583
590
  CREATE TABLE IF NOT EXISTS public.voorraad_floriday_artikel_wachtrij ();
584
591
  ALTER TABLE public.voorraad_floriday_artikel_wachtrij ADD COLUMN IF NOT EXISTS floriday_id text NOT NULL;
585
592
  ALTER TABLE public.voorraad_floriday_artikel_wachtrij ADD COLUMN IF NOT EXISTS connection_id uuid;
586
593
  ALTER TABLE public.voorraad_floriday_artikel_wachtrij ADD COLUMN IF NOT EXISTS aangemeld_at timestamp with time zone DEFAULT now() NOT NULL;
587
594
 
595
+ -- voorraad_floriday_versie_fouten
596
+ CREATE TABLE IF NOT EXISTS public.voorraad_floriday_versie_fouten ();
597
+ ALTER TABLE public.voorraad_floriday_versie_fouten ADD COLUMN IF NOT EXISTS connection_id uuid NOT NULL;
598
+ ALTER TABLE public.voorraad_floriday_versie_fouten ADD COLUMN IF NOT EXISTS floriday_id text NOT NULL;
599
+ ALTER TABLE public.voorraad_floriday_versie_fouten ADD COLUMN IF NOT EXISTS opeenvolgend integer DEFAULT 0 NOT NULL;
600
+ ALTER TABLE public.voorraad_floriday_versie_fouten ADD COLUMN IF NOT EXISTS laatste_reden text;
601
+ ALTER TABLE public.voorraad_floriday_versie_fouten ADD COLUMN IF NOT EXISTS onbekend_sinds timestamp with time zone;
602
+ ALTER TABLE public.voorraad_floriday_versie_fouten ADD COLUMN IF NOT EXISTS updated_at timestamp with time zone DEFAULT now() NOT NULL;
603
+
604
+ -- voorraad_floriday_versie_rondes
605
+ CREATE TABLE IF NOT EXISTS public.voorraad_floriday_versie_rondes ();
606
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS id uuid DEFAULT gen_random_uuid() NOT NULL;
607
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS connection_id uuid;
608
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS uitgevoerd_at timestamp with time zone DEFAULT clock_timestamp() NOT NULL;
609
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS volledig boolean DEFAULT false NOT NULL;
610
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS fouten integer DEFAULT 0 NOT NULL;
611
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS gecontroleerd integer DEFAULT 0 NOT NULL;
612
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS in_cache integer DEFAULT 0 NOT NULL;
613
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS actueel integer DEFAULT 0 NOT NULL;
614
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS vervangen integer DEFAULT 0 NOT NULL;
615
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS vervallen integer DEFAULT 0 NOT NULL;
616
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS gemarkeerd boolean DEFAULT false NOT NULL;
617
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS melding text;
618
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS created_at timestamp with time zone DEFAULT now() NOT NULL;
619
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS status text;
620
+ ALTER TABLE public.voorraad_floriday_versie_rondes ADD COLUMN IF NOT EXISTS onbekend integer DEFAULT 0 NOT NULL;
621
+
622
+ -- voorraad_floriday_versieronde_stand
623
+ CREATE TABLE IF NOT EXISTS public.voorraad_floriday_versieronde_stand ();
624
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ADD COLUMN IF NOT EXISTS connection_id uuid NOT NULL;
625
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ADD COLUMN IF NOT EXISTS ronde_id uuid;
626
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ADD COLUMN IF NOT EXISTS gestart_at timestamp with time zone;
627
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ADD COLUMN IF NOT EXISTS laatste_poging_at timestamp with time zone;
628
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ADD COLUMN IF NOT EXISTS laatste_einde_at timestamp with time zone;
629
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ADD COLUMN IF NOT EXISTS updated_at timestamp with time zone DEFAULT now() NOT NULL;
630
+
631
+ -- voorraad_floriday_versieronde_uitkomst
632
+ CREATE TABLE IF NOT EXISTS public.voorraad_floriday_versieronde_uitkomst ();
633
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS ronde_id uuid NOT NULL;
634
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS floriday_id text NOT NULL;
635
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS status text NOT NULL;
636
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS opvolger_id text;
637
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS bron text;
638
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS reden text;
639
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD COLUMN IF NOT EXISTS created_at timestamp with time zone DEFAULT now() NOT NULL;
640
+
641
+ -- voorraad_floriday_vervallen
642
+ CREATE TABLE IF NOT EXISTS public.voorraad_floriday_vervallen ();
643
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS floriday_id text NOT NULL;
644
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS connection_id uuid;
645
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS status text NOT NULL;
646
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS opvolger_id text;
647
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS bron text NOT NULL;
648
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS ronde_id uuid;
649
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS vastgesteld_at timestamp with time zone DEFAULT now() NOT NULL;
650
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS verwerkt_at timestamp with time zone;
651
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS uitkomst text;
652
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS product_id uuid;
653
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS opgeheven_at timestamp with time zone;
654
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS created_at timestamp with time zone DEFAULT now() NOT NULL;
655
+ ALTER TABLE public.voorraad_floriday_vervallen ADD COLUMN IF NOT EXISTS updated_at timestamp with time zone DEFAULT now() NOT NULL;
656
+
588
657
  -- voorraad_instellingen
589
658
  CREATE TABLE IF NOT EXISTS public.voorraad_instellingen ();
590
659
  ALTER TABLE public.voorraad_instellingen ADD COLUMN IF NOT EXISTS id boolean DEFAULT true NOT NULL;
@@ -3736,7 +3805,7 @@ CREATE OR REPLACE FUNCTION public.floriday_relink_products(p_connection_id uuid
3736
3805
  AS $function$
3737
3806
  DECLARE
3738
3807
  v_conn uuid; v_cache_count int; v_row RECORD; v_cf jsonb; v_cf_id text; v_match text;
3739
- v_linked int := 0; v_repaired int := 0; v_cleared int := 0;
3808
+ v_linked int := 0; v_verwijderd int := 0; v_repaired int := 0; v_cleared int := 0;
3740
3809
  BEGIN
3741
3810
  PERFORM public.voorraad_vereis('ingelogd', 'floriday_relink_products');
3742
3811
  v_conn := p_connection_id;
@@ -3750,7 +3819,7 @@ BEGIN
3750
3819
  SELECT count(*) INTO v_cache_count FROM public.floriday_trade_items_cache
3751
3820
  WHERE connection_id = v_conn AND COALESCE(is_deleted,false) = false;
3752
3821
 
3753
- FOR v_row IN SELECT id, trade_item_key, floriday_trade_item_id, custom_fields FROM public.products LOOP
3822
+ FOR v_row IN SELECT id, trade_item_key, floriday_trade_item_id, custom_fields, floriday_verwijderd_at FROM public.products LOOP
3754
3823
  v_cf := CASE WHEN jsonb_typeof(v_row.custom_fields) = 'object' THEN v_row.custom_fields ELSE '{}'::jsonb END;
3755
3824
  v_cf_id := NULLIF(btrim(COALESCE(v_cf->>'floriday_id','')), '');
3756
3825
  v_match := NULL;
@@ -3772,6 +3841,18 @@ BEGIN
3772
3841
  v_match := NULL;
3773
3842
  END IF;
3774
3843
 
3844
+ IF v_match IS NULL AND v_row.floriday_trade_item_id IS NOT NULL AND EXISTS (SELECT 1 FROM public.floriday_trade_items_cache c
3845
+ WHERE c.connection_id = v_conn AND lower(c.floriday_id) = lower(btrim(v_row.floriday_trade_item_id))
3846
+ AND (COALESCE(c.is_deleted,false) OR COALESCE((c.data->>'isDeleted')::boolean,false))) THEN
3847
+ -- Verwijderd in Floriday: koppeling behouden, artikel op niet actief (status "Verwijderd in Floriday").
3848
+ IF v_row.floriday_verwijderd_at IS NULL THEN
3849
+ UPDATE public.products SET floriday_verwijderd_at = now(), updated_at = now() WHERE id = v_row.id;
3850
+ INSERT INTO public.voorraad_koppel_log(run_id, soort, floriday_id, product_id, oud, nieuw)
3851
+ VALUES (NULL, 'niet_actief', v_row.floriday_trade_item_id, v_row.id, jsonb_build_object('floriday_verwijderd_at', NULL), jsonb_build_object('floriday_verwijderd_at', now(), 'bron', 'relink'));
3852
+ v_verwijderd := v_verwijderd + 1;
3853
+ END IF;
3854
+ CONTINUE;
3855
+ END IF;
3775
3856
  IF v_match IS NULL AND v_row.floriday_trade_item_id IS NOT NULL AND v_cache_count > 0 THEN
3776
3857
  UPDATE public.products SET floriday_trade_item_id = NULL,
3777
3858
  custom_fields = jsonb_set(v_cf, '{floriday_id}', 'null'::jsonb, true), updated_at = now()
@@ -3790,7 +3871,7 @@ BEGIN
3790
3871
  END LOOP;
3791
3872
 
3792
3873
  RETURN jsonb_build_object('ok', true, 'connection_id', v_conn, 'cache_items', v_cache_count,
3793
- 'linked', v_linked, 'repaired', v_repaired, 'cleared', v_cleared, 'match', 'floriday_id_only');
3874
+ 'linked', v_linked, 'repaired', v_repaired, 'cleared', v_cleared, 'verwijderd_in_floriday', v_verwijderd, 'match', 'floriday_id_only');
3794
3875
  END; $function$
3795
3876
  ;
3796
3877
  REVOKE ALL ON FUNCTION floriday_relink_products(uuid) FROM PUBLIC;
@@ -5914,6 +5995,41 @@ END $function$
5914
5995
  REVOKE ALL ON FUNCTION run_floriday_stock_reconcile() FROM PUBLIC;
5915
5996
  REVOKE ALL ON FUNCTION run_floriday_stock_reconcile() FROM anon;
5916
5997
  GRANT EXECUTE ON FUNCTION run_floriday_stock_reconcile() TO service_role;
5998
+ CREATE OR REPLACE FUNCTION public.run_floriday_versieronde(p_nieuw boolean DEFAULT false)
5999
+ RETURNS jsonb
6000
+ LANGUAGE plpgsql
6001
+ SECURITY DEFINER
6002
+ SET search_path TO 'public'
6003
+ AS $function$
6004
+ DECLARE v_conn uuid; v_bezig boolean; v_einde timestamptz; v_ok boolean; v_doen boolean;
6005
+ BEGIN
6006
+ PERFORM public.voorraad_vereis('server', 'run_floriday_versieronde');
6007
+ BEGIN SELECT x.connection_id INTO v_conn FROM public.get_active_floriday_context() x LIMIT 1;
6008
+ EXCEPTION WHEN others THEN v_conn := NULL; END;
6009
+ IF v_conn IS NULL THEN RETURN jsonb_build_object('ok', true, 'melding', 'geen Floriday-koppeling'); END IF;
6010
+ SELECT ronde_id IS NOT NULL, laatste_einde_at INTO v_bezig, v_einde FROM public.voorraad_floriday_versieronde_stand WHERE connection_id = v_conn;
6011
+ v_bezig := COALESCE(v_bezig, false);
6012
+ v_ok := public.voorraad_floriday_versieronde_geslaagd(v_conn);
6013
+ v_doen := p_nieuw OR v_bezig OR (NOT v_ok AND (v_einde IS NULL OR v_einde < now() - interval '15 minutes'));
6014
+ IF v_doen THEN
6015
+ BEGIN
6016
+ IF NOT EXISTS (SELECT 1 FROM cron.job WHERE jobname = 'voorraad-floriday-versieronde-herhaal') THEN
6017
+ PERFORM cron.schedule('voorraad-floriday-versieronde-herhaal', '*/5 * * * *', 'SELECT public.run_floriday_versieronde(false);');
6018
+ END IF;
6019
+ EXCEPTION WHEN others THEN NULL; END;
6020
+ INSERT INTO public.voorraad_floriday_versieronde_stand(connection_id, laatste_poging_at) VALUES (v_conn, now())
6021
+ ON CONFLICT (connection_id) DO UPDATE SET laatste_poging_at = now(), updated_at = now();
6022
+ PERFORM public.voorraad_hook_post('/api/public/hooks/floriday-stock-reconcile?taak=versies', 55000);
6023
+ ELSIF v_ok AND NOT v_bezig THEN
6024
+ BEGIN PERFORM cron.unschedule('voorraad-floriday-versieronde-herhaal'); EXCEPTION WHEN others THEN NULL; END;
6025
+ END IF;
6026
+ RETURN jsonb_build_object('ok', true, 'gewekt', v_doen, 'bezig', v_bezig, 'geslaagd', v_ok);
6027
+ END $function$
6028
+ ;
6029
+ REVOKE ALL ON FUNCTION run_floriday_versieronde(boolean) FROM PUBLIC;
6030
+ REVOKE ALL ON FUNCTION run_floriday_versieronde(boolean) FROM anon;
6031
+ GRANT EXECUTE ON FUNCTION run_floriday_versieronde(boolean) TO authenticated;
6032
+ GRANT EXECUTE ON FUNCTION run_floriday_versieronde(boolean) TO service_role;
5917
6033
  CREATE OR REPLACE FUNCTION public.run_logistics_tasks_dispatch()
5918
6034
  RETURNS void
5919
6035
  LANGUAGE plpgsql
@@ -8167,6 +8283,22 @@ BEGIN
8167
8283
  'telmoment', v_tel,
8168
8284
  'verpakking_ok', (v_soort = 'GROUP' OR (v_pak AND v_pak_ok)),
8169
8285
  'gearchiveerd_at', p.gearchiveerd_at, 'orders_gearchiveerd', CASE WHEN p.gearchiveerd_at IS NULL THEN 0 ELSE COALESCE((public.voorraad_orders_gearchiveerd(p.id)->0->>'regels')::int, 0) END,
8286
+ 'floriday_verwijderd_at', p.floriday_verwijderd_at,
8287
+ 'trade_item_key', p.trade_item_key,
8288
+ 'controle', jsonb_build_object(
8289
+ 'mutatie_sleutels', (SELECT to_jsonb(array_agg(DISTINCT k)) FROM (
8290
+ SELECT unnest(ARRAY[v_key, p.trade_item_key, p.id::text]) AS k
8291
+ UNION SELECT 'group:' || gi.product_group_id::text FROM public.product_group_items gi
8292
+ WHERE gi.trade_item_id IN (v_key, p.trade_item_key, p.id::text)) x WHERE k IS NOT NULL),
8293
+ 'zelfde_sleutel_ids', (SELECT COALESCE(to_jsonb(array_agg(q.id)), '[]'::jsonb) FROM (SELECT q.id FROM public.products q
8294
+ WHERE q.id = p.id OR (p.trade_item_key IS NOT NULL AND q.trade_item_key = p.trade_item_key) LIMIT 50) q)),
8295
+ 'eigen_velden', jsonb_build_object(
8296
+ 'definities', (SELECT COALESCE(jsonb_agg(jsonb_build_object('id', f.id, 'field_key', f.field_key, 'field_label', f.field_label,
8297
+ 'field_type', f.field_type, 'options', f.options, 'show_in_template', f.show_in_template, 'show_in_columns', f.show_in_columns,
8298
+ 'show_in_detail', f.show_in_detail, 'sort_order', f.sort_order) ORDER BY f.sort_order, f.created_at), '[]'::jsonb)
8299
+ FROM public.voorraad_custom_fields f),
8300
+ 'waarden', (SELECT COALESCE(jsonb_object_agg(f.field_key, p.custom_fields->f.field_key), '{}'::jsonb)
8301
+ FROM public.voorraad_custom_fields f WHERE jsonb_typeof(p.custom_fields) = 'object' AND p.custom_fields ? f.field_key)),
8170
8302
  'bijgewerkt', now());
8171
8303
  END $function$
8172
8304
  ;
@@ -9299,6 +9431,50 @@ END $function$
9299
9431
  REVOKE ALL ON FUNCTION voorraad_correctie_1144(boolean,integer,integer) FROM PUBLIC;
9300
9432
  REVOKE ALL ON FUNCTION voorraad_correctie_1144(boolean,integer,integer) FROM anon;
9301
9433
  GRANT EXECUTE ON FUNCTION voorraad_correctie_1144(boolean,integer,integer) TO service_role;
9434
+ CREATE OR REPLACE FUNCTION public.voorraad_correctie_1148(p_uitvoeren boolean DEFAULT false)
9435
+ RETURNS jsonb
9436
+ LANGUAGE plpgsql
9437
+ SECURITY DEFINER
9438
+ SET search_path TO 'public'
9439
+ AS $function$
9440
+ DECLARE r record; v_opv uuid; v_lijst jsonb := '[]'::jsonb; n_arch int := 0; n_overslaan int := 0; v_reden text; v_open int; v_stock numeric;
9441
+ BEGIN
9442
+ PERFORM public.voorraad_vereis('server', 'voorraad_correctie_1148');
9443
+ FOR r IN
9444
+ SELECT p.id, p.product, p.custom_fields, v.floriday_id, v.opvolger_id
9445
+ FROM public.voorraad_floriday_vervallen v JOIN public.products p ON p.id = public.voorraad_floriday_product_van(v.floriday_id)
9446
+ WHERE v.opgeheven_at IS NULL AND p.gearchiveerd_at IS NULL AND p.custom_fields->>'voorraad_auto_aangemaakt' = 'true'
9447
+ ORDER BY p.product
9448
+ LOOP
9449
+ SELECT COALESCE(max(s.physical_stock),0) INTO v_stock FROM public.trade_item_stock s
9450
+ WHERE s.archived_at IS NULL AND s.trade_item_key IN (r.floriday_id, 'product:' || r.id::text);
9451
+ SELECT count(*) INTO v_open FROM public.order_items oi JOIN public.orders o ON o.id = oi.order_id
9452
+ WHERE oi.product_id = r.id AND NOT public.voorraad_order_geannuleerd(o.status, o.cancelled_at, o.deleted_at)
9453
+ AND NOT public.voorraad_order_vertrokken_voor(o.id, now());
9454
+ v_reden := CASE WHEN v_stock <> 0 THEN 'heeft voorraad' WHEN v_open > 0 THEN 'heeft open orders'
9455
+ WHEN jsonb_typeof(r.custom_fields->'floriday_velden_aangepast') = 'array' AND jsonb_array_length(r.custom_fields->'floriday_velden_aangepast') > 0 THEN 'door gebruiker aangepast' END;
9456
+ v_opv := CASE WHEN r.opvolger_id IS NOT NULL THEN public.voorraad_floriday_product_van(r.opvolger_id) END;
9457
+ v_lijst := v_lijst || jsonb_build_object('product_id', r.id, 'naam', r.product, 'floriday_id', r.floriday_id, 'opvolger_artikel', v_opv,
9458
+ 'actie', CASE WHEN v_reden IS NULL THEN 'archiveren' ELSE 'overslaan' END, 'reden', v_reden);
9459
+ IF v_reden IS NOT NULL THEN n_overslaan := n_overslaan + 1; CONTINUE; END IF;
9460
+ n_arch := n_arch + 1;
9461
+ IF p_uitvoeren THEN
9462
+ UPDATE public.products SET gearchiveerd_at = now(), custom_fields = custom_fields || jsonb_build_object('voorraad_floriday_vervallen', true), updated_at = now()
9463
+ WHERE id = r.id AND gearchiveerd_at IS NULL;
9464
+ UPDATE public.floriday_inventory_settings SET erp_leading = NULL, stock_mode = 'DISABLED', updated_at = now() WHERE product_id = r.id;
9465
+ UPDATE public.voorraad_floriday_vervallen SET verwerkt_at = now(), uitkomst = 'gearchiveerd_correctie', product_id = r.id WHERE floriday_id = r.floriday_id;
9466
+ END IF;
9467
+ END LOOP;
9468
+ INSERT INTO public.voorraad_correcties(correctie, uitgevoerd_door, proef, aantallen, hash_ok)
9469
+ VALUES ('1148', COALESCE(auth.uid()::text, session_user::text), NOT p_uitvoeren,
9470
+ jsonb_build_object('archiveren', n_arch, 'overslaan', n_overslaan), true);
9471
+ RETURN jsonb_build_object('uitgevoerd', p_uitvoeren, 'archiveren', n_arch, 'overslaan', n_overslaan, 'regels', v_lijst);
9472
+ END $function$
9473
+ ;
9474
+ REVOKE ALL ON FUNCTION voorraad_correctie_1148(boolean) FROM PUBLIC;
9475
+ REVOKE ALL ON FUNCTION voorraad_correctie_1148(boolean) FROM anon;
9476
+ GRANT EXECUTE ON FUNCTION voorraad_correctie_1148(boolean) TO authenticated;
9477
+ GRANT EXECUTE ON FUNCTION voorraad_correctie_1148(boolean) TO service_role;
9302
9478
  CREATE OR REPLACE FUNCTION public.voorraad_correctie_status(p_correctie text DEFAULT '1098'::text)
9303
9479
  RETURNS jsonb
9304
9480
  LANGUAGE plpgsql
@@ -9362,7 +9538,7 @@ CREATE OR REPLACE FUNCTION public.voorraad_defaults_versie()
9362
9538
  LANGUAGE sql
9363
9539
  IMMUTABLE
9364
9540
  SET search_path TO 'public'
9365
- AS $function$ SELECT 2 $function$
9541
+ AS $function$ SELECT 3 $function$
9366
9542
  ;
9367
9543
  REVOKE ALL ON FUNCTION voorraad_defaults_versie() FROM PUBLIC;
9368
9544
  REVOKE ALL ON FUNCTION voorraad_defaults_versie() FROM anon;
@@ -9452,6 +9628,7 @@ DECLARE
9452
9628
  v_idx text := 'bestaat'; v_job text := 'bestaat'; v_res jsonb; v_job_ok boolean;
9453
9629
  BEGIN
9454
9630
  PERFORM public.voorraad_vereis('ingelogd', 'voorraad_ensure_defaults');
9631
+ BEGIN PERFORM public.voorraad_floriday_versieronde_inplannen(); EXCEPTION WHEN others THEN RAISE LOG '[voorraad] versieronde inplannen: %', SQLERRM; END;
9455
9632
  BEGIN
9456
9633
  BEGIN v_job_ok := EXISTS (SELECT 1 FROM cron.job WHERE jobname = 'voorraad-floriday-artikelen-uurlijks'); EXCEPTION WHEN others THEN v_job_ok := true; END;
9457
9634
  IF EXISTS (SELECT 1 FROM public.voorraad_defaults_state s WHERE s.id AND s.versie = v_versie)
@@ -9575,7 +9752,7 @@ DECLARE
9575
9752
  c record; v_name text; v_gtin text; v_code text; v_photo text; v_ver text; v_del boolean;
9576
9753
  v_p record; v_c uuid[]; v_tier text; v_new uuid; v_sturing text; v_own_key text;
9577
9754
  n_aan int := 0; n_kop int := 0; n_twijfel int := 0; n_uit int := 0; n_bij int := 0; n_fout int := 0; n_rest int := 0;
9578
- v_vb jsonb := '[]'::jsonb; v_aangepast text[];
9755
+ v_vb jsonb := '[]'::jsonb; v_aangepast text[]; v_ronde_ok boolean; n_wacht int := 0;
9579
9756
  BEGIN
9580
9757
  PERFORM public.voorraad_vereis('ingelogd', 'voorraad_floriday_artikelen_aanmaken');
9581
9758
  v_dups := public.voorraad_floriday_dubbele_ids();
@@ -9584,6 +9761,7 @@ BEGIN
9584
9761
  END IF;
9585
9762
  v_conn := COALESCE(p_connection_id, (SELECT x.connection_id FROM public.get_active_floriday_context() x LIMIT 1));
9586
9763
  IF v_conn IS NULL THEN RETURN jsonb_build_object('ok', true, 'melding', 'Geen actieve Floriday-koppeling'); END IF;
9764
+ v_ronde_ok := public.voorraad_floriday_versieronde_geslaagd(v_conn);
9587
9765
  IF p_uitvoeren AND NOT pg_try_advisory_xact_lock(hashtext('voorraad_floriday_artikelen_aanmaken')) THEN
9588
9766
  RETURN jsonb_build_object('ok', false, 'melding', 'Er loopt al een ronde');
9589
9767
  END IF;
@@ -9598,9 +9776,10 @@ BEGIN
9598
9776
  AND (
9599
9777
  (NOT (COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false))
9600
9778
  AND NOT EXISTS (SELECT 1 FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = lower(t.floriday_id))
9601
- AND NOT EXISTS (SELECT 1 FROM public.voorraad_koppel_twijfel w WHERE w.floriday_id = t.floriday_id AND w.opgelost_at IS NULL AND w.laatst_gezien > now() - interval '1 hour' AND p_uitvoeren))
9779
+ AND NOT EXISTS (SELECT 1 FROM public.voorraad_koppel_twijfel w WHERE w.floriday_id = t.floriday_id AND w.opgelost_at IS NULL AND w.laatst_gezien > now() - interval '1 hour' AND p_uitvoeren)
9780
+ AND NOT EXISTS (SELECT 1 FROM public.voorraad_floriday_vervallen v WHERE v.floriday_id = t.floriday_id AND v.opgeheven_at IS NULL))
9602
9781
  OR ((COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false))
9603
- AND EXISTS (SELECT 1 FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = lower(t.floriday_id) AND p.floriday_verwijderd_at IS NULL))
9782
+ AND EXISTS (SELECT 1 FROM public.products p WHERE p.id = public.voorraad_floriday_product_van(t.floriday_id) AND p.floriday_verwijderd_at IS NULL))
9604
9783
  OR (NOT (COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false))
9605
9784
  AND EXISTS (SELECT 1 FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = lower(t.floriday_id)
9606
9785
  AND (p.floriday_verwijderd_at IS NOT NULL
@@ -9620,13 +9799,19 @@ BEGIN
9620
9799
  SELECT e->>'url' INTO v_photo FROM jsonb_array_elements(CASE WHEN jsonb_typeof(c.data->'photos') = 'array' THEN c.data->'photos' ELSE '[]'::jsonb END) e
9621
9800
  ORDER BY COALESCE((e->>'primary')::boolean, false) DESC LIMIT 1;
9622
9801
  v_ver := c.data->>'tradeItemVersion';
9623
- SELECT p.* INTO v_p FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = lower(c.floriday_id) LIMIT 1;
9802
+ SELECT p.* INTO v_p FROM public.products p
9803
+ WHERE p.id = CASE WHEN c.del THEN public.voorraad_floriday_product_van(c.floriday_id)
9804
+ ELSE (SELECT q.id FROM public.products q WHERE lower(btrim(q.floriday_trade_item_id)) = lower(c.floriday_id) LIMIT 1) END
9805
+ LIMIT 1;
9624
9806
 
9625
9807
  BEGIN
9626
9808
  IF c.del THEN
9627
9809
  -- Verwijderd in Floriday: eigen artikel op niet actief, nooit verwijderen.
9628
9810
  IF p_uitvoeren THEN
9629
- UPDATE public.products SET floriday_verwijderd_at = now(), updated_at = now() WHERE id = v_p.id;
9811
+ UPDATE public.products SET floriday_verwijderd_at = now(),
9812
+ floriday_trade_item_id = CASE WHEN floriday_trade_item_id IS NULL AND NOT EXISTS (SELECT 1 FROM public.products q
9813
+ WHERE q.id <> v_p.id AND lower(btrim(q.floriday_trade_item_id)) = lower(c.floriday_id)) THEN c.floriday_id ELSE floriday_trade_item_id END,
9814
+ updated_at = now() WHERE id = v_p.id;
9630
9815
  INSERT INTO public.voorraad_koppel_log(run_id, soort, floriday_id, product_id, oud, nieuw)
9631
9816
  VALUES (v_run, 'niet_actief', c.floriday_id, v_p.id, jsonb_build_object('floriday_verwijderd_at', NULL), jsonb_build_object('floriday_verwijderd_at', now()));
9632
9817
  END IF;
@@ -9705,7 +9890,11 @@ BEGIN
9705
9890
  END IF;
9706
9891
  ELSE
9707
9892
  -- Geen match: eigen artikel aanmaken op dezelfde voorraadsleutel als het Floriday-product.
9708
- IF v_name IS NULL THEN
9893
+ IF NOT v_ronde_ok OR EXISTS (SELECT 1 FROM public.voorraad_floriday_versie_fouten f
9894
+ WHERE f.connection_id = v_conn AND f.floriday_id = c.floriday_id AND f.onbekend_sinds IS NOT NULL) THEN
9895
+ -- Nog geen geslaagde versieronde: niets nieuws aanmaken (koppelen gebeurde hierboven al).
9896
+ n_wacht := n_wacht + 1;
9897
+ ELSIF v_name IS NULL THEN
9709
9898
  IF p_uitvoeren THEN
9710
9899
  INSERT INTO public.voorraad_koppel_twijfel(floriday_id, connection_id, naam, reden)
9711
9900
  VALUES (c.floriday_id, v_conn, NULL, 'Floriday-product heeft geen naam')
@@ -9746,7 +9935,7 @@ BEGIN
9746
9935
 
9747
9936
  RETURN jsonb_build_object('ok', true, 'uitgevoerd', p_uitvoeren, 'run_id', CASE WHEN p_uitvoeren THEN v_run END,
9748
9937
  'aangemaakt', n_aan, 'gekoppeld', n_kop, 'twijfel', n_twijfel, 'niet_actief', n_uit, 'bijgewerkt', n_bij,
9749
- 'fouten', n_fout, 'resterend', n_rest, 'sturing', v_sturing,
9938
+ 'fouten', n_fout, 'resterend', n_rest, 'wacht_op_versieronde', n_wacht, 'sturing', v_sturing,
9750
9939
  'voorbeelden', (SELECT COALESCE(jsonb_agg(e), '[]'::jsonb) FROM (SELECT e FROM jsonb_array_elements(v_vb) e LIMIT 25) z));
9751
9940
  END $function$
9752
9941
  ;
@@ -9764,6 +9953,7 @@ DECLARE v jsonb; v_t timestamptz := now();
9764
9953
  BEGIN
9765
9954
  PERFORM public.voorraad_vereis('server', 'voorraad_floriday_artikelen_vangnet');
9766
9955
  v := public.voorraad_floriday_artikelen_aanmaken(NULL, 500, true, 45);
9956
+ v := v || jsonb_build_object('vervallen', public.voorraad_floriday_vervallen_verwerken(true));
9767
9957
  IF COALESCE((v->>'resterend')::int, 0) = 0 THEN
9768
9958
  DELETE FROM public.voorraad_floriday_artikel_wachtrij WHERE aangemeld_at <= v_t;
9769
9959
  END IF;
@@ -9835,6 +10025,340 @@ $function$
9835
10025
  REVOKE ALL ON FUNCTION voorraad_floriday_leads_key(text) FROM PUBLIC;
9836
10026
  REVOKE ALL ON FUNCTION voorraad_floriday_leads_key(text) FROM anon;
9837
10027
  GRANT EXECUTE ON FUNCTION voorraad_floriday_leads_key(text) TO service_role;
10028
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_product_van(p_floriday_id text)
10029
+ RETURNS uuid
10030
+ LANGUAGE plpgsql
10031
+ STABLE SECURITY DEFINER
10032
+ SET search_path TO 'public'
10033
+ AS $function$
10034
+ DECLARE v uuid; v_k text := lower(btrim(COALESCE(p_floriday_id,''))); v_ids uuid[];
10035
+ BEGIN
10036
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_floriday_product_van');
10037
+ IF v_k = '' THEN RETURN NULL; END IF;
10038
+ SELECT p.id INTO v FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = v_k LIMIT 1;
10039
+ IF v IS NOT NULL THEN RETURN v; END IF;
10040
+ SELECT array_agg(DISTINCT p.id) INTO v_ids FROM public.products p
10041
+ WHERE p.floriday_trade_item_id IS NULL
10042
+ AND (lower(btrim(COALESCE(p.trade_item_key,''))) = v_k
10043
+ OR lower(COALESCE(p.custom_fields->>'floriday_id','')) = v_k
10044
+ OR p.id IN (SELECT l.product_id FROM public.voorraad_koppel_log l
10045
+ WHERE lower(l.floriday_id) = v_k AND l.soort IN ('aangemaakt','gekoppeld') AND l.product_id IS NOT NULL));
10046
+ IF array_length(v_ids, 1) = 1 THEN RETURN v_ids[1]; END IF;
10047
+ RETURN NULL;
10048
+ END $function$
10049
+ ;
10050
+ REVOKE ALL ON FUNCTION voorraad_floriday_product_van(text) FROM PUBLIC;
10051
+ REVOKE ALL ON FUNCTION voorraad_floriday_product_van(text) FROM anon;
10052
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_product_van(text) TO authenticated;
10053
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_product_van(text) TO service_role;
10054
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versieronde_geslaagd(p_connection_id uuid)
10055
+ RETURNS boolean
10056
+ LANGUAGE plpgsql
10057
+ STABLE SECURITY DEFINER
10058
+ SET search_path TO 'public'
10059
+ AS $function$
10060
+ BEGIN
10061
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_floriday_versieronde_geslaagd');
10062
+ RETURN EXISTS (SELECT 1 FROM public.voorraad_floriday_versie_rondes r WHERE r.connection_id = p_connection_id AND r.gemarkeerd);
10063
+ END $function$
10064
+ ;
10065
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_geslaagd(uuid) FROM PUBLIC;
10066
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_geslaagd(uuid) FROM anon;
10067
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_geslaagd(uuid) TO authenticated;
10068
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_geslaagd(uuid) TO service_role;
10069
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versieronde_inplannen()
10070
+ RETURNS jsonb
10071
+ LANGUAGE plpgsql
10072
+ SECURITY DEFINER
10073
+ SET search_path TO 'public'
10074
+ AS $function$
10075
+ DECLARE v_conn uuid; v_res jsonb;
10076
+ BEGIN
10077
+ PERFORM public.voorraad_vereis('server', 'voorraad_floriday_versieronde_inplannen');
10078
+ BEGIN SELECT x.connection_id INTO v_conn FROM public.get_active_floriday_context() x LIMIT 1;
10079
+ EXCEPTION WHEN others THEN v_conn := NULL; END;
10080
+ IF v_conn IS NULL THEN RETURN jsonb_build_object('ok', true, 'melding', 'geen Floriday-koppeling'); END IF;
10081
+ BEGIN
10082
+ IF NOT EXISTS (SELECT 1 FROM cron.job WHERE jobname = 'voorraad-floriday-versieronde-dagelijks') THEN
10083
+ -- 03:30 UTC = 04:30 Amsterdam (wintertijd), 05:30 in de zomer.
10084
+ PERFORM cron.schedule('voorraad-floriday-versieronde-dagelijks', '30 3 * * *', 'SELECT public.run_floriday_versieronde(true);');
10085
+ END IF;
10086
+ EXCEPTION WHEN others THEN RETURN jsonb_build_object('ok', false, 'melding', 'inplannen mislukt: ' || SQLERRM); END;
10087
+ IF NOT public.voorraad_floriday_versieronde_geslaagd(v_conn)
10088
+ AND NOT EXISTS (SELECT 1 FROM public.voorraad_floriday_versieronde_stand s WHERE s.connection_id = v_conn AND s.laatste_poging_at > now() - interval '5 minutes') THEN
10089
+ v_res := public.run_floriday_versieronde(false);
10090
+ END IF;
10091
+ RETURN jsonb_build_object('ok', true, 'gestart', v_res);
10092
+ END $function$
10093
+ ;
10094
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_inplannen() FROM PUBLIC;
10095
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_inplannen() FROM anon;
10096
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_inplannen() TO authenticated;
10097
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_inplannen() TO service_role;
10098
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versieronde_melding()
10099
+ RETURNS text
10100
+ LANGUAGE plpgsql
10101
+ STABLE SECURITY DEFINER
10102
+ SET search_path TO 'public'
10103
+ AS $function$
10104
+ DECLARE r record; v_conn uuid;
10105
+ BEGIN
10106
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_floriday_versieronde_melding');
10107
+ BEGIN SELECT x.connection_id INTO v_conn FROM public.get_active_floriday_context() x LIMIT 1;
10108
+ EXCEPTION WHEN others THEN v_conn := NULL; END;
10109
+ IF v_conn IS NULL THEN RETURN NULL; END IF;
10110
+ SELECT * INTO r FROM public.voorraad_floriday_versie_rondes WHERE connection_id = v_conn AND COALESCE(status,'') <> 'onvolledig'
10111
+ ORDER BY uitgevoerd_at DESC LIMIT 1;
10112
+ IF r.status = 'mislukt' THEN
10113
+ RETURN 'Controle van Floriday-artikelen mislukt: ' || COALESCE(r.melding, 'onbekende oorzaak') || '; wordt automatisch opnieuw geprobeerd.';
10114
+ END IF;
10115
+ RETURN NULL;
10116
+ END $function$
10117
+ ;
10118
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_melding() FROM PUBLIC;
10119
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_melding() FROM anon;
10120
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_melding() TO authenticated;
10121
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_melding() TO service_role;
10122
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versieronde_portie(p_connection_id uuid, p_ronde_id uuid, p_uitkomsten jsonb, p_verbindingsfout text DEFAULT NULL::text)
10123
+ RETURNS jsonb
10124
+ LANGUAGE plpgsql
10125
+ SECURITY DEFINER
10126
+ SET search_path TO 'public'
10127
+ AS $function$
10128
+ DECLARE v_huidig uuid; v_rest int; n_blok int; n_onb int; v_res jsonb; v_rid uuid; v_uit jsonb; v_status text; v_meld text;
10129
+ BEGIN
10130
+ PERFORM public.voorraad_vereis('server', 'voorraad_floriday_versieronde_portie');
10131
+ SELECT ronde_id INTO v_huidig FROM public.voorraad_floriday_versieronde_stand WHERE connection_id = p_connection_id FOR UPDATE;
10132
+ IF v_huidig IS DISTINCT FROM p_ronde_id THEN RETURN jsonb_build_object('ok', false, 'melding', 'Ronde is al afgerond'); END IF;
10133
+
10134
+ IF NULLIF(btrim(COALESCE(p_verbindingsfout,'')),'') IS NOT NULL THEN
10135
+ INSERT INTO public.voorraad_floriday_versie_rondes(connection_id, volledig, fouten, status, gemarkeerd, melding)
10136
+ VALUES (p_connection_id, false, 1, 'mislukt', false, 'geen verbinding met Floriday (' || left(p_verbindingsfout, 200) || ')');
10137
+ DELETE FROM public.voorraad_floriday_versieronde_uitkomst WHERE ronde_id = p_ronde_id;
10138
+ UPDATE public.voorraad_floriday_versieronde_stand SET ronde_id = NULL, laatste_einde_at = now(), updated_at = now() WHERE connection_id = p_connection_id;
10139
+ RETURN jsonb_build_object('ok', false, 'afgerond', true, 'status', 'mislukt');
10140
+ END IF;
10141
+
10142
+ INSERT INTO public.voorraad_floriday_versieronde_uitkomst(ronde_id, floriday_id, status, opvolger_id, bron, reden)
10143
+ SELECT p_ronde_id, e->>'floriday_id', e->>'status', NULLIF(e->>'opvolger_id',''), NULLIF(e->>'bron',''), NULLIF(e->>'reden','')
10144
+ FROM jsonb_array_elements(CASE WHEN jsonb_typeof(p_uitkomsten) = 'array' THEN p_uitkomsten ELSE '[]'::jsonb END) e
10145
+ WHERE e->>'status' IN ('actueel','vervangen','vervallen','fout') AND NULLIF(e->>'floriday_id','') IS NOT NULL
10146
+ ON CONFLICT (ronde_id, floriday_id) DO NOTHING;
10147
+
10148
+ SELECT count(*) INTO v_rest FROM public.floriday_trade_items_cache t
10149
+ WHERE t.connection_id = p_connection_id AND NOT (COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false))
10150
+ AND NOT EXISTS (SELECT 1 FROM public.voorraad_floriday_versieronde_uitkomst u WHERE u.ronde_id = p_ronde_id AND u.floriday_id = t.floriday_id);
10151
+ IF v_rest > 0 THEN RETURN jsonb_build_object('ok', true, 'afgerond', false, 'resterend', v_rest); END IF;
10152
+
10153
+ -- Afronden: foutentellers per artikel (één keer per ronde).
10154
+ INSERT INTO public.voorraad_floriday_versie_fouten(connection_id, floriday_id, opeenvolgend, laatste_reden)
10155
+ SELECT p_connection_id, u.floriday_id, 1, u.reden FROM public.voorraad_floriday_versieronde_uitkomst u WHERE u.ronde_id = p_ronde_id AND u.status = 'fout'
10156
+ ON CONFLICT (connection_id, floriday_id) DO UPDATE SET opeenvolgend = public.voorraad_floriday_versie_fouten.opeenvolgend + 1,
10157
+ laatste_reden = EXCLUDED.laatste_reden, updated_at = now();
10158
+ UPDATE public.voorraad_floriday_versie_fouten SET onbekend_sinds = now()
10159
+ WHERE connection_id = p_connection_id AND opeenvolgend >= 3 AND onbekend_sinds IS NULL;
10160
+ DELETE FROM public.voorraad_floriday_versie_fouten f USING public.voorraad_floriday_versieronde_uitkomst u
10161
+ WHERE f.connection_id = p_connection_id AND u.ronde_id = p_ronde_id AND u.floriday_id = f.floriday_id AND u.status <> 'fout';
10162
+ SELECT count(*) FILTER (WHERE f.opeenvolgend < 3), count(*) FILTER (WHERE f.opeenvolgend >= 3) INTO n_blok, n_onb
10163
+ FROM public.voorraad_floriday_versieronde_uitkomst u JOIN public.voorraad_floriday_versie_fouten f
10164
+ ON f.connection_id = p_connection_id AND f.floriday_id = u.floriday_id
10165
+ WHERE u.ronde_id = p_ronde_id AND u.status = 'fout';
10166
+
10167
+ IF n_blok > 0 THEN
10168
+ INSERT INTO public.voorraad_floriday_versie_rondes(connection_id, volledig, fouten, status, gemarkeerd, onbekend, melding)
10169
+ VALUES (p_connection_id, false, n_blok, 'onvolledig', false, n_onb,
10170
+ n_blok || CASE WHEN n_blok = 1 THEN ' artikel gaf' ELSE ' artikelen gaven' END || ' geen antwoord; volgende ronde opnieuw')
10171
+ RETURNING id INTO v_rid;
10172
+ v_status := 'onvolledig';
10173
+ ELSE
10174
+ SELECT COALESCE(jsonb_agg(jsonb_build_object('floriday_id', u.floriday_id, 'status', u.status, 'opvolger_id', u.opvolger_id, 'bron', u.bron)), '[]'::jsonb)
10175
+ INTO v_uit FROM public.voorraad_floriday_versieronde_uitkomst u WHERE u.ronde_id = p_ronde_id AND u.status <> 'fout';
10176
+ v_res := public.voorraad_floriday_versies_vastleggen(p_connection_id, jsonb_build_object('volledig', true, 'fouten', 0, 'uitkomsten', v_uit));
10177
+ v_rid := (v_res->>'ronde_id')::uuid;
10178
+ v_status := CASE WHEN (v_res->>'ok')::boolean THEN 'geslaagd' ELSE 'mislukt' END;
10179
+ v_meld := CASE WHEN v_status = 'mislukt' THEN 'te veel artikelen lijken tegelijk vervallen; ter controle is niets aangepast' END;
10180
+ UPDATE public.voorraad_floriday_versie_rondes SET status = v_status, onbekend = n_onb, melding = COALESCE(v_meld, melding) WHERE id = v_rid;
10181
+ END IF;
10182
+ DELETE FROM public.voorraad_floriday_versieronde_uitkomst WHERE ronde_id = p_ronde_id;
10183
+ UPDATE public.voorraad_floriday_versieronde_stand SET ronde_id = NULL, laatste_einde_at = now(), updated_at = now() WHERE connection_id = p_connection_id;
10184
+ IF v_status = 'geslaagd' THEN
10185
+ PERFORM public.voorraad_floriday_artikelen_aanmaken(p_connection_id, 500, true, 30);
10186
+ PERFORM public.voorraad_floriday_vervallen_verwerken(true);
10187
+ END IF;
10188
+ RETURN jsonb_build_object('ok', v_status = 'geslaagd', 'afgerond', true, 'status', v_status, 'onbekend', n_onb, 'blokkerend', n_blok, 'ronde', v_res);
10189
+ END $function$
10190
+ ;
10191
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_portie(uuid,uuid,jsonb,text) FROM PUBLIC;
10192
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_portie(uuid,uuid,jsonb,text) FROM anon;
10193
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_portie(uuid,uuid,jsonb,text) TO authenticated;
10194
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_portie(uuid,uuid,jsonb,text) TO service_role;
10195
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versieronde_status()
10196
+ RETURNS jsonb
10197
+ LANGUAGE plpgsql
10198
+ STABLE SECURITY DEFINER
10199
+ SET search_path TO 'public'
10200
+ AS $function$
10201
+ DECLARE v_conn uuid; v_beh boolean;
10202
+ BEGIN
10203
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_floriday_versieronde_status');
10204
+ v_beh := public.voorraad_is_beheerder();
10205
+ IF NOT v_beh THEN RETURN jsonb_build_object('beheerder', false); END IF;
10206
+ BEGIN SELECT x.connection_id INTO v_conn FROM public.get_active_floriday_context() x LIMIT 1;
10207
+ EXCEPTION WHEN others THEN v_conn := NULL; END;
10208
+ RETURN jsonb_build_object('beheerder', true, 'heeft_koppeling', v_conn IS NOT NULL,
10209
+ 'laatste', (SELECT jsonb_build_object('uitgevoerd_at', r.uitgevoerd_at, 'status', COALESCE(r.status, CASE WHEN r.gemarkeerd THEN 'geslaagd' ELSE 'mislukt' END),
10210
+ 'melding', r.melding, 'gecontroleerd', r.gecontroleerd, 'vervangen', r.vervangen, 'vervallen', r.vervallen, 'onbekend', r.onbekend)
10211
+ FROM public.voorraad_floriday_versie_rondes r WHERE r.connection_id = v_conn ORDER BY r.uitgevoerd_at DESC LIMIT 1),
10212
+ 'bezig', EXISTS (SELECT 1 FROM public.voorraad_floriday_versieronde_stand s WHERE s.connection_id = v_conn AND s.ronde_id IS NOT NULL),
10213
+ 'geslaagd_ooit', COALESCE(public.voorraad_floriday_versieronde_geslaagd(v_conn), false),
10214
+ 'vervangen', (SELECT count(*) FROM public.voorraad_floriday_vervallen v WHERE v.opgeheven_at IS NULL AND v.status = 'vervangen'),
10215
+ 'vervallen', (SELECT count(*) FROM public.voorraad_floriday_vervallen v WHERE v.opgeheven_at IS NULL AND v.status = 'vervallen'),
10216
+ 'onbekend', (SELECT count(*) FROM public.voorraad_floriday_versie_fouten f WHERE f.connection_id = v_conn AND f.onbekend_sinds IS NOT NULL));
10217
+ END $function$
10218
+ ;
10219
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_status() FROM PUBLIC;
10220
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_status() FROM anon;
10221
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_status() TO authenticated;
10222
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_status() TO service_role;
10223
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versieronde_volgende(p_connection_id uuid, p_aantal integer DEFAULT 200)
10224
+ RETURNS jsonb
10225
+ LANGUAGE plpgsql
10226
+ SECURITY DEFINER
10227
+ SET search_path TO 'public'
10228
+ AS $function$
10229
+ DECLARE v_ronde uuid; v_ids jsonb;
10230
+ BEGIN
10231
+ PERFORM public.voorraad_vereis('server', 'voorraad_floriday_versieronde_volgende');
10232
+ INSERT INTO public.voorraad_floriday_versieronde_stand(connection_id) VALUES (p_connection_id) ON CONFLICT (connection_id) DO NOTHING;
10233
+ SELECT ronde_id INTO v_ronde FROM public.voorraad_floriday_versieronde_stand WHERE connection_id = p_connection_id FOR UPDATE;
10234
+ IF v_ronde IS NULL THEN
10235
+ v_ronde := gen_random_uuid();
10236
+ UPDATE public.voorraad_floriday_versieronde_stand SET ronde_id = v_ronde, gestart_at = now(), updated_at = now() WHERE connection_id = p_connection_id;
10237
+ END IF;
10238
+ SELECT COALESCE(jsonb_agg(x.floriday_id), '[]'::jsonb) INTO v_ids FROM (
10239
+ SELECT t.floriday_id FROM public.floriday_trade_items_cache t
10240
+ WHERE t.connection_id = p_connection_id AND NOT (COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false))
10241
+ AND NOT EXISTS (SELECT 1 FROM public.voorraad_floriday_versieronde_uitkomst u WHERE u.ronde_id = v_ronde AND u.floriday_id = t.floriday_id)
10242
+ ORDER BY t.floriday_id LIMIT GREATEST(LEAST(COALESCE(p_aantal, 200), 500), 1)) x;
10243
+ RETURN jsonb_build_object('ronde_id', v_ronde, 'ids', v_ids);
10244
+ END $function$
10245
+ ;
10246
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_volgende(uuid,integer) FROM PUBLIC;
10247
+ REVOKE ALL ON FUNCTION voorraad_floriday_versieronde_volgende(uuid,integer) FROM anon;
10248
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_volgende(uuid,integer) TO authenticated;
10249
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versieronde_volgende(uuid,integer) TO service_role;
10250
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_versies_vastleggen(p_connection_id uuid, p_ronde jsonb, p_max_aandeel numeric DEFAULT 0.5)
10251
+ RETURNS jsonb
10252
+ LANGUAGE plpgsql
10253
+ SECURITY DEFINER
10254
+ SET search_path TO 'public'
10255
+ AS $function$
10256
+ DECLARE v_vol boolean; v_fout int; v_gec int; v_cache int; n_act int; n_verv int; n_vall int; v_ok boolean := false; v_meld text;
10257
+ v_ronde uuid; v_uit jsonb; v_res jsonb := NULL;
10258
+ BEGIN
10259
+ PERFORM public.voorraad_vereis('server', 'voorraad_floriday_versies_vastleggen');
10260
+ IF p_connection_id IS NULL THEN RAISE EXCEPTION 'Geen Floriday-koppeling opgegeven' USING ERRCODE = '22023'; END IF;
10261
+ v_uit := CASE WHEN jsonb_typeof(p_ronde->'uitkomsten') = 'array' THEN p_ronde->'uitkomsten' ELSE '[]'::jsonb END;
10262
+ v_vol := COALESCE((p_ronde->>'volledig')::boolean, false);
10263
+ v_fout := COALESCE((p_ronde->>'fouten')::int, 0);
10264
+ v_gec := jsonb_array_length(v_uit);
10265
+ SELECT count(*) INTO v_cache FROM public.floriday_trade_items_cache t
10266
+ WHERE t.connection_id = p_connection_id AND NOT (COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false));
10267
+ SELECT count(*) FILTER (WHERE e->>'status' = 'actueel'), count(*) FILTER (WHERE e->>'status' = 'vervangen'), count(*) FILTER (WHERE e->>'status' = 'vervallen')
10268
+ INTO n_act, n_verv, n_vall FROM jsonb_array_elements(v_uit) e;
10269
+ IF NOT v_vol OR v_fout > 0 THEN
10270
+ v_meld := 'Onvolledige of mislukte ronde: niets als vervallen gemarkeerd';
10271
+ ELSIF v_gec + (SELECT count(*) FROM public.voorraad_floriday_versie_fouten f JOIN public.floriday_trade_items_cache t
10272
+ ON t.connection_id = f.connection_id AND t.floriday_id = f.floriday_id
10273
+ WHERE f.connection_id = p_connection_id AND f.onbekend_sinds IS NOT NULL
10274
+ AND NOT EXISTS (SELECT 1 FROM jsonb_array_elements(v_uit) e WHERE e->>'floriday_id' = f.floriday_id)) < v_cache THEN
10275
+ v_meld := format('Ronde controleerde %s van %s Floriday-artikelen: niets als vervallen gemarkeerd', v_gec, v_cache);
10276
+ ELSIF v_gec > 0 AND (n_verv + n_vall)::numeric / v_gec > p_max_aandeel THEN
10277
+ v_meld := format('%s van %s artikelen zouden vervallen (meer dan %s%%): niets gemarkeerd, controleer de koppeling', n_verv + n_vall, v_gec, round(p_max_aandeel * 100));
10278
+ ELSE
10279
+ v_ok := true;
10280
+ END IF;
10281
+ INSERT INTO public.voorraad_floriday_versie_rondes(connection_id, volledig, fouten, gecontroleerd, in_cache, actueel, vervangen, vervallen, gemarkeerd, melding)
10282
+ VALUES (p_connection_id, v_vol, v_fout, v_gec, v_cache, n_act, n_verv, n_vall, v_ok, v_meld) RETURNING id INTO v_ronde;
10283
+ IF v_ok THEN
10284
+ INSERT INTO public.voorraad_floriday_vervallen(floriday_id, connection_id, status, opvolger_id, bron, ronde_id)
10285
+ SELECT e->>'floriday_id', p_connection_id, e->>'status', NULLIF(e->>'opvolger_id',''), COALESCE(NULLIF(e->>'bron',''), 'volledige_ronde'), v_ronde
10286
+ FROM jsonb_array_elements(v_uit) e WHERE e->>'status' IN ('vervangen','vervallen') AND NULLIF(e->>'floriday_id','') IS NOT NULL
10287
+ ON CONFLICT (floriday_id) DO UPDATE SET status = EXCLUDED.status, opvolger_id = EXCLUDED.opvolger_id, bron = EXCLUDED.bron,
10288
+ ronde_id = EXCLUDED.ronde_id, opgeheven_at = NULL,
10289
+ verwerkt_at = CASE WHEN public.voorraad_floriday_vervallen.opgeheven_at IS NOT NULL THEN NULL ELSE public.voorraad_floriday_vervallen.verwerkt_at END;
10290
+ -- Weer actueel: markering opheffen (gearchiveerde artikelen blijven gearchiveerd).
10291
+ UPDATE public.voorraad_floriday_vervallen v SET opgeheven_at = now()
10292
+ FROM jsonb_array_elements(v_uit) e
10293
+ WHERE e->>'status' = 'actueel' AND v.floriday_id = e->>'floriday_id' AND v.opgeheven_at IS NULL;
10294
+ v_res := public.voorraad_floriday_vervallen_verwerken(true);
10295
+ END IF;
10296
+ RETURN jsonb_build_object('ok', v_ok, 'ronde_id', v_ronde, 'melding', v_meld, 'gecontroleerd', v_gec, 'in_cache', v_cache,
10297
+ 'actueel', n_act, 'vervangen', n_verv, 'vervallen', n_vall, 'verwerkt', v_res);
10298
+ END $function$
10299
+ ;
10300
+ REVOKE ALL ON FUNCTION voorraad_floriday_versies_vastleggen(uuid,jsonb,numeric) FROM PUBLIC;
10301
+ REVOKE ALL ON FUNCTION voorraad_floriday_versies_vastleggen(uuid,jsonb,numeric) FROM anon;
10302
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versies_vastleggen(uuid,jsonb,numeric) TO authenticated;
10303
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_versies_vastleggen(uuid,jsonb,numeric) TO service_role;
10304
+ CREATE OR REPLACE FUNCTION public.voorraad_floriday_vervallen_verwerken(p_uitvoeren boolean DEFAULT true)
10305
+ RETURNS jsonb
10306
+ LANGUAGE plpgsql
10307
+ SECURITY DEFINER
10308
+ SET search_path TO 'public'
10309
+ AS $function$
10310
+ DECLARE r record; v_best uuid; v_opv uuid; v_new uuid; c record; v_name text; v_code text; v_gtin text;
10311
+ n_alias int := 0; n_arch int := 0; n_best int := 0; n_wacht int := 0; v_run uuid := gen_random_uuid();
10312
+ BEGIN
10313
+ PERFORM public.voorraad_vereis('server', 'voorraad_floriday_vervallen_verwerken');
10314
+ IF p_uitvoeren THEN PERFORM set_config('voorraad.floriday_sync', 'on', true); END IF;
10315
+ FOR r IN SELECT * FROM public.voorraad_floriday_vervallen WHERE opgeheven_at IS NULL AND verwerkt_at IS NULL ORDER BY floriday_id LOOP
10316
+ v_best := public.voorraad_floriday_product_van(r.floriday_id);
10317
+ IF v_best IS NOT NULL THEN
10318
+ n_best := n_best + 1;
10319
+ IF p_uitvoeren THEN
10320
+ UPDATE public.voorraad_floriday_vervallen SET verwerkt_at = now(), uitkomst = 'bestaand_artikel', product_id = v_best WHERE floriday_id = r.floriday_id;
10321
+ END IF;
10322
+ CONTINUE;
10323
+ END IF;
10324
+ IF r.opvolger_id IS NOT NULL THEN
10325
+ v_opv := public.voorraad_floriday_product_van(r.opvolger_id);
10326
+ IF v_opv IS NULL THEN n_wacht := n_wacht + 1; CONTINUE; END IF;
10327
+ n_alias := n_alias + 1;
10328
+ IF p_uitvoeren THEN
10329
+ INSERT INTO public.voorraad_floriday_alias(floriday_id, product_id, bron) VALUES (r.floriday_id, v_opv, r.bron)
10330
+ ON CONFLICT (floriday_id) DO NOTHING;
10331
+ UPDATE public.voorraad_floriday_vervallen SET verwerkt_at = now(), uitkomst = 'alias', product_id = v_opv WHERE floriday_id = r.floriday_id;
10332
+ INSERT INTO public.voorraad_koppel_log(run_id, soort, floriday_id, product_id, oud, nieuw)
10333
+ VALUES (v_run, 'vervallen_alias', r.floriday_id, v_opv, NULL, jsonb_build_object('opvolger', r.opvolger_id, 'bron', r.bron));
10334
+ END IF;
10335
+ CONTINUE;
10336
+ END IF;
10337
+ n_arch := n_arch + 1;
10338
+ IF p_uitvoeren THEN
10339
+ SELECT t.data INTO c FROM public.floriday_trade_items_cache t WHERE t.floriday_id = r.floriday_id LIMIT 1;
10340
+ v_name := NULLIF(btrim(COALESCE(CASE WHEN jsonb_typeof(c.data->'tradeItemName') = 'string' THEN c.data->>'tradeItemName' END,
10341
+ c.data->'tradeItemName'->>'nl', c.data->'tradeItemName'->>'en')), '');
10342
+ v_code := NULLIF(btrim(COALESCE(c.data->>'supplierArticleCode', c.data->>'articleCode')), '');
10343
+ v_gtin := NULLIF(btrim(COALESCE(c.data->>'articleGtin', c.data->>'gtin')), '');
10344
+ INSERT INTO public.products(product, batch, location, barcode, article_number, floriday_trade_item_id, trade_item_key, custom_fields, gearchiveerd_at)
10345
+ VALUES (COALESCE(v_name, '(vervallen Floriday-versie)'), '', '', v_gtin, v_code, r.floriday_id, r.floriday_id,
10346
+ jsonb_build_object('voorraad_auto_aangemaakt', true, 'voorraad_floriday_vervallen', true, 'voorraad_floriday_vervallen_bron', r.bron,
10347
+ 'voorraad_auto_aangemaakt_at', now()), now())
10348
+ RETURNING id INTO v_new;
10349
+ UPDATE public.floriday_inventory_settings SET erp_leading = NULL, stock_mode = 'DISABLED', updated_at = now() WHERE product_id = v_new;
10350
+ UPDATE public.voorraad_floriday_vervallen SET verwerkt_at = now(), uitkomst = 'gearchiveerd_aangemaakt', product_id = v_new WHERE floriday_id = r.floriday_id;
10351
+ INSERT INTO public.voorraad_koppel_log(run_id, soort, floriday_id, product_id, oud, nieuw)
10352
+ VALUES (v_run, 'vervallen_gearchiveerd', r.floriday_id, v_new, NULL, jsonb_build_object('naam', v_name, 'bron', r.bron));
10353
+ END IF;
10354
+ END LOOP;
10355
+ RETURN jsonb_build_object('alias', n_alias, 'gearchiveerd', n_arch, 'bestaand_artikel', n_best, 'wacht_op_opvolger', n_wacht, 'uitgevoerd', p_uitvoeren);
10356
+ END $function$
10357
+ ;
10358
+ REVOKE ALL ON FUNCTION voorraad_floriday_vervallen_verwerken(boolean) FROM PUBLIC;
10359
+ REVOKE ALL ON FUNCTION voorraad_floriday_vervallen_verwerken(boolean) FROM anon;
10360
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_vervallen_verwerken(boolean) TO authenticated;
10361
+ GRANT EXECUTE ON FUNCTION voorraad_floriday_vervallen_verwerken(boolean) TO service_role;
9838
10362
  CREATE OR REPLACE FUNCTION public.voorraad_floriday_volgt(p_product_id uuid)
9839
10363
  RETURNS boolean
9840
10364
  LANGUAGE plpgsql
@@ -9913,6 +10437,29 @@ REVOKE ALL ON FUNCTION voorraad_fust_dimensions() FROM PUBLIC;
9913
10437
  REVOKE ALL ON FUNCTION voorraad_fust_dimensions() FROM anon;
9914
10438
  GRANT EXECUTE ON FUNCTION voorraad_fust_dimensions() TO authenticated;
9915
10439
  GRANT EXECUTE ON FUNCTION voorraad_fust_dimensions() TO service_role;
10440
+ CREATE OR REPLACE FUNCTION public.voorraad_fust_historisch_vervallen(p_order_item_id uuid)
10441
+ RETURNS boolean
10442
+ LANGUAGE plpgsql
10443
+ STABLE SECURITY DEFINER
10444
+ SET search_path TO 'public'
10445
+ AS $function$
10446
+ DECLARE v record; v_ti text;
10447
+ BEGIN
10448
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_fust_historisch_vervallen');
10449
+ SELECT oi.order_id, oi.product_id, oi.source_line_key, p.custom_fields->>'voorraad_floriday_vervallen' AS verv
10450
+ INTO v FROM public.order_items oi LEFT JOIN public.products p ON p.id = oi.product_id WHERE oi.id = p_order_item_id;
10451
+ IF v.order_id IS NULL OR v.product_id IS NULL THEN RETURN false; END IF;
10452
+ IF NOT public.voorraad_order_vertrokken_voor(v.order_id, now()) THEN RETURN false; END IF;
10453
+ IF v.verv = 'true' THEN RETURN true; END IF;
10454
+ IF NULLIF(btrim(COALESCE(v.source_line_key,'')),'') IS NULL THEN RETURN false; END IF;
10455
+ v_ti := lower(COALESCE(public.voorraad_orderregel_trade_item_bron(v.order_id, v.source_line_key)->>'trade_item_id',''));
10456
+ RETURN v_ti <> '' AND EXISTS (SELECT 1 FROM public.voorraad_floriday_alias a WHERE lower(a.floriday_id) = v_ti);
10457
+ END $function$
10458
+ ;
10459
+ REVOKE ALL ON FUNCTION voorraad_fust_historisch_vervallen(uuid) FROM PUBLIC;
10460
+ REVOKE ALL ON FUNCTION voorraad_fust_historisch_vervallen(uuid) FROM anon;
10461
+ GRANT EXECUTE ON FUNCTION voorraad_fust_historisch_vervallen(uuid) TO authenticated;
10462
+ GRANT EXECUTE ON FUNCTION voorraad_fust_historisch_vervallen(uuid) TO service_role;
9916
10463
  CREATE OR REPLACE FUNCTION public.voorraad_fust_instellingen_opslaan(p_fust_type_id uuid, p_saldo_bijhouden boolean, p_eigen_naam text)
9917
10464
  RETURNS jsonb
9918
10465
  LANGUAGE plpgsql
@@ -9995,6 +10542,9 @@ BEGIN
9995
10542
  -- Vóór het fust-startmoment: geen herberekening, het geboekte aantal blijft juist.
9996
10543
  aantal := COALESCE((SELECT sum(b.quantity)::int FROM public.order_fust_bookings b WHERE b.order_item_id = p_order_item_id AND b.fust_type_id = v_ft), 0);
9997
10544
  bron := 'vóór fust-startmoment: niet herberekend';
10545
+ ELSIF public.voorraad_fust_historisch_vervallen(p_order_item_id) THEN
10546
+ aantal := COALESCE((SELECT sum(b.quantity)::int FROM public.order_fust_bookings b WHERE b.order_item_id = p_order_item_id AND b.fust_type_id = v_ft), 0);
10547
+ bron := 'historische regel van vervallen Floriday-versie: niet herberekend';
9998
10548
  END IF;
9999
10549
  RETURN NEXT;
10000
10550
  END $function$
@@ -10238,7 +10788,7 @@ CREATE OR REPLACE FUNCTION public.voorraad_install_check()
10238
10788
  STABLE SECURITY DEFINER
10239
10789
  SET search_path TO 'public'
10240
10790
  AS $function$
10241
- DECLARE v_f text[] := ARRAY['voorraad_instellingen_lezen','voorraad_twijfel_nieuw_artikel','voorraad_eigen_velden_opslaan','voorraad_traysticker_opslaan','voorraad_floriday_volgt','voorraad_artikel_archiveren','voorraad_orders_gearchiveerd','voorraad_twijfel_kiezen','voorraad_twijfel_lijst','voorraad_voorraad_instellingen_opslaan','voorraad_artikel_detail','voorraad_artikel_opslaan','voorraad_voorraad_corrigeren','voorraad_lijst','voorraad_floriday_artikelen_aanmaken','voorraad_floriday_artikelen_vangnet','voorraad_orderregel_trade_item','voorraad_orderregel_trade_item_bron','voorraad_correctie_1144','voorraad_telmoment_lijst','voorraad_telmoment_opslaan','voorraad_order_vertrokken_voor','voorraad_fust_startmoment_opslaan','voorraad_fust_startmoment_auto','voorraad_fust_instellingen_opslaan','voorraad_koppeling_check','voorraad_instellingen_opslaan','voorraad_ensure_defaults','voorraad_defaults_check','voorraad_defaults_versie','voorraad_canoniek_artikel','voorraad_canoniek_sleutel','voorraad_artikel_prijs','voorraad_dubbele_voorraadregels','voorraad_correctie_1131','voorraad_correctie_1132','voorraad_gateway_routes_check','voorraad_placeholder_code_reason','trg_products_placeholder_code','voorraad_fust_juist','voorraad_correctie_1121','voorraad_correctie_1121_regels','voorraad_correctie_1123','voorraad_correctie_1124','voorraad_load_carriers','voorraad_packing_from_floriday','voorraad_packing_missing','voorraad_correctie_1126','voorraad_correctie_1127','trg_voorraad_link_primary_packing','voorraad_order_geannuleerd','voorraad_article_vbn','voorraad_correctie_1112','voorraad_reverse_order_mutations','voorraad_withdraw_stock_row','voorraad_floriday_klaarzetten_toegestaan','voorraad_afboeken','voorraad_voorraad_opslaan','voorraad_correctie_1140','voorraad_overzicht_orderregel_koppeling','voorraad_orderregel_sleutel','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'];
10791
+ DECLARE v_f text[] := ARRAY['voorraad_floriday_versieronde_geslaagd','voorraad_is_beheerder','voorraad_floriday_versieronde_volgende','voorraad_floriday_versieronde_portie','run_floriday_versieronde','voorraad_floriday_versieronde_inplannen','voorraad_floriday_versieronde_melding','voorraad_floriday_versieronde_status','voorraad_floriday_product_van','voorraad_floriday_vervallen_verwerken','voorraad_floriday_versies_vastleggen','voorraad_fust_historisch_vervallen','voorraad_correctie_1148','voorraad_instellingen_lezen','voorraad_twijfel_nieuw_artikel','voorraad_eigen_velden_opslaan','voorraad_traysticker_opslaan','voorraad_floriday_volgt','voorraad_artikel_archiveren','voorraad_orders_gearchiveerd','voorraad_twijfel_kiezen','voorraad_twijfel_lijst','voorraad_voorraad_instellingen_opslaan','voorraad_artikel_detail','voorraad_artikel_opslaan','voorraad_voorraad_corrigeren','voorraad_lijst','voorraad_floriday_artikelen_aanmaken','voorraad_floriday_artikelen_vangnet','voorraad_orderregel_trade_item','voorraad_orderregel_trade_item_bron','voorraad_correctie_1144','voorraad_telmoment_lijst','voorraad_telmoment_opslaan','voorraad_order_vertrokken_voor','voorraad_fust_startmoment_opslaan','voorraad_fust_startmoment_auto','voorraad_fust_instellingen_opslaan','voorraad_koppeling_check','voorraad_instellingen_opslaan','voorraad_ensure_defaults','voorraad_defaults_check','voorraad_defaults_versie','voorraad_canoniek_artikel','voorraad_canoniek_sleutel','voorraad_artikel_prijs','voorraad_dubbele_voorraadregels','voorraad_correctie_1131','voorraad_correctie_1132','voorraad_gateway_routes_check','voorraad_placeholder_code_reason','trg_products_placeholder_code','voorraad_fust_juist','voorraad_correctie_1121','voorraad_correctie_1121_regels','voorraad_correctie_1123','voorraad_correctie_1124','voorraad_load_carriers','voorraad_packing_from_floriday','voorraad_packing_missing','voorraad_correctie_1126','voorraad_correctie_1127','trg_voorraad_link_primary_packing','voorraad_order_geannuleerd','voorraad_article_vbn','voorraad_correctie_1112','voorraad_reverse_order_mutations','voorraad_withdraw_stock_row','voorraad_floriday_klaarzetten_toegestaan','voorraad_afboeken','voorraad_voorraad_opslaan','voorraad_correctie_1140','voorraad_overzicht_orderregel_koppeling','voorraad_orderregel_sleutel','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'];
10242
10792
  v_t text[] := ARRAY['trg_voorraad_link_primary_packing@products','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'];
10243
10793
  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','Ingelogd mag standaardstatus lezen@voorraad_defaults_state','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'];
10244
10794
  v_open text[] := ARRAY['voorraad_is_server','voorraad_vereis'];
@@ -10320,6 +10870,22 @@ REVOKE ALL ON FUNCTION voorraad_instellingen_opslaan(text) FROM PUBLIC;
10320
10870
  REVOKE ALL ON FUNCTION voorraad_instellingen_opslaan(text) FROM anon;
10321
10871
  GRANT EXECUTE ON FUNCTION voorraad_instellingen_opslaan(text) TO authenticated;
10322
10872
  GRANT EXECUTE ON FUNCTION voorraad_instellingen_opslaan(text) TO service_role;
10873
+ CREATE OR REPLACE FUNCTION public.voorraad_is_beheerder()
10874
+ RETURNS boolean
10875
+ LANGUAGE plpgsql
10876
+ STABLE SECURITY DEFINER
10877
+ SET search_path TO 'public'
10878
+ AS $function$
10879
+ BEGIN
10880
+ PERFORM public.voorraad_vereis('ingelogd', 'voorraad_is_beheerder');
10881
+ IF public.voorraad_is_server() THEN RETURN true; END IF;
10882
+ RETURN EXISTS (SELECT 1 FROM public.user_roles r WHERE r.user_id = auth.uid() AND r.role::text IN ('admin','superadmin'));
10883
+ END $function$
10884
+ ;
10885
+ REVOKE ALL ON FUNCTION voorraad_is_beheerder() FROM PUBLIC;
10886
+ REVOKE ALL ON FUNCTION voorraad_is_beheerder() FROM anon;
10887
+ GRANT EXECUTE ON FUNCTION voorraad_is_beheerder() TO authenticated;
10888
+ GRANT EXECUTE ON FUNCTION voorraad_is_beheerder() TO service_role;
10323
10889
  CREATE OR REPLACE FUNCTION public.voorraad_is_server()
10324
10890
  RETURNS boolean
10325
10891
  LANGUAGE sql
@@ -10352,7 +10918,8 @@ BEGIN
10352
10918
  SELECT count(*) INTO v_zonder FROM public.floriday_trade_items_cache t
10353
10919
  WHERE NOT (COALESCE(t.is_deleted,false) OR COALESCE((t.data->>'isDeleted')::boolean,false))
10354
10920
  AND t.connection_id = (SELECT x.connection_id FROM public.get_active_floriday_context() x LIMIT 1)
10355
- AND NOT EXISTS (SELECT 1 FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = lower(t.floriday_id));
10921
+ AND NOT EXISTS (SELECT 1 FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = lower(t.floriday_id))
10922
+ AND NOT EXISTS (SELECT 1 FROM public.voorraad_floriday_vervallen v WHERE v.floriday_id = t.floriday_id AND v.opgeheven_at IS NULL);
10356
10923
  SELECT count(*) INTO v_twijfel FROM public.voorraad_koppel_twijfel WHERE opgelost_at IS NULL;
10357
10924
  v_start := EXISTS (SELECT 1 FROM public.fust_startmoment);
10358
10925
  IF jsonb_array_length(v_dups) > 0 THEN v_f := v_f || to_jsonb('Er zijn artikelen met hetzelfde Floriday-id; automatisch aanmaken staat stil'::text); END IF;
@@ -10396,7 +10963,7 @@ DECLARE
10396
10963
  v_tel jsonb; v_totaal int; v_rijen jsonb; v_meld jsonb; v_twijfel int; v_twijfel_rijen jsonb := '[]'::jsonb;
10397
10964
  BEGIN
10398
10965
  PERFORM public.voorraad_vereis('ingelogd', 'voorraad_lijst');
10399
- IF COALESCE(p_filter,'alles') NOT IN ('alles','onder_minimum','verpakking','niet_gekoppeld','prijs','twijfel','gearchiveerd') THEN
10966
+ IF COALESCE(p_filter,'alles') NOT IN ('alles','onder_minimum','verpakking','niet_gekoppeld','verwijderd_floriday','prijs','twijfel','gearchiveerd') THEN
10400
10967
  RAISE EXCEPTION 'Onbekend filter "%"', p_filter USING ERRCODE = '22023';
10401
10968
  END IF;
10402
10969
  IF COALESCE(p_sort,'naam') NOT IN ('naam','artikelnummer','liggend','gereserveerd','vrij','inkomend','prijs') THEN
@@ -10420,7 +10987,7 @@ BEGIN
10420
10987
  COALESCE(NULLIF(btrim(p.product),''), NULLIF(p.custom_fields#>>'{floriday_payload,name}',''), '(naamloos)') AS naam,
10421
10988
  COALESCE(NULLIF(btrim(p.article_number),''), NULLIF(p.custom_fields#>>'{floriday_payload,articleCode}','')) AS artikelnummer,
10422
10989
  NULLIF(btrim(COALESCE(p.floriday_trade_item_id,'')),'') AS floriday_id,
10423
- p.sale_price AS prijs, p.unit AS eenheid, p.gearchiveerd_at, p.barcode,
10990
+ p.sale_price AS prijs, p.unit AS eenheid, p.gearchiveerd_at, p.barcode, p.floriday_verwijderd_at,
10424
10991
  -- Voorraadkolommen zijn NOT NULL: COALESCE kiest dus de eerste bestaande rij (s1, dan s2, dan s3).
10425
10992
  COALESCE(s1.physical_stock, s2.physical_stock, s3.physical_stock, 0) AS liggend,
10426
10993
  COALESCE(s1.reserved_stock, s2.reserved_stock, s3.reserved_stock, 0) AS gereserveerd,
@@ -10447,7 +11014,8 @@ BEGIN
10447
11014
  GREATEST(b.liggend - b.gereserveerd, 0) AS vrij,
10448
11015
  (b.minimum > 0 AND (b.liggend - b.gereserveerd) < b.minimum) AS f_onder_minimum,
10449
11016
  (b.soort <> 'GROUP' AND (NOT b.heeft_verpakking OR NOT b.verpakking_ok)) AS f_verpakking,
10450
- (v_kop AND b.floriday_id IS NULL) AS f_niet_gekoppeld,
11017
+ (v_kop AND b.floriday_id IS NULL AND b.floriday_verwijderd_at IS NULL) AS f_niet_gekoppeld,
11018
+ (v_kop AND b.floriday_verwijderd_at IS NOT NULL) AS f_verwijderd_floriday,
10451
11019
  (lower(btrim(COALESCE(b.eenheid,''))) <> 'stuks' OR b.prijs IS NULL OR b.prijs <= 0) AS f_prijs
10452
11020
  FROM basis b
10453
11021
  WHERE v_q IS NULL
@@ -10459,6 +11027,7 @@ BEGIN
10459
11027
  'onder_minimum', count(*) FILTER (WHERE gearchiveerd_at IS NULL AND f_onder_minimum),
10460
11028
  'verpakking', count(*) FILTER (WHERE gearchiveerd_at IS NULL AND f_verpakking),
10461
11029
  'niet_gekoppeld', count(*) FILTER (WHERE gearchiveerd_at IS NULL AND f_niet_gekoppeld),
11030
+ 'verwijderd_floriday', count(*) FILTER (WHERE gearchiveerd_at IS NULL AND f_verwijderd_floriday),
10462
11031
  'prijs', count(*) FILTER (WHERE gearchiveerd_at IS NULL AND f_prijs),
10463
11032
  'gearchiveerd', count(*) FILTER (WHERE gearchiveerd_at IS NOT NULL),
10464
11033
  'onderdelen_zonder_prijs', count(*) FILTER (WHERE gearchiveerd_at IS NULL AND is_onderdeel AND f_prijs)) AS t
@@ -10472,6 +11041,7 @@ BEGIN
10472
11041
  WHEN 'onder_minimum' THEN g.f_onder_minimum
10473
11042
  WHEN 'verpakking' THEN g.f_verpakking
10474
11043
  WHEN 'niet_gekoppeld' THEN g.f_niet_gekoppeld
11044
+ WHEN 'verwijderd_floriday' THEN g.f_verwijderd_floriday
10475
11045
  WHEN 'prijs' THEN g.f_prijs
10476
11046
  ELSE true END
10477
11047
  END
@@ -10499,6 +11069,7 @@ BEGIN
10499
11069
  'voorraad_sleutel', pg.voorraad_sleutel, 'gearchiveerd_at', pg.gearchiveerd_at,
10500
11070
  'onder_minimum', pg.f_onder_minimum,
10501
11071
  'status', CASE WHEN pg.gearchiveerd_at IS NOT NULL THEN 'gearchiveerd'
11072
+ WHEN pg.f_verwijderd_floriday THEN 'verwijderd_floriday'
10502
11073
  WHEN pg.f_verpakking THEN 'verpakking' WHEN pg.f_niet_gekoppeld THEN 'niet_gekoppeld'
10503
11074
  WHEN pg.f_prijs THEN 'prijs' ELSE 'ok' END)
10504
11075
  ORDER BY pg.rn), '[]'::jsonb)
@@ -10526,6 +11097,7 @@ BEGIN
10526
11097
 
10527
11098
  v_meld := jsonb_build_object(
10528
11099
  'telmoment_ontbreekt', NOT EXISTS (SELECT 1 FROM public.voorraad_telmoment),
11100
+ 'versieronde_mislukt', public.voorraad_floriday_versieronde_melding(),
10529
11101
  'onderdelen_zonder_prijs', COALESCE((v_tel->>'onderdelen_zonder_prijs')::int, 0),
10530
11102
  'orders_gearchiveerd', public.voorraad_orders_gearchiveerd(NULL));
10531
11103
 
@@ -10693,6 +11265,7 @@ BEGIN
10693
11265
  IF v_k IS NULL THEN RETURN jsonb_build_object('status', 'geen_match'); END IF;
10694
11266
  IF array_length(v_k, 1) > 1 THEN RETURN jsonb_build_object('status', 'meerdere_kandidaten', 'kandidaten', to_jsonb(v_k)); END IF;
10695
11267
  SELECT array_agg(p.id) INTO v_p FROM public.products p WHERE lower(btrim(p.floriday_trade_item_id)) = v_k[1];
11268
+ IF v_p IS NULL THEN SELECT array_agg(a.product_id) INTO v_p FROM public.voorraad_floriday_alias a WHERE lower(a.floriday_id) = v_k[1]; END IF;
10696
11269
  IF v_p IS NULL THEN RETURN jsonb_build_object('status', 'geen_eigen_artikel', 'trade_item_id', v_k[1]); END IF;
10697
11270
  IF array_length(v_p, 1) > 1 THEN RETURN jsonb_build_object('status', 'meerdere_artikelen', 'trade_item_id', v_k[1], 'artikelen', to_jsonb(v_p)); END IF;
10698
11271
  RETURN jsonb_build_object('status', 'eenduidig', 'trade_item_id', v_k[1], 'product_id', v_p[1]);
@@ -11659,7 +12232,13 @@ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraa
11659
12232
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_correcties_pkey' AND conrelid = 'public.voorraad_correcties'::regclass) THEN ALTER TABLE public.voorraad_correcties ADD CONSTRAINT voorraad_correcties_pkey PRIMARY KEY (id); END IF; END $c$;
11660
12233
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_custom_fields_pkey' AND conrelid = 'public.voorraad_custom_fields'::regclass) THEN ALTER TABLE public.voorraad_custom_fields ADD CONSTRAINT voorraad_custom_fields_pkey PRIMARY KEY (id); END IF; END $c$;
11661
12234
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_defaults_state_pkey' AND conrelid = 'public.voorraad_defaults_state'::regclass) THEN ALTER TABLE public.voorraad_defaults_state ADD CONSTRAINT voorraad_defaults_state_pkey PRIMARY KEY (id); END IF; END $c$;
12235
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_alias_pkey' AND conrelid = 'public.voorraad_floriday_alias'::regclass) THEN ALTER TABLE public.voorraad_floriday_alias ADD CONSTRAINT voorraad_floriday_alias_pkey PRIMARY KEY (floriday_id); END IF; END $c$;
11662
12236
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_artikel_wachtrij_pkey' AND conrelid = 'public.voorraad_floriday_artikel_wachtrij'::regclass) THEN ALTER TABLE public.voorraad_floriday_artikel_wachtrij ADD CONSTRAINT voorraad_floriday_artikel_wachtrij_pkey PRIMARY KEY (floriday_id); END IF; END $c$;
12237
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_versie_fouten_pkey' AND conrelid = 'public.voorraad_floriday_versie_fouten'::regclass) THEN ALTER TABLE public.voorraad_floriday_versie_fouten ADD CONSTRAINT voorraad_floriday_versie_fouten_pkey PRIMARY KEY (connection_id, floriday_id); END IF; END $c$;
12238
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_versie_rondes_pkey' AND conrelid = 'public.voorraad_floriday_versie_rondes'::regclass) THEN ALTER TABLE public.voorraad_floriday_versie_rondes ADD CONSTRAINT voorraad_floriday_versie_rondes_pkey PRIMARY KEY (id); END IF; END $c$;
12239
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_versieronde_stand_pkey' AND conrelid = 'public.voorraad_floriday_versieronde_stand'::regclass) THEN ALTER TABLE public.voorraad_floriday_versieronde_stand ADD CONSTRAINT voorraad_floriday_versieronde_stand_pkey PRIMARY KEY (connection_id); END IF; END $c$;
12240
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_versieronde_uitkomst_pkey' AND conrelid = 'public.voorraad_floriday_versieronde_uitkomst'::regclass) THEN ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ADD CONSTRAINT voorraad_floriday_versieronde_uitkomst_pkey PRIMARY KEY (ronde_id, floriday_id); END IF; END $c$;
12241
+ DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_floriday_vervallen_pkey' AND conrelid = 'public.voorraad_floriday_vervallen'::regclass) THEN ALTER TABLE public.voorraad_floriday_vervallen ADD CONSTRAINT voorraad_floriday_vervallen_pkey PRIMARY KEY (floriday_id); END IF; END $c$;
11663
12242
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_instellingen_pkey' AND conrelid = 'public.voorraad_instellingen'::regclass) THEN ALTER TABLE public.voorraad_instellingen ADD CONSTRAINT voorraad_instellingen_pkey PRIMARY KEY (id); END IF; END $c$;
11664
12243
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_koppel_log_pkey' AND conrelid = 'public.voorraad_koppel_log'::regclass) THEN ALTER TABLE public.voorraad_koppel_log ADD CONSTRAINT voorraad_koppel_log_pkey PRIMARY KEY (id); END IF; END $c$;
11665
12244
  DO $c$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'voorraad_koppel_twijfel_pkey' AND conrelid = 'public.voorraad_koppel_twijfel'::regclass) THEN ALTER TABLE public.voorraad_koppel_twijfel ADD CONSTRAINT voorraad_koppel_twijfel_pkey PRIMARY KEY (floriday_id); END IF; END $c$;
@@ -11790,6 +12369,7 @@ CREATE INDEX IF NOT EXISTS stock_import_runs_user_created_idx ON public.stock_im
11790
12369
  CREATE INDEX IF NOT EXISTS stock_integrity_alerts_open_idx ON public.stock_integrity_alerts USING btree (created_at DESC) WHERE (acknowledged_at IS NULL);
11791
12370
  CREATE INDEX IF NOT EXISTS trade_item_prices_lookup ON public.trade_item_prices USING btree (trade_item_key, price_group_id);
11792
12371
  CREATE INDEX IF NOT EXISTS trade_item_stock_trade_item_key_idx ON public.trade_item_stock USING btree (trade_item_key);
12372
+ CREATE INDEX IF NOT EXISTS voorraad_floriday_alias_lower_idx ON public.voorraad_floriday_alias USING btree (lower(floriday_id));
11793
12373
  CREATE INDEX IF NOT EXISTS voorraad_koppel_log_item_idx ON public.voorraad_koppel_log USING btree (order_item_id);
11794
12374
  CREATE INDEX IF NOT EXISTS voorraad_koppel_log_run_idx ON public.voorraad_koppel_log USING btree (run_id);
11795
12375
  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]));
@@ -11946,10 +12526,34 @@ ALTER TABLE public.voorraad_defaults_state ENABLE ROW LEVEL SECURITY;
11946
12526
  REVOKE ALL ON public.voorraad_defaults_state FROM anon;
11947
12527
  GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_defaults_state TO authenticated;
11948
12528
  GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_defaults_state TO service_role;
12529
+ ALTER TABLE public.voorraad_floriday_alias ENABLE ROW LEVEL SECURITY;
12530
+ REVOKE ALL ON public.voorraad_floriday_alias FROM anon;
12531
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_alias TO authenticated;
12532
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_alias TO service_role;
11949
12533
  ALTER TABLE public.voorraad_floriday_artikel_wachtrij ENABLE ROW LEVEL SECURITY;
11950
12534
  REVOKE ALL ON public.voorraad_floriday_artikel_wachtrij FROM anon;
11951
12535
  GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_artikel_wachtrij TO authenticated;
11952
12536
  GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_artikel_wachtrij TO service_role;
12537
+ ALTER TABLE public.voorraad_floriday_versie_fouten ENABLE ROW LEVEL SECURITY;
12538
+ REVOKE ALL ON public.voorraad_floriday_versie_fouten FROM anon;
12539
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versie_fouten TO authenticated;
12540
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versie_fouten TO service_role;
12541
+ ALTER TABLE public.voorraad_floriday_versie_rondes ENABLE ROW LEVEL SECURITY;
12542
+ REVOKE ALL ON public.voorraad_floriday_versie_rondes FROM anon;
12543
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versie_rondes TO authenticated;
12544
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versie_rondes TO service_role;
12545
+ ALTER TABLE public.voorraad_floriday_versieronde_stand ENABLE ROW LEVEL SECURITY;
12546
+ REVOKE ALL ON public.voorraad_floriday_versieronde_stand FROM anon;
12547
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versieronde_stand TO authenticated;
12548
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versieronde_stand TO service_role;
12549
+ ALTER TABLE public.voorraad_floriday_versieronde_uitkomst ENABLE ROW LEVEL SECURITY;
12550
+ REVOKE ALL ON public.voorraad_floriday_versieronde_uitkomst FROM anon;
12551
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versieronde_uitkomst TO authenticated;
12552
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_versieronde_uitkomst TO service_role;
12553
+ ALTER TABLE public.voorraad_floriday_vervallen ENABLE ROW LEVEL SECURITY;
12554
+ REVOKE ALL ON public.voorraad_floriday_vervallen FROM anon;
12555
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_vervallen TO authenticated;
12556
+ GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_floriday_vervallen TO service_role;
11953
12557
  ALTER TABLE public.voorraad_instellingen ENABLE ROW LEVEL SECURITY;
11954
12558
  REVOKE ALL ON public.voorraad_instellingen FROM anon;
11955
12559
  GRANT DELETE, INSERT, REFERENCES, SELECT, TRIGGER, TRUNCATE, UPDATE ON public.voorraad_instellingen TO authenticated;
@@ -12127,8 +12731,18 @@ DROP POLICY IF EXISTS "Authenticated can update voorraad custom fields" ON publi
12127
12731
  CREATE POLICY "Authenticated can update voorraad custom fields" ON public.voorraad_custom_fields AS PERMISSIVE FOR UPDATE TO authenticated USING (true) WITH CHECK (true);
12128
12732
  DROP POLICY IF EXISTS "Ingelogd mag standaardstatus lezen" ON public.voorraad_defaults_state;
12129
12733
  CREATE POLICY "Ingelogd mag standaardstatus lezen" ON public.voorraad_defaults_state AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12734
+ DROP POLICY IF EXISTS "Ingelogd lezen alias" ON public.voorraad_floriday_alias;
12735
+ CREATE POLICY "Ingelogd lezen alias" ON public.voorraad_floriday_alias AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12130
12736
  DROP POLICY IF EXISTS voorraad_floriday_artikel_wachtrij_lezen ON public.voorraad_floriday_artikel_wachtrij;
12131
12737
  CREATE POLICY voorraad_floriday_artikel_wachtrij_lezen ON public.voorraad_floriday_artikel_wachtrij AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12738
+ DROP POLICY IF EXISTS "Ingelogd lezen versie fouten" ON public.voorraad_floriday_versie_fouten;
12739
+ CREATE POLICY "Ingelogd lezen versie fouten" ON public.voorraad_floriday_versie_fouten AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12740
+ DROP POLICY IF EXISTS "Ingelogd lezen versierondes" ON public.voorraad_floriday_versie_rondes;
12741
+ CREATE POLICY "Ingelogd lezen versierondes" ON public.voorraad_floriday_versie_rondes AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12742
+ DROP POLICY IF EXISTS "Ingelogd lezen versieronde stand" ON public.voorraad_floriday_versieronde_stand;
12743
+ CREATE POLICY "Ingelogd lezen versieronde stand" ON public.voorraad_floriday_versieronde_stand AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12744
+ DROP POLICY IF EXISTS "Ingelogd lezen vervallen" ON public.voorraad_floriday_vervallen;
12745
+ CREATE POLICY "Ingelogd lezen vervallen" ON public.voorraad_floriday_vervallen AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12132
12746
  DROP POLICY IF EXISTS voorraad_instellingen_lezen ON public.voorraad_instellingen;
12133
12747
  CREATE POLICY voorraad_instellingen_lezen ON public.voorraad_instellingen AS PERMISSIVE FOR SELECT TO authenticated USING (true);
12134
12748
  DROP POLICY IF EXISTS voorraad_koppel_log_lezen ON public.voorraad_koppel_log;
@@ -12293,6 +12907,8 @@ DROP TRIGGER IF EXISTS trg_voorraad_buffer_state_updated_at ON public.voorraad_b
12293
12907
  CREATE TRIGGER trg_voorraad_buffer_state_updated_at BEFORE UPDATE ON public.voorraad_buffer_state FOR EACH ROW EXECUTE FUNCTION voorraad_touch_updated_at();
12294
12908
  DROP TRIGGER IF EXISTS update_voorraad_custom_fields_updated_at ON public.voorraad_custom_fields;
12295
12909
  CREATE TRIGGER update_voorraad_custom_fields_updated_at BEFORE UPDATE ON public.voorraad_custom_fields FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
12910
+ DROP TRIGGER IF EXISTS voorraad_floriday_vervallen_touch ON public.voorraad_floriday_vervallen;
12911
+ CREATE TRIGGER voorraad_floriday_vervallen_touch BEFORE UPDATE ON public.voorraad_floriday_vervallen FOR EACH ROW EXECUTE FUNCTION voorraad_touch_updated_at();
12296
12912
  DROP TRIGGER IF EXISTS trg_voorraad_event_log_updated_at ON public.voorraad_logistics_event_log;
12297
12913
  CREATE TRIGGER trg_voorraad_event_log_updated_at BEFORE UPDATE ON public.voorraad_logistics_event_log FOR EACH ROW EXECUTE FUNCTION voorraad_touch_updated_at();
12298
12914
  DROP TRIGGER IF EXISTS update_voorraad_publish_jobs_updated_at ON public.voorraad_publish_jobs;
@@ -12316,3 +12932,7 @@ BEGIN
12316
12932
  RAISE NOTICE 'Voorraad: pg_cron ontbreekt, vaste taken overgeslagen';
12317
12933
  END IF;
12318
12934
  END $cron$;
12935
+
12936
+ -- realtime-publicatie voor live bijwerken van de artikelpagina
12937
+ DO $rt$ BEGIN IF to_regclass('public.products') IS NOT NULL AND EXISTS (SELECT 1 FROM pg_publication WHERE pubname='supabase_realtime') AND NOT EXISTS (SELECT 1 FROM pg_publication_tables WHERE pubname='supabase_realtime' AND schemaname='public' AND tablename='products') THEN ALTER PUBLICATION supabase_realtime ADD TABLE public.products; END IF; END $rt$;
12938
+ DO $rt$ BEGIN IF to_regclass('public.trade_item_stock') IS NOT NULL AND EXISTS (SELECT 1 FROM pg_publication WHERE pubname='supabase_realtime') AND NOT EXISTS (SELECT 1 FROM pg_publication_tables WHERE pubname='supabase_realtime' AND schemaname='public' AND tablename='trade_item_stock') THEN ALTER PUBLICATION supabase_realtime ADD TABLE public.trade_item_stock; END IF; END $rt$;