@flowselections/pick-schermen-kwekers 1.0.77 โ†’ 1.0.80

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.
@@ -3578,37 +3578,13 @@ CREATE OR REPLACE FUNCTION public.pick_seed_reference_data()
3578
3578
  SECURITY DEFINER
3579
3579
  SET search_path TO 'public'
3580
3580
  AS $function$
3581
- DECLARE
3582
- v_statuses integer := 0;
3583
- v_types integer := 0;
3581
+ DECLARE r jsonb;
3584
3582
  BEGIN
3585
- INSERT INTO public.pick_document_statuses (code, name, color, sort_order, is_open, is_terminal) VALUES
3586
- ('new', 'Nieuw', '#94a3b8', 10, true, false),
3587
- ('queued', 'In wachtrij', '#3b82f6', 20, true, false),
3588
- ('reserved', 'Gereserveerd', '#f59e0b', 30, true, false),
3589
- ('printing', 'Wordt geprint', '#8b5cf6', 40, true, false),
3590
- ('printed', 'Geprint', '#0ea5e9', 50, true, false),
3591
- ('picking', 'Wordt gepickt', '#14b8a6', 60, true, false),
3592
- ('picked', 'Gepickt', '#22c55e', 70, true, false),
3593
- ('done', 'Afgerond', '#16a34a', 80, false, true),
3594
- ('cancelled', 'Geannuleerd', '#ef4444', 90, false, true)
3595
- ON CONFLICT (code) DO NOTHING;
3596
- GET DIAGNOSTICS v_statuses = ROW_COUNT;
3597
-
3598
- INSERT INTO public.pick_document_types (code, name, description, priority, color, icon, sort_order, printer_id) VALUES
3599
- ('pakbon', 'Pakbon', 'Pakbon voor uitgaande order', 10, '#3b82f6', 'FileText', 10, NULL),
3600
- ('veilingbrief', 'Veilingbrief', 'Veilingbrief', 20, '#f59e0b', 'FileSpreadsheet', 20, NULL),
3601
- ('productiebon', 'Productiebon', 'Bon voor productieopdracht', 10, '#f97316', 'Factory', 30, NULL),
3602
- ('productielijst', 'Productielijst', 'Verzamellijst productie', 20, '#fb923c', 'ListChecks', 40, NULL),
3603
- ('transportbrief', 'Transportbrief', 'Transportdocument', 30, '#0ea5e9', 'Truck', 50, NULL),
3604
- ('retourbon', 'Retourbon', 'Retourdocument', 40, '#ef4444', 'Undo2', 60, NULL),
3605
- ('controlelijst', 'Controlelijst', 'Kwaliteitscontrolelijst', 50, '#8b5cf6', 'ShieldCheck', 70, NULL)
3606
- ON CONFLICT (code) DO NOTHING;
3607
- GET DIAGNOSTICS v_types = ROW_COUNT;
3608
-
3609
- RETURN jsonb_build_object('statuses_toegevoegd', v_statuses, 'types_toegevoegd', v_types);
3610
- END;
3611
- $function$;
3583
+ r := public.pick_ensure_defaults();
3584
+ RETURN r || jsonb_build_object(
3585
+ 'statuses_toegevoegd', coalesce((r->'statussen'->>'toegevoegd')::int, 0),
3586
+ 'types_toegevoegd', coalesce((r->'documenttypes'->>'toegevoegd')::int, 0));
3587
+ END $function$;
3612
3588
 
3613
3589
  CREATE OR REPLACE FUNCTION public.pick_set_station_print_plek(p_device_key text, _station_id uuid, _print_plek_id uuid)
3614
3590
  RETURNS uuid
@@ -3878,10 +3854,18 @@ CREATE OR REPLACE FUNCTION public.pick_sync_queue_throttled(_min_seconds integer
3878
3854
  SET search_path TO 'public'
3879
3855
  AS $function$
3880
3856
  DECLARE last_at timestamptz; needs_cleanup boolean; res jsonb; err text; prev_err text; req_at timestamptz; t0 timestamptz;
3857
+ v_def jsonb := '{}'::jsonb;
3881
3858
  BEGIN
3859
+ BEGIN
3860
+ PERFORM public.pick_ensure_defaults_intern();
3861
+ EXCEPTION WHEN OTHERS THEN
3862
+ RAISE WARNING 'pick_ensure_defaults: %', SQLERRM;
3863
+ v_def := jsonb_build_object('standaardgegevens_fout', SQLERRM);
3864
+ END;
3865
+
3882
3866
  SELECT s.last_error INTO prev_err FROM public.pick_sync_state s WHERE s.id;
3883
3867
  IF NOT pg_try_advisory_xact_lock(hashtext('pick_sync_queue')) THEN
3884
- RETURN jsonb_build_object('synced', false, 'reason', 'busy', 'error', prev_err);
3868
+ RETURN v_def || jsonb_build_object('synced', false, 'reason', 'busy', 'error', prev_err);
3885
3869
  END IF;
3886
3870
 
3887
3871
  SELECT s.last_sync_at, COALESCE(s.last_cleanup_at, 'epoch'::timestamptz) < now() - interval '6 hours', s.sync_requested_at
@@ -3890,7 +3874,7 @@ BEGIN
3890
3874
 
3891
3875
  IF last_at IS NOT NULL AND last_at > now() - make_interval(secs => GREATEST(_min_seconds, 5))
3892
3876
  AND (req_at IS NULL OR req_at <= last_at) THEN
3893
- RETURN jsonb_build_object('synced', false, 'reason', 'throttled', 'last_sync_at', last_at, 'error', prev_err);
3877
+ RETURN v_def || jsonb_build_object('synced', false, 'reason', 'throttled', 'last_sync_at', last_at, 'error', prev_err);
3894
3878
  END IF;
3895
3879
 
3896
3880
  t0 := clock_timestamp();
@@ -3905,14 +3889,14 @@ BEGIN
3905
3889
 
3906
3890
  IF err IS NOT NULL THEN
3907
3891
  RAISE WARNING 'pick_sync_queue: %', err;
3908
- RETURN jsonb_build_object('synced', false, 'reason', 'error', 'error', err, 'last_sync_at', now());
3892
+ RETURN v_def || jsonb_build_object('synced', false, 'reason', 'error', 'error', err, 'last_sync_at', now());
3909
3893
  END IF;
3910
3894
 
3911
3895
  IF needs_cleanup THEN
3912
3896
  PERFORM public.pick_cleanup_maintenance();
3913
3897
  END IF;
3914
3898
 
3915
- RETURN jsonb_build_object('synced', true, 'last_sync_at', now(), 'duur_ms', (extract(epoch FROM clock_timestamp() - t0) * 1000)::integer);
3899
+ RETURN v_def || jsonb_build_object('synced', true, 'last_sync_at', now(), 'duur_ms', (extract(epoch FROM clock_timestamp() - t0) * 1000)::integer);
3916
3900
  END $function$;
3917
3901
 
3918
3902
  CREATE OR REPLACE FUNCTION public.pick_sync_queue_throttled(p_device_key text, _min_seconds integer DEFAULT 60)
@@ -4100,13 +4084,11 @@ BEGIN
4100
4084
  IF to_regprocedure('public.layouts_vroege_sticker_waarschuwing(date,date)') IS NULL THEN
4101
4085
  v := v || jsonb_build_object('niveau','info','tekst','Vroege stickerwaarschuwing nog niet beschikbaar (Layouts/Engine)');
4102
4086
  END IF;
4103
- -- 1.0.63: printstatus uit de Engine.
4104
4087
  IF to_regprocedure('public.logistics_print_status(uuid[])') IS NULL THEN
4105
4088
  v := v || jsonb_build_object('niveau','waarschuwing','tekst','Pickschermen: printstatus uit Engine niet beschikbaar (logistics_print_status ontbreekt). Engine te oud: printed_at nog bij aanmaken.');
4106
4089
  ELSE
4107
4090
  v := v || jsonb_build_object('niveau','info','tekst','Pickschermen: printstatus uit Engine beschikbaar (logistics_print_status aanwezig); printed_at pas bij voltooid.');
4108
4091
  END IF;
4109
- -- Functies met eigen interne controle (aanwezig, interne controle ja/nee).
4110
4092
  FOREACH t IN ARRAY ARRAY['public.pick_read_print_job_uitwijk(text,uuid[])','public._pick_job_of_station(uuid,uuid)','public.pickstation_print_status(text,uuid[])'] LOOP
4111
4093
  v_oid := to_regprocedure(t);
4112
4094
  v_ctl := v_oid IS NOT NULL AND position('42501' IN pg_get_functiondef(v_oid)) > 0;
@@ -4117,7 +4099,6 @@ BEGIN
4117
4099
  v := v || jsonb_build_object('niveau','fout','tekst','Functie zonder interne controle: '||t);
4118
4100
  END IF;
4119
4101
  END LOOP;
4120
- -- 1.0.67: stickerbundel levert printopdrachten en stickervraag.
4121
4102
  v_oid := to_regprocedure('public.pickstation_cart_sticker_states(text,uuid[])');
4122
4103
  IF v_oid IS NULL THEN
4123
4104
  v := v || jsonb_build_object('niveau','fout','tekst','Pickschermen: stickerbundel ontbreekt (pickstation_cart_sticker_states).');
@@ -4126,7 +4107,6 @@ BEGIN
4126
4107
  ELSE
4127
4108
  v := v || jsonb_build_object('niveau','info','tekst','Pickschermen: stickerbundel levert printopdrachten.');
4128
4109
  END IF;
4129
- -- 1.0.71: pickregels-controle set-based (รฉรฉn karplan per order).
4130
4110
  v_oid := to_regprocedure('public.pick_verify_rows(jsonb)');
4131
4111
  IF to_regprocedure('public.pick_queue_cart_plans(uuid[])') IS NULL OR v_oid IS NULL
4132
4112
  OR position('pick_queue_cart_plans' IN pg_get_functiondef(v_oid)) = 0 THEN
@@ -4170,12 +4150,19 @@ BEGIN
4170
4150
  AND p.prorettype <> 'trigger'::regtype
4171
4151
  AND has_function_privilege('anon', p.oid, 'execute')
4172
4152
  HAVING count(*) > 0), '[]'::jsonb);
4173
- -- 1.0.65: alle databaseobjecten van de module (schema/pickschermen.sql).
4174
4153
  IF cardinality(public.pickschermen_missing_objects()) = 0 THEN
4175
4154
  v := v || jsonb_build_object('niveau','ok','tekst','Pickschermen: alle databaseobjecten van de module aanwezig');
4176
4155
  ELSE
4177
4156
  v := v || jsonb_build_object('niveau','fout','tekst','Pickschermen: niet alle databaseobjecten aanwezig; ontbreekt: '||array_to_string(public.pickschermen_missing_objects(), ', '));
4178
4157
  END IF;
4158
+ -- 1.0.78: standaardgegevens zelfherstellend.
4159
+ IF to_regprocedure('public.pick_ensure_defaults_intern()') IS NULL OR to_regclass('public.pick_defaults_state') IS NULL THEN
4160
+ v := v || jsonb_build_object('niveau','fout','tekst','Pickschermen: zelfherstel standaardgegevens ontbreekt (pick_ensure_defaults_intern).');
4161
+ ELSIF NOT EXISTS (SELECT 1 FROM public.pick_defaults_state WHERE id) THEN
4162
+ v := v || jsonb_build_object('niveau','waarschuwing','tekst','Pickschermen: standaardgegevens nog niet aangemaakt; dat gebeurt bij de eerstvolgende synchronisatie of bij het openen van Pickstations.');
4163
+ ELSE
4164
+ v := v || jsonb_build_object('niveau','info','tekst','Pickschermen: standaardgegevens aanwezig (versie '||(SELECT applied_version FROM public.pick_defaults_state WHERE id)||').');
4165
+ END IF;
4179
4166
  RETURN jsonb_build_object(
4180
4167
  'ok', NOT EXISTS (SELECT 1 FROM jsonb_array_elements(v) e WHERE e->>'niveau'='fout'),
4181
4168
  'apparaatsleutel_verplicht', coalesce(v_req,false),
@@ -4193,13 +4180,12 @@ CREATE OR REPLACE FUNCTION public.pickschermen_missing_objects()
4193
4180
  AS $function$
4194
4181
  DECLARE t text; v_mis text[] := '{}';
4195
4182
  BEGIN
4196
- FOREACH t IN ARRAY ARRAY['pick_buffer_event_cursor','pick_countries','pick_document_statuses','pick_document_types','pick_queue','pick_queue_locks','pick_screen_document_types','pick_settings','pick_station_devices','pick_station_heartbeats','pick_station_history','pick_station_logs','pick_station_pair_codes','pick_station_permissions','pick_station_printers','pick_station_screens','pick_station_signals','pick_station_tasks','pick_station_types','pick_station_users','pick_stations','pick_sync_state','pick_taken','pick_task_document_types'] LOOP
4183
+ FOREACH t IN ARRAY ARRAY['pick_buffer_event_cursor','pick_countries','pick_defaults_state','pick_document_statuses','pick_document_types','pick_queue','pick_queue_locks','pick_screen_document_types','pick_settings','pick_station_devices','pick_station_heartbeats','pick_station_history','pick_station_logs','pick_station_pair_codes','pick_station_permissions','pick_station_printers','pick_station_screens','pick_station_signals','pick_station_tasks','pick_station_types','pick_station_users','pick_stations','pick_sync_state','pick_taken','pick_task_document_types'] LOOP
4197
4184
  IF to_regclass('public.'||t) IS NULL THEN v_mis := v_mis || ('tabel '||t); END IF;
4198
4185
  END LOOP;
4199
- FOREACH t IN ARRAY string_to_array('_pick_job_of_station(uuid,uuid);_pick_printstatus_via_engine();_pick_station_for_cart(uuid);_pick_sticker_ids_for_cart(uuid);pick_active_printers();pick_active_printers(text);pick_apply_buffer_events();pick_apply_buffer_events(text);pick_assert_printable(pick_queue);pick_assert_station(text);pick_available_pick_days(integer);pick_available_pick_days(text,integer);pick_buffer_order_ids(uuid);pick_build_key_variants();pick_cart_breakdown(uuid);pick_claim_document(text,uuid,uuid,uuid,text,integer);pick_claim_document(uuid,uuid,uuid,text,integer);pick_claim_next_document(text,uuid,uuid,text,text,integer,date);pick_claim_next_document(uuid,uuid,text,text,integer,date);pick_cleanup_maintenance(integer,integer);pick_complete_print(text,uuid,uuid,text);pick_complete_print(uuid,uuid,text);pick_complete_print_cart(text,uuid,uuid,text,text);pick_complete_print_cart(uuid,uuid,text,text);pick_complete_print_carts(text,uuid,text,text[]);pick_complete_print_carts(uuid,text,text[]);pick_create_pair_code(uuid);pick_current_pick_day();pick_current_pick_day(text);pick_day_counts(text,uuid,uuid,date);pick_day_counts(uuid,uuid,date);pick_device_check(text,uuid,uuid,text,text,text);pick_device_gate(text);pick_device_key_required();pick_document_layout_data(uuid);pick_enqueue_print_job(text,uuid,uuid,text,boolean);pick_enqueue_print_job(text,uuid,uuid,text,boolean,text);pick_enqueue_print_job(uuid,uuid,text,boolean);pick_enqueue_print_job(uuid,uuid,text,boolean,text);pick_enqueue_print_job_from_cart(uuid,uuid,text,boolean,text,jsonb);pick_ensure_settings();pick_find_sent_elsewhere(uuid,text);pick_has_station_role();pick_is_reference_admin();pick_is_server();pick_key_hash(text);pick_mark_printed(text,uuid,text,text);pick_mark_printed(uuid,text,text);pick_order_context(uuid,text);pick_preview_job(text,text,uuid);pick_preview_job(text,uuid);pick_print_job_status(text,uuid);pick_print_job_status(uuid);pick_print_jobs_status(text,uuid[]);pick_print_jobs_status(uuid[]);pick_print_plekken();pick_print_plekken(text);pick_protect_required_reference_rows();pick_queue_apply_cart_breakdown();pick_queue_audit();pick_queue_cart_plan(text,uuid);pick_queue_cart_plan(uuid);pick_queue_cart_plan_v152(uuid);pick_queue_cart_plans(uuid[]);pick_queue_enforce_routing();pick_read_by_code(text,text,uuid);pick_read_country_counts(text,uuid,uuid);pick_read_locks(text,uuid);pick_read_print_job_uitwijk(text,uuid[]);pick_read_queue(text,uuid,uuid,text,text,uuid,boolean,boolean,text,jsonb,integer,integer);pick_read_station(text,text);pick_read_unscanned_earlier(text,uuid,text);pick_read_vroege_sticker_waarschuwing(text,uuid);pick_reference_data_status();pick_reference_data_status(text);pick_release_expired_locks();pick_release_expired_locks(text);pick_release_lock(text,uuid);pick_release_lock(uuid);pick_report_missing_cart_plan();pick_report_missing_cart_plan(text);pick_reprint_cart(text,uuid,text,text,integer);pick_reprint_cart(uuid,text,text,integer);pick_reprint_document(text,uuid,text,integer);pick_reprint_document(uuid,text,integer);pick_reset_print(text,uuid,text);pick_reset_print(text,uuid,text,text);pick_reset_print(uuid,text);pick_reset_print(uuid,text,text);pick_reset_print_job(text,uuid,text,text,uuid);pick_reset_print_job(uuid,text,text,uuid);pick_reset_print_jobs(text,uuid,text,uuid[],text[]);pick_reset_print_jobs(uuid,text,uuid[],text[]);pick_resolve_scan_code(text,text);pick_restore_to_queue(text,uuid,text);pick_restore_to_queue(uuid,text);pick_revoke_device(uuid);pick_role_allowed(text);pick_seed_reference_data();pick_set_station_print_plek(text,uuid,uuid);pick_shared_cart_message(text,pick_queue);pick_read_shared_cart_messages(uuid,text[]);pick_read_shared_cart_messages(text,uuid,text[]);pick_set_station_print_plek(uuid,uuid);pick_signal_station(uuid);pick_signal_trg();pick_station_cleanup_print_plek();pick_station_dashboard();pick_station_dashboard(text);pick_station_devices_list(uuid);pick_station_print_plek(text,uuid);pick_station_print_plek(uuid);pick_station_print_plekken();pick_station_print_plekken(text);pick_station_slugify(text,uuid);pick_stations_set_slug();pick_sticker_past_controle(uuid);pick_sync_pick_day(date);pick_sync_pick_day(text,date);pick_sync_queue_throttled(integer);pick_sync_queue_throttled(text,integer);pick_touch_updated_at();pick_verify_rows(jsonb);pick_verify_rows(text,jsonb);pickschermen_install_check();pickschermen_missing_objects();pickstation_auto_send_status(text,text,uuid);pickstation_auto_send_status(text,uuid);pickstation_cart_sticker_state(text,text,uuid);pickstation_cart_sticker_state(text,uuid);pickstation_cart_sticker_states(text,text,uuid[]);pickstation_cart_sticker_states(text,uuid[]);pickstation_device_status(text,text);pickstation_document_for_order(text,text,uuid);pickstation_document_for_order(text,uuid);pickstation_get_orders_raw();pickstation_get_orders_raw(text);pickstation_get_planning_context();pickstation_get_planning_context(text);pickstation_get_settings();pickstation_get_settings(text);pickstation_log_print(text,text,text,text,text[],text);pickstation_log_print(text,text,text,text[],text);pickstation_logistics_barcode_lookup(text,text);pickstation_logistics_cart_plan_status(text,text);pickstation_logistics_cart_slip_plan(text,uuid);pickstation_logistics_is_pick_workday(text,date);pickstation_logistics_order_released(text,text);pickstation_logistics_pick_mode(text);pickstation_logistics_shipping_note_from_barcode(text,text,boolean,uuid);pickstation_logistics_working_hours_status(text);pickstation_order_sticker_meldingen(text,text,uuid);pickstation_order_sticker_meldingen(text,uuid);pickstation_pair_device(text,text,text);pickstation_print_status(text,text,uuid[]);pickstation_print_status(text,uuid[]);pickstation_resolve_delivery_orders(text,text[]);pickstation_resolve_delivery_orders(text[]);pickstation_set_cart_status(text,text,integer,text);pickstation_sticker_past_controle(text,text,uuid);pickstation_sticker_past_controle(text,uuid);pickstation_sticker_reprint(text,text,uuid,text);pickstation_sticker_reprint(text,uuid,text);sync_order_cart_totals()', ';') LOOP
4186
+ FOREACH t IN ARRAY string_to_array('_pick_job_of_station(uuid,uuid);_pick_printstatus_via_engine();_pick_station_for_cart(uuid);_pick_sticker_ids_for_cart(uuid);pick_active_printers();pick_active_printers(text);pick_apply_buffer_events();pick_apply_buffer_events(text);pick_assert_printable(pick_queue);pick_assert_station(text);pick_available_pick_days(integer);pick_available_pick_days(text,integer);pick_buffer_order_ids(uuid);pick_build_key_variants();pick_cart_breakdown(uuid);pick_claim_document(text,uuid,uuid,uuid,text,integer);pick_claim_document(uuid,uuid,uuid,text,integer);pick_claim_next_document(text,uuid,uuid,text,text,integer,date);pick_claim_next_document(uuid,uuid,text,text,integer,date);pick_cleanup_maintenance(integer,integer);pick_complete_print(text,uuid,uuid,text);pick_complete_print(uuid,uuid,text);pick_complete_print_cart(text,uuid,uuid,text,text);pick_complete_print_cart(uuid,uuid,text,text);pick_complete_print_carts(text,uuid,text,text[]);pick_complete_print_carts(uuid,text,text[]);pick_create_pair_code(uuid);pick_current_pick_day();pick_current_pick_day(text);pick_day_counts(text,uuid,uuid,date);pick_day_counts(uuid,uuid,date);pick_device_check(text,uuid,uuid,text,text,text);pick_device_gate(text);pick_device_key_required();pick_document_layout_data(uuid);pick_enqueue_print_job(text,uuid,uuid,text,boolean);pick_enqueue_print_job(text,uuid,uuid,text,boolean,text);pick_enqueue_print_job(uuid,uuid,text,boolean);pick_enqueue_print_job(uuid,uuid,text,boolean,text);pick_enqueue_print_job_from_cart(uuid,uuid,text,boolean,text,jsonb);pick_ensure_settings();pick_find_sent_elsewhere(uuid,text);pick_has_station_role();pick_is_reference_admin();pick_is_server();pick_key_hash(text);pick_mark_printed(text,uuid,text,text);pick_mark_printed(uuid,text,text);pick_order_context(uuid,text);pick_preview_job(text,text,uuid);pick_preview_job(text,uuid);pick_print_job_status(text,uuid);pick_print_job_status(uuid);pick_print_jobs_status(text,uuid[]);pick_print_jobs_status(uuid[]);pick_print_plekken();pick_print_plekken(text);pick_protect_required_reference_rows();pick_queue_apply_cart_breakdown();pick_queue_audit();pick_queue_cart_plan(text,uuid);pick_queue_cart_plan(uuid);pick_queue_cart_plan_v152(uuid);pick_queue_cart_plans(uuid[]);pick_queue_enforce_routing();pick_read_by_code(text,text,uuid);pick_read_country_counts(text,uuid,uuid);pick_read_locks(text,uuid);pick_read_print_job_uitwijk(text,uuid[]);pick_read_queue(text,uuid,uuid,text,text,uuid,boolean,boolean,text,jsonb,integer,integer);pick_read_station(text,text);pick_read_unscanned_earlier(text,uuid,text);pick_read_vroege_sticker_waarschuwing(text,uuid);pick_reference_data_status();pick_reference_data_status(text);pick_release_expired_locks();pick_release_expired_locks(text);pick_release_lock(text,uuid);pick_release_lock(uuid);pick_report_missing_cart_plan();pick_report_missing_cart_plan(text);pick_reprint_cart(text,uuid,text,text,integer);pick_reprint_cart(uuid,text,text,integer);pick_reprint_document(text,uuid,text,integer);pick_reprint_document(uuid,text,integer);pick_reset_print(text,uuid,text);pick_reset_print(text,uuid,text,text);pick_reset_print(uuid,text);pick_reset_print(uuid,text,text);pick_reset_print_job(text,uuid,text,text,uuid);pick_reset_print_job(uuid,text,text,uuid);pick_reset_print_jobs(text,uuid,text,uuid[],text[]);pick_reset_print_jobs(uuid,text,uuid[],text[]);pick_resolve_scan_code(text,text);pick_restore_to_queue(text,uuid,text);pick_restore_to_queue(uuid,text);pick_revoke_device(uuid);pick_role_allowed(text);pick_seed_reference_data();pick_ensure_defaults();pick_ensure_defaults_intern();_pick_defaults_apply(text,text[],jsonb);pick_track_user_modification();pick_set_station_print_plek(text,uuid,uuid);pick_shared_cart_message(text,pick_queue);pick_read_shared_cart_messages(uuid,text[]);pick_read_shared_cart_messages(text,uuid,text[]);pick_set_station_print_plek(uuid,uuid);pick_signal_station(uuid);pick_signal_trg();pick_station_cleanup_print_plek();pick_station_dashboard();pick_station_dashboard(text);pick_station_devices_list(uuid);pick_station_print_plek(text,uuid);pick_station_print_plek(uuid);pick_station_print_plekken();pick_station_print_plekken(text);pick_station_slugify(text,uuid);pick_stations_set_slug();pick_sticker_past_controle(uuid);pick_sync_pick_day(date);pick_sync_pick_day(text,date);pick_sync_queue_throttled(integer);pick_sync_queue_throttled(text,integer);pick_touch_updated_at();pick_verify_rows(jsonb);pick_verify_rows(text,jsonb);pickschermen_install_check();pickschermen_missing_objects();pickstation_auto_send_status(text,text,uuid);pickstation_auto_send_status(text,uuid);pickstation_cart_sticker_state(text,text,uuid);pickstation_cart_sticker_state(text,uuid);pickstation_cart_sticker_states(text,text,uuid[]);pickstation_cart_sticker_states(text,uuid[]);pickstation_device_status(text,text);pickstation_document_for_order(text,text,uuid);pickstation_document_for_order(text,uuid);pickstation_get_orders_raw();pickstation_get_orders_raw(text);pickstation_get_planning_context();pickstation_get_planning_context(text);pickstation_get_settings();pickstation_get_settings(text);pickstation_log_print(text,text,text,text,text[],text);pickstation_log_print(text,text,text,text[],text);pickstation_logistics_barcode_lookup(text,text);pickstation_logistics_cart_plan_status(text,text);pickstation_logistics_cart_slip_plan(text,uuid);pickstation_logistics_is_pick_workday(text,date);pickstation_logistics_order_released(text,text);pickstation_logistics_pick_mode(text);pickstation_logistics_shipping_note_from_barcode(text,text,boolean,uuid);pickstation_logistics_working_hours_status(text);pickstation_order_sticker_meldingen(text,text,uuid);pickstation_order_sticker_meldingen(text,uuid);pickstation_pair_device(text,text,text);pickstation_print_status(text,text,uuid[]);pickstation_print_status(text,uuid[]);pickstation_resolve_delivery_orders(text,text[]);pickstation_resolve_delivery_orders(text[]);pickstation_set_cart_status(text,text,integer,text);pickstation_sticker_past_controle(text,text,uuid);pickstation_sticker_past_controle(text,uuid);pickstation_sticker_reprint(text,text,uuid,text);pickstation_sticker_reprint(text,uuid,text);sync_order_cart_totals()', ';') LOOP
4200
4187
  IF to_regprocedure('public.'||t) IS NULL THEN v_mis := v_mis || ('functie '||t); END IF;
4201
4188
  END LOOP;
4202
- -- Alleen verwacht als de Engine-tabel logistics_tasks bestaat.
4203
4189
  IF to_regclass('public.logistics_tasks') IS NOT NULL
4204
4190
  AND to_regprocedure('public.pickstation_logistics_complete_task(text,uuid,jsonb)') IS NULL THEN
4205
4191
  v_mis := v_mis || 'functie pickstation_logistics_complete_task(text,uuid,jsonb)'::text;
@@ -5405,6 +5391,281 @@ DO $$ DECLARE f text; BEGIN
5405
5391
  END LOOP; END $$;
5406
5392
 
5407
5393
  -- 4. Rechten op functies (alleen toekennen, nooit intrekken)
5394
+ -- 1.0.78: standaardgegevens (systeemregels) en klantinstellingen zelfherstellend.
5395
+ -- Systeemtabellen: per regel bijhouden wat van ons komt en welke velden de klant aanpaste.
5396
+ ALTER TABLE public.pick_document_statuses ADD COLUMN IF NOT EXISTS is_system boolean;
5397
+ ALTER TABLE public.pick_document_statuses ADD COLUMN IF NOT EXISTS user_modified_at timestamptz;
5398
+ ALTER TABLE public.pick_document_statuses ADD COLUMN IF NOT EXISTS user_modified_fields text[] NOT NULL DEFAULT '{}'::text[];
5399
+ ALTER TABLE public.pick_document_types ADD COLUMN IF NOT EXISTS is_system boolean;
5400
+ ALTER TABLE public.pick_document_types ADD COLUMN IF NOT EXISTS user_modified_at timestamptz;
5401
+ ALTER TABLE public.pick_document_types ADD COLUMN IF NOT EXISTS user_modified_fields text[] NOT NULL DEFAULT '{}'::text[];
5402
+ ALTER TABLE public.pick_station_types ADD COLUMN IF NOT EXISTS is_system boolean;
5403
+ ALTER TABLE public.pick_station_types ADD COLUMN IF NOT EXISTS user_modified_at timestamptz;
5404
+ ALTER TABLE public.pick_station_types ADD COLUMN IF NOT EXISTS user_modified_fields text[] NOT NULL DEFAULT '{}'::text[];
5405
+ ALTER TABLE public.pick_station_tasks ADD COLUMN IF NOT EXISTS is_system boolean;
5406
+ ALTER TABLE public.pick_station_tasks ADD COLUMN IF NOT EXISTS user_modified_at timestamptz;
5407
+ ALTER TABLE public.pick_station_tasks ADD COLUMN IF NOT EXISTS user_modified_fields text[] NOT NULL DEFAULT '{}'::text[];
5408
+ ALTER TABLE public.pick_countries ADD COLUMN IF NOT EXISTS is_system boolean;
5409
+ ALTER TABLE public.pick_countries ADD COLUMN IF NOT EXISTS user_modified_at timestamptz;
5410
+ ALTER TABLE public.pick_countries ADD COLUMN IF NOT EXISTS user_modified_fields text[] NOT NULL DEFAULT '{}'::text[];
5411
+
5412
+ -- Laatst toegepaste standaardversie (รฉรฉn rij).
5413
+ CREATE TABLE IF NOT EXISTS public.pick_defaults_state (
5414
+ id boolean PRIMARY KEY DEFAULT true CHECK (id),
5415
+ applied_version integer NOT NULL,
5416
+ applied_at timestamptz NOT NULL DEFAULT now(),
5417
+ laatste_resultaat jsonb
5418
+ );
5419
+ GRANT SELECT ON public.pick_defaults_state TO authenticated;
5420
+ GRANT ALL ON public.pick_defaults_state TO service_role;
5421
+ ALTER TABLE public.pick_defaults_state ENABLE ROW LEVEL SECURITY;
5422
+ DO $p$ BEGIN
5423
+ IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='pick_defaults_state' AND policyname='pick_defaults_state_lezen') THEN
5424
+ CREATE POLICY pick_defaults_state_lezen ON public.pick_defaults_state FOR SELECT TO authenticated USING (true);
5425
+ END IF;
5426
+ END $p$;
5427
+
5428
+ -- Markeert per veld een aanpassing door de gebruiker. Wijzigingen vanuit
5429
+ -- pick_ensure_defaults_intern (transactievlag pick.defaults_apply) tellen niet mee.
5430
+ CREATE OR REPLACE FUNCTION public.pick_track_user_modification()
5431
+ RETURNS trigger
5432
+ LANGUAGE plpgsql
5433
+ SET search_path TO 'public'
5434
+ AS $function$
5435
+ DECLARE f text; o jsonb; n jsonb; v_new text[];
5436
+ BEGIN
5437
+ IF coalesce(current_setting('pick.defaults_apply', true), '') = 'on' THEN
5438
+ RETURN NEW;
5439
+ END IF;
5440
+ o := to_jsonb(OLD); n := to_jsonb(NEW);
5441
+ v_new := coalesce(NEW.user_modified_fields, '{}'::text[]);
5442
+ FOREACH f IN ARRAY TG_ARGV::text[] LOOP
5443
+ IF (o -> f) IS DISTINCT FROM (n -> f) AND NOT (f = ANY (v_new)) THEN
5444
+ v_new := v_new || f;
5445
+ END IF;
5446
+ END LOOP;
5447
+ IF v_new IS DISTINCT FROM coalesce(OLD.user_modified_fields, '{}'::text[]) THEN
5448
+ NEW.user_modified_fields := v_new;
5449
+ NEW.user_modified_at := now();
5450
+ END IF;
5451
+ RETURN NEW;
5452
+ END $function$;
5453
+
5454
+ DO $t$ BEGIN
5455
+ IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname='pick_track_user_mod_statuses' AND tgrelid='public.pick_document_statuses'::regclass) THEN
5456
+ CREATE TRIGGER pick_track_user_mod_statuses BEFORE UPDATE ON public.pick_document_statuses FOR EACH ROW
5457
+ EXECUTE FUNCTION public.pick_track_user_modification('name','color','sort_order','is_open','is_terminal','active');
5458
+ END IF;
5459
+ IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname='pick_track_user_mod_types' AND tgrelid='public.pick_document_types'::regclass) THEN
5460
+ CREATE TRIGGER pick_track_user_mod_types BEFORE UPDATE ON public.pick_document_types FOR EACH ROW
5461
+ EXECUTE FUNCTION public.pick_track_user_modification('name','description','priority','color','icon','sort_order','active');
5462
+ END IF;
5463
+ IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname='pick_track_user_mod_station_types' AND tgrelid='public.pick_station_types'::regclass) THEN
5464
+ CREATE TRIGGER pick_track_user_mod_station_types BEFORE UPDATE ON public.pick_station_types FOR EACH ROW
5465
+ EXECUTE FUNCTION public.pick_track_user_modification('name','description','icon','color','sort_order','active');
5466
+ END IF;
5467
+ IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname='pick_track_user_mod_tasks' AND tgrelid='public.pick_station_tasks'::regclass) THEN
5468
+ CREATE TRIGGER pick_track_user_mod_tasks BEFORE UPDATE ON public.pick_station_tasks FOR EACH ROW
5469
+ EXECUTE FUNCTION public.pick_track_user_modification('name','description','icon','color','sort_order','active');
5470
+ END IF;
5471
+ IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname='pick_track_user_mod_countries' AND tgrelid='public.pick_countries'::regclass) THEN
5472
+ CREATE TRIGGER pick_track_user_mod_countries BEFORE UPDATE ON public.pick_countries FOR EACH ROW
5473
+ EXECUTE FUNCTION public.pick_track_user_modification('name','flag','sort_order','active');
5474
+ END IF;
5475
+ END $t$;
5476
+
5477
+ -- Past de standaardregels van รฉรฉn systeemtabel toe. Schrijft alleen als een waarde echt verschilt.
5478
+ CREATE OR REPLACE FUNCTION public._pick_defaults_apply(p_tabel text, p_velden text[], p_rijen jsonb)
5479
+ RETURNS jsonb
5480
+ LANGUAGE plpgsql
5481
+ SECURITY DEFINER
5482
+ SET search_path TO 'public'
5483
+ AS $function$
5484
+ DECLARE r jsonb; cur jsonb; f text; v_diff text[]; v_set text; v_cols text;
5485
+ n_ins int := 0; n_upd int := 0; n_adopt int := 0; n_keep int := 0; n_off int := 0; n int;
5486
+ v_codes text[];
5487
+ BEGIN
5488
+ IF p_tabel NOT IN ('pick_document_statuses','pick_document_types','pick_station_types','pick_station_tasks','pick_countries') THEN
5489
+ RAISE EXCEPTION 'Onbekende tabel voor standaardgegevens: %', p_tabel;
5490
+ END IF;
5491
+ SELECT array_agg(e->>'code') INTO v_codes FROM jsonb_array_elements(p_rijen) e;
5492
+ FOR r IN SELECT * FROM jsonb_array_elements(p_rijen) LOOP
5493
+ EXECUTE format('SELECT to_jsonb(t) FROM public.%I t WHERE t.code = $1', p_tabel) INTO cur USING r->>'code';
5494
+ IF cur IS NULL THEN
5495
+ SELECT string_agg(quote_ident(k), ',') INTO v_cols FROM jsonb_object_keys(r || '{"is_system":true}'::jsonb) k;
5496
+ EXECUTE format('INSERT INTO public.%I (%s) SELECT %s FROM jsonb_populate_record(NULL::public.%I, $1) ON CONFLICT (code) DO NOTHING',
5497
+ p_tabel, v_cols, v_cols, p_tabel) USING (r || '{"is_system":true}'::jsonb);
5498
+ GET DIAGNOSTICS n = ROW_COUNT; n_ins := n_ins + n;
5499
+ ELSIF cur->'is_system' IS NULL OR cur->'is_system' = 'null'::jsonb THEN
5500
+ -- Eerste keer: veld voor veld vergelijken; alleen afwijkende velden gelden als klantaanpassing.
5501
+ v_diff := '{}'::text[];
5502
+ FOREACH f IN ARRAY p_velden LOOP
5503
+ IF r ? f AND (cur -> f) IS DISTINCT FROM (r -> f) THEN v_diff := v_diff || f; END IF;
5504
+ END LOOP;
5505
+ EXECUTE format('UPDATE public.%I SET is_system = true, user_modified_fields = $2, user_modified_at = CASE WHEN cardinality($2) > 0 THEN now() END WHERE code = $1', p_tabel)
5506
+ USING r->>'code', v_diff;
5507
+ n_adopt := n_adopt + 1;
5508
+ ELSIF (cur->'is_system') = 'true'::jsonb THEN
5509
+ v_set := NULL;
5510
+ FOREACH f IN ARRAY p_velden LOOP
5511
+ IF r ? f AND (cur -> f) IS DISTINCT FROM (r -> f)
5512
+ AND NOT (cur->'user_modified_fields') ? f THEN
5513
+ v_set := coalesce(v_set || ', ', '') || format('%I = (jsonb_populate_record(NULL::public.%I, $2)).%I', f, p_tabel, f);
5514
+ END IF;
5515
+ END LOOP;
5516
+ IF v_set IS NOT NULL THEN
5517
+ EXECUTE format('UPDATE public.%I SET %s WHERE code = $1', p_tabel, v_set) USING r->>'code', r;
5518
+ n_upd := n_upd + 1;
5519
+ ELSE
5520
+ n_keep := n_keep + 1;
5521
+ END IF;
5522
+ ELSE
5523
+ n_keep := n_keep + 1; -- eigen regel van de klant met dezelfde code: ongemoeid
5524
+ END IF;
5525
+ END LOOP;
5526
+ -- Vervallen standaardregels: op niet actief, nooit verwijderen; klantkeuze voor 'active' blijft.
5527
+ EXECUTE format('UPDATE public.%I SET active = false WHERE is_system IS TRUE AND active AND NOT (code = ANY ($1)) AND NOT (''active'' = ANY (user_modified_fields))', p_tabel)
5528
+ USING v_codes;
5529
+ GET DIAGNOSTICS n_off = ROW_COUNT;
5530
+ RETURN jsonb_build_object('toegevoegd', n_ins, 'bijgewerkt', n_upd, 'overgenomen', n_adopt, 'ongewijzigd', n_keep, 'uitgezet', n_off);
5531
+ END $function$;
5532
+
5533
+ -- Het eigenlijke werk. Niet rechtstreeks aanroepbaar via de API (alleen service_role en interne functies).
5534
+ CREATE OR REPLACE FUNCTION public.pick_ensure_defaults_intern()
5535
+ RETURNS jsonb
5536
+ LANGUAGE plpgsql
5537
+ SECURITY DEFINER
5538
+ SET search_path TO 'public'
5539
+ AS $function$
5540
+ DECLARE
5541
+ c_versie constant integer := 1;
5542
+ c_statussen constant jsonb := '[
5543
+ {"code":"new","name":"Nieuw","color":"#94a3b8","sort_order":10,"is_open":true,"is_terminal":false,"active":true},
5544
+ {"code":"queued","name":"In wachtrij","color":"#3b82f6","sort_order":20,"is_open":true,"is_terminal":false,"active":true},
5545
+ {"code":"reserved","name":"Gereserveerd","color":"#f59e0b","sort_order":30,"is_open":true,"is_terminal":false,"active":true},
5546
+ {"code":"printing","name":"Wordt geprint","color":"#8b5cf6","sort_order":40,"is_open":true,"is_terminal":false,"active":true},
5547
+ {"code":"printed","name":"Geprint","color":"#0ea5e9","sort_order":50,"is_open":true,"is_terminal":false,"active":true},
5548
+ {"code":"picking","name":"Wordt gepickt","color":"#14b8a6","sort_order":60,"is_open":true,"is_terminal":false,"active":true},
5549
+ {"code":"picked","name":"Gepickt","color":"#22c55e","sort_order":70,"is_open":true,"is_terminal":false,"active":true},
5550
+ {"code":"done","name":"Afgerond","color":"#16a34a","sort_order":80,"is_open":false,"is_terminal":true,"active":true},
5551
+ {"code":"cancelled","name":"Geannuleerd","color":"#ef4444","sort_order":90,"is_open":false,"is_terminal":true,"active":true}]';
5552
+ c_types constant jsonb := '[
5553
+ {"code":"pakbon","name":"Pakbon","description":"Pakbon voor uitgaande order","priority":10,"color":"#3b82f6","icon":"FileText","sort_order":10,"active":true},
5554
+ {"code":"veilingbrief","name":"Veilingbrief","description":"Veilingbrief","priority":20,"color":"#f59e0b","icon":"FileSpreadsheet","sort_order":20,"active":true},
5555
+ {"code":"productiebon","name":"Productiebon","description":"Bon voor productieopdracht","priority":10,"color":"#f97316","icon":"Factory","sort_order":30,"active":true},
5556
+ {"code":"productielijst","name":"Productielijst","description":"Verzamellijst productie","priority":20,"color":"#fb923c","icon":"ListChecks","sort_order":40,"active":true},
5557
+ {"code":"transportbrief","name":"Transportbrief","description":"Transportdocument","priority":30,"color":"#0ea5e9","icon":"Truck","sort_order":50,"active":true},
5558
+ {"code":"retourbon","name":"Retourbon","description":"Retourdocument","priority":40,"color":"#ef4444","icon":"Undo2","sort_order":60,"active":true},
5559
+ {"code":"controlelijst","name":"Controlelijst","description":"Kwaliteitscontrolelijst","priority":50,"color":"#8b5cf6","icon":"ShieldCheck","sort_order":70,"active":true}]';
5560
+ c_stationtypes constant jsonb := '[
5561
+ {"code":"orders","name":"Orders","description":"Pickstation voor uitgaande orders","icon":"Package","color":"#3b82f6","sort_order":10,"active":true},
5562
+ {"code":"production","name":"Productie","description":"Pickstation voor productie","icon":"Factory","color":"#f97316","sort_order":20,"active":true},
5563
+ {"code":"stock","name":"Voorraad","description":"Pickstation voor voorraadmutaties","icon":"Boxes","color":"#14b8a6","sort_order":30,"active":true},
5564
+ {"code":"quality","name":"Kwaliteit","description":"Kwaliteitscontrole","icon":"ShieldCheck","color":"#8b5cf6","sort_order":40,"active":true},
5565
+ {"code":"expedition","name":"Expeditie","description":"Expeditie en verzending","icon":"Truck","color":"#0ea5e9","sort_order":50,"active":true}]';
5566
+ c_taken constant jsonb := '[
5567
+ {"code":"order_picking","name":"Order picking","description":"Picken van uitgaande orders","icon":"Package","color":"#3b82f6","sort_order":10,"active":true},
5568
+ {"code":"production_picking","name":"Productie picking","description":"Picken voor productieopdrachten","icon":"Factory","color":"#f97316","sort_order":20,"active":true},
5569
+ {"code":"buffer_picking","name":"Buffer picking","description":"Picken uit buffer","icon":"Layers","color":"#a855f7","sort_order":30,"active":true},
5570
+ {"code":"stock_picking","name":"Voorraad picking","description":"Picken uit voorraad","icon":"Boxes","color":"#14b8a6","sort_order":40,"active":true},
5571
+ {"code":"return_picking","name":"Retour picking","description":"Verwerken van retouren","icon":"Undo2","color":"#ef4444","sort_order":50,"active":true},
5572
+ {"code":"internal_move","name":"Interne verplaatsingen","description":"Verplaatsen tussen locaties","icon":"ArrowLeftRight","color":"#64748b","sort_order":60,"active":true},
5573
+ {"code":"quality_control","name":"Kwaliteitscontrole","description":"Controleren van orders","icon":"ShieldCheck","color":"#8b5cf6","sort_order":70,"active":true},
5574
+ {"code":"expedition","name":"Expeditie","description":"Klaarzetten voor transport","icon":"Truck","color":"#0ea5e9","sort_order":80,"active":true}]';
5575
+ c_landen constant jsonb := '[
5576
+ {"code":"NL","name":"Nederland","flag":"๐Ÿ‡ณ๐Ÿ‡ฑ","sort_order":10,"active":true},
5577
+ {"code":"DE","name":"Duitsland","flag":"๐Ÿ‡ฉ๐Ÿ‡ช","sort_order":20,"active":true},
5578
+ {"code":"BE","name":"Belgiรซ","flag":"๐Ÿ‡ง๐Ÿ‡ช","sort_order":30,"active":true},
5579
+ {"code":"FR","name":"Frankrijk","flag":"๐Ÿ‡ซ๐Ÿ‡ท","sort_order":40,"active":true},
5580
+ {"code":"IT","name":"Italiรซ","flag":"๐Ÿ‡ฎ๐Ÿ‡น","sort_order":50,"active":true},
5581
+ {"code":"ES","name":"Spanje","flag":"๐Ÿ‡ช๐Ÿ‡ธ","sort_order":60,"active":true},
5582
+ {"code":"CH","name":"Zwitserland","flag":"๐Ÿ‡จ๐Ÿ‡ญ","sort_order":70,"active":true},
5583
+ {"code":"AT","name":"Oostenrijk","flag":"๐Ÿ‡ฆ๐Ÿ‡น","sort_order":80,"active":true},
5584
+ {"code":"GB","name":"Verenigd Koninkrijk","flag":"๐Ÿ‡ฌ๐Ÿ‡ง","sort_order":90,"active":true},
5585
+ {"code":"PL","name":"Polen","flag":"๐Ÿ‡ต๐Ÿ‡ฑ","sort_order":100,"active":true},
5586
+ {"code":"DK","name":"Denemarken","flag":"๐Ÿ‡ฉ๐Ÿ‡ฐ","sort_order":110,"active":true},
5587
+ {"code":"SE","name":"Zweden","flag":"๐Ÿ‡ธ๐Ÿ‡ช","sort_order":120,"active":true}]';
5588
+ c_koppelingen constant jsonb := '[
5589
+ ["order_picking","pakbon"],["order_picking","veilingbrief"],["order_picking","transportbrief"],
5590
+ ["production_picking","productiebon"],["production_picking","productielijst"],["return_picking","retourbon"]]';
5591
+ v_res jsonb := '{}'::jsonb; n int;
5592
+ BEGIN
5593
+ -- Snelle uitstap: zelfde versie en alle vaste rijen aanwezig โ†’ niets doen, niets schrijven.
5594
+ IF EXISTS (SELECT 1 FROM public.pick_defaults_state s WHERE s.id AND s.applied_version = c_versie)
5595
+ AND EXISTS (SELECT 1 FROM public.pick_settings WHERE id)
5596
+ AND (SELECT count(*) FROM public.pick_document_statuses WHERE code IN (SELECT e->>'code' FROM jsonb_array_elements(c_statussen) e)) = jsonb_array_length(c_statussen)
5597
+ AND (SELECT count(*) FROM public.pick_document_types WHERE code IN (SELECT e->>'code' FROM jsonb_array_elements(c_types) e)) = jsonb_array_length(c_types)
5598
+ AND (SELECT count(*) FROM public.pick_station_types WHERE code IN (SELECT e->>'code' FROM jsonb_array_elements(c_stationtypes) e)) = jsonb_array_length(c_stationtypes)
5599
+ AND (SELECT count(*) FROM public.pick_station_tasks WHERE code IN (SELECT e->>'code' FROM jsonb_array_elements(c_taken) e)) = jsonb_array_length(c_taken)
5600
+ AND (SELECT count(*) FROM public.pick_countries WHERE code IN (SELECT e->>'code' FROM jsonb_array_elements(c_landen) e)) = jsonb_array_length(c_landen)
5601
+ AND (SELECT count(*) FROM jsonb_array_elements(c_koppelingen) k
5602
+ JOIN public.pick_station_tasks t ON t.code = k->>0
5603
+ JOIN public.pick_document_types d ON d.code = k->>1
5604
+ JOIN public.pick_task_document_types x ON x.task_id = t.id AND x.document_type_id = d.id) = jsonb_array_length(c_koppelingen)
5605
+ THEN
5606
+ RETURN jsonb_build_object('ok', true, 'versie', c_versie, 'snel', true);
5607
+ END IF;
5608
+
5609
+ PERFORM pg_advisory_xact_lock(hashtext('pick_ensure_defaults'));
5610
+ PERFORM set_config('pick.defaults_apply', 'on', true);
5611
+
5612
+ v_res := v_res || jsonb_build_object('statussen', public._pick_defaults_apply('pick_document_statuses', ARRAY['name','color','sort_order','is_open','is_terminal','active'], c_statussen));
5613
+ v_res := v_res || jsonb_build_object('documenttypes', public._pick_defaults_apply('pick_document_types', ARRAY['name','description','priority','color','icon','sort_order','active'], c_types));
5614
+ v_res := v_res || jsonb_build_object('stationtypes', public._pick_defaults_apply('pick_station_types', ARRAY['name','description','icon','color','sort_order','active'], c_stationtypes));
5615
+ v_res := v_res || jsonb_build_object('taken', public._pick_defaults_apply('pick_station_tasks', ARRAY['name','description','icon','color','sort_order','active'], c_taken));
5616
+ v_res := v_res || jsonb_build_object('landen', public._pick_defaults_apply('pick_countries', ARRAY['name','flag','sort_order','active'], c_landen));
5617
+
5618
+ INSERT INTO public.pick_task_document_types (task_id, document_type_id)
5619
+ SELECT t.id, d.id FROM jsonb_array_elements(c_koppelingen) k
5620
+ JOIN public.pick_station_tasks t ON t.code = k->>0
5621
+ JOIN public.pick_document_types d ON d.code = k->>1
5622
+ ON CONFLICT (task_id, document_type_id) DO NOTHING;
5623
+ GET DIAGNOSTICS n = ROW_COUNT;
5624
+ v_res := v_res || jsonb_build_object('koppelingen_toegevoegd', n);
5625
+
5626
+ -- Klantinstelling: alleen aanmaken als hij ontbreekt. device_key_required=false is gelijk aan
5627
+ -- het gedrag bij een ontbrekende rij (pick_device_key_required: coalesce(..., false)).
5628
+ INSERT INTO public.pick_settings (id, device_key_required) VALUES (true, false) ON CONFLICT (id) DO NOTHING;
5629
+ GET DIAGNOSTICS n = ROW_COUNT;
5630
+ v_res := v_res || jsonb_build_object('instellingen_aangemaakt', n);
5631
+
5632
+ INSERT INTO public.pick_defaults_state (id, applied_version, applied_at, laatste_resultaat)
5633
+ VALUES (true, c_versie, now(), v_res)
5634
+ ON CONFLICT (id) DO UPDATE SET applied_version = EXCLUDED.applied_version, applied_at = EXCLUDED.applied_at,
5635
+ laatste_resultaat = EXCLUDED.laatste_resultaat
5636
+ WHERE public.pick_defaults_state.applied_version IS DISTINCT FROM EXCLUDED.applied_version
5637
+ OR public.pick_defaults_state.laatste_resultaat IS DISTINCT FROM EXCLUDED.laatste_resultaat;
5638
+
5639
+ PERFORM set_config('pick.defaults_apply', '', true);
5640
+ RETURN jsonb_build_object('ok', true, 'versie', c_versie, 'snel', false) || v_res;
5641
+ EXCEPTION WHEN OTHERS THEN
5642
+ PERFORM set_config('pick.defaults_apply', '', true);
5643
+ RAISE;
5644
+ END $function$;
5645
+
5646
+ -- Publieke ingang: alleen ingelogd of server. Fout wordt een gewone reden, geen exception.
5647
+ CREATE OR REPLACE FUNCTION public.pick_ensure_defaults()
5648
+ RETURNS jsonb
5649
+ LANGUAGE plpgsql
5650
+ SECURITY DEFINER
5651
+ SET search_path TO 'public'
5652
+ AS $function$
5653
+ BEGIN
5654
+ IF NOT (auth.uid() IS NOT NULL OR public.pick_is_server()) THEN
5655
+ RAISE EXCEPTION 'Alleen een ingelogde gebruiker of de server kan de standaardgegevens aanmaken.' USING ERRCODE = '42501';
5656
+ END IF;
5657
+ BEGIN
5658
+ RETURN public.pick_ensure_defaults_intern();
5659
+ EXCEPTION WHEN OTHERS THEN
5660
+ RETURN jsonb_build_object('ok', false, 'reden', SQLERRM);
5661
+ END;
5662
+ END $function$;
5663
+
5664
+ -- "Standaardwaarden herstellen": zelfde handtekening, overschrijft nooit klantaanpassingen.
5665
+
5666
+
5667
+ -- Synchronisatie: begint met het interne zelfherstel (werkt ook voor het anonieme pickstation).
5668
+
5408
5669
  DO $g$ BEGIN IF to_regprocedure('public._pick_job_of_station(uuid,uuid)') IS NOT NULL THEN EXECUTE 'GRANT EXECUTE ON FUNCTION public._pick_job_of_station(uuid,uuid) TO service_role'; END IF; END $g$;
5409
5670
  DO $g$ BEGIN IF to_regprocedure('public._pick_printstatus_via_engine()') IS NOT NULL THEN EXECUTE 'GRANT EXECUTE ON FUNCTION public._pick_printstatus_via_engine() TO anon, authenticated, service_role'; END IF; END $g$;
5410
5671
  DO $g$ BEGIN IF to_regprocedure('public._pick_station_for_cart(uuid)') IS NOT NULL THEN EXECUTE 'GRANT EXECUTE ON FUNCTION public._pick_station_for_cart(uuid) TO service_role'; END IF; END $g$;
@@ -5567,3 +5828,11 @@ DO $g$ BEGIN IF to_regprocedure('public.pickstation_sticker_past_controle(text,u
5567
5828
  DO $g$ BEGIN IF to_regprocedure('public.pickstation_sticker_reprint(text,text,uuid,text)') IS NOT NULL THEN EXECUTE 'GRANT EXECUTE ON FUNCTION public.pickstation_sticker_reprint(text,text,uuid,text) TO anon, authenticated, service_role'; END IF; END $g$;
5568
5829
  DO $g$ BEGIN IF to_regprocedure('public.pickstation_sticker_reprint(text,uuid,text)') IS NOT NULL THEN EXECUTE 'GRANT EXECUTE ON FUNCTION public.pickstation_sticker_reprint(text,uuid,text) TO anon, authenticated, service_role'; END IF; END $g$;
5569
5830
  DO $g$ BEGIN IF to_regprocedure('public.sync_order_cart_totals()') IS NOT NULL THEN EXECUTE 'GRANT EXECUTE ON FUNCTION public.sync_order_cart_totals() TO service_role'; END IF; END $g$;
5831
+
5832
+ -- 1.0.78: rechten nieuwe functies (alleen nieuwe functies krijgen een REVOKE).
5833
+ REVOKE ALL ON FUNCTION public.pick_ensure_defaults_intern() FROM PUBLIC, anon, authenticated;
5834
+ GRANT EXECUTE ON FUNCTION public.pick_ensure_defaults_intern() TO service_role;
5835
+ REVOKE ALL ON FUNCTION public._pick_defaults_apply(text, text[], jsonb) FROM PUBLIC, anon, authenticated;
5836
+ GRANT EXECUTE ON FUNCTION public._pick_defaults_apply(text, text[], jsonb) TO service_role;
5837
+ REVOKE ALL ON FUNCTION public.pick_ensure_defaults() FROM PUBLIC, anon;
5838
+ GRANT EXECUTE ON FUNCTION public.pick_ensure_defaults() TO authenticated, service_role;