@flowselections/logistiek-engine 1.0.185 → 1.0.187
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.
|
@@ -4548,169 +4548,7 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
4548
4548
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_allowed_load_carriers overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
4549
4549
|
END $fsdo$;
|
|
4550
4550
|
|
|
4551
|
-
DO $fsdo$ BEGIN
|
|
4552
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_apply_buffer_decision(p_order_id uuid)
|
|
4553
|
-
RETURNS uuid
|
|
4554
|
-
LANGUAGE plpgsql
|
|
4555
|
-
SECURITY DEFINER
|
|
4556
|
-
SET search_path TO 'public'
|
|
4557
|
-
AS $function$
|
|
4558
|
-
DECLARE
|
|
4559
|
-
o public.orders%ROWTYPE;
|
|
4560
|
-
cf jsonb; d jsonb; v_ref text; v_close timestamptz; v_key text;
|
|
4561
|
-
v_buffer uuid; v_closed boolean; v_try int := 0; v_on_cart boolean;
|
|
4562
|
-
BEGIN
|
|
4563
|
-
SELECT * INTO o FROM public.orders WHERE id = p_order_id;
|
|
4564
|
-
IF NOT FOUND OR o.deleted_at IS NOT NULL THEN RETURN NULL; END IF;
|
|
4565
|
-
cf := COALESCE(o.custom_fields, '{}'::jsonb);
|
|
4566
|
-
|
|
4567
|
-
IF public.logistics_order_buffer_excluded(o.id) THEN
|
|
4568
|
-
IF o.buffer_id IS NOT NULL THEN
|
|
4569
|
-
SELECT EXISTS (SELECT 1 FROM public.order_items oi
|
|
4570
|
-
JOIN logistics_active.order_cart_items ci ON ci.order_item_id = oi.id
|
|
4571
|
-
JOIN logistics_active.order_carts oc ON oc.id = ci.cart_id
|
|
4572
|
-
WHERE oi.order_id = o.id AND oc.buffer_id = o.buffer_id)
|
|
4573
|
-
INTO v_on_cart;
|
|
4574
|
-
IF NOT v_on_cart THEN
|
|
4575
|
-
PERFORM set_config('logistics.buffer_writer', 'engine', true);
|
|
4576
|
-
UPDATE public.orders SET buffer_id = NULL WHERE id = o.id;
|
|
4577
|
-
BEGIN
|
|
4578
|
-
INSERT INTO public.logistics_planner_trace(order_id, message)
|
|
4579
|
-
VALUES (o.id, 'afgemeld; uit buffer gehaald');
|
|
4580
|
-
EXCEPTION WHEN others THEN NULL; END;
|
|
4581
|
-
END IF;
|
|
4582
|
-
END IF;
|
|
4583
|
-
RETURN NULL;
|
|
4584
|
-
END IF;
|
|
4585
|
-
|
|
4586
|
-
d := public.logistics_buffer_decision(public.logistics_buffer_payload(o.id), NULL);
|
|
4587
|
-
|
|
4588
|
-
IF COALESCE((d ->> 'buffer')::boolean, false) IS NOT TRUE OR (d ->> 'bufferRef') IS NULL THEN
|
|
4589
|
-
IF o.buffer_id IS NOT NULL THEN
|
|
4590
|
-
UPDATE public.order_carts SET buffer_id = NULL WHERE order_id = o.id;
|
|
4591
|
-
PERFORM set_config('logistics.buffer_writer', 'engine', true);
|
|
4592
|
-
UPDATE public.orders SET buffer_id = NULL WHERE id = o.id;
|
|
4593
|
-
END IF;
|
|
4594
|
-
DELETE FROM public.order_buffers b
|
|
4595
|
-
WHERE NOT EXISTS (SELECT 1 FROM public.orders x WHERE x.buffer_id = b.id)
|
|
4596
|
-
AND NOT EXISTS (SELECT 1 FROM public.order_carts oc WHERE oc.buffer_id = b.id);
|
|
4597
|
-
RETURN NULL;
|
|
4598
|
-
END IF;
|
|
4599
|
-
|
|
4600
|
-
v_ref := d ->> 'bufferRef';
|
|
4601
|
-
BEGIN v_close := NULLIF(d ->> 'bufferCloseAt', '')::timestamptz;
|
|
4602
|
-
EXCEPTION WHEN others THEN v_close := NULL; END;
|
|
4603
|
-
|
|
4604
|
-
LOOP
|
|
4605
|
-
v_key := CASE WHEN v_try = 0 THEN v_ref ELSE v_ref || '#' || v_try END;
|
|
4606
|
-
SELECT id INTO v_buffer FROM public.order_buffers WHERE buffer_key = v_key;
|
|
4607
|
-
IF v_buffer IS NULL THEN
|
|
4608
|
-
INSERT INTO public.order_buffers (buffer_key, grouping_mode, pickup_date, pickup_location, customer_id, close_at)
|
|
4609
|
-
VALUES (v_key, 'engine',
|
|
4610
|
-
COALESCE(cf ->> 'pickup_moment', cf ->> 'pickup_date', o.delivery_date::text),
|
|
4611
|
-
COALESCE(cf ->> 'delivery_location_gln', cf ->> 'delivery_location_id', cf ->> 'delivery_location'),
|
|
4612
|
-
o.customer_id, v_close)
|
|
4613
|
-
ON CONFLICT (buffer_key) DO UPDATE SET grouping_mode = EXCLUDED.grouping_mode
|
|
4614
|
-
RETURNING id INTO v_buffer;
|
|
4615
|
-
EXIT;
|
|
4616
|
-
END IF;
|
|
4617
|
-
IF o.buffer_id = v_buffer THEN EXIT; END IF;
|
|
4618
|
-
|
|
4619
|
-
-- 1.0.164: ook een buffer met een geprinte, gescande of verstuurde kar/order is dicht voor nieuwe orders.
|
|
4620
|
-
v_closed := public.logistics_buffer_closed_for_join(v_buffer);
|
|
4621
|
-
|
|
4622
|
-
IF NOT COALESCE(v_closed, false) THEN
|
|
4623
|
-
UPDATE public.order_buffers
|
|
4624
|
-
SET close_at = LEAST(COALESCE(close_at, v_close), COALESCE(v_close, close_at)), updated_at = now()
|
|
4625
|
-
WHERE id = v_buffer;
|
|
4626
|
-
EXIT;
|
|
4627
|
-
END IF;
|
|
4628
|
-
UPDATE public.order_buffers SET closed_at = COALESCE(closed_at, now()), updated_at = now() WHERE id = v_buffer;
|
|
4629
|
-
v_try := v_try + 1; v_buffer := NULL;
|
|
4630
|
-
IF v_try > 50 THEN RAISE EXCEPTION 'Kan geen open orderbuffer vinden voor sleutel %', v_ref; END IF;
|
|
4631
|
-
END LOOP;
|
|
4632
|
-
|
|
4633
|
-
IF o.buffer_id IS DISTINCT FROM v_buffer THEN
|
|
4634
|
-
PERFORM set_config('logistics.buffer_writer', 'engine', true);
|
|
4635
|
-
UPDATE public.orders SET buffer_id = v_buffer WHERE id = o.id;
|
|
4636
|
-
DELETE FROM public.order_buffers b
|
|
4637
|
-
WHERE NOT EXISTS (SELECT 1 FROM public.orders x WHERE x.buffer_id = b.id)
|
|
4638
|
-
AND NOT EXISTS (SELECT 1 FROM public.order_carts oc WHERE oc.buffer_id = b.id);
|
|
4639
|
-
END IF;
|
|
4640
|
-
RETURN v_buffer;
|
|
4641
|
-
END;
|
|
4642
|
-
$function$
|
|
4643
|
-
$fsdef$;
|
|
4644
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
4645
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_apply_buffer_decision overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
4646
|
-
END $fsdo$;
|
|
4647
|
-
|
|
4648
|
-
DO $fsdo$ BEGIN
|
|
4649
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_apply_cart_swap(p_delete_ids uuid[], p_new_carts jsonb)
|
|
4650
|
-
RETURNS jsonb
|
|
4651
|
-
LANGUAGE plpgsql
|
|
4652
|
-
SECURITY DEFINER
|
|
4653
|
-
SET search_path TO 'public'
|
|
4654
|
-
AS $function$
|
|
4655
|
-
DECLARE
|
|
4656
|
-
v_del uuid[] := COALESCE(p_delete_ids, ARRAY[]::uuid[]);
|
|
4657
|
-
v_cart jsonb; v_row jsonb; v_id uuid; v_map jsonb := '[]'::jsonb;
|
|
4658
|
-
v_jobs int := 0; v_carts int := 0; v_items int := 0;
|
|
4659
|
-
BEGIN
|
|
4660
|
-
IF jsonb_typeof(COALESCE(p_new_carts, '[]'::jsonb)) <> 'array' THEN
|
|
4661
|
-
RAISE EXCEPTION 'Nieuwe karren ontbreken of zijn ongeldig.';
|
|
4662
|
-
END IF;
|
|
4663
|
-
|
|
4664
|
-
IF array_length(v_del, 1) IS NOT NULL THEN
|
|
4665
|
-
UPDATE public.print_jobs
|
|
4666
|
-
SET status = 'geannuleerd'::print_job_status,
|
|
4667
|
-
foutmelding = 'Vervallen: kar verwijderd bij herindeling',
|
|
4668
|
-
updated_at = now()
|
|
4669
|
-
WHERE status IN ('wachtend'::print_job_status, 'bezig'::print_job_status)
|
|
4670
|
-
AND (payload->>'cart_id') = ANY(SELECT id::text FROM unnest(v_del) AS id);
|
|
4671
|
-
GET DIAGNOSTICS v_jobs = ROW_COUNT;
|
|
4672
|
-
DELETE FROM public.pakbon_barcode_inhoud WHERE cart_id = ANY(SELECT id::text FROM unnest(v_del) AS id);
|
|
4673
|
-
DELETE FROM public.order_cart_layer_positions WHERE cart_id = ANY(v_del);
|
|
4674
|
-
DELETE FROM public.order_cart_items WHERE cart_id = ANY(v_del);
|
|
4675
|
-
DELETE FROM public.order_carts
|
|
4676
|
-
WHERE id = ANY(v_del)
|
|
4677
|
-
AND COALESCE(pickup_locked, false) IS FALSE;
|
|
4678
|
-
GET DIAGNOSTICS v_carts = ROW_COUNT;
|
|
4679
|
-
END IF;
|
|
4680
|
-
|
|
4681
|
-
FOR v_cart IN SELECT value FROM jsonb_array_elements(COALESCE(p_new_carts, '[]'::jsonb)) LOOP
|
|
4682
|
-
v_row := v_cart->'row';
|
|
4683
|
-
v_id := gen_random_uuid();
|
|
4684
|
-
INSERT INTO public.order_carts (id, order_id, buffer_id, cart_number, total_carts, is_auto, is_complete, source,
|
|
4685
|
-
occupancy_pct, total_layers_used, carrier_type, carrier_type_id, max_layers, weight_kg, algorithm_version, layout_method)
|
|
4686
|
-
SELECT v_id, r.order_id, r.buffer_id, r.cart_number, r.total_carts, COALESCE(r.is_auto, true), COALESCE(r.is_complete, false),
|
|
4687
|
-
COALESCE(r.source, 'auto'), COALESCE(r.occupancy_pct, 0), COALESCE(r.total_layers_used, 0),
|
|
4688
|
-
COALESCE(r.carrier_type, 'trolley'), r.carrier_type_id, r.max_layers, r.weight_kg, COALESCE(r.algorithm_version, 1), r.layout_method
|
|
4689
|
-
FROM jsonb_to_record(v_row) AS r(order_id uuid, buffer_id uuid, cart_number integer, total_carts integer, is_auto boolean,
|
|
4690
|
-
is_complete boolean, source text, occupancy_pct numeric, total_layers_used numeric, carrier_type text, carrier_type_id uuid,
|
|
4691
|
-
max_layers integer, weight_kg numeric, algorithm_version integer, layout_method text);
|
|
4692
|
-
|
|
4693
|
-
INSERT INTO public.order_cart_items (cart_id, order_item_id, product_id, product_name, crates, boxes, weight_kg,
|
|
4694
|
-
plants_per_crate, crates_per_layer, layers_per_cart, layer_fraction, layer_share_pct, layer_index, crates_in_layer, components)
|
|
4695
|
-
SELECT v_id, i.order_item_id, i.product_id, i.product_name, i.crates, i.boxes, i.weight_kg,
|
|
4696
|
-
COALESCE(i.plants_per_crate, 1), COALESCE(i.crates_per_layer, 1), COALESCE(i.layers_per_cart, 1),
|
|
4697
|
-
COALESCE(i.layer_fraction, 0), COALESCE(i.layer_share_pct, 0), i.layer_index, i.crates_in_layer,
|
|
4698
|
-
CASE WHEN jsonb_typeof(i.components) = 'array' THEN i.components END
|
|
4699
|
-
FROM jsonb_to_recordset(COALESCE(v_cart->'items', '[]'::jsonb)) AS i(order_item_id uuid, product_id uuid, product_name text,
|
|
4700
|
-
crates integer, boxes integer, weight_kg numeric, plants_per_crate integer, crates_per_layer integer, layers_per_cart integer,
|
|
4701
|
-
layer_fraction numeric, layer_share_pct numeric, layer_index integer, crates_in_layer integer, components jsonb);
|
|
4702
|
-
v_items := v_items + jsonb_array_length(COALESCE(v_cart->'items', '[]'::jsonb));
|
|
4703
4551
|
|
|
4704
|
-
v_map := v_map || jsonb_build_object('planIndex', (v_cart->>'planIndex')::integer, 'id', v_id);
|
|
4705
|
-
END LOOP;
|
|
4706
|
-
|
|
4707
|
-
RETURN jsonb_build_object('karren', v_map, 'verwijderd', v_carts, 'printopdrachtenGeannuleerd', v_jobs, 'regels', v_items);
|
|
4708
|
-
END;
|
|
4709
|
-
$function$
|
|
4710
|
-
$fsdef$;
|
|
4711
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
4712
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_apply_cart_swap overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
4713
|
-
END $fsdo$;
|
|
4714
4552
|
|
|
4715
4553
|
DO $fsdo$ BEGIN
|
|
4716
4554
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_apply_document_layouts()
|
|
@@ -5600,80 +5438,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
5600
5438
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_blocked_overview overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
5601
5439
|
END $fsdo$;
|
|
5602
5440
|
|
|
5603
|
-
DO $fsdo$ BEGIN
|
|
5604
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_brief_transport(p_order_id uuid, p_cart_id uuid DEFAULT NULL::uuid)
|
|
5605
|
-
RETURNS jsonb
|
|
5606
|
-
LANGUAGE plpgsql
|
|
5607
|
-
STABLE SECURITY DEFINER
|
|
5608
|
-
SET search_path TO 'public'
|
|
5609
|
-
AS $function$
|
|
5610
|
-
DECLARE
|
|
5611
|
-
o record; v_carrier_id uuid; v_bron text; ca public.carriers%ROWTYPE;
|
|
5612
|
-
v_naam text; v_code text; v_date date; v_time time; n int;
|
|
5613
|
-
v_wens text; onbekend text[] := '{}'::text[]; uit jsonb := '{}'::jsonb;
|
|
5614
|
-
BEGIN
|
|
5615
|
-
SELECT id, custom_fields, floriday_sales_order_id INTO o FROM public.orders WHERE id = p_order_id AND deleted_at IS NULL;
|
|
5616
|
-
IF o.id IS NULL THEN
|
|
5617
|
-
RETURN jsonb_build_object('onbekend', jsonb_build_array('order'));
|
|
5618
|
-
END IF;
|
|
5619
|
-
|
|
5620
|
-
IF coalesce(o.custom_fields->>'carrier','') ~* '^[0-9a-f-]{36}$' THEN
|
|
5621
|
-
v_carrier_id := (o.custom_fields->>'carrier')::uuid; v_bron := 'order';
|
|
5622
|
-
ELSIF coalesce(o.custom_fields->>'delivery_location','') ~* '^[0-9a-f-]{36}$' THEN
|
|
5623
|
-
SELECT carrier_id INTO v_carrier_id FROM public.customer_delivery_locations
|
|
5624
|
-
WHERE id = (o.custom_fields->>'delivery_location')::uuid;
|
|
5625
|
-
v_bron := 'afleverlocatie';
|
|
5626
|
-
END IF;
|
|
5627
|
-
IF v_carrier_id IS NOT NULL THEN
|
|
5628
|
-
SELECT * INTO ca FROM public.carriers WHERE id = v_carrier_id;
|
|
5629
|
-
END IF;
|
|
5630
|
-
|
|
5631
|
-
IF ca.id IS NOT NULL AND nullif(trim(ca.name),'') IS NOT NULL THEN
|
|
5632
|
-
uit := uit || jsonb_build_object('vervoerder', jsonb_build_object('naam', ca.name), 'vervoerder_bron', v_bron);
|
|
5633
|
-
ELSE
|
|
5634
|
-
SELECT count(*), min(fc.name), min(nullif(fc.gln_code,'')) INTO n, v_naam, v_code
|
|
5635
|
-
FROM public.floriday_delivery_orders_cache d
|
|
5636
|
-
JOIN public.floriday_carriers_cache fc ON fc.organization_id::text = d.data->>'carrierOrganizationId'
|
|
5637
|
-
WHERE o.floriday_sales_order_id IS NOT NULL
|
|
5638
|
-
AND d.data::text LIKE '%' || o.floriday_sales_order_id::text || '%'
|
|
5639
|
-
AND coalesce(d.is_deleted,false) = false;
|
|
5640
|
-
IF n = 1 AND nullif(trim(v_naam),'') IS NOT NULL THEN
|
|
5641
|
-
uit := uit || jsonb_build_object('vervoerder', jsonb_build_object('naam', v_naam) ||
|
|
5642
|
-
CASE WHEN v_code IS NOT NULL THEN jsonb_build_object('code', v_code) ELSE '{}'::jsonb END,
|
|
5643
|
-
'vervoerder_bron', 'floriday');
|
|
5644
|
-
ELSE
|
|
5645
|
-
onbekend := array_append(onbekend, CASE WHEN n > 1 THEN 'vervoerder_niet_eenduidig' ELSE 'vervoerder' END);
|
|
5646
|
-
END IF;
|
|
5647
|
-
END IF;
|
|
5648
|
-
|
|
5649
|
-
SELECT pick_date INTO v_date FROM public.logistics_order_pick_day WHERE order_id = p_order_id;
|
|
5650
|
-
IF v_date IS NULL OR ca.id IS NULL OR jsonb_typeof(ca.pickup_moments) IS DISTINCT FROM 'array' THEN
|
|
5651
|
-
onbekend := array_append(onbekend, 'ophaalmoment');
|
|
5652
|
-
ELSIF ca.pickup_weekdays IS NOT NULL AND array_length(ca.pickup_weekdays,1) > 0
|
|
5653
|
-
AND NOT (extract(isodow FROM v_date)::int = ANY (ca.pickup_weekdays)) THEN
|
|
5654
|
-
onbekend := array_append(onbekend, 'ophaalmoment');
|
|
5655
|
-
ELSE
|
|
5656
|
-
v_wens := nullif(o.custom_fields->>'pickup_moment','');
|
|
5657
|
-
SELECT count(*), min(nullif(m->>'pickup_time','')::time) INTO n, v_time
|
|
5658
|
-
FROM jsonb_array_elements(ca.pickup_moments) m
|
|
5659
|
-
WHERE nullif(m->>'pickup_time','') IS NOT NULL
|
|
5660
|
-
AND coalesce(nullif(m->>'pickup_days',''),'0') = '0'
|
|
5661
|
-
AND (v_wens IS NULL OR left(m->>'pickup_time',5) = left(v_wens,5));
|
|
5662
|
-
IF n = 1 THEN
|
|
5663
|
-
uit := uit || jsonb_build_object('ophaalmoment',
|
|
5664
|
-
to_char(((v_date + v_time) AT TIME ZONE public.logistics_tz()) AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"'));
|
|
5665
|
-
ELSE
|
|
5666
|
-
onbekend := array_append(onbekend, CASE WHEN n > 1 THEN 'ophaalmoment_niet_eenduidig' ELSE 'ophaalmoment' END);
|
|
5667
|
-
END IF;
|
|
5668
|
-
END IF;
|
|
5669
|
-
|
|
5670
|
-
RETURN uit || jsonb_build_object('onbekend', to_jsonb(onbekend));
|
|
5671
|
-
END;
|
|
5672
|
-
$function$
|
|
5673
|
-
$fsdef$;
|
|
5674
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
5675
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_brief_transport overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
5676
|
-
END $fsdo$;
|
|
5677
5441
|
|
|
5678
5442
|
DO $fsdo$ BEGIN
|
|
5679
5443
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_buffer_closed_for_join(p_buffer uuid)
|
|
@@ -6240,36 +6004,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
6240
6004
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_buffer_open_key overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
6241
6005
|
END $fsdo$;
|
|
6242
6006
|
|
|
6243
|
-
DO $fsdo$ BEGIN
|
|
6244
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_buffer_payload(p_order_id uuid)
|
|
6245
|
-
RETURNS jsonb
|
|
6246
|
-
LANGUAGE sql
|
|
6247
|
-
STABLE SECURITY DEFINER
|
|
6248
|
-
SET search_path TO 'public'
|
|
6249
|
-
AS $function$
|
|
6250
|
-
SELECT jsonb_build_object(
|
|
6251
|
-
'orderRef', COALESCE(o.order_number, o.id::text),
|
|
6252
|
-
'checkinAt', COALESCE(cf ->> 'checkin_at', cf ->> 'checkin_moment', cf ->> 'pickup_moment', cf ->> 'pickup_datetime'),
|
|
6253
|
-
'pickupAt', COALESCE(cf ->> 'pickup_datetime', cf ->> 'pickup_moment', cf ->> 'checkin_at'),
|
|
6254
|
-
'customerRef', o.customer_id::text,
|
|
6255
|
-
'floridayCustomerRef', COALESCE(cf ->> 'floriday_customer_id', cf ->> 'floriday_customer_ref'),
|
|
6256
|
-
'floridaySalesOrderRef', COALESCE(o.floriday_sales_order_id::text, cf ->> 'floriday_sales_order_id'),
|
|
6257
|
-
'bvoCustomerRef', COALESCE(cf ->> 'bvo_customer_ref', cf ->> 'bvo_customer_id'),
|
|
6258
|
-
'deliveryLocationRef', COALESCE(cf ->> 'delivery_location_gln', cf ->> 'delivery_location_id', cf ->> 'delivery_location'),
|
|
6259
|
-
'deliveryDate', o.delivery_date::text,
|
|
6260
|
-
'carrierRef', COALESCE(cf ->> 'carrier_id', cf ->> 'carrier'),
|
|
6261
|
-
'loadCarrierType', COALESCE(cf ->> 'load_carrier_type', 'trolley'),
|
|
6262
|
-
'orderType', COALESCE(cf ->> 'order_type', o.order_source, 'standaard'),
|
|
6263
|
-
'isReservation', COALESCE(o.is_reservation, false)
|
|
6264
|
-
)
|
|
6265
|
-
FROM public.orders o
|
|
6266
|
-
CROSS JOIN LATERAL (SELECT COALESCE(o.custom_fields, '{}'::jsonb) AS cf) x
|
|
6267
|
-
WHERE o.id = p_order_id;
|
|
6268
|
-
$function$
|
|
6269
|
-
$fsdef$;
|
|
6270
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
6271
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_buffer_payload overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
6272
|
-
END $fsdo$;
|
|
6273
6007
|
|
|
6274
6008
|
DO $fsdo$ BEGIN
|
|
6275
6009
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_buffer_simulate(p_orders jsonb DEFAULT '[]'::jsonb, p_strategy_id uuid DEFAULT NULL::uuid)
|
|
@@ -6756,45 +6490,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
6756
6490
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_capacity_plan_day overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
6757
6491
|
END $fsdo$;
|
|
6758
6492
|
|
|
6759
|
-
DO $fsdo$ BEGIN
|
|
6760
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_carrier_for_location(p_location text, p_customer_id uuid)
|
|
6761
|
-
RETURNS uuid
|
|
6762
|
-
LANGUAGE plpgsql
|
|
6763
|
-
STABLE SECURITY DEFINER
|
|
6764
|
-
SET search_path TO 'public'
|
|
6765
|
-
AS $function$
|
|
6766
|
-
DECLARE v_raw text := nullif(btrim(coalesce(p_location,'')),''); v_lid uuid := public.logistics_try_uuid(v_raw);
|
|
6767
|
-
dl_country text; dl_province text; dl_city text; c_country text; c_city text; v_id uuid; v_country text; v_city text; v_prov text;
|
|
6768
|
-
BEGIN
|
|
6769
|
-
IF v_raw IS NOT NULL THEN
|
|
6770
|
-
SELECT l.country, l.province, l.city INTO dl_country, dl_province, dl_city FROM public.customer_delivery_locations l
|
|
6771
|
-
WHERE (v_lid IS NOT NULL AND l.id = v_lid) OR l.gln = v_raw
|
|
6772
|
-
ORDER BY (v_lid IS NOT NULL AND l.id = v_lid) DESC
|
|
6773
|
-
LIMIT 1;
|
|
6774
|
-
END IF;
|
|
6775
|
-
IF p_customer_id IS NOT NULL THEN
|
|
6776
|
-
SELECT cu.country, cu.city INTO c_country, c_city FROM public.customers cu WHERE cu.id = p_customer_id;
|
|
6777
|
-
END IF;
|
|
6778
|
-
v_country := public.afh_normalize_country(coalesce(dl_country, c_country));
|
|
6779
|
-
v_city := public.afh_city_code(v_country, coalesce(dl_city, c_city));
|
|
6780
|
-
v_prov := public.afh_normalize_nl_province(dl_province);
|
|
6781
|
-
SELECT ca.id INTO v_id FROM public.carriers ca
|
|
6782
|
-
WHERE nullif(trim(ca.email),'') IS NOT NULL
|
|
6783
|
-
AND ((v_country = ANY(ca.service_countries))
|
|
6784
|
-
OR (v_prov = ANY(ca.service_provinces))
|
|
6785
|
-
OR (v_city = ANY(ca.service_cities))
|
|
6786
|
-
OR ca.is_default)
|
|
6787
|
-
ORDER BY CASE WHEN ca.is_default AND NOT (
|
|
6788
|
-
(v_country = ANY(ca.service_countries))
|
|
6789
|
-
OR (v_prov = ANY(ca.service_provinces))
|
|
6790
|
-
OR (v_city = ANY(ca.service_cities))) THEN 1 ELSE 0 END, ca.sort_order, ca.id
|
|
6791
|
-
LIMIT 1;
|
|
6792
|
-
RETURN v_id;
|
|
6793
|
-
END $function$
|
|
6794
|
-
$fsdef$;
|
|
6795
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
6796
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_carrier_for_location overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
6797
|
-
END $fsdo$;
|
|
6798
6493
|
|
|
6799
6494
|
DO $fsdo$ BEGIN
|
|
6800
6495
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_carrier_minutes(p_carrier text, p_settings jsonb)
|
|
@@ -7873,49 +7568,11 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
7873
7568
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_cart_scanned overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
7874
7569
|
END $fsdo$;
|
|
7875
7570
|
|
|
7571
|
+
|
|
7876
7572
|
DO $fsdo$ BEGIN
|
|
7877
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.
|
|
7878
|
-
RETURNS
|
|
7879
|
-
LANGUAGE
|
|
7880
|
-
STABLE SECURITY DEFINER
|
|
7881
|
-
SET search_path TO 'public'
|
|
7882
|
-
AS $function$
|
|
7883
|
-
WITH deelname_ruw AS (
|
|
7884
|
-
SELECT oc.id AS cart_id, oc.cart_number AS cart_index, oc.order_id AS order_uuid, oc.created_at
|
|
7885
|
-
FROM public.order_carts oc
|
|
7886
|
-
WHERE oc.order_id IS NOT NULL AND (p_order_uuid IS NULL OR oc.order_id = p_order_uuid)
|
|
7887
|
-
UNION
|
|
7888
|
-
SELECT oc.id, oc.cart_number, oi.order_id, oc.created_at
|
|
7889
|
-
FROM public.order_carts oc
|
|
7890
|
-
JOIN public.order_cart_items oci ON oci.cart_id = oc.id
|
|
7891
|
-
JOIN logistics_active.order_items oi ON oi.id = oci.order_item_id
|
|
7892
|
-
WHERE oc.order_id IS NULL AND oi.order_id IS NOT NULL AND (p_order_uuid IS NULL OR oi.order_id = p_order_uuid)
|
|
7893
|
-
),
|
|
7894
|
-
deelname AS (
|
|
7895
|
-
SELECT DISTINCT ON (d.order_uuid, d.cart_index) d.*
|
|
7896
|
-
FROM deelname_ruw d
|
|
7897
|
-
ORDER BY d.order_uuid, d.cart_index, d.created_at DESC, d.cart_id
|
|
7898
|
-
),
|
|
7899
|
-
genummerd AS (
|
|
7900
|
-
SELECT d.order_uuid, d.cart_id, d.cart_index,
|
|
7901
|
-
dense_rank() OVER (PARTITION BY d.order_uuid ORDER BY d.cart_index)::int AS cart_seq,
|
|
7902
|
-
count(*) OVER (PARTITION BY d.order_uuid)::int AS cart_total
|
|
7903
|
-
FROM deelname d
|
|
7904
|
-
)
|
|
7905
|
-
SELECT g.order_uuid, g.cart_id, g.cart_index, g.cart_seq,
|
|
7906
|
-
COALESCE(cn.cart_number, g.cart_seq::text) AS cart_number, g.cart_total
|
|
7907
|
-
FROM genummerd g
|
|
7908
|
-
LEFT JOIN public.cart_numbers cn ON cn.order_id = g.order_uuid::text AND cn.cart_index = g.cart_index;
|
|
7909
|
-
$function$
|
|
7910
|
-
$fsdef$;
|
|
7911
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
7912
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_cart_seq overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
7913
|
-
END $fsdo$;
|
|
7914
|
-
|
|
7915
|
-
DO $fsdo$ BEGIN
|
|
7916
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_cart_slip_plan(p_order_id uuid)
|
|
7917
|
-
RETURNS jsonb
|
|
7918
|
-
LANGUAGE plpgsql
|
|
7573
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_cart_slip_plan(p_order_id uuid)
|
|
7574
|
+
RETURNS jsonb
|
|
7575
|
+
LANGUAGE plpgsql
|
|
7919
7576
|
STABLE SECURITY DEFINER
|
|
7920
7577
|
SET search_path TO 'public'
|
|
7921
7578
|
AS $function$
|
|
@@ -9684,111 +9341,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
9684
9341
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_document_layout overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
9685
9342
|
END $fsdo$;
|
|
9686
9343
|
|
|
9687
|
-
DO $fsdo$ BEGIN
|
|
9688
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_document_layout_v2(_document_code text, _is_partial boolean DEFAULT false)
|
|
9689
|
-
RETURNS jsonb
|
|
9690
|
-
LANGUAGE plpgsql
|
|
9691
|
-
STABLE SECURITY DEFINER
|
|
9692
|
-
SET search_path TO 'public'
|
|
9693
|
-
AS $function$
|
|
9694
|
-
DECLARE
|
|
9695
|
-
v_types public.doc_layout_type[];
|
|
9696
|
-
v_code text;
|
|
9697
|
-
v_keys text[];
|
|
9698
|
-
v_key text;
|
|
9699
|
-
v_fields jsonb;
|
|
9700
|
-
v_chosen uuid;
|
|
9701
|
-
v_used_key text;
|
|
9702
|
-
v_layout public.document_layouts%ROWTYPE;
|
|
9703
|
-
BEGIN
|
|
9704
|
-
v_code := lower(btrim(coalesce(_document_code, '')));
|
|
9705
|
-
v_types := public.logistics_document_type_map(v_code);
|
|
9706
|
-
|
|
9707
|
-
-- Geordende sleutellijst: eigen instelling eerst, daarna de terugval.
|
|
9708
|
-
-- Pakbon kent twee varianten: een volle kar en een deelorder (geen volle kar).
|
|
9709
|
-
v_keys := CASE
|
|
9710
|
-
WHEN v_code LIKE '%pakbon%' AND COALESCE(_is_partial, false)
|
|
9711
|
-
THEN ARRAY['packing_slip_partial_layout', 'packing_slip_layout']
|
|
9712
|
-
WHEN v_code LIKE '%pakbon%' THEN ARRAY['packing_slip_layout']
|
|
9713
|
-
WHEN v_code LIKE '%sticker%' OR v_code LIKE '%etiket%' THEN ARRAY['sticker_layout']
|
|
9714
|
-
WHEN v_code LIKE '%afleverbrief%' OR v_code LIKE '%afleverbon%'
|
|
9715
|
-
THEN ARRAY['delivery_note_layout', 'shipping_note_layout']
|
|
9716
|
-
WHEN v_code LIKE '%veilingbrief%' OR v_code LIKE '%veilingbon%'
|
|
9717
|
-
THEN ARRAY['auction_note_layout', 'shipping_note_layout']
|
|
9718
|
-
WHEN v_code LIKE '%verzendbrief%' OR v_code LIKE '%transportbrief%'
|
|
9719
|
-
OR v_code LIKE '%verzendlabel%' THEN ARRAY['shipping_note_layout']
|
|
9720
|
-
WHEN v_code LIKE '%productiebon%' OR v_code LIKE '%productielijst%'
|
|
9721
|
-
THEN ARRAY['production_note_layout']
|
|
9722
|
-
ELSE NULL
|
|
9723
|
-
END;
|
|
9724
|
-
|
|
9725
|
-
IF v_keys IS NOT NULL THEN
|
|
9726
|
-
FOREACH v_key IN ARRAY v_keys LOOP
|
|
9727
|
-
SELECT settings->'pickstations'->'fields'
|
|
9728
|
-
INTO v_fields
|
|
9729
|
-
FROM public.logistics_rule_configs
|
|
9730
|
-
WHERE nullif(settings->'pickstations'->'fields'->>v_key, '') IS NOT NULL
|
|
9731
|
-
ORDER BY is_active DESC, (status = 'actief') DESC, updated_at DESC
|
|
9732
|
-
LIMIT 1;
|
|
9733
|
-
|
|
9734
|
-
BEGIN
|
|
9735
|
-
v_chosen := nullif(v_fields->>v_key, '')::uuid;
|
|
9736
|
-
EXCEPTION WHEN invalid_text_representation THEN
|
|
9737
|
-
v_chosen := NULL;
|
|
9738
|
-
END;
|
|
9739
|
-
|
|
9740
|
-
IF v_chosen IS NOT NULL THEN
|
|
9741
|
-
v_used_key := v_key;
|
|
9742
|
-
EXIT;
|
|
9743
|
-
END IF;
|
|
9744
|
-
END LOOP;
|
|
9745
|
-
END IF;
|
|
9746
|
-
|
|
9747
|
-
IF v_chosen IS NOT NULL THEN
|
|
9748
|
-
SELECT * INTO v_layout
|
|
9749
|
-
FROM public.document_layouts
|
|
9750
|
-
WHERE id = v_chosen
|
|
9751
|
-
AND actief IS TRUE;
|
|
9752
|
-
IF v_layout.id IS NULL THEN
|
|
9753
|
-
v_used_key := NULL;
|
|
9754
|
-
END IF;
|
|
9755
|
-
END IF;
|
|
9756
|
-
|
|
9757
|
-
IF v_layout.id IS NULL AND array_length(v_types, 1) IS NOT NULL THEN
|
|
9758
|
-
SELECT * INTO v_layout
|
|
9759
|
-
FROM public.document_layouts
|
|
9760
|
-
WHERE actief IS TRUE
|
|
9761
|
-
AND documenttype = ANY (v_types)
|
|
9762
|
-
ORDER BY array_position(v_types, documenttype), is_standaard DESC, updated_at DESC
|
|
9763
|
-
LIMIT 1;
|
|
9764
|
-
END IF;
|
|
9765
|
-
|
|
9766
|
-
IF v_layout.id IS NULL THEN
|
|
9767
|
-
RETURN NULL;
|
|
9768
|
-
END IF;
|
|
9769
|
-
|
|
9770
|
-
RETURN jsonb_build_object(
|
|
9771
|
-
'layoutId', v_layout.id,
|
|
9772
|
-
'layoutName', v_layout.naam,
|
|
9773
|
-
'layoutVersion', v_layout.huidige_versie,
|
|
9774
|
-
'layoutDocumentType', v_layout.documenttype::text,
|
|
9775
|
-
'layoutSettingKey', v_used_key,
|
|
9776
|
-
'layoutVariant', CASE WHEN COALESCE(_is_partial, false) THEN 'partial_order' ELSE 'full_cart' END,
|
|
9777
|
-
'layoutFallbackUsed', (v_used_key IS NOT NULL AND v_keys IS NOT NULL AND v_used_key <> v_keys[1]),
|
|
9778
|
-
'layout_id', v_layout.id,
|
|
9779
|
-
'layout_name', v_layout.naam,
|
|
9780
|
-
'layout_version', v_layout.huidige_versie,
|
|
9781
|
-
'layout_document_type', v_layout.documenttype::text,
|
|
9782
|
-
'layout_setting_key', v_used_key,
|
|
9783
|
-
'layout_variant', CASE WHEN COALESCE(_is_partial, false) THEN 'partial_order' ELSE 'full_cart' END,
|
|
9784
|
-
'layout_fallback_used', (v_used_key IS NOT NULL AND v_keys IS NOT NULL AND v_used_key <> v_keys[1])
|
|
9785
|
-
);
|
|
9786
|
-
END;
|
|
9787
|
-
$function$
|
|
9788
|
-
$fsdef$;
|
|
9789
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
9790
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_document_layout_v2 overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
9791
|
-
END $fsdo$;
|
|
9792
9344
|
|
|
9793
9345
|
DO $fsdo$ BEGIN
|
|
9794
9346
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_document_station(_document_code text)
|
|
@@ -12310,30 +11862,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
12310
11862
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_order_buffer_excluded overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
12311
11863
|
END $fsdo$;
|
|
12312
11864
|
|
|
12313
|
-
DO $fsdo$ BEGIN
|
|
12314
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_order_carrier_id(p_order_id uuid)
|
|
12315
|
-
RETURNS uuid
|
|
12316
|
-
LANGUAGE plpgsql
|
|
12317
|
-
STABLE SECURITY DEFINER
|
|
12318
|
-
SET search_path TO 'public'
|
|
12319
|
-
AS $function$
|
|
12320
|
-
DECLARE v_own uuid; v_id uuid; o record;
|
|
12321
|
-
BEGIN
|
|
12322
|
-
SELECT ord.custom_fields cf, ord.customer_id INTO o FROM public.orders ord WHERE ord.id = p_order_id;
|
|
12323
|
-
IF NOT FOUND THEN RETURN NULL; END IF;
|
|
12324
|
-
v_own := public.logistics_try_uuid(o.cf->>'carrier');
|
|
12325
|
-
IF v_own IS NOT NULL THEN
|
|
12326
|
-
SELECT id INTO v_id FROM public.carriers WHERE id = v_own;
|
|
12327
|
-
IF v_id IS NOT NULL THEN RETURN v_id; END IF;
|
|
12328
|
-
END IF;
|
|
12329
|
-
RETURN public.logistics_carrier_for_location(
|
|
12330
|
-
coalesce(nullif(o.cf->>'delivery_location',''), nullif(o.cf->>'delivery_location_id',''), nullif(o.cf->>'delivery_location_gln','')),
|
|
12331
|
-
o.customer_id);
|
|
12332
|
-
END $function$
|
|
12333
|
-
$fsdef$;
|
|
12334
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
12335
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_order_carrier_id overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
12336
|
-
END $fsdo$;
|
|
12337
11865
|
|
|
12338
11866
|
DO $fsdo$ BEGIN
|
|
12339
11867
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_order_cart_approval(_order_ref text)
|
|
@@ -12548,48 +12076,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
12548
12076
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_order_definitively_blocked overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
12549
12077
|
END $fsdo$;
|
|
12550
12078
|
|
|
12551
|
-
DO $fsdo$ BEGIN
|
|
12552
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_order_departure(p_order_id uuid)
|
|
12553
|
-
RETURNS jsonb
|
|
12554
|
-
LANGUAGE plpgsql
|
|
12555
|
-
STABLE SECURITY DEFINER
|
|
12556
|
-
SET search_path TO 'public'
|
|
12557
|
-
AS $function$
|
|
12558
|
-
DECLARE o record; v jsonb; v_own jsonb; v_txt text; v_at timestamptz;
|
|
12559
|
-
BEGIN
|
|
12560
|
-
IF public.logistics_tz() IS NULL THEN
|
|
12561
|
-
RETURN jsonb_build_object('ok', false, 'reason', 'De tijdzone van de vestiging ontbreekt. Stel die in bij Werktijden.');
|
|
12562
|
-
END IF;
|
|
12563
|
-
SELECT id, created_at, delivery_date, custom_fields INTO o FROM public.orders WHERE id = p_order_id;
|
|
12564
|
-
IF NOT FOUND OR coalesce(o.delivery_date,'') !~ '^\d{4}-\d{2}-\d{2}' THEN
|
|
12565
|
-
RETURN jsonb_build_object('ok', false, 'reason', 'De leverdatum van de order is onbekend.');
|
|
12566
|
-
END IF;
|
|
12567
|
-
|
|
12568
|
-
v_own := CASE WHEN jsonb_typeof(o.custom_fields->'own_transport') = 'object' THEN o.custom_fields->'own_transport' END;
|
|
12569
|
-
IF v_own IS NOT NULL THEN
|
|
12570
|
-
v_txt := nullif(btrim(coalesce(v_own->>'pickup_at', '')), '');
|
|
12571
|
-
IF v_txt IS NOT NULL THEN
|
|
12572
|
-
IF v_txt !~ '(Z|[+-]\d{2}(:?\d{2})?)$' THEN
|
|
12573
|
-
RETURN jsonb_build_object('ok', false, 'ownTransport', true,
|
|
12574
|
-
'reason', 'De ophaaltijd bij eigen vervoer mist een tijdzone.');
|
|
12575
|
-
END IF;
|
|
12576
|
-
BEGIN
|
|
12577
|
-
v_at := v_txt::timestamptz;
|
|
12578
|
-
EXCEPTION WHEN OTHERS THEN
|
|
12579
|
-
RETURN jsonb_build_object('ok', false, 'ownTransport', true,
|
|
12580
|
-
'reason', 'De ophaaltijd bij eigen vervoer is geen geldige tijd.');
|
|
12581
|
-
END;
|
|
12582
|
-
END IF;
|
|
12583
|
-
RETURN public.logistics_own_transport_departure(left(o.delivery_date,10)::date, v_at);
|
|
12584
|
-
END IF;
|
|
12585
|
-
|
|
12586
|
-
v := public.logistics_departure_calc(public.logistics_order_carrier_id(p_order_id), left(o.delivery_date,10)::date, o.created_at, NULL);
|
|
12587
|
-
RETURN v - 'moments';
|
|
12588
|
-
END $function$
|
|
12589
|
-
$fsdef$;
|
|
12590
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
12591
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_order_departure overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
12592
|
-
END $fsdo$;
|
|
12593
12079
|
|
|
12594
12080
|
DO $fsdo$ BEGIN
|
|
12595
12081
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_order_departure_list(p_order_ids uuid[])
|
|
@@ -13866,70 +13352,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
13866
13352
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_own_transport_departure overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
13867
13353
|
END $fsdo$;
|
|
13868
13354
|
|
|
13869
|
-
DO $fsdo$ BEGIN
|
|
13870
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_packing_autofix(p_limit integer DEFAULT 100)
|
|
13871
|
-
RETURNS integer
|
|
13872
|
-
LANGUAGE plpgsql
|
|
13873
|
-
SECURITY DEFINER
|
|
13874
|
-
SET search_path TO 'public'
|
|
13875
|
-
AS $function$
|
|
13876
|
-
DECLARE
|
|
13877
|
-
r record;
|
|
13878
|
-
v_reden text;
|
|
13879
|
-
v_aantal integer := 0;
|
|
13880
|
-
BEGIN
|
|
13881
|
-
FOR r IN
|
|
13882
|
-
SELECT d.*
|
|
13883
|
-
FROM public.logistics_packing_deviations d
|
|
13884
|
-
WHERE d.resolved_at IS NULL
|
|
13885
|
-
AND d.scope = 'order_line'
|
|
13886
|
-
AND d.needs_human = false
|
|
13887
|
-
AND d.order_id IS NOT NULL
|
|
13888
|
-
AND d.order_item_id IS NOT NULL
|
|
13889
|
-
ORDER BY d.first_seen_at
|
|
13890
|
-
LIMIT GREATEST(1, LEAST(p_limit, 500))
|
|
13891
|
-
LOOP
|
|
13892
|
-
v_reden := public.logistics_packing_block_reason(r.order_id, r.order_item_id);
|
|
13893
|
-
|
|
13894
|
-
IF v_reden IS NOT NULL THEN
|
|
13895
|
-
UPDATE public.logistics_packing_deviations
|
|
13896
|
-
SET needs_human = true, human_reason = v_reden
|
|
13897
|
-
WHERE id = r.id;
|
|
13898
|
-
CONTINUE;
|
|
13899
|
-
END IF;
|
|
13900
|
-
|
|
13901
|
-
UPDATE public.order_items oi
|
|
13902
|
-
SET plants_per_crate = COALESCE(
|
|
13903
|
-
(r.floriday_packing->>'pieces_per_package')::int, oi.plants_per_crate),
|
|
13904
|
-
crates_per_layer = COALESCE(
|
|
13905
|
-
(r.floriday_packing->>'packages_per_layer')::int, oi.crates_per_layer),
|
|
13906
|
-
layers_per_cart = COALESCE(
|
|
13907
|
-
(r.floriday_packing->>'layers_per_load_carrier')::int, oi.layers_per_cart)
|
|
13908
|
-
WHERE oi.id = r.order_item_id
|
|
13909
|
-
AND oi.packing_locked_at IS NULL;
|
|
13910
|
-
|
|
13911
|
-
IF FOUND THEN
|
|
13912
|
-
v_aantal := v_aantal + 1;
|
|
13913
|
-
UPDATE public.logistics_packing_deviations
|
|
13914
|
-
SET auto_fixed_at = now(),
|
|
13915
|
-
resolved_at = now(),
|
|
13916
|
-
human_reason = 'automatisch bijgewerkt naar de Floriday-stand'
|
|
13917
|
-
WHERE id = r.id;
|
|
13918
|
-
|
|
13919
|
-
PERFORM public.logistics_trace_event(
|
|
13920
|
-
r.order_id, 'stap:belading_synchronisatie', 'ok',
|
|
13921
|
-
'belading bijgewerkt naar de Floriday-stand'
|
|
13922
|
-
);
|
|
13923
|
-
END IF;
|
|
13924
|
-
END LOOP;
|
|
13925
|
-
|
|
13926
|
-
RETURN v_aantal;
|
|
13927
|
-
END;
|
|
13928
|
-
$function$
|
|
13929
|
-
$fsdef$;
|
|
13930
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
13931
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_packing_autofix overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
13932
|
-
END $fsdo$;
|
|
13933
13355
|
|
|
13934
13356
|
DO $fsdo$ BEGIN
|
|
13935
13357
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_packing_block_reason(p_order_id uuid, p_order_item_id uuid)
|
|
@@ -17241,346 +16663,41 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
17241
16663
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_recalc_tick_kick overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
17242
16664
|
END $fsdo$;
|
|
17243
16665
|
|
|
16666
|
+
|
|
16667
|
+
|
|
17244
16668
|
DO $fsdo$ BEGIN
|
|
17245
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.
|
|
17246
|
-
RETURNS
|
|
16669
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_refresh_pick_queue_status(p_ref text)
|
|
16670
|
+
RETURNS integer
|
|
17247
16671
|
LANGUAGE plpgsql
|
|
17248
16672
|
SECURITY DEFINER
|
|
17249
16673
|
SET search_path TO 'public'
|
|
17250
16674
|
AS $function$
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17268
|
-
|
|
17269
|
-
|
|
17270
|
-
|
|
17271
|
-
|
|
17272
|
-
|
|
17273
|
-
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
DROP TABLE IF EXISTS _rt_frozen;
|
|
17278
|
-
CREATE TEMP TABLE _rt_open (order_item_id uuid PRIMARY KEY, product_id uuid, qty numeric, created_at timestamptz, order_id uuid) ON COMMIT DROP;
|
|
17279
|
-
CREATE TEMP TABLE _rt_pexp (product_id uuid, ord bigint, kind text, ref text, qty numeric, note text) ON COMMIT DROP;
|
|
17280
|
-
CREATE TEMP TABLE _rt_gm (group_id uuid, raw_key text, canon_key text, ord bigint) ON COMMIT DROP;
|
|
17281
|
-
CREATE TEMP TABLE _rt_raw (raw_key text PRIMARY KEY, canon_key text) ON COMMIT DROP;
|
|
17282
|
-
CREATE TEMP TABLE _rt_pkeys (product_id uuid, canon_key text) ON COMMIT DROP;
|
|
17283
|
-
CREATE TEMP TABLE _rt_keys (canon_key text PRIMARY KEY) ON COMMIT DROP;
|
|
17284
|
-
CREATE TEMP TABLE _rt_lines (order_item_id uuid PRIMARY KEY) ON COMMIT DROP;
|
|
17285
|
-
CREATE TEMP TABLE _rt_demand (trade_item_key text PRIMARY KEY, qty numeric NOT NULL DEFAULT 0) ON COMMIT DROP;
|
|
17286
|
-
CREATE TEMP TABLE _rt_alloc (order_item_id uuid, trade_item_key text, qty numeric, source text, group_id uuid) ON COMMIT DROP;
|
|
17287
|
-
CREATE TEMP TABLE _rt_frozen (order_item_id uuid PRIMARY KEY) ON COMMIT DROP;
|
|
17288
|
-
|
|
17289
|
-
INSERT INTO _rt_open
|
|
17290
|
-
SELECT oi.id, oi.product_id, COALESCE(oi.quantity, 0)::numeric, o.created_at, oi.order_id
|
|
17291
|
-
FROM logistics_active.order_items oi
|
|
17292
|
-
JOIN public.orders o ON o.id = oi.order_id
|
|
17293
|
-
WHERE o.status = 'Nog te picken' AND NOT public.logistics_reserved_order_excluded(o.id)
|
|
17294
|
-
AND COALESCE(oi.quantity, 0) > 0
|
|
17295
|
-
AND oi.product_id IS NOT NULL
|
|
17296
|
-
AND NOT EXISTS (SELECT 1 FROM public.stock_mutation_log sml WHERE sml.order_item_id = oi.id AND sml.mutation_type = 'consumption');
|
|
17297
|
-
-- Groepsregel naast eigen ledenregels: nooit reserveren.
|
|
17298
|
-
DELETE FROM _rt_open o WHERE o.order_item_id IN (SELECT d.order_item_id FROM public.logistics_double_group_lines(NULL) d);
|
|
17299
|
-
|
|
17300
|
-
INSERT INTO _rt_pexp (product_id, ord, kind, ref, qty, note)
|
|
17301
|
-
SELECT d.pid, e.ord, e.kind, e.ref, e.qty, e.note
|
|
17302
|
-
FROM (SELECT DISTINCT product_id AS pid FROM _rt_open UNION SELECT p_product_id) d,
|
|
17303
|
-
LATERAL public.logistics_expand_line(d.pid, 1) WITH ORDINALITY AS e(kind, ref, qty, note, ord);
|
|
17304
|
-
|
|
17305
|
-
INSERT INTO _rt_gm (group_id, raw_key, ord)
|
|
17306
|
-
SELECT g.gid, m.raw_key, m.ord
|
|
17307
|
-
FROM (SELECT DISTINCT ref::uuid AS gid FROM _rt_pexp WHERE kind = 'group') g,
|
|
17308
|
-
LATERAL (
|
|
17309
|
-
SELECT public.resolve_group_member_stock_key(pgi.trade_item_id) AS raw_key,
|
|
17310
|
-
row_number() OVER (ORDER BY pgi.sort_order ASC NULLS LAST, pgi.created_at ASC, pgi.id ASC) AS ord
|
|
17311
|
-
FROM public.product_group_items pgi
|
|
17312
|
-
WHERE pgi.product_group_id = g.gid) m
|
|
17313
|
-
WHERE m.raw_key IS NOT NULL
|
|
17314
|
-
AND m.raw_key NOT LIKE 'group:%';
|
|
17315
|
-
|
|
17316
|
-
INSERT INTO _rt_raw (raw_key, canon_key)
|
|
17317
|
-
SELECT x.k, public.logistics_reserved_key(x.k)
|
|
17318
|
-
FROM (SELECT ref AS k FROM _rt_pexp WHERE kind = 'item' UNION SELECT raw_key FROM _rt_gm) x;
|
|
17319
|
-
UPDATE _rt_gm g SET canon_key = r.canon_key FROM _rt_raw r WHERE r.raw_key = g.raw_key;
|
|
17320
|
-
|
|
17321
|
-
INSERT INTO _rt_pkeys (product_id, canon_key)
|
|
17322
|
-
SELECT DISTINCT e.product_id, r.canon_key
|
|
17323
|
-
FROM _rt_pexp e JOIN _rt_raw r ON r.raw_key = e.ref
|
|
17324
|
-
WHERE e.kind = 'item' AND r.canon_key IS NOT NULL
|
|
17325
|
-
UNION
|
|
17326
|
-
SELECT DISTINCT e.product_id, g.canon_key
|
|
17327
|
-
FROM _rt_pexp e JOIN _rt_gm g ON g.group_id = e.ref::uuid
|
|
17328
|
-
WHERE e.kind = 'group' AND g.canon_key IS NOT NULL;
|
|
17329
|
-
|
|
17330
|
-
INSERT INTO _rt_keys SELECT DISTINCT canon_key FROM _rt_pkeys WHERE product_id = p_product_id ON CONFLICT DO NOTHING;
|
|
17331
|
-
LOOP
|
|
17332
|
-
SELECT count(*) INTO v_nkeys FROM _rt_keys;
|
|
17333
|
-
EXIT WHEN v_nkeys = v_nkeys_prev;
|
|
17334
|
-
v_nkeys_prev := v_nkeys;
|
|
17335
|
-
INSERT INTO _rt_lines
|
|
17336
|
-
SELECT o.order_item_id FROM _rt_open o
|
|
17337
|
-
WHERE EXISTS (SELECT 1 FROM _rt_pkeys pk JOIN _rt_keys k ON k.canon_key = pk.canon_key
|
|
17338
|
-
WHERE pk.product_id = o.product_id)
|
|
17339
|
-
ON CONFLICT DO NOTHING;
|
|
17340
|
-
INSERT INTO _rt_keys
|
|
17341
|
-
SELECT DISTINCT pk.canon_key FROM _rt_pkeys pk
|
|
17342
|
-
JOIN _rt_open o ON o.product_id = pk.product_id
|
|
17343
|
-
JOIN _rt_lines l ON l.order_item_id = o.order_item_id
|
|
17344
|
-
ON CONFLICT DO NOTHING;
|
|
17345
|
-
SELECT count(*) INTO v_nlines FROM _rt_lines;
|
|
17346
|
-
IF v_nlines > v_max_lines OR (SELECT count(*) FROM _rt_keys) > v_max_keys THEN
|
|
17347
|
-
PERFORM set_config('app.recomputing_reserved', 'off', true);
|
|
17348
|
-
PERFORM public.recompute_all_reserved_stock();
|
|
17349
|
-
v_ms := round(extract(epoch FROM clock_timestamp() - v_t0) * 1000, 1);
|
|
17350
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
17351
|
-
'phase', 'reservering', 'step', 'reservering herberekenen', 'status', 'waarschuwing',
|
|
17352
|
-
'actor', 'logistics_recompute_reserved_targeted', 'errorClass', 'omvang',
|
|
17353
|
-
'reason', 'Gerichte herberekening te groot; volledige herberekening uitgevoerd.',
|
|
17354
|
-
'values', jsonb_build_object('product_id', p_product_id, 'regels', v_nlines,
|
|
17355
|
-
'sleutels', (SELECT count(*) FROM _rt_keys), 'duur_ms', v_ms)));
|
|
17356
|
-
RETURN jsonb_build_object('status', 'volledig', 'regels', v_nlines, 'duur_ms', v_ms);
|
|
17357
|
-
END IF;
|
|
17358
|
-
END LOOP;
|
|
17359
|
-
|
|
17360
|
-
-- Bevroren regels eerst, naar rato van het huidige aantal.
|
|
17361
|
-
IF v_freeze THEN
|
|
17362
|
-
INSERT INTO _rt_frozen
|
|
17363
|
-
SELECT o.order_item_id FROM _rt_open o JOIN _rt_lines l ON l.order_item_id = o.order_item_id
|
|
17364
|
-
WHERE EXISTS (SELECT 1 FROM public.logistics_reservation_allocations a WHERE a.order_item_id = o.order_item_id AND a.source <> 'error')
|
|
17365
|
-
AND public.logistics_allocation_frozen(o.order_id)
|
|
17366
|
-
ON CONFLICT DO NOTHING;
|
|
17367
|
-
INSERT INTO _rt_alloc
|
|
17368
|
-
SELECT f.order_item_id, s.trade_item_key, s.qty, s.source, s.group_id
|
|
17369
|
-
FROM _rt_frozen f
|
|
17370
|
-
JOIN _rt_open o ON o.order_item_id = f.order_item_id
|
|
17371
|
-
CROSS JOIN LATERAL public.logistics_frozen_allocation_scaled(f.order_item_id, o.qty) s;
|
|
17372
|
-
INSERT INTO _rt_demand AS d
|
|
17373
|
-
SELECT trade_item_key, SUM(qty) FROM _rt_alloc GROUP BY trade_item_key
|
|
17374
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
17375
|
-
INSERT INTO _rt_keys SELECT DISTINCT trade_item_key FROM _rt_alloc ON CONFLICT DO NOTHING;
|
|
17376
|
-
END IF;
|
|
17377
|
-
|
|
17378
|
-
FOR oi_rec IN
|
|
17379
|
-
SELECT o.order_item_id AS id, o.product_id, o.qty
|
|
17380
|
-
FROM _rt_open o JOIN _rt_lines l ON l.order_item_id = o.order_item_id
|
|
17381
|
-
WHERE NOT EXISTS (SELECT 1 FROM _rt_frozen f WHERE f.order_item_id = o.order_item_id)
|
|
17382
|
-
ORDER BY o.created_at, o.order_item_id
|
|
17383
|
-
LOOP
|
|
17384
|
-
SELECT string_agg(e.note, '; ') INTO v_err FROM _rt_pexp e WHERE e.product_id = oi_rec.product_id AND e.kind = 'error';
|
|
17385
|
-
IF v_err IS NOT NULL THEN
|
|
17386
|
-
v_struct := v_struct || jsonb_build_object('order_item_id', oi_rec.id, 'product_id', oi_rec.product_id, 'reden', v_err);
|
|
17387
|
-
v_struct_qty := v_struct_qty + oi_rec.qty;
|
|
17388
|
-
CONTINUE;
|
|
17389
|
-
END IF;
|
|
17390
|
-
|
|
17391
|
-
FOR part IN
|
|
17392
|
-
SELECT e.kind, e.ref, e.qty * oi_rec.qty AS qty
|
|
17393
|
-
FROM _rt_pexp e WHERE e.product_id = oi_rec.product_id ORDER BY e.ord
|
|
17394
|
-
LOOP
|
|
17395
|
-
IF part.kind = 'item' THEN
|
|
17396
|
-
SELECT canon_key INTO v_key FROM _rt_raw WHERE raw_key = part.ref;
|
|
17397
|
-
IF v_key IS NULL THEN
|
|
17398
|
-
v_skipped := v_skipped || to_jsonb(part.ref);
|
|
17399
|
-
v_skipped_qty := v_skipped_qty + part.qty;
|
|
17400
|
-
ELSE
|
|
17401
|
-
INSERT INTO _rt_demand AS d VALUES (v_key, part.qty)
|
|
17402
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
17403
|
-
INSERT INTO _rt_alloc VALUES (oi_rec.id, v_key, part.qty, 'item', NULL);
|
|
17404
|
-
END IF;
|
|
17405
|
-
ELSE
|
|
17406
|
-
v_remaining := part.qty;
|
|
17407
|
-
v_last_key := NULL;
|
|
17408
|
-
FOR member_rec IN
|
|
17409
|
-
SELECT g.canon_key FROM _rt_gm g WHERE g.group_id = part.ref::uuid ORDER BY g.ord
|
|
17410
|
-
LOOP
|
|
17411
|
-
v_key := member_rec.canon_key;
|
|
17412
|
-
IF v_key IS NULL THEN CONTINUE; END IF;
|
|
17413
|
-
v_last_key := v_key;
|
|
17414
|
-
IF v_remaining <= 0 THEN CONTINUE; END IF;
|
|
17415
|
-
|
|
17416
|
-
SELECT GREATEST(COALESCE(MAX(s.physical_stock), 0)
|
|
17417
|
-
- COALESCE((SELECT d.qty FROM _rt_demand d WHERE d.trade_item_key = v_key), 0), 0)
|
|
17418
|
-
INTO v_available
|
|
17419
|
-
FROM public.trade_item_stock s
|
|
17420
|
-
WHERE s.trade_item_key = v_key;
|
|
17421
|
-
|
|
17422
|
-
IF COALESCE(v_available, 0) <= 0 THEN CONTINUE; END IF;
|
|
17423
|
-
v_take := LEAST(v_available, v_remaining);
|
|
17424
|
-
INSERT INTO _rt_demand AS d VALUES (v_key, v_take)
|
|
17425
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
17426
|
-
INSERT INTO _rt_alloc VALUES (oi_rec.id, v_key, v_take, 'group', part.ref::uuid);
|
|
17427
|
-
v_remaining := v_remaining - v_take;
|
|
17428
|
-
END LOOP;
|
|
17429
|
-
|
|
17430
|
-
IF v_remaining > 0 THEN
|
|
17431
|
-
IF v_last_key IS NULL THEN
|
|
17432
|
-
v_skipped := v_skipped || to_jsonb('group:' || part.ref);
|
|
17433
|
-
v_skipped_qty := v_skipped_qty + v_remaining;
|
|
17434
|
-
ELSE
|
|
17435
|
-
INSERT INTO _rt_demand AS d VALUES (v_last_key, v_remaining)
|
|
17436
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
17437
|
-
INSERT INTO _rt_alloc VALUES (oi_rec.id, v_last_key, v_remaining, 'group', part.ref::uuid);
|
|
17438
|
-
END IF;
|
|
17439
|
-
END IF;
|
|
17440
|
-
END IF;
|
|
17441
|
-
END LOOP;
|
|
17442
|
-
END LOOP;
|
|
17443
|
-
|
|
17444
|
-
DELETE FROM public.logistics_reservation_allocations a
|
|
17445
|
-
WHERE a.order_item_id IN (SELECT l.order_item_id FROM _rt_lines l);
|
|
17446
|
-
INSERT INTO public.logistics_reservation_allocations (order_item_id, trade_item_key, qty, source, group_id, line_qty)
|
|
17447
|
-
SELECT r.order_item_id, r.trade_item_key, SUM(r.qty), r.source, r.group_id, MAX(o.qty)
|
|
17448
|
-
FROM _rt_alloc r
|
|
17449
|
-
LEFT JOIN _rt_open o ON o.order_item_id = r.order_item_id
|
|
17450
|
-
WHERE r.qty > 0
|
|
17451
|
-
GROUP BY r.order_item_id, r.trade_item_key, r.source, r.group_id;
|
|
17452
|
-
|
|
17453
|
-
PERFORM set_config('stock.change_source', 'RESERVATION_RECOMPUTE', true);
|
|
17454
|
-
UPDATE public.trade_item_stock s
|
|
17455
|
-
SET reserved_stock = CEIL(COALESCE(d.qty, 0))::integer,
|
|
17456
|
-
change_source = 'RESERVATION_RECOMPUTE',
|
|
17457
|
-
updated_at = now()
|
|
17458
|
-
FROM _rt_keys k
|
|
17459
|
-
LEFT JOIN _rt_demand d ON d.trade_item_key = k.canon_key
|
|
17460
|
-
WHERE s.trade_item_key = k.canon_key
|
|
17461
|
-
AND s.reserved_stock IS DISTINCT FROM CEIL(COALESCE(d.qty, 0))::integer;
|
|
17462
|
-
GET DIAGNOSTICS v_changed = ROW_COUNT;
|
|
17463
|
-
|
|
17464
|
-
v_ms := round(extract(epoch FROM clock_timestamp() - v_t0) * 1000, 1);
|
|
17465
|
-
|
|
17466
|
-
IF jsonb_array_length(v_skipped) > 0 THEN
|
|
17467
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
17468
|
-
'phase', 'reservering', 'step', 'reservering herberekenen', 'status', 'waarschuwing',
|
|
17469
|
-
'actor', 'logistics_recompute_reserved_targeted', 'errorClass', 'ontbrekende_gegevens',
|
|
17470
|
-
'reason', 'Geen voorraadrij en geen actieve Floriday-koppeling om die aan te maken; reservering voor deze artikelen niet berekend.',
|
|
17471
|
-
'values', jsonb_build_object('product_id', p_product_id,
|
|
17472
|
-
'sleutels', (SELECT jsonb_agg(DISTINCT x) FROM jsonb_array_elements_text(v_skipped) x),
|
|
17473
|
-
'gemiste_vraag_stuks', v_skipped_qty)));
|
|
17474
|
-
END IF;
|
|
17475
|
-
|
|
17476
|
-
IF jsonb_array_length(v_struct) > 0 THEN
|
|
17477
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
17478
|
-
'phase', 'reservering', 'step', 'reservering herberekenen', 'status', 'waarschuwing',
|
|
17479
|
-
'actor', 'logistics_recompute_reserved_targeted', 'errorClass', 'structuur',
|
|
17480
|
-
'reason', 'Samenstelling met een lus of te diepe nesting; voor deze bestelregels is niets gereserveerd.',
|
|
17481
|
-
'values', jsonb_build_object('regels', v_struct, 'gemiste_vraag_stuks', v_struct_qty)));
|
|
17482
|
-
END IF;
|
|
17483
|
-
|
|
17484
|
-
IF v_ms > v_trace_ms THEN
|
|
17485
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
17486
|
-
'phase', 'reservering', 'step', 'reservering herberekenen', 'status', 'waarschuwing',
|
|
17487
|
-
'actor', 'logistics_recompute_reserved_targeted', 'errorClass', 'traag',
|
|
17488
|
-
'reason', 'Gerichte herberekening duurde langer dan verwacht.',
|
|
17489
|
-
'values', jsonb_build_object('product_id', p_product_id, 'regels', v_nlines,
|
|
17490
|
-
'sleutels', (SELECT count(*) FROM _rt_keys), 'duur_ms', v_ms)));
|
|
17491
|
-
END IF;
|
|
17492
|
-
|
|
17493
|
-
IF v_freeze THEN
|
|
17494
|
-
SELECT array_agg(order_item_id) INTO v_frozen_ids FROM _rt_frozen;
|
|
17495
|
-
SELECT array_agg(order_item_id) INTO v_line_ids FROM _rt_lines;
|
|
17496
|
-
PERFORM public.logistics_report_frozen_shortage(v_frozen_ids);
|
|
17497
|
-
PERFORM public.logistics_allocation_check_changes(v_line_ids);
|
|
17498
|
-
END IF;
|
|
17499
|
-
|
|
17500
|
-
PERFORM set_config('app.recomputing_reserved', 'off', true);
|
|
17501
|
-
RETURN jsonb_build_object('status', 'gericht', 'regels', v_nlines,
|
|
17502
|
-
'sleutels', (SELECT count(*) FROM _rt_keys), 'gewijzigd', v_changed, 'duur_ms', v_ms);
|
|
17503
|
-
END
|
|
17504
|
-
$function$
|
|
17505
|
-
$fsdef$;
|
|
17506
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
17507
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_recompute_reserved_targeted overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
17508
|
-
END $fsdo$;
|
|
17509
|
-
|
|
17510
|
-
DO $fsdo$ BEGIN
|
|
17511
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_reconcile_missing_plan_queue()
|
|
17512
|
-
RETURNS integer
|
|
17513
|
-
LANGUAGE plpgsql
|
|
17514
|
-
SECURITY DEFINER
|
|
17515
|
-
SET search_path TO 'public'
|
|
17516
|
-
AS $function$
|
|
17517
|
-
DECLARE r record; n integer := 0;
|
|
17518
|
-
BEGIN
|
|
17519
|
-
FOR r IN
|
|
17520
|
-
SELECT o.id FROM public.orders o
|
|
17521
|
-
WHERE o.deleted_at IS NULL
|
|
17522
|
-
AND COALESCE(o.is_reservation,false) = false
|
|
17523
|
-
AND o.plan_locked_at IS NULL
|
|
17524
|
-
AND o.order_number IS NOT NULL
|
|
17525
|
-
AND (o.created_at >= now() - interval '14 days' OR o.updated_at >= now() - interval '14 days')
|
|
17526
|
-
AND NOT EXISTS (SELECT 1 FROM public.logistics_tasks t WHERE t.order_ref = o.order_number)
|
|
17527
|
-
AND NOT EXISTS (SELECT 1 FROM public.logistics_plan_queue q
|
|
17528
|
-
WHERE q.order_id = o.id AND q.status IN ('pending','running'))
|
|
17529
|
-
-- Geblokkeerd en sindsdien niets veranderd aan order, regels of product: niet opnieuw proberen.
|
|
17530
|
-
AND NOT EXISTS (
|
|
17531
|
-
SELECT 1 FROM public.logistics_plan_queue q
|
|
17532
|
-
WHERE q.order_id = o.id AND q.status = 'geblokkeerd'
|
|
17533
|
-
AND q.updated_at >= COALESCE(o.updated_at, o.created_at)
|
|
17534
|
-
AND NOT EXISTS (SELECT 1 FROM logistics_active.order_items oi WHERE oi.order_id = o.id AND oi.created_at > q.updated_at)
|
|
17535
|
-
AND NOT EXISTS (SELECT 1 FROM logistics_active.order_items oi JOIN public.products p ON p.id = oi.product_id
|
|
17536
|
-
WHERE oi.order_id = o.id AND p.updated_at > q.updated_at))
|
|
17537
|
-
ORDER BY o.created_at ASC
|
|
17538
|
-
LIMIT 500
|
|
17539
|
-
LOOP
|
|
17540
|
-
PERFORM public.logistics_plan_enqueue(r.id, 'reconcile');
|
|
17541
|
-
n := n + 1;
|
|
17542
|
-
END LOOP;
|
|
17543
|
-
RETURN n;
|
|
17544
|
-
END;
|
|
17545
|
-
$function$
|
|
17546
|
-
$fsdef$;
|
|
17547
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
17548
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_reconcile_missing_plan_queue overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
17549
|
-
END $fsdo$;
|
|
17550
|
-
|
|
17551
|
-
DO $fsdo$ BEGIN
|
|
17552
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_refresh_pick_queue_status(p_ref text)
|
|
17553
|
-
RETURNS integer
|
|
17554
|
-
LANGUAGE plpgsql
|
|
17555
|
-
SECURITY DEFINER
|
|
17556
|
-
SET search_path TO 'public'
|
|
17557
|
-
AS $function$
|
|
17558
|
-
declare v_status jsonb; v_ref text; v_updated integer := 0;
|
|
17559
|
-
begin
|
|
17560
|
-
v_ref := btrim(coalesce(p_ref, ''));
|
|
17561
|
-
if v_ref = '' then return 0; end if;
|
|
17562
|
-
v_status := public.logistics_cart_plan_status(v_ref);
|
|
17563
|
-
v_ref := coalesce(v_status->>'orderRef', v_ref);
|
|
17564
|
-
update public.pick_queue q
|
|
17565
|
-
set payload = coalesce(q.payload, '{}'::jsonb) || jsonb_build_object(
|
|
17566
|
-
'cartPlanReady', coalesce((v_status->>'ready')::boolean, false),
|
|
17567
|
-
'cartPlanReleased', coalesce((v_status->>'released')::boolean, false),
|
|
17568
|
-
'cartPlanReason', v_status->>'reason',
|
|
17569
|
-
'cartPlanState', v_status->>'state',
|
|
17570
|
-
'pickMode', v_status->>'pickMode',
|
|
17571
|
-
'totalCarts', coalesce((v_status->>'totalCarts')::integer, 0),
|
|
17572
|
-
'fullCarts', coalesce((v_status->>'fullCarts')::integer, 0),
|
|
17573
|
-
'partialCarts', coalesce((v_status->>'partialCarts')::integer, 0)),
|
|
17574
|
-
updated_at = now()
|
|
17575
|
-
where q.cancelled_at is null
|
|
17576
|
-
and (q.order_number = v_ref or coalesce(q.payload->>'cartRowFor', '') = v_ref);
|
|
17577
|
-
get diagnostics v_updated = row_count;
|
|
17578
|
-
return v_updated;
|
|
17579
|
-
end; $function$
|
|
17580
|
-
$fsdef$;
|
|
17581
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
17582
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_refresh_pick_queue_status overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
17583
|
-
END $fsdo$;
|
|
16675
|
+
declare v_status jsonb; v_ref text; v_updated integer := 0;
|
|
16676
|
+
begin
|
|
16677
|
+
v_ref := btrim(coalesce(p_ref, ''));
|
|
16678
|
+
if v_ref = '' then return 0; end if;
|
|
16679
|
+
v_status := public.logistics_cart_plan_status(v_ref);
|
|
16680
|
+
v_ref := coalesce(v_status->>'orderRef', v_ref);
|
|
16681
|
+
update public.pick_queue q
|
|
16682
|
+
set payload = coalesce(q.payload, '{}'::jsonb) || jsonb_build_object(
|
|
16683
|
+
'cartPlanReady', coalesce((v_status->>'ready')::boolean, false),
|
|
16684
|
+
'cartPlanReleased', coalesce((v_status->>'released')::boolean, false),
|
|
16685
|
+
'cartPlanReason', v_status->>'reason',
|
|
16686
|
+
'cartPlanState', v_status->>'state',
|
|
16687
|
+
'pickMode', v_status->>'pickMode',
|
|
16688
|
+
'totalCarts', coalesce((v_status->>'totalCarts')::integer, 0),
|
|
16689
|
+
'fullCarts', coalesce((v_status->>'fullCarts')::integer, 0),
|
|
16690
|
+
'partialCarts', coalesce((v_status->>'partialCarts')::integer, 0)),
|
|
16691
|
+
updated_at = now()
|
|
16692
|
+
where q.cancelled_at is null
|
|
16693
|
+
and (q.order_number = v_ref or coalesce(q.payload->>'cartRowFor', '') = v_ref);
|
|
16694
|
+
get diagnostics v_updated = row_count;
|
|
16695
|
+
return v_updated;
|
|
16696
|
+
end; $function$
|
|
16697
|
+
$fsdef$;
|
|
16698
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
16699
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_refresh_pick_queue_status overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
16700
|
+
END $fsdo$;
|
|
17584
16701
|
|
|
17585
16702
|
DO $fsdo$ BEGIN
|
|
17586
16703
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_refresh_pickup_moments(p_weeks integer DEFAULT 4)
|
|
@@ -18947,265 +18064,78 @@ BEGIN
|
|
|
18947
18064
|
|
|
18948
18065
|
BEGIN
|
|
18949
18066
|
v_pid := CASE WHEN v_raw LIKE 'product:%' THEN substring(v_raw from 9)::uuid ELSE v_raw::uuid END;
|
|
18950
|
-
EXCEPTION WHEN others THEN
|
|
18951
|
-
v_pid := NULL;
|
|
18952
|
-
END;
|
|
18953
|
-
|
|
18954
|
-
IF v_pid IS NOT NULL THEN
|
|
18955
|
-
SELECT COALESCE(NULLIF(btrim(COALESCE(p.floriday_trade_item_id, '')), ''),
|
|
18956
|
-
NULLIF(btrim(COALESCE(p.trade_item_key, '')), ''), p.id::text)
|
|
18957
|
-
INTO v_key FROM public.products p WHERE p.id = v_pid LIMIT 1;
|
|
18958
|
-
ELSE
|
|
18959
|
-
SELECT COALESCE(NULLIF(btrim(COALESCE(p.floriday_trade_item_id, '')), ''),
|
|
18960
|
-
NULLIF(btrim(COALESCE(p.trade_item_key, '')), ''), p.id::text)
|
|
18961
|
-
INTO v_key FROM public.products p
|
|
18962
|
-
WHERE p.floriday_trade_item_id = v_raw OR p.trade_item_key = v_raw LIMIT 1;
|
|
18963
|
-
END IF;
|
|
18964
|
-
v_key := COALESCE(v_key, v_raw);
|
|
18965
|
-
|
|
18966
|
-
IF EXISTS (SELECT 1 FROM public.trade_item_stock s WHERE s.trade_item_key = v_key) THEN
|
|
18967
|
-
RETURN v_key;
|
|
18968
|
-
END IF;
|
|
18969
|
-
RETURN NULL;
|
|
18970
|
-
END
|
|
18971
|
-
$function$
|
|
18972
|
-
$fsdef$;
|
|
18973
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
18974
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_reserved_key overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
18975
|
-
END $fsdo$;
|
|
18976
|
-
|
|
18977
|
-
DO $fsdo$ BEGIN
|
|
18978
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_reserved_order_excluded(p_order_id uuid)
|
|
18979
|
-
RETURNS boolean
|
|
18980
|
-
LANGUAGE plpgsql
|
|
18981
|
-
STABLE SECURITY DEFINER
|
|
18982
|
-
SET search_path TO 'public'
|
|
18983
|
-
AS $function$
|
|
18984
|
-
DECLARE r record; a jsonb;
|
|
18985
|
-
BEGIN
|
|
18986
|
-
SELECT o.deleted_at, o.cancelled_at, o.status INTO r FROM public.orders o WHERE o.id = p_order_id;
|
|
18987
|
-
IF NOT FOUND THEN RETURN false; END IF;
|
|
18988
|
-
IF r.deleted_at IS NOT NULL OR r.cancelled_at IS NOT NULL
|
|
18989
|
-
OR lower(coalesce(r.status, '')) IN ('geannuleerd', 'cancelled') THEN
|
|
18990
|
-
RETURN true;
|
|
18991
|
-
END IF;
|
|
18992
|
-
BEGIN
|
|
18993
|
-
a := public.logistics_order_is_archived(p_order_id);
|
|
18994
|
-
RETURN coalesce((a->>'gearchiveerd')::boolean, false);
|
|
18995
|
-
EXCEPTION WHEN OTHERS THEN
|
|
18996
|
-
RETURN false; -- leesfout: order blijft meetellen (fail closed)
|
|
18997
|
-
END;
|
|
18998
|
-
END $function$
|
|
18999
|
-
$fsdef$;
|
|
19000
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
19001
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_reserved_order_excluded overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
19002
|
-
END $fsdo$;
|
|
19003
|
-
|
|
19004
|
-
DO $fsdo$ BEGIN
|
|
19005
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_reserved_stock_nightly()
|
|
19006
|
-
RETURNS void
|
|
19007
|
-
LANGUAGE plpgsql
|
|
19008
|
-
SECURITY DEFINER
|
|
19009
|
-
SET search_path TO 'public'
|
|
19010
|
-
AS $function$
|
|
19011
|
-
BEGIN
|
|
19012
|
-
PERFORM set_config('statement_timeout', '600000', true);
|
|
19013
|
-
PERFORM public.recompute_all_reserved_stock();
|
|
19014
|
-
END
|
|
19015
|
-
$function$
|
|
19016
|
-
$fsdef$;
|
|
19017
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
19018
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_reserved_stock_nightly overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
19019
|
-
END $fsdo$;
|
|
19020
|
-
|
|
19021
|
-
DO $fsdo$ BEGIN
|
|
19022
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_resolve_pick_document(_queue_item_id uuid, _voorbeeld boolean, _session_id text, _is_herprint boolean)
|
|
19023
|
-
RETURNS jsonb
|
|
19024
|
-
LANGUAGE plpgsql
|
|
19025
|
-
STABLE SECURITY DEFINER
|
|
19026
|
-
SET search_path TO 'public'
|
|
19027
|
-
AS $function$
|
|
19028
|
-
DECLARE
|
|
19029
|
-
item public.pick_queue;
|
|
19030
|
-
dt public.pick_document_types;
|
|
19031
|
-
doc_code text;
|
|
19032
|
-
target_layout uuid;
|
|
19033
|
-
target_plek uuid;
|
|
19034
|
-
layout_meta jsonb;
|
|
19035
|
-
v_types public.doc_layout_type[];
|
|
19036
|
-
doc_type public.doc_layout_type := 'vrij';
|
|
19037
|
-
layout_type public.doc_layout_type;
|
|
19038
|
-
pdf_url text;
|
|
19039
|
-
pdf_b64 text;
|
|
19040
|
-
herkomst text;
|
|
19041
|
-
v_variant text;
|
|
19042
|
-
v_is_partial boolean := false;
|
|
19043
|
-
v_cart_id uuid;
|
|
19044
|
-
v_cart jsonb;
|
|
19045
|
-
v_order_id uuid;
|
|
19046
|
-
v_barcode text;
|
|
19047
|
-
v_barcode_on boolean := public.logistics_pick_barcode_enabled();
|
|
19048
|
-
BEGIN
|
|
19049
|
-
SELECT * INTO item FROM public.pick_queue WHERE id = _queue_item_id;
|
|
19050
|
-
IF NOT FOUND THEN
|
|
19051
|
-
RAISE EXCEPTION 'Dit document bestaat niet meer.' USING ERRCODE = 'P0002';
|
|
19052
|
-
END IF;
|
|
19053
|
-
|
|
19054
|
-
SELECT * INTO dt FROM public.pick_document_types WHERE id = item.document_type_id;
|
|
19055
|
-
|
|
19056
|
-
doc_code := lower(btrim(coalesce(
|
|
19057
|
-
nullif(item.payload->>'documentType', ''),
|
|
19058
|
-
nullif(dt.code, ''),
|
|
19059
|
-
''
|
|
19060
|
-
)));
|
|
19061
|
-
|
|
19062
|
-
v_types := public.logistics_document_type_map(doc_code);
|
|
19063
|
-
|
|
19064
|
-
BEGIN
|
|
19065
|
-
v_cart_id := nullif(coalesce(
|
|
19066
|
-
item.payload->>'cartId', item.payload->>'cart_id',
|
|
19067
|
-
item.payload->'data'->>'cartId', item.payload->'data'->>'cart_id'
|
|
19068
|
-
), '')::uuid;
|
|
19069
|
-
EXCEPTION WHEN invalid_text_representation THEN
|
|
19070
|
-
v_cart_id := NULL;
|
|
19071
|
-
END;
|
|
19072
|
-
|
|
19073
|
-
IF v_cart_id IS NOT NULL THEN
|
|
19074
|
-
SELECT COALESCE(c.order_id, (
|
|
19075
|
-
SELECT oi.order_id FROM logistics_active.order_cart_items ci
|
|
19076
|
-
JOIN logistics_active.order_items oi ON oi.id = ci.order_item_id
|
|
19077
|
-
WHERE ci.cart_id = c.id LIMIT 1))
|
|
19078
|
-
INTO v_order_id
|
|
19079
|
-
FROM logistics_active.order_carts c WHERE c.id = v_cart_id;
|
|
19080
|
-
|
|
19081
|
-
IF v_order_id IS NOT NULL THEN
|
|
19082
|
-
SELECT c INTO v_cart
|
|
19083
|
-
FROM jsonb_array_elements(public.logistics_cart_slip_plan(v_order_id)->'carts') AS c
|
|
19084
|
-
WHERE (c->>'cartId')::uuid = v_cart_id;
|
|
19085
|
-
END IF;
|
|
19086
|
-
|
|
19087
|
-
IF v_barcode_on THEN
|
|
19088
|
-
v_barcode := COALESCE(
|
|
19089
|
-
(SELECT b.barcode FROM public.logistics_cart_barcode b WHERE b.cart_id = v_cart_id),
|
|
19090
|
-
public.logistics_cart_barcode_value(v_cart_id)
|
|
19091
|
-
);
|
|
19092
|
-
IF v_cart IS NOT NULL THEN
|
|
19093
|
-
v_cart := v_cart || jsonb_build_object('barcode', v_barcode);
|
|
19094
|
-
END IF;
|
|
19095
|
-
END IF;
|
|
19096
|
-
END IF;
|
|
19097
|
-
|
|
19098
|
-
IF v_cart IS NOT NULL THEN
|
|
19099
|
-
v_is_partial := NOT COALESCE((v_cart->>'isFullCart')::boolean, false);
|
|
19100
|
-
ELSE
|
|
19101
|
-
v_variant := nullif(coalesce(
|
|
19102
|
-
item.payload->>'slipVariant',
|
|
19103
|
-
item.payload->'data'->>'slipVariant'
|
|
19104
|
-
), '');
|
|
19105
|
-
IF v_variant IS NOT NULL THEN
|
|
19106
|
-
v_is_partial := (v_variant = 'partial_order');
|
|
19107
|
-
ELSIF nullif(coalesce(item.payload->>'pickUnit', item.payload->'data'->>'pickUnit'), '') IS NOT NULL THEN
|
|
19108
|
-
v_is_partial := (coalesce(item.payload->>'pickUnit', item.payload->'data'->>'pickUnit') = 'order');
|
|
19109
|
-
ELSE
|
|
19110
|
-
v_is_partial := (item.cart_count IS NOT NULL AND item.cart_count <= 1);
|
|
19111
|
-
END IF;
|
|
19112
|
-
END IF;
|
|
19113
|
-
|
|
19114
|
-
BEGIN
|
|
19115
|
-
target_layout := nullif(coalesce(
|
|
19116
|
-
item.payload->'layout'->>'layout_id',
|
|
19117
|
-
item.payload->>'layout_id'
|
|
19118
|
-
), '')::uuid;
|
|
19119
|
-
EXCEPTION WHEN invalid_text_representation THEN
|
|
19120
|
-
target_layout := NULL;
|
|
19121
|
-
END;
|
|
19122
|
-
|
|
19123
|
-
IF target_layout IS NULL AND doc_code <> '' THEN
|
|
19124
|
-
layout_meta := public.logistics_document_layout_v2(doc_code, v_is_partial);
|
|
19125
|
-
BEGIN
|
|
19126
|
-
target_layout := nullif(layout_meta->>'layout_id', '')::uuid;
|
|
19127
|
-
EXCEPTION WHEN invalid_text_representation THEN
|
|
19128
|
-
target_layout := NULL;
|
|
19129
|
-
END;
|
|
19130
|
-
END IF;
|
|
19131
|
-
|
|
19132
|
-
SELECT l.documenttype INTO layout_type
|
|
19133
|
-
FROM public.document_layouts l
|
|
19134
|
-
WHERE l.id = target_layout AND l.actief IS TRUE;
|
|
19135
|
-
|
|
19136
|
-
IF layout_type IS NULL THEN target_layout := NULL; END IF;
|
|
18067
|
+
EXCEPTION WHEN others THEN
|
|
18068
|
+
v_pid := NULL;
|
|
18069
|
+
END;
|
|
19137
18070
|
|
|
19138
|
-
|
|
18071
|
+
IF v_pid IS NOT NULL THEN
|
|
18072
|
+
SELECT COALESCE(NULLIF(btrim(COALESCE(p.floriday_trade_item_id, '')), ''),
|
|
18073
|
+
NULLIF(btrim(COALESCE(p.trade_item_key, '')), ''), p.id::text)
|
|
18074
|
+
INTO v_key FROM public.products p WHERE p.id = v_pid LIMIT 1;
|
|
18075
|
+
ELSE
|
|
18076
|
+
SELECT COALESCE(NULLIF(btrim(COALESCE(p.floriday_trade_item_id, '')), ''),
|
|
18077
|
+
NULLIF(btrim(COALESCE(p.trade_item_key, '')), ''), p.id::text)
|
|
18078
|
+
INTO v_key FROM public.products p
|
|
18079
|
+
WHERE p.floriday_trade_item_id = v_raw OR p.trade_item_key = v_raw LIMIT 1;
|
|
18080
|
+
END IF;
|
|
18081
|
+
v_key := COALESCE(v_key, v_raw);
|
|
19139
18082
|
|
|
19140
|
-
IF
|
|
19141
|
-
|
|
19142
|
-
FROM public.print_plek_koppelingen k
|
|
19143
|
-
WHERE k.bron IN ('pickstation', 'pick_station')
|
|
19144
|
-
AND k.bron_id = item.station_id::text
|
|
19145
|
-
ORDER BY k.created_at
|
|
19146
|
-
LIMIT 1;
|
|
18083
|
+
IF EXISTS (SELECT 1 FROM public.trade_item_stock s WHERE s.trade_item_key = v_key) THEN
|
|
18084
|
+
RETURN v_key;
|
|
19147
18085
|
END IF;
|
|
18086
|
+
RETURN NULL;
|
|
18087
|
+
END
|
|
18088
|
+
$function$
|
|
18089
|
+
$fsdef$;
|
|
18090
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
18091
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_reserved_key overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
18092
|
+
END $fsdo$;
|
|
19148
18093
|
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
18094
|
+
DO $fsdo$ BEGIN
|
|
18095
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_reserved_order_excluded(p_order_id uuid)
|
|
18096
|
+
RETURNS boolean
|
|
18097
|
+
LANGUAGE plpgsql
|
|
18098
|
+
STABLE SECURITY DEFINER
|
|
18099
|
+
SET search_path TO 'public'
|
|
18100
|
+
AS $function$
|
|
18101
|
+
DECLARE r record; a jsonb;
|
|
18102
|
+
BEGIN
|
|
18103
|
+
SELECT o.deleted_at, o.cancelled_at, o.status INTO r FROM public.orders o WHERE o.id = p_order_id;
|
|
18104
|
+
IF NOT FOUND THEN RETURN false; END IF;
|
|
18105
|
+
IF r.deleted_at IS NOT NULL OR r.cancelled_at IS NOT NULL
|
|
18106
|
+
OR lower(coalesce(r.status, '')) IN ('geannuleerd', 'cancelled') THEN
|
|
18107
|
+
RETURN true;
|
|
18108
|
+
END IF;
|
|
18109
|
+
BEGIN
|
|
18110
|
+
a := public.logistics_order_is_archived(p_order_id);
|
|
18111
|
+
RETURN coalesce((a->>'gearchiveerd')::boolean, false);
|
|
18112
|
+
EXCEPTION WHEN OTHERS THEN
|
|
18113
|
+
RETURN false; -- leesfout: order blijft meetellen (fail closed)
|
|
18114
|
+
END;
|
|
18115
|
+
END $function$
|
|
18116
|
+
$fsdef$;
|
|
18117
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
18118
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_reserved_order_excluded overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
18119
|
+
END $fsdo$;
|
|
19152
18120
|
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19164
|
-
'pdf_url', pdf_url,
|
|
19165
|
-
'pdf_base64', pdf_b64,
|
|
19166
|
-
'herkomst', herkomst,
|
|
19167
|
-
'render_html', nullif(item.payload->>'render_html', ''),
|
|
19168
|
-
'print_plek_id', target_plek,
|
|
19169
|
-
'foutmelding',
|
|
19170
|
-
CASE WHEN target_layout IS NULL AND pdf_url IS NULL AND pdf_b64 IS NULL
|
|
19171
|
-
THEN 'Geen actieve layout gevonden voor documentsoort "' || COALESCE(nullif(doc_code, ''), 'onbekend') || '". Maak een layout aan in de Layout maker of koppel er een in de Logistiek Engine.'
|
|
19172
|
-
ELSE NULL END,
|
|
19173
|
-
'payload', jsonb_build_object(
|
|
19174
|
-
'source', 'pickstation',
|
|
19175
|
-
'voorbeeld', COALESCE(_voorbeeld, false),
|
|
19176
|
-
'queue_item_id', item.id,
|
|
19177
|
-
'station_id', item.station_id,
|
|
19178
|
-
'print_plek_id', target_plek,
|
|
19179
|
-
'session_id', _session_id,
|
|
19180
|
-
'is_herprint', COALESCE(_is_herprint, false),
|
|
19181
|
-
'document_number', item.document_number,
|
|
19182
|
-
'document_type_code', COALESCE(nullif(doc_code, ''), dt.code),
|
|
19183
|
-
'layout_variant', CASE WHEN v_is_partial THEN 'partial_order' ELSE 'full_cart' END,
|
|
19184
|
-
'layout_id', target_layout,
|
|
19185
|
-
'report_key', dt.report_key,
|
|
19186
|
-
'print_template', dt.print_template,
|
|
19187
|
-
'order_number', item.order_number,
|
|
19188
|
-
'customer_name', item.customer_name,
|
|
19189
|
-
'reference', item.reference,
|
|
19190
|
-
'barcode', CASE WHEN v_barcode_on THEN COALESCE(v_barcode, item.barcode) ELSE item.barcode END,
|
|
19191
|
-
'cart_id', v_cart_id,
|
|
19192
|
-
'cart_index', v_cart->>'cartIndex',
|
|
19193
|
-
'cart_total', v_cart->>'cartTotal',
|
|
19194
|
-
'cart_label', v_cart->>'cartLabel',
|
|
19195
|
-
'cart_items', COALESCE(v_cart->'items', '[]'::jsonb),
|
|
19196
|
-
'country_code', item.country_code,
|
|
19197
|
-
'data', COALESCE(item.payload, '{}'::jsonb)
|
|
19198
|
-
|| jsonb_build_object('print_plek_id', target_plek)
|
|
19199
|
-
|| COALESCE(jsonb_build_object('cart', v_cart), '{}'::jsonb)
|
|
19200
|
-
)
|
|
19201
|
-
);
|
|
19202
|
-
END;
|
|
18121
|
+
DO $fsdo$ BEGIN
|
|
18122
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_reserved_stock_nightly()
|
|
18123
|
+
RETURNS void
|
|
18124
|
+
LANGUAGE plpgsql
|
|
18125
|
+
SECURITY DEFINER
|
|
18126
|
+
SET search_path TO 'public'
|
|
18127
|
+
AS $function$
|
|
18128
|
+
BEGIN
|
|
18129
|
+
PERFORM set_config('statement_timeout', '600000', true);
|
|
18130
|
+
PERFORM public.recompute_all_reserved_stock();
|
|
18131
|
+
END
|
|
19203
18132
|
$function$
|
|
19204
18133
|
$fsdef$;
|
|
19205
18134
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
19206
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
18135
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_reserved_stock_nightly overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
19207
18136
|
END $fsdo$;
|
|
19208
18137
|
|
|
18138
|
+
|
|
19209
18139
|
DO $fsdo$ BEGIN
|
|
19210
18140
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_resolve_product_id(p_label text)
|
|
19211
18141
|
RETURNS uuid
|
|
@@ -21350,193 +20280,27 @@ DO $fsdo$ BEGIN
|
|
|
21350
20280
|
IMMUTABLE
|
|
21351
20281
|
SET search_path TO 'public'
|
|
21352
20282
|
AS $function$
|
|
21353
|
-
DECLARE t text; m text[];
|
|
21354
|
-
BEGIN
|
|
21355
|
-
IF p IS NULL OR p = 'null'::jsonb THEN RETURN NULL; END IF;
|
|
21356
|
-
IF jsonb_typeof(p) = 'object' THEN
|
|
21357
|
-
IF (p->>'width') ~ '^\d+(\.\d+)?$' AND (p->>'height') ~ '^\d+(\.\d+)?$' THEN
|
|
21358
|
-
RETURN ARRAY[(p->>'width')::numeric, (p->>'height')::numeric];
|
|
21359
|
-
END IF;
|
|
21360
|
-
t := p::text;
|
|
21361
|
-
ELSE
|
|
21362
|
-
t := p #>> '{}';
|
|
21363
|
-
END IF;
|
|
21364
|
-
m := regexp_match(coalesce(t,''), '(\d+(?:[.,]\d+)?)\s*[xX×*]\s*(\d+(?:[.,]\d+)?)');
|
|
21365
|
-
IF m IS NULL THEN RETURN NULL; END IF;
|
|
21366
|
-
RETURN ARRAY[replace(m[1],',','.')::numeric, replace(m[2],',','.')::numeric];
|
|
21367
|
-
END; $function$
|
|
21368
|
-
$fsdef$;
|
|
21369
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
21370
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_sticker_parse_size overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
21371
|
-
END $fsdo$;
|
|
21372
|
-
|
|
21373
|
-
DO $fsdo$ BEGIN
|
|
21374
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_sticker_sync(p_limit integer DEFAULT 200)
|
|
21375
|
-
RETURNS jsonb
|
|
21376
|
-
LANGUAGE plpgsql
|
|
21377
|
-
SECURITY DEFINER
|
|
21378
|
-
SET search_path TO 'public'
|
|
21379
|
-
AS $function$
|
|
21380
|
-
DECLARE
|
|
21381
|
-
s jsonb; v_rel text; v_station text; v_tray text;
|
|
21382
|
-
st record; o record; d jsonb; fi jsonb; v_n int; v_order uuid; v_onr text;
|
|
21383
|
-
v_copies int; v_size numeric[]; v_type text; v_should text; v_keep uuid[]; v_del text; v_fo text; v_cart uuid;
|
|
21384
|
-
v_crates_tot int; v_pieces_tot int; r record; v_rows int;
|
|
21385
|
-
n_st int := 0; n_tray int := 0;
|
|
21386
|
-
BEGIN
|
|
21387
|
-
SELECT settings INTO s FROM public.logistics_rule_configs
|
|
21388
|
-
ORDER BY is_active DESC, (status = 'actief') DESC, updated_at DESC LIMIT 1;
|
|
21389
|
-
v_rel := public.logistics_rule_text(s, 'pickstations', 'sticker_release', 'with_pick_release');
|
|
21390
|
-
v_station := CASE WHEN v_rel = 'with_packing_slip'
|
|
21391
|
-
THEN public.logistics_rule_text(s, 'pickstations', 'packing_slip_station', '')
|
|
21392
|
-
ELSE public.logistics_rule_text(s, 'pickstations', 'sticker_station', '') END;
|
|
21393
|
-
v_tray := public.logistics_rule_text(s, 'pickstations', 'traysticker_release', 'uit');
|
|
21394
|
-
|
|
21395
|
-
FOR st IN SELECT * FROM public.floriday_customer_stickers_cache ORDER BY updated_at DESC LIMIT greatest(p_limit,1) LOOP
|
|
21396
|
-
n_st := n_st + 1;
|
|
21397
|
-
d := coalesce(st.data, '{}'::jsonb);
|
|
21398
|
-
fi := coalesce(d->'stickerFileInformation', '{}'::jsonb);
|
|
21399
|
-
v_size := CASE WHEN st.sticker_width_mm IS NOT NULL AND st.sticker_height_mm IS NOT NULL
|
|
21400
|
-
THEN ARRAY[st.sticker_width_mm::numeric, st.sticker_height_mm::numeric]
|
|
21401
|
-
ELSE public.logistics_sticker_parse_size(d->'stickerSize') END;
|
|
21402
|
-
v_type := upper(nullif(btrim(coalesce(st.sticker_type, d->>'stickerType', '')), ''));
|
|
21403
|
-
v_should := lower(coalesce(st.should_be_printed::text, fi->>'shouldBePrinted', ''));
|
|
21404
|
-
|
|
21405
|
-
-- Koppeling volgens Suppliers API 2026v1: alleen via salesOrderId.
|
|
21406
|
-
SELECT count(*), (array_agg(id))[1], (array_agg(order_number))[1] INTO v_n, v_order, v_onr
|
|
21407
|
-
FROM public.orders WHERE deleted_at IS NULL
|
|
21408
|
-
AND nullif(btrim(coalesce(st.sales_order_id, d->>'salesOrderId', '')), '') IS NOT NULL
|
|
21409
|
-
AND floriday_sales_order_id = coalesce(st.sales_order_id, d->>'salesOrderId');
|
|
21410
|
-
|
|
21411
|
-
IF coalesce(st.is_deleted,false) OR lower(coalesce(d->>'isDeleted','')) = 'true' THEN
|
|
21412
|
-
UPDATE public.logistics_sticker_prints SET status = 'niet_printen', reden = 'De koper heeft deze sticker verwijderd.'
|
|
21413
|
-
WHERE soort = 'sticker' AND bron_id = st.floriday_id AND status NOT IN ('in_printwachtrij','afgemeld');
|
|
21414
|
-
CONTINUE;
|
|
21415
|
-
END IF;
|
|
21416
|
-
IF lower(coalesce(d->>'isHandled','')) = 'true' THEN
|
|
21417
|
-
UPDATE public.logistics_sticker_prints SET status = 'afgemeld', reden = 'Al afgemeld in Floriday.', handled_at = coalesce(handled_at, now())
|
|
21418
|
-
WHERE soort = 'sticker' AND bron_id = st.floriday_id AND status <> 'afgemeld';
|
|
21419
|
-
CONTINUE;
|
|
21420
|
-
END IF;
|
|
21421
|
-
IF v_n = 1 AND public.logistics_sales_order_external_fulfilled(v_order, coalesce(st.sales_order_id, d->>'salesOrderId')) THEN
|
|
21422
|
-
UPDATE public.logistics_sticker_prints SET status = 'niet_printen', reden = 'Afgehandeld in Floriday; door ons niet geprint en niet afgemeld.'
|
|
21423
|
-
WHERE soort = 'sticker' AND bron_id = st.floriday_id AND status NOT IN ('in_printwachtrij','afgemeld');
|
|
21424
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, 0, v_size, NULL, NULL, 'niet_printen', 'Afgehandeld in Floriday; door ons niet geprint en niet afgemeld.');
|
|
21425
|
-
CONTINUE;
|
|
21426
|
-
END IF;
|
|
21427
|
-
IF v_n <> 1 THEN
|
|
21428
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, NULL, NULL, NULL, 0, v_size, NULL, NULL, 'geblokkeerd',
|
|
21429
|
-
format('Geen eenduidige order bij Floriday-verkooporder %s (%s gevonden).', coalesce(st.sales_order_id, d->>'salesOrderId', 'onbekend'), v_n));
|
|
21430
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21431
|
-
CONTINUE;
|
|
21432
|
-
END IF;
|
|
21433
|
-
IF v_should = 'false' THEN
|
|
21434
|
-
-- Geen printopdracht; zichtbaar als 'niet_printen'. Wordt ook niet afgemeld in Floriday.
|
|
21435
|
-
UPDATE public.logistics_sticker_prints SET status = 'niet_printen',
|
|
21436
|
-
reden = 'Floriday: deze sticker hoeft niet geprint te worden (shouldBePrinted = false).'
|
|
21437
|
-
WHERE soort = 'sticker' AND bron_id = st.floriday_id AND cart_id IS NOT NULL AND status NOT IN ('in_printwachtrij','afgemeld');
|
|
21438
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, 0, v_size, NULL, NULL, 'niet_printen',
|
|
21439
|
-
'Floriday: deze sticker hoeft niet geprint te worden (shouldBePrinted = false).');
|
|
21440
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21441
|
-
CONTINUE;
|
|
21442
|
-
END IF;
|
|
21443
|
-
IF lower(coalesce(fi->>'deliverSeparately','')) = 'true' THEN
|
|
21444
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, 0, v_size, NULL, NULL, 'geblokkeerd',
|
|
21445
|
-
'Sticker moet apart worden geleverd (deliverSeparately); kies handmatig hoe die mee gaat.');
|
|
21446
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21447
|
-
CONTINUE;
|
|
21448
|
-
END IF;
|
|
21449
|
-
IF nullif(btrim(coalesce(d->>'salesOrderCorrectionRequestId','')),'') IS NOT NULL THEN
|
|
21450
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, 0, v_size, NULL, NULL, 'wacht_op_moment',
|
|
21451
|
-
'Wacht tot de correctie op de verkooporder is verwerkt.');
|
|
21452
|
-
CONTINUE;
|
|
21453
|
-
END IF;
|
|
21454
|
-
v_copies := CASE WHEN (fi->>'numberOfCopies') ~ '^\d+$' THEN (fi->>'numberOfCopies')::int ELSE NULL END;
|
|
21455
|
-
IF coalesce(v_copies,0) <= 0 THEN
|
|
21456
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, 0, v_size, NULL, NULL, 'geblokkeerd',
|
|
21457
|
-
'Floriday gaf geen aantal kopieën (numberOfCopies) mee; niet geprint.');
|
|
21458
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21459
|
-
CONTINUE;
|
|
21460
|
-
END IF;
|
|
21461
|
-
IF v_type IS NULL OR v_type NOT IN ('POT','PRODUCT','SLEEVE','PACKAGE','LAYER','LOAD_CARRIER') THEN
|
|
21462
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, v_copies, v_size, NULL, NULL, 'geblokkeerd',
|
|
21463
|
-
format('Onbekende of niet-ondersteunde stickersoort (%s); kies handmatig hoe deze sticker mee gaat.', coalesce(v_type,'leeg')));
|
|
21464
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21465
|
-
CONTINUE;
|
|
21466
|
-
END IF;
|
|
21467
|
-
|
|
21468
|
-
v_keep := ARRAY[]::uuid[]; v_rows := 0; v_crates_tot := 0; v_pieces_tot := 0;
|
|
21469
|
-
FOR r IN SELECT * FROM public.logistics_sticker_distribution(v_order, v_type, v_copies, nullif(btrim(coalesce(st.trade_item_id,'')),'')) LOOP
|
|
21470
|
-
v_rows := v_rows + 1; v_keep := v_keep || r.cart_id;
|
|
21471
|
-
v_crates_tot := v_crates_tot + r.crates; v_pieces_tot := v_pieces_tot + r.pieces;
|
|
21472
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, r.cart_id, r.kopieen, v_size,
|
|
21473
|
-
public.logistics_sticker_cart_plek(r.cart_id, v_station), NULL,
|
|
21474
|
-
CASE WHEN public.logistics_cart_slip_queued(r.cart_id) THEN 'klaar' ELSE 'wacht_op_moment' END,
|
|
21475
|
-
CASE WHEN public.logistics_cart_slip_queued(r.cart_id) THEN NULL ELSE 'Wacht op de pakbon van deze kar.' END);
|
|
21476
|
-
END LOOP;
|
|
21477
|
-
IF v_rows = 0 THEN
|
|
21478
|
-
PERFORM public.logistics_sticker_upsert('sticker', st.floriday_id, v_order, v_onr, NULL, v_copies, v_size, NULL, NULL, 'geblokkeerd',
|
|
21479
|
-
'De verdeling over karren sluit niet: de order staat (nog) niet op een kar, of de karren hebben geen fusten/stuks van dit artikel.');
|
|
21480
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21481
|
-
CONTINUE;
|
|
21482
|
-
END IF;
|
|
21483
|
-
UPDATE public.logistics_sticker_prints SET sticker_type = v_type WHERE soort='sticker' AND bron_id = st.floriday_id;
|
|
21484
|
-
IF (v_type IN ('PACKAGE','LAYER') AND v_crates_tot <> v_copies) OR (v_type IN ('POT','PRODUCT','SLEEVE') AND v_pieces_tot <> v_copies) THEN
|
|
21485
|
-
BEGIN
|
|
21486
|
-
INSERT INTO public.logistics_trace_events(phase, step, status, reason, order_ref)
|
|
21487
|
-
SELECT 'stickers', 'Aantal klantstickers wijkt af', 'waarschuwing',
|
|
21488
|
-
format('Floriday vraagt %s (%s); op de karren: %s fusten / %s stuks. Het aantal van Floriday wordt geprint.',
|
|
21489
|
-
v_copies, v_type, v_crates_tot, v_pieces_tot), v_onr
|
|
21490
|
-
WHERE NOT EXISTS (SELECT 1 FROM public.logistics_trace_events e WHERE e.order_ref = v_onr AND e.step = 'Aantal klantstickers wijkt af'
|
|
21491
|
-
AND e.created_at > now() - interval '1 day');
|
|
21492
|
-
EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
20283
|
+
DECLARE t text; m text[];
|
|
20284
|
+
BEGIN
|
|
20285
|
+
IF p IS NULL OR p = 'null'::jsonb THEN RETURN NULL; END IF;
|
|
20286
|
+
IF jsonb_typeof(p) = 'object' THEN
|
|
20287
|
+
IF (p->>'width') ~ '^\d+(\.\d+)?$' AND (p->>'height') ~ '^\d+(\.\d+)?$' THEN
|
|
20288
|
+
RETURN ARRAY[(p->>'width')::numeric, (p->>'height')::numeric];
|
|
21493
20289
|
END IF;
|
|
21494
|
-
|
|
21495
|
-
|
|
21496
|
-
|
|
21497
|
-
AND (cart_id IS NULL OR NOT (cart_id = ANY (v_keep)))
|
|
21498
|
-
AND status NOT IN ('in_printwachtrij','afgemeld','niet_printen');
|
|
21499
|
-
END LOOP;
|
|
21500
|
-
|
|
21501
|
-
IF v_tray <> 'uit' THEN
|
|
21502
|
-
FOR o IN
|
|
21503
|
-
SELECT o.id, o.order_number, nullif(btrim(o.floriday_sales_order_id),'') AS sales
|
|
21504
|
-
FROM public.orders o
|
|
21505
|
-
WHERE o.deleted_at IS NULL AND nullif(btrim(o.floriday_sales_order_id),'') IS NOT NULL
|
|
21506
|
-
AND o.delivery_date >= current_date - 2
|
|
21507
|
-
AND EXISTS (SELECT 1 FROM logistics_active.order_carts oc WHERE oc.order_id = o.id)
|
|
21508
|
-
ORDER BY o.delivery_date LIMIT greatest(p_limit,1)
|
|
21509
|
-
LOOP
|
|
21510
|
-
SELECT d2.floriday_id INTO v_del FROM public.floriday_delivery_orders_cache d2
|
|
21511
|
-
WHERE d2.data @> jsonb_build_object('fulfillmentRequests', jsonb_build_array(jsonb_build_object('salesOrderId', o.sales)))
|
|
21512
|
-
ORDER BY d2.fetched_at DESC LIMIT 1;
|
|
21513
|
-
IF v_del IS NULL THEN CONTINUE; END IF;
|
|
21514
|
-
IF EXISTS (SELECT 1 FROM public.logistics_sticker_prints WHERE soort = 'traysticker' AND bron_id = v_del) THEN
|
|
21515
|
-
v_fo := public.logistics_afhandeling_fulfillment_order(o.id)->>'fulfillmentOrderId';
|
|
21516
|
-
IF v_fo IS NOT NULL THEN
|
|
21517
|
-
UPDATE public.logistics_sticker_prints SET fulfillment_order_id = v_fo
|
|
21518
|
-
WHERE soort = 'traysticker' AND bron_id = v_del AND fulfillment_order_id IS DISTINCT FROM v_fo
|
|
21519
|
-
AND status NOT IN ('in_printwachtrij','afgemeld');
|
|
21520
|
-
END IF;
|
|
21521
|
-
CONTINUE;
|
|
21522
|
-
END IF;
|
|
21523
|
-
SELECT oc.id INTO v_cart FROM logistics_active.order_carts oc WHERE oc.order_id = o.id ORDER BY oc.cart_number, oc.created_at LIMIT 1;
|
|
21524
|
-
v_fo := public.logistics_afhandeling_fulfillment_order(o.id)->>'fulfillmentOrderId';
|
|
21525
|
-
PERFORM public.logistics_sticker_upsert('traysticker', v_del, o.id, o.order_number, v_cart, 1, NULL,
|
|
21526
|
-
public.logistics_sticker_cart_plek(v_cart, v_station), v_fo, 'wacht_op_moment',
|
|
21527
|
-
'Wacht op geaccepteerde belading in Floriday.');
|
|
21528
|
-
n_tray := n_tray + 1;
|
|
21529
|
-
END LOOP;
|
|
20290
|
+
t := p::text;
|
|
20291
|
+
ELSE
|
|
20292
|
+
t := p #>> '{}';
|
|
21530
20293
|
END IF;
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
20294
|
+
m := regexp_match(coalesce(t,''), '(\d+(?:[.,]\d+)?)\s*[xX×*]\s*(\d+(?:[.,]\d+)?)');
|
|
20295
|
+
IF m IS NULL THEN RETURN NULL; END IF;
|
|
20296
|
+
RETURN ARRAY[replace(m[1],',','.')::numeric, replace(m[2],',','.')::numeric];
|
|
21534
20297
|
END; $function$
|
|
21535
20298
|
$fsdef$;
|
|
21536
20299
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
21537
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
20300
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_sticker_parse_size overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
21538
20301
|
END $fsdo$;
|
|
21539
20302
|
|
|
20303
|
+
|
|
21540
20304
|
DO $fsdo$ BEGIN
|
|
21541
20305
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_sticker_touch()
|
|
21542
20306
|
RETURNS trigger
|
|
@@ -22396,64 +21160,6 @@ EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR inva
|
|
|
22396
21160
|
RAISE NOTICE 'logistiek-engine: functie public.logistics_tasks_prune overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
22397
21161
|
END $fsdo$;
|
|
22398
21162
|
|
|
22399
|
-
DO $fsdo$ BEGIN
|
|
22400
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_tick()
|
|
22401
|
-
RETURNS jsonb
|
|
22402
|
-
LANGUAGE plpgsql
|
|
22403
|
-
SECURITY DEFINER
|
|
22404
|
-
SET search_path TO 'public'
|
|
22405
|
-
AS $function$
|
|
22406
|
-
DECLARE v_result jsonb := '{}'::jsonb; v_start timestamptz := clock_timestamp(); v_t timestamptz; v_err boolean := false;
|
|
22407
|
-
BEGIN
|
|
22408
|
-
v_t := clock_timestamp();
|
|
22409
|
-
BEGIN
|
|
22410
|
-
PERFORM set_config('statement_timeout', '15000', true);
|
|
22411
|
-
PERFORM public.logistics_rebuffer_pending();
|
|
22412
|
-
v_result := v_result || jsonb_build_object('rebuffer', 'ok');
|
|
22413
|
-
EXCEPTION WHEN OTHERS THEN
|
|
22414
|
-
v_err := true;
|
|
22415
|
-
IF SQLERRM ILIKE '%tijdzone%' THEN
|
|
22416
|
-
v_result := v_result || jsonb_build_object('rebuffer', 'overgeslagen: tijdzone ontbreekt in Werktijden');
|
|
22417
|
-
BEGIN
|
|
22418
|
-
UPDATE public.logistics_rebuffer_state SET last_error = 'Herindelen overgeslagen: de tijdzone ontbreekt in Werktijden.', updated_at = now() WHERE id;
|
|
22419
|
-
EXCEPTION WHEN OTHERS THEN NULL; END;
|
|
22420
|
-
ELSE
|
|
22421
|
-
v_result := v_result || jsonb_build_object('rebuffer', left(SQLERRM, 200));
|
|
22422
|
-
END IF;
|
|
22423
|
-
END;
|
|
22424
|
-
v_result := v_result || jsonb_build_object('rebuffer_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
22425
|
-
|
|
22426
|
-
v_t := clock_timestamp();
|
|
22427
|
-
BEGIN
|
|
22428
|
-
PERFORM set_config('statement_timeout', '20000', true);
|
|
22429
|
-
PERFORM public.run_logistics_tasks_dispatch();
|
|
22430
|
-
v_result := v_result || jsonb_build_object('taken', 'ok');
|
|
22431
|
-
EXCEPTION WHEN OTHERS THEN
|
|
22432
|
-
v_err := true; v_result := v_result || jsonb_build_object('taken', left(SQLERRM, 200));
|
|
22433
|
-
END;
|
|
22434
|
-
v_result := v_result || jsonb_build_object('taken_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
22435
|
-
|
|
22436
|
-
v_t := clock_timestamp();
|
|
22437
|
-
BEGIN
|
|
22438
|
-
PERFORM set_config('statement_timeout', '20000', true);
|
|
22439
|
-
v_result := v_result || jsonb_build_object('afgerond', public.logistics_order_finalize_run(25, 120));
|
|
22440
|
-
EXCEPTION WHEN OTHERS THEN
|
|
22441
|
-
v_err := true; v_result := v_result || jsonb_build_object('afgerond', left(SQLERRM, 200));
|
|
22442
|
-
END;
|
|
22443
|
-
v_result := v_result || jsonb_build_object('afgerond_ms', (extract(epoch from clock_timestamp()-v_t)*1000)::int);
|
|
22444
|
-
|
|
22445
|
-
BEGIN
|
|
22446
|
-
INSERT INTO public.logistics_tick_runs(started_at, finished_at, duration_ms, has_error, steps)
|
|
22447
|
-
VALUES (v_start, clock_timestamp(), (extract(epoch from clock_timestamp()-v_start)*1000)::int, v_err, v_result);
|
|
22448
|
-
EXCEPTION WHEN OTHERS THEN NULL;
|
|
22449
|
-
END;
|
|
22450
|
-
PERFORM set_config('statement_timeout', '30000', true);
|
|
22451
|
-
RETURN v_result;
|
|
22452
|
-
END $function$
|
|
22453
|
-
$fsdef$;
|
|
22454
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
22455
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_tick overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
22456
|
-
END $fsdo$;
|
|
22457
21163
|
|
|
22458
21164
|
DO $fsdo$ BEGIN
|
|
22459
21165
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_tick_base_url_check()
|
|
@@ -24279,724 +22985,468 @@ DO $fsdo$ BEGIN
|
|
|
24279
22985
|
LANGUAGE sql
|
|
24280
22986
|
STABLE SECURITY DEFINER
|
|
24281
22987
|
SET search_path TO 'public'
|
|
24282
|
-
AS $function$ SELECT nullif(btrim(t.timezone), '') FROM public.logistics_time_settings t ORDER BY t.updated_at DESC NULLS LAST LIMIT 1 $function$
|
|
24283
|
-
$fsdef$;
|
|
24284
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24285
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_tz overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24286
|
-
END $fsdo$;
|
|
24287
|
-
|
|
24288
|
-
DO $fsdo$ BEGIN
|
|
24289
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_unit_all_carts_scanned(p_order_id uuid)
|
|
24290
|
-
RETURNS boolean
|
|
24291
|
-
LANGUAGE sql
|
|
24292
|
-
STABLE SECURITY DEFINER
|
|
24293
|
-
SET search_path TO 'public'
|
|
24294
|
-
AS $function$
|
|
24295
|
-
SELECT NOT EXISTS (SELECT 1 FROM unnest(public.logistics_unit_order_ids(p_order_id)) m
|
|
24296
|
-
WHERE NOT public.logistics_order_all_carts_scanned(m))
|
|
24297
|
-
AND NOT EXISTS (SELECT 1 FROM public.orders o JOIN logistics_active.order_carts c ON c.buffer_id = o.buffer_id AND c.order_id IS NULL
|
|
24298
|
-
WHERE o.id = p_order_id AND cardinality(public.logistics_unit_order_ids(p_order_id)) > 1
|
|
24299
|
-
AND NOT public.logistics_cart_scanned(c.id))
|
|
24300
|
-
$function$
|
|
24301
|
-
$fsdef$;
|
|
24302
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24303
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_unit_all_carts_scanned overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24304
|
-
END $fsdo$;
|
|
24305
|
-
|
|
24306
|
-
DO $fsdo$ BEGIN
|
|
24307
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_unit_order_ids(p_order_id uuid)
|
|
24308
|
-
RETURNS uuid[]
|
|
24309
|
-
LANGUAGE sql
|
|
24310
|
-
STABLE SECURITY DEFINER
|
|
24311
|
-
SET search_path TO 'public'
|
|
24312
|
-
AS $function$
|
|
24313
|
-
WITH o AS (SELECT id, buffer_id FROM public.orders WHERE id = p_order_id),
|
|
24314
|
-
m AS (SELECT o2.id, o2.order_number FROM o JOIN public.orders o2 ON o2.buffer_id = o.buffer_id
|
|
24315
|
-
WHERE o.buffer_id IS NOT NULL AND o2.deleted_at IS NULL AND o2.cancelled_at IS NULL)
|
|
24316
|
-
SELECT CASE WHEN (SELECT count(*) FROM m) > 1 THEN (SELECT array_agg(id ORDER BY order_number, id) FROM m)
|
|
24317
|
-
ELSE ARRAY[p_order_id] END
|
|
24318
|
-
$function$
|
|
24319
|
-
$fsdef$;
|
|
24320
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24321
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_unit_order_ids overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24322
|
-
END $fsdo$;
|
|
24323
|
-
|
|
24324
|
-
DO $fsdo$ BEGIN
|
|
24325
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_upsert_task(p_user_id uuid, p_run_id uuid, p_order_ref text, p_buffer_ref text, p_strategy_id uuid, p_rule_config_id uuid, p_rule_version integer, p_task_type text, p_owner text, p_sequence integer, p_start timestamp with time zone, p_end timestamp with time zone, p_shadow boolean, p_payload jsonb)
|
|
24326
|
-
RETURNS text
|
|
24327
|
-
LANGUAGE plpgsql
|
|
24328
|
-
SECURITY DEFINER
|
|
24329
|
-
SET search_path TO 'public'
|
|
24330
|
-
AS $function$
|
|
24331
|
-
DECLARE existing public.logistics_tasks%ROWTYPE;
|
|
24332
|
-
BEGIN
|
|
24333
|
-
SELECT * INTO existing FROM public.logistics_tasks
|
|
24334
|
-
WHERE user_id = p_user_id AND order_ref = p_order_ref AND task_type = p_task_type
|
|
24335
|
-
AND status NOT IN ('cancelled','superseded')
|
|
24336
|
-
ORDER BY created_at DESC LIMIT 1;
|
|
24337
|
-
|
|
24338
|
-
IF FOUND THEN
|
|
24339
|
-
IF existing.status IN ('claimed','in_progress','done','skipped') THEN
|
|
24340
|
-
RETURN 'locked';
|
|
24341
|
-
END IF;
|
|
24342
|
-
UPDATE public.logistics_tasks SET
|
|
24343
|
-
plan_run_id = p_run_id, buffer_ref = p_buffer_ref, strategy_id = p_strategy_id,
|
|
24344
|
-
rule_config_id = p_rule_config_id, rule_version = p_rule_version,
|
|
24345
|
-
owner_module = p_owner, sequence = p_sequence,
|
|
24346
|
-
planned_start = p_start, planned_end = p_end, due_at = COALESCE(p_end, p_start),
|
|
24347
|
-
shadow = p_shadow, payload = p_payload, status = 'planned', error = NULL, updated_at = now()
|
|
24348
|
-
WHERE id = existing.id;
|
|
24349
|
-
RETURN 'revised';
|
|
24350
|
-
END IF;
|
|
24351
|
-
|
|
24352
|
-
INSERT INTO public.logistics_tasks (
|
|
24353
|
-
user_id, plan_run_id, order_ref, buffer_ref, strategy_id, rule_config_id, rule_version,
|
|
24354
|
-
task_type, owner_module, sequence, planned_start, planned_end, due_at, shadow, payload
|
|
24355
|
-
) VALUES (
|
|
24356
|
-
p_user_id, p_run_id, p_order_ref, p_buffer_ref, p_strategy_id, p_rule_config_id, p_rule_version,
|
|
24357
|
-
p_task_type, p_owner, p_sequence, p_start, p_end, COALESCE(p_end, p_start), p_shadow, p_payload
|
|
24358
|
-
);
|
|
24359
|
-
RETURN 'created';
|
|
24360
|
-
END; $function$
|
|
24361
|
-
$fsdef$;
|
|
24362
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24363
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_upsert_task overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24364
|
-
END $fsdo$;
|
|
24365
|
-
|
|
24366
|
-
DO $fsdo$ BEGIN
|
|
24367
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_valid_timezone(_tz text)
|
|
24368
|
-
RETURNS boolean
|
|
24369
|
-
LANGUAGE sql
|
|
24370
|
-
STABLE SECURITY DEFINER
|
|
24371
|
-
SET search_path TO 'public'
|
|
24372
|
-
AS $function$
|
|
24373
|
-
SELECT EXISTS (SELECT 1 FROM pg_timezone_names n WHERE n.name = _tz)
|
|
24374
|
-
$function$
|
|
24375
|
-
$fsdef$;
|
|
24376
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24377
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_valid_timezone overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24378
|
-
END $fsdo$;
|
|
24379
|
-
|
|
24380
|
-
DO $fsdo$ BEGIN
|
|
24381
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_verkoop_order_link(p_order_id uuid)
|
|
24382
|
-
RETURNS text
|
|
24383
|
-
LANGUAGE plpgsql
|
|
24384
|
-
STABLE SECURITY DEFINER
|
|
24385
|
-
SET search_path TO 'public'
|
|
24386
|
-
AS $function$
|
|
24387
|
-
DECLARE v_base text; v_path text;
|
|
24388
|
-
BEGIN
|
|
24389
|
-
IF p_order_id IS NULL THEN RETURN NULL; END IF;
|
|
24390
|
-
v_base := public.logistics_shell_base_url();
|
|
24391
|
-
SELECT nullif(btrim(value), '') INTO v_path FROM public.module_runtime_config WHERE key = 'verkoop_order_path' LIMIT 1;
|
|
24392
|
-
IF v_base IS NULL OR v_path IS NULL OR position('{orderId}' in v_path) = 0 OR left(v_path, 1) <> '/' THEN
|
|
24393
|
-
RETURN NULL;
|
|
24394
|
-
END IF;
|
|
24395
|
-
RETURN v_base || replace(v_path, '{orderId}', p_order_id::text);
|
|
24396
|
-
END $function$
|
|
24397
|
-
$fsdef$;
|
|
24398
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24399
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_verkoop_order_link overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24400
|
-
END $fsdo$;
|
|
24401
|
-
|
|
24402
|
-
DO $fsdo$ BEGIN
|
|
24403
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_working_hours_status()
|
|
24404
|
-
RETURNS jsonb
|
|
24405
|
-
LANGUAGE sql
|
|
24406
|
-
STABLE SECURITY DEFINER
|
|
24407
|
-
SET search_path TO 'public'
|
|
24408
|
-
AS $function$
|
|
24409
|
-
SELECT jsonb_build_object(
|
|
24410
|
-
'timezone', public.logistics_opening_timezone(),
|
|
24411
|
-
'windows', COALESCE((SELECT jsonb_agg(jsonb_build_object('id', h.id, 'weekday', h.weekday, 'opens', h.opens, 'closes', h.closes, 'note', h.note) ORDER BY h.weekday, h.opens)
|
|
24412
|
-
FROM public.logistics_opening_hours h WHERE h.is_active), '[]'::jsonb),
|
|
24413
|
-
'exceptions', COALESCE((SELECT jsonb_agg(jsonb_build_object('id', e.id, 'day', e.day, 'closed', e.is_closed, 'opens', e.opens, 'closes', e.closes, 'note', e.note) ORDER BY e.day)
|
|
24414
|
-
FROM public.logistics_opening_exceptions e WHERE e.day >= current_date - 7), '[]'::jsonb),
|
|
24415
|
-
'usable', (public.logistics_opening_timezone() IS NOT NULL AND EXISTS (SELECT 1 FROM public.logistics_opening_hours WHERE is_active))
|
|
24416
|
-
);
|
|
24417
|
-
$function$
|
|
24418
|
-
$fsdef$;
|
|
24419
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24420
|
-
RAISE NOTICE 'logistiek-engine: functie public.logistics_working_hours_status overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24421
|
-
END $fsdo$;
|
|
24422
|
-
|
|
24423
|
-
DO $fsdo$ BEGIN
|
|
24424
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_write_buffer_layer_positions(p_buffer_id uuid)
|
|
24425
|
-
RETURNS integer
|
|
24426
|
-
LANGUAGE plpgsql
|
|
24427
|
-
SECURITY DEFINER
|
|
24428
|
-
SET search_path TO 'public'
|
|
24429
|
-
AS $function$
|
|
24430
|
-
declare c record; v_total int := 0;
|
|
24431
|
-
begin
|
|
24432
|
-
for c in select id from logistics_active.order_carts where buffer_id = p_buffer_id loop
|
|
24433
|
-
v_total := v_total + public.logistics_write_cart_layer_positions(c.id);
|
|
24434
|
-
end loop;
|
|
24435
|
-
return v_total;
|
|
24436
|
-
end;
|
|
24437
|
-
$function$
|
|
22988
|
+
AS $function$ SELECT nullif(btrim(t.timezone), '') FROM public.logistics_time_settings t ORDER BY t.updated_at DESC NULLS LAST LIMIT 1 $function$
|
|
24438
22989
|
$fsdef$;
|
|
24439
22990
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24440
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
22991
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_tz overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24441
22992
|
END $fsdo$;
|
|
24442
22993
|
|
|
24443
22994
|
DO $fsdo$ BEGIN
|
|
24444
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.
|
|
24445
|
-
RETURNS
|
|
24446
|
-
LANGUAGE
|
|
24447
|
-
SECURITY DEFINER
|
|
22995
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_unit_all_carts_scanned(p_order_id uuid)
|
|
22996
|
+
RETURNS boolean
|
|
22997
|
+
LANGUAGE sql
|
|
22998
|
+
STABLE SECURITY DEFINER
|
|
24448
22999
|
SET search_path TO 'public'
|
|
24449
23000
|
AS $function$
|
|
24450
|
-
|
|
24451
|
-
|
|
24452
|
-
|
|
24453
|
-
|
|
24454
|
-
|
|
24455
|
-
v_max_layers int;
|
|
24456
|
-
it record;
|
|
24457
|
-
v_w numeric; v_h numeric;
|
|
24458
|
-
v_layer int := 1;
|
|
24459
|
-
v_x numeric := 0; v_y numeric := 0; v_row_h numeric := 0;
|
|
24460
|
-
v_n int; i int;
|
|
24461
|
-
v_written int := 0;
|
|
24462
|
-
v_seq int := 0;
|
|
24463
|
-
v_full boolean := false;
|
|
24464
|
-
v_fit_a int; v_fit_b int;
|
|
24465
|
-
v_kegs jsonb := '[]'::jsonb;
|
|
24466
|
-
v_slots jsonb := '[]'::jsonb;
|
|
24467
|
-
v_used boolean[] := '{}';
|
|
24468
|
-
v_pos jsonb;
|
|
24469
|
-
v_keg jsonb;
|
|
24470
|
-
v_ov record;
|
|
24471
|
-
v_overrides jsonb := '{}'::jsonb;
|
|
24472
|
-
v_k int; v_s int; v_slot jsonb;
|
|
24473
|
-
v_placed jsonb := '[]'::jsonb;
|
|
24474
|
-
begin
|
|
24475
|
-
select * into v_cart from logistics_active.order_carts where id = p_cart_id;
|
|
24476
|
-
if v_cart.id is null then return 0; end if;
|
|
24477
|
-
|
|
24478
|
-
if coalesce((
|
|
24479
|
-
select settings->'karrenindeling'->'fields'->>'cart_layout_method'
|
|
24480
|
-
from public.logistics_rule_configs
|
|
24481
|
-
where is_active
|
|
24482
|
-
order by updated_at desc limit 1), 'belading') <> 'afmetingen' then
|
|
24483
|
-
delete from public.order_cart_layer_positions where cart_id = p_cart_id;
|
|
24484
|
-
return 0;
|
|
24485
|
-
end if;
|
|
24486
|
-
|
|
24487
|
-
select * into v_lc from public.load_carrier_types
|
|
24488
|
-
where (v_cart.carrier_type_id is not null and id = v_cart.carrier_type_id)
|
|
24489
|
-
or (v_cart.carrier_type_id is null and code = v_cart.carrier_type)
|
|
24490
|
-
limit 1;
|
|
24491
|
-
if v_lc.id is null then
|
|
24492
|
-
select * into v_lc from public.load_carrier_types where is_active and is_default order by sort_order limit 1;
|
|
24493
|
-
end if;
|
|
24494
|
-
|
|
24495
|
-
v_layer_w := nullif(v_lc.layer_width_cm, 0) * 10;
|
|
24496
|
-
v_layer_h := nullif(v_lc.layer_length_cm, 0) * 10;
|
|
24497
|
-
v_max_layers := greatest(1, coalesce(v_cart.max_layers, v_lc.layers_per_carrier, 1));
|
|
24498
|
-
|
|
24499
|
-
if v_layer_w is null or v_layer_h is null then
|
|
24500
|
-
delete from public.order_cart_layer_positions where cart_id = p_cart_id;
|
|
24501
|
-
return 0;
|
|
24502
|
-
end if;
|
|
24503
|
-
|
|
24504
|
-
-- handmatige plaatsingen bewaren vóór het vervangen
|
|
24505
|
-
for v_ov in
|
|
24506
|
-
select keg_id, layer, x, y, width, height, rotation, manual_overridden_at, manual_overridden_by
|
|
24507
|
-
from public.order_cart_layer_positions
|
|
24508
|
-
where cart_id = p_cart_id and manual_override
|
|
24509
|
-
loop
|
|
24510
|
-
v_overrides := v_overrides || jsonb_build_object(v_ov.keg_id, jsonb_build_object(
|
|
24511
|
-
'layer', v_ov.layer, 'x', v_ov.x, 'y', v_ov.y,
|
|
24512
|
-
'w', v_ov.width, 'h', v_ov.height,
|
|
24513
|
-
'at', v_ov.manual_overridden_at, 'by', v_ov.manual_overridden_by));
|
|
24514
|
-
end loop;
|
|
24515
|
-
|
|
24516
|
-
-- 1. fustlijst opbouwen (stabiele volgorde, stabiele keg-namen)
|
|
24517
|
-
for it in
|
|
24518
|
-
select ci.id, ci.order_item_id, ci.product_id,
|
|
24519
|
-
coalesce(ci.product_name, p.product) as product_name,
|
|
24520
|
-
greatest(0, coalesce(ci.crates, 0)) as crates,
|
|
24521
|
-
d.fust_width_mm as fw, d.fust_length_mm as fl, d.fust_name as fust_name
|
|
24522
|
-
from logistics_active.order_cart_items ci
|
|
24523
|
-
left join public.logistics_product_dimensions d on d.product_id = ci.product_id
|
|
24524
|
-
left join public.products p on p.id = ci.product_id
|
|
24525
|
-
where ci.cart_id = p_cart_id
|
|
24526
|
-
order by coalesce(ci.layer_index, 999), ci.id
|
|
24527
|
-
loop
|
|
24528
|
-
v_n := it.crates;
|
|
24529
|
-
if v_n <= 0 then continue; end if;
|
|
24530
|
-
if it.fw is null or it.fl is null or it.fw <= 0 or it.fl <= 0 then continue; end if;
|
|
24531
|
-
|
|
24532
|
-
v_fit_a := floor(v_layer_w / it.fw) * floor(v_layer_h / it.fl);
|
|
24533
|
-
v_fit_b := floor(v_layer_w / it.fl) * floor(v_layer_h / it.fw);
|
|
24534
|
-
if v_fit_a >= v_fit_b then
|
|
24535
|
-
v_w := it.fw; v_h := it.fl;
|
|
24536
|
-
else
|
|
24537
|
-
v_w := it.fl; v_h := it.fw;
|
|
24538
|
-
end if;
|
|
24539
|
-
if v_w > v_layer_w or v_h > v_layer_h then continue; end if;
|
|
24540
|
-
|
|
24541
|
-
for i in 1..v_n loop
|
|
24542
|
-
v_seq := v_seq + 1;
|
|
24543
|
-
v_kegs := v_kegs || jsonb_build_array(jsonb_build_object(
|
|
24544
|
-
'keg', 'F' || v_seq,
|
|
24545
|
-
'product_id', it.product_id,
|
|
24546
|
-
'order_item_id', it.order_item_id,
|
|
24547
|
-
'label', coalesce(it.product_name, 'Fust') || coalesce(' - ' || it.fust_name, ''),
|
|
24548
|
-
'w', v_w, 'h', v_h));
|
|
24549
|
-
end loop;
|
|
24550
|
-
end loop;
|
|
24551
|
-
|
|
24552
|
-
-- 2. beschikbare plekken berekenen in dezelfde volgorde
|
|
24553
|
-
for v_k in 0 .. jsonb_array_length(v_kegs) - 1 loop
|
|
24554
|
-
v_keg := v_kegs -> v_k;
|
|
24555
|
-
v_w := (v_keg->>'w')::numeric; v_h := (v_keg->>'h')::numeric;
|
|
24556
|
-
if v_x + v_w > v_layer_w + 0.001 then
|
|
24557
|
-
v_x := 0; v_y := v_y + v_row_h; v_row_h := 0;
|
|
24558
|
-
end if;
|
|
24559
|
-
if v_y + v_h > v_layer_h + 0.001 then
|
|
24560
|
-
v_layer := v_layer + 1; v_x := 0; v_y := 0; v_row_h := 0;
|
|
24561
|
-
if v_layer > v_max_layers then
|
|
24562
|
-
v_full := true;
|
|
24563
|
-
exit;
|
|
24564
|
-
end if;
|
|
24565
|
-
end if;
|
|
24566
|
-
v_slots := v_slots || jsonb_build_array(jsonb_build_object(
|
|
24567
|
-
'layer', v_layer, 'x', v_x, 'y', v_y, 'w', v_w, 'h', v_h));
|
|
24568
|
-
v_used := v_used || false;
|
|
24569
|
-
v_x := v_x + v_w;
|
|
24570
|
-
v_row_h := greatest(v_row_h, v_h);
|
|
24571
|
-
end loop;
|
|
24572
|
-
|
|
24573
|
-
-- 3. handmatige plekken eerst vastzetten
|
|
24574
|
-
for v_k in 0 .. greatest(jsonb_array_length(v_kegs) - 1, -1) loop
|
|
24575
|
-
exit when jsonb_array_length(v_kegs) = 0;
|
|
24576
|
-
v_keg := v_kegs -> v_k;
|
|
24577
|
-
v_pos := v_overrides -> (v_keg->>'keg');
|
|
24578
|
-
if v_pos is null then continue; end if;
|
|
24579
|
-
if (v_pos->>'w')::numeric is distinct from (v_keg->>'w')::numeric
|
|
24580
|
-
or (v_pos->>'h')::numeric is distinct from (v_keg->>'h')::numeric then
|
|
24581
|
-
insert into public.logistics_layer_override_log(cart_id, keg_id, product_id, reason, details)
|
|
24582
|
-
values (p_cart_id, v_keg->>'keg', nullif(v_keg->>'product_id','')::uuid,
|
|
24583
|
-
'afmeting_gewijzigd', jsonb_build_object('override', v_pos, 'nieuw', v_keg));
|
|
24584
|
-
v_overrides := v_overrides - (v_keg->>'keg');
|
|
24585
|
-
continue;
|
|
24586
|
-
end if;
|
|
24587
|
-
v_s := null;
|
|
24588
|
-
for i in 0 .. jsonb_array_length(v_slots) - 1 loop
|
|
24589
|
-
v_slot := v_slots -> i;
|
|
24590
|
-
if not v_used[i+1]
|
|
24591
|
-
and (v_slot->>'layer')::int = (v_pos->>'layer')::int
|
|
24592
|
-
and (v_slot->>'x')::numeric = (v_pos->>'x')::numeric
|
|
24593
|
-
and (v_slot->>'y')::numeric = (v_pos->>'y')::numeric then
|
|
24594
|
-
v_s := i; exit;
|
|
24595
|
-
end if;
|
|
24596
|
-
end loop;
|
|
24597
|
-
if v_s is null then
|
|
24598
|
-
insert into public.logistics_layer_override_log(cart_id, keg_id, product_id, reason, details)
|
|
24599
|
-
values (p_cart_id, v_keg->>'keg', nullif(v_keg->>'product_id','')::uuid,
|
|
24600
|
-
'plek_vervallen', jsonb_build_object('override', v_pos));
|
|
24601
|
-
v_overrides := v_overrides - (v_keg->>'keg');
|
|
24602
|
-
continue;
|
|
24603
|
-
end if;
|
|
24604
|
-
v_used[v_s+1] := true;
|
|
24605
|
-
v_placed := v_placed || jsonb_build_array(v_keg || jsonb_build_object(
|
|
24606
|
-
'layer', (v_pos->>'layer')::int, 'x', (v_pos->>'x')::numeric, 'y', (v_pos->>'y')::numeric,
|
|
24607
|
-
'manual', true, 'at', v_pos->>'at', 'by', v_pos->>'by'));
|
|
24608
|
-
end loop;
|
|
24609
|
-
|
|
24610
|
-
-- overrides van fusten die niet meer in de kar zitten
|
|
24611
|
-
for v_ov in select key from jsonb_each(v_overrides) as t(key, value) loop
|
|
24612
|
-
if not exists (
|
|
24613
|
-
select 1 from jsonb_array_elements(v_placed) e where e->>'keg' = v_ov.key
|
|
24614
|
-
) then
|
|
24615
|
-
insert into public.logistics_layer_override_log(cart_id, keg_id, reason, details)
|
|
24616
|
-
values (p_cart_id, v_ov.key, 'fust_niet_meer_in_kar', v_overrides -> v_ov.key);
|
|
24617
|
-
end if;
|
|
24618
|
-
end loop;
|
|
24619
|
-
|
|
24620
|
-
-- 4. overige fusten om de vaste plekken heen indelen
|
|
24621
|
-
v_s := 0;
|
|
24622
|
-
for v_k in 0 .. greatest(jsonb_array_length(v_kegs) - 1, -1) loop
|
|
24623
|
-
exit when jsonb_array_length(v_kegs) = 0;
|
|
24624
|
-
v_keg := v_kegs -> v_k;
|
|
24625
|
-
if exists (select 1 from jsonb_array_elements(v_placed) e where e->>'keg' = v_keg->>'keg') then
|
|
24626
|
-
continue;
|
|
24627
|
-
end if;
|
|
24628
|
-
while v_s < jsonb_array_length(v_slots) and v_used[v_s+1] loop
|
|
24629
|
-
v_s := v_s + 1;
|
|
24630
|
-
end loop;
|
|
24631
|
-
exit when v_s >= jsonb_array_length(v_slots);
|
|
24632
|
-
v_slot := v_slots -> v_s;
|
|
24633
|
-
v_used[v_s+1] := true;
|
|
24634
|
-
v_placed := v_placed || jsonb_build_array(v_keg || jsonb_build_object(
|
|
24635
|
-
'layer', (v_slot->>'layer')::int, 'x', (v_slot->>'x')::numeric, 'y', (v_slot->>'y')::numeric,
|
|
24636
|
-
'manual', false));
|
|
24637
|
-
end loop;
|
|
24638
|
-
|
|
24639
|
-
-- 5. atomair vervangen inclusief teruggeschreven handmatige vlaggen
|
|
24640
|
-
delete from public.order_cart_layer_positions where cart_id = p_cart_id;
|
|
24641
|
-
|
|
24642
|
-
for v_k in 0 .. greatest(jsonb_array_length(v_placed) - 1, -1) loop
|
|
24643
|
-
exit when jsonb_array_length(v_placed) = 0;
|
|
24644
|
-
v_keg := v_placed -> v_k;
|
|
24645
|
-
insert into public.order_cart_layer_positions
|
|
24646
|
-
(cart_id, layer, keg_id, x, y, width, height, rotation,
|
|
24647
|
-
layer_width, layer_height, product_id, order_item_id, label,
|
|
24648
|
-
source, algorithm_version, manual_override, manual_overridden_at, manual_overridden_by)
|
|
24649
|
-
values
|
|
24650
|
-
(p_cart_id, (v_keg->>'layer')::int, v_keg->>'keg',
|
|
24651
|
-
(v_keg->>'x')::numeric, (v_keg->>'y')::numeric,
|
|
24652
|
-
(v_keg->>'w')::numeric, (v_keg->>'h')::numeric, 0,
|
|
24653
|
-
v_layer_w, v_layer_h,
|
|
24654
|
-
nullif(v_keg->>'product_id','')::uuid,
|
|
24655
|
-
nullif(v_keg->>'order_item_id','')::uuid,
|
|
24656
|
-
v_keg->>'label',
|
|
24657
|
-
'sql-grid-v5', 5,
|
|
24658
|
-
coalesce((v_keg->>'manual')::boolean, false),
|
|
24659
|
-
nullif(v_keg->>'at','')::timestamptz,
|
|
24660
|
-
nullif(v_keg->>'by','')::uuid);
|
|
24661
|
-
v_written := v_written + 1;
|
|
24662
|
-
end loop;
|
|
24663
|
-
|
|
24664
|
-
-- 6. karregels volgen de werkelijke posities
|
|
24665
|
-
update public.order_cart_items ci
|
|
24666
|
-
set layer_index = s.min_layer,
|
|
24667
|
-
crates_in_layer = s.max_per_layer
|
|
24668
|
-
from (
|
|
24669
|
-
select order_item_id,
|
|
24670
|
-
min(layer) as min_layer,
|
|
24671
|
-
max(cnt) as max_per_layer
|
|
24672
|
-
from (
|
|
24673
|
-
select order_item_id, layer, count(*) as cnt
|
|
24674
|
-
from public.order_cart_layer_positions
|
|
24675
|
-
where cart_id = p_cart_id and order_item_id is not null
|
|
24676
|
-
group by order_item_id, layer
|
|
24677
|
-
) g
|
|
24678
|
-
group by order_item_id
|
|
24679
|
-
) s
|
|
24680
|
-
where ci.cart_id = p_cart_id and ci.order_item_id = s.order_item_id;
|
|
24681
|
-
|
|
24682
|
-
return v_written;
|
|
24683
|
-
end;
|
|
23001
|
+
SELECT NOT EXISTS (SELECT 1 FROM unnest(public.logistics_unit_order_ids(p_order_id)) m
|
|
23002
|
+
WHERE NOT public.logistics_order_all_carts_scanned(m))
|
|
23003
|
+
AND NOT EXISTS (SELECT 1 FROM public.orders o JOIN logistics_active.order_carts c ON c.buffer_id = o.buffer_id AND c.order_id IS NULL
|
|
23004
|
+
WHERE o.id = p_order_id AND cardinality(public.logistics_unit_order_ids(p_order_id)) > 1
|
|
23005
|
+
AND NOT public.logistics_cart_scanned(c.id))
|
|
24684
23006
|
$function$
|
|
24685
23007
|
$fsdef$;
|
|
24686
23008
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24687
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
23009
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_unit_all_carts_scanned overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24688
23010
|
END $fsdo$;
|
|
24689
23011
|
|
|
24690
23012
|
DO $fsdo$ BEGIN
|
|
24691
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.
|
|
24692
|
-
RETURNS
|
|
24693
|
-
LANGUAGE
|
|
23013
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_unit_order_ids(p_order_id uuid)
|
|
23014
|
+
RETURNS uuid[]
|
|
23015
|
+
LANGUAGE sql
|
|
24694
23016
|
STABLE SECURITY DEFINER
|
|
24695
23017
|
SET search_path TO 'public'
|
|
24696
23018
|
AS $function$
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24702
|
-
|
|
24703
|
-
v_orders := public.pick_buffer_order_ids(_order_id);
|
|
24704
|
-
IF v_orders IS NULL OR cardinality(v_orders) = 0 THEN v_orders := ARRAY[_order_id]; END IF;
|
|
24705
|
-
SELECT o.order_number INTO v_ref FROM public.orders o WHERE o.id = _order_id;
|
|
24706
|
-
v_status := public.logistics_cart_plan_status(v_ref);
|
|
24707
|
-
v_ready := COALESCE((v_status->>'ready')::boolean, false);
|
|
24708
|
-
v_released := COALESCE((v_status->>'released')::boolean, false);
|
|
24709
|
-
IF v_ready THEN
|
|
24710
|
-
v_total := COALESCE((v_status->>'cartTotal')::integer, (v_status->>'totalCarts')::integer, 0);
|
|
24711
|
-
SELECT
|
|
24712
|
-
count(*) FILTER (WHERE COALESCE((c->>'isFullCart')::boolean, false)),
|
|
24713
|
-
count(*) FILTER (WHERE NOT COALESCE((c->>'isFullCart')::boolean, false)),
|
|
24714
|
-
count(*) FILTER (WHERE COALESCE((c->>'isShared')::boolean, false))
|
|
24715
|
-
INTO v_full, v_partial, v_shared
|
|
24716
|
-
FROM jsonb_array_elements(COALESCE(v_status->'carts', '[]'::jsonb)) c;
|
|
24717
|
-
IF v_total = 0 THEN v_total := v_full + v_partial; END IF;
|
|
24718
|
-
IF v_total > 0 AND v_full + v_partial <> v_total THEN
|
|
24719
|
-
v_partial := GREATEST(v_total - v_full, 0);
|
|
24720
|
-
END IF;
|
|
24721
|
-
END IF;
|
|
24722
|
-
SELECT COALESCE(sum(ci.crates), 0)::integer INTO v_crates
|
|
24723
|
-
FROM public.order_cart_items ci
|
|
24724
|
-
JOIN logistics_active.order_items oi ON oi.id = ci.order_item_id
|
|
24725
|
-
WHERE oi.order_id = ANY(v_orders);
|
|
24726
|
-
RETURN jsonb_build_object(
|
|
24727
|
-
'totalCarts', COALESCE(v_total, 0),
|
|
24728
|
-
'fullCarts', COALESCE(v_full, 0),
|
|
24729
|
-
'partialCarts', COALESCE(v_partial, 0),
|
|
24730
|
-
'sharedCarts', COALESCE(v_shared, 0),
|
|
24731
|
-
'crates', COALESCE(v_crates, 0),
|
|
24732
|
-
'cartPlanReady', v_ready,
|
|
24733
|
-
'cartPlanReleased', v_released,
|
|
24734
|
-
'cartPlanReason', v_status->>'reason'
|
|
24735
|
-
) || public.logistics_pick_mode();
|
|
24736
|
-
END; $function$
|
|
23019
|
+
WITH o AS (SELECT id, buffer_id FROM public.orders WHERE id = p_order_id),
|
|
23020
|
+
m AS (SELECT o2.id, o2.order_number FROM o JOIN public.orders o2 ON o2.buffer_id = o.buffer_id
|
|
23021
|
+
WHERE o.buffer_id IS NOT NULL AND o2.deleted_at IS NULL AND o2.cancelled_at IS NULL)
|
|
23022
|
+
SELECT CASE WHEN (SELECT count(*) FROM m) > 1 THEN (SELECT array_agg(id ORDER BY order_number, id) FROM m)
|
|
23023
|
+
ELSE ARRAY[p_order_id] END
|
|
23024
|
+
$function$
|
|
24737
23025
|
$fsdef$;
|
|
24738
23026
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24739
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
23027
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_unit_order_ids overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24740
23028
|
END $fsdo$;
|
|
24741
23029
|
|
|
24742
23030
|
DO $fsdo$ BEGIN
|
|
24743
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.
|
|
24744
|
-
RETURNS
|
|
23031
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_upsert_task(p_user_id uuid, p_run_id uuid, p_order_ref text, p_buffer_ref text, p_strategy_id uuid, p_rule_config_id uuid, p_rule_version integer, p_task_type text, p_owner text, p_sequence integer, p_start timestamp with time zone, p_end timestamp with time zone, p_shadow boolean, p_payload jsonb)
|
|
23032
|
+
RETURNS text
|
|
24745
23033
|
LANGUAGE plpgsql
|
|
24746
23034
|
SECURITY DEFINER
|
|
24747
23035
|
SET search_path TO 'public'
|
|
24748
23036
|
AS $function$
|
|
24749
|
-
|
|
24750
|
-
|
|
24751
|
-
|
|
24752
|
-
|
|
24753
|
-
|
|
24754
|
-
|
|
24755
|
-
into v_doc_code, v_row_cart
|
|
24756
|
-
from public.pick_queue q
|
|
24757
|
-
left join public.pick_document_types t on t.id = q.document_type_id
|
|
24758
|
-
where q.id = _queue_item_id;
|
|
24759
|
-
|
|
24760
|
-
if v_doc_code = 'pakbon' then
|
|
24761
|
-
-- Karregel: precies die ene kar. Orderregel: per kar één opdracht.
|
|
24762
|
-
if v_row_cart is not null then
|
|
24763
|
-
return public.pick_enqueue_print_job(_queue_item_id, _printer_id, _session_id,
|
|
24764
|
-
coalesce(_is_herprint,false), v_row_cart);
|
|
24765
|
-
end if;
|
|
24766
|
-
|
|
24767
|
-
begin
|
|
24768
|
-
v_plan := public.pick_queue_cart_plan(_queue_item_id);
|
|
24769
|
-
exception when others then v_plan := null; end;
|
|
24770
|
-
|
|
24771
|
-
if v_plan is null or jsonb_array_length(coalesce(v_plan->'carts','[]'::jsonb)) = 0 then
|
|
24772
|
-
raise exception 'Het karplan voor dit document is nog niet klaar; er wordt geen pakbon zonder barcode geprint.' using errcode='check_violation';
|
|
24773
|
-
end if;
|
|
24774
|
-
|
|
24775
|
-
for v_cart in select c from jsonb_array_elements(v_plan->'carts') as c loop
|
|
24776
|
-
v_last := public.pick_enqueue_print_job(_queue_item_id, _printer_id, _session_id,
|
|
24777
|
-
coalesce(_is_herprint,false), v_cart->>'cartId');
|
|
24778
|
-
end loop;
|
|
24779
|
-
return v_last;
|
|
24780
|
-
end if;
|
|
24781
|
-
|
|
24782
|
-
doc := public.logistics_resolve_pick_document(_queue_item_id, false, _session_id, coalesce(_is_herprint,false));
|
|
24783
|
-
|
|
24784
|
-
if nullif(doc->>'barcode','') is not null then
|
|
24785
|
-
begin v_cart_id := nullif(doc->>'cart_id','')::uuid;
|
|
24786
|
-
exception when invalid_text_representation then v_cart_id := null; end;
|
|
24787
|
-
if v_cart_id is not null then perform public.logistics_ensure_cart_barcode(v_cart_id); end if;
|
|
24788
|
-
end if;
|
|
24789
|
-
|
|
24790
|
-
select p.id into target_printer from public.printers p
|
|
24791
|
-
where p.id = _printer_id and p.actief and nullif(p.extern_printer_id,'') is not null;
|
|
23037
|
+
DECLARE existing public.logistics_tasks%ROWTYPE;
|
|
23038
|
+
BEGIN
|
|
23039
|
+
SELECT * INTO existing FROM public.logistics_tasks
|
|
23040
|
+
WHERE user_id = p_user_id AND order_ref = p_order_ref AND task_type = p_task_type
|
|
23041
|
+
AND status NOT IN ('cancelled','superseded')
|
|
23042
|
+
ORDER BY created_at DESC LIMIT 1;
|
|
24792
23043
|
|
|
24793
|
-
|
|
24794
|
-
|
|
24795
|
-
|
|
24796
|
-
|
|
24797
|
-
|
|
24798
|
-
|
|
24799
|
-
|
|
24800
|
-
|
|
24801
|
-
|
|
23044
|
+
IF FOUND THEN
|
|
23045
|
+
IF existing.status IN ('claimed','in_progress','done','skipped') THEN
|
|
23046
|
+
RETURN 'locked';
|
|
23047
|
+
END IF;
|
|
23048
|
+
UPDATE public.logistics_tasks SET
|
|
23049
|
+
plan_run_id = p_run_id, buffer_ref = p_buffer_ref, strategy_id = p_strategy_id,
|
|
23050
|
+
rule_config_id = p_rule_config_id, rule_version = p_rule_version,
|
|
23051
|
+
owner_module = p_owner, sequence = p_sequence,
|
|
23052
|
+
planned_start = p_start, planned_end = p_end, due_at = COALESCE(p_end, p_start),
|
|
23053
|
+
shadow = p_shadow, payload = p_payload, status = 'planned', error = NULL, updated_at = now()
|
|
23054
|
+
WHERE id = existing.id;
|
|
23055
|
+
RETURN 'revised';
|
|
23056
|
+
END IF;
|
|
24802
23057
|
|
|
24803
|
-
|
|
24804
|
-
|
|
24805
|
-
|
|
23058
|
+
INSERT INTO public.logistics_tasks (
|
|
23059
|
+
user_id, plan_run_id, order_ref, buffer_ref, strategy_id, rule_config_id, rule_version,
|
|
23060
|
+
task_type, owner_module, sequence, planned_start, planned_end, due_at, shadow, payload
|
|
23061
|
+
) VALUES (
|
|
23062
|
+
p_user_id, p_run_id, p_order_ref, p_buffer_ref, p_strategy_id, p_rule_config_id, p_rule_version,
|
|
23063
|
+
p_task_type, p_owner, p_sequence, p_start, p_end, COALESCE(p_end, p_start), p_shadow, p_payload
|
|
23064
|
+
);
|
|
23065
|
+
RETURN 'created';
|
|
23066
|
+
END; $function$
|
|
23067
|
+
$fsdef$;
|
|
23068
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
23069
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_upsert_task overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
23070
|
+
END $fsdo$;
|
|
24806
23071
|
|
|
24807
|
-
|
|
24808
|
-
|
|
23072
|
+
DO $fsdo$ BEGIN
|
|
23073
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_valid_timezone(_tz text)
|
|
23074
|
+
RETURNS boolean
|
|
23075
|
+
LANGUAGE sql
|
|
23076
|
+
STABLE SECURITY DEFINER
|
|
23077
|
+
SET search_path TO 'public'
|
|
23078
|
+
AS $function$
|
|
23079
|
+
SELECT EXISTS (SELECT 1 FROM pg_timezone_names n WHERE n.name = _tz)
|
|
23080
|
+
$function$
|
|
24809
23081
|
$fsdef$;
|
|
24810
23082
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24811
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
23083
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_valid_timezone overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24812
23084
|
END $fsdo$;
|
|
24813
23085
|
|
|
24814
23086
|
DO $fsdo$ BEGIN
|
|
24815
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.
|
|
24816
|
-
RETURNS
|
|
23087
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_verkoop_order_link(p_order_id uuid)
|
|
23088
|
+
RETURNS text
|
|
24817
23089
|
LANGUAGE plpgsql
|
|
24818
|
-
SECURITY DEFINER
|
|
23090
|
+
STABLE SECURITY DEFINER
|
|
24819
23091
|
SET search_path TO 'public'
|
|
24820
23092
|
AS $function$
|
|
24821
|
-
DECLARE
|
|
24822
|
-
item public.pick_queue;
|
|
24823
|
-
dt public.pick_document_types;
|
|
24824
|
-
doc_code text;
|
|
24825
|
-
target_printer uuid;
|
|
24826
|
-
target_layout uuid;
|
|
24827
|
-
target_plek uuid;
|
|
24828
|
-
layout_meta jsonb;
|
|
24829
|
-
v_types public.doc_layout_type[];
|
|
24830
|
-
doc_type public.doc_layout_type := 'vrij';
|
|
24831
|
-
layout_type public.doc_layout_type;
|
|
24832
|
-
pdf_url text;
|
|
24833
|
-
pdf_b64 text;
|
|
24834
|
-
herkomst text;
|
|
24835
|
-
job_id uuid;
|
|
24836
|
-
cart_plan jsonb := NULL;
|
|
24837
|
-
selected_cart jsonb := NULL;
|
|
24838
|
-
v_cart_uuid uuid;
|
|
24839
|
-
v_barcode text;
|
|
24840
|
-
v_barcode_on boolean := public.logistics_pick_barcode_enabled();
|
|
24841
|
-
v_is_partial boolean := false;
|
|
24842
|
-
v_sleutel text;
|
|
23093
|
+
DECLARE v_base text; v_path text;
|
|
24843
23094
|
BEGIN
|
|
24844
|
-
|
|
24845
|
-
|
|
23095
|
+
IF p_order_id IS NULL THEN RETURN NULL; END IF;
|
|
23096
|
+
v_base := public.logistics_shell_base_url();
|
|
23097
|
+
SELECT nullif(btrim(value), '') INTO v_path FROM public.module_runtime_config WHERE key = 'verkoop_order_path' LIMIT 1;
|
|
23098
|
+
IF v_base IS NULL OR v_path IS NULL OR position('{orderId}' in v_path) = 0 OR left(v_path, 1) <> '/' THEN
|
|
23099
|
+
RETURN NULL;
|
|
23100
|
+
END IF;
|
|
23101
|
+
RETURN v_base || replace(v_path, '{orderId}', p_order_id::text);
|
|
23102
|
+
END $function$
|
|
23103
|
+
$fsdef$;
|
|
23104
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
23105
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_verkoop_order_link overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
23106
|
+
END $fsdo$;
|
|
24846
23107
|
|
|
24847
|
-
|
|
23108
|
+
DO $fsdo$ BEGIN
|
|
23109
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_working_hours_status()
|
|
23110
|
+
RETURNS jsonb
|
|
23111
|
+
LANGUAGE sql
|
|
23112
|
+
STABLE SECURITY DEFINER
|
|
23113
|
+
SET search_path TO 'public'
|
|
23114
|
+
AS $function$
|
|
23115
|
+
SELECT jsonb_build_object(
|
|
23116
|
+
'timezone', public.logistics_opening_timezone(),
|
|
23117
|
+
'windows', COALESCE((SELECT jsonb_agg(jsonb_build_object('id', h.id, 'weekday', h.weekday, 'opens', h.opens, 'closes', h.closes, 'note', h.note) ORDER BY h.weekday, h.opens)
|
|
23118
|
+
FROM public.logistics_opening_hours h WHERE h.is_active), '[]'::jsonb),
|
|
23119
|
+
'exceptions', COALESCE((SELECT jsonb_agg(jsonb_build_object('id', e.id, 'day', e.day, 'closed', e.is_closed, 'opens', e.opens, 'closes', e.closes, 'note', e.note) ORDER BY e.day)
|
|
23120
|
+
FROM public.logistics_opening_exceptions e WHERE e.day >= current_date - 7), '[]'::jsonb),
|
|
23121
|
+
'usable', (public.logistics_opening_timezone() IS NOT NULL AND EXISTS (SELECT 1 FROM public.logistics_opening_hours WHERE is_active))
|
|
23122
|
+
);
|
|
23123
|
+
$function$
|
|
23124
|
+
$fsdef$;
|
|
23125
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
23126
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_working_hours_status overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
23127
|
+
END $fsdo$;
|
|
24848
23128
|
|
|
24849
|
-
|
|
24850
|
-
|
|
24851
|
-
|
|
24852
|
-
|
|
24853
|
-
|
|
23129
|
+
DO $fsdo$ BEGIN
|
|
23130
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_write_buffer_layer_positions(p_buffer_id uuid)
|
|
23131
|
+
RETURNS integer
|
|
23132
|
+
LANGUAGE plpgsql
|
|
23133
|
+
SECURITY DEFINER
|
|
23134
|
+
SET search_path TO 'public'
|
|
23135
|
+
AS $function$
|
|
23136
|
+
declare c record; v_total int := 0;
|
|
23137
|
+
begin
|
|
23138
|
+
for c in select id from logistics_active.order_carts where buffer_id = p_buffer_id loop
|
|
23139
|
+
v_total := v_total + public.logistics_write_cart_layer_positions(c.id);
|
|
23140
|
+
end loop;
|
|
23141
|
+
return v_total;
|
|
23142
|
+
end;
|
|
23143
|
+
$function$
|
|
23144
|
+
$fsdef$;
|
|
23145
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
23146
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_write_buffer_layer_positions overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
23147
|
+
END $fsdo$;
|
|
24854
23148
|
|
|
24855
|
-
|
|
23149
|
+
DO $fsdo$ BEGIN
|
|
23150
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_write_cart_layer_positions(p_cart_id uuid)
|
|
23151
|
+
RETURNS integer
|
|
23152
|
+
LANGUAGE plpgsql
|
|
23153
|
+
SECURITY DEFINER
|
|
23154
|
+
SET search_path TO 'public'
|
|
23155
|
+
AS $function$
|
|
23156
|
+
declare
|
|
23157
|
+
v_cart record;
|
|
23158
|
+
v_lc record;
|
|
23159
|
+
v_layer_w numeric;
|
|
23160
|
+
v_layer_h numeric;
|
|
23161
|
+
v_max_layers int;
|
|
23162
|
+
it record;
|
|
23163
|
+
v_w numeric; v_h numeric;
|
|
23164
|
+
v_layer int := 1;
|
|
23165
|
+
v_x numeric := 0; v_y numeric := 0; v_row_h numeric := 0;
|
|
23166
|
+
v_n int; i int;
|
|
23167
|
+
v_written int := 0;
|
|
23168
|
+
v_seq int := 0;
|
|
23169
|
+
v_full boolean := false;
|
|
23170
|
+
v_fit_a int; v_fit_b int;
|
|
23171
|
+
v_kegs jsonb := '[]'::jsonb;
|
|
23172
|
+
v_slots jsonb := '[]'::jsonb;
|
|
23173
|
+
v_used boolean[] := '{}';
|
|
23174
|
+
v_pos jsonb;
|
|
23175
|
+
v_keg jsonb;
|
|
23176
|
+
v_ov record;
|
|
23177
|
+
v_overrides jsonb := '{}'::jsonb;
|
|
23178
|
+
v_k int; v_s int; v_slot jsonb;
|
|
23179
|
+
v_placed jsonb := '[]'::jsonb;
|
|
23180
|
+
begin
|
|
23181
|
+
select * into v_cart from logistics_active.order_carts where id = p_cart_id;
|
|
23182
|
+
if v_cart.id is null then return 0; end if;
|
|
24856
23183
|
|
|
24857
|
-
|
|
24858
|
-
|
|
24859
|
-
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
23184
|
+
if coalesce((
|
|
23185
|
+
select settings->'karrenindeling'->'fields'->>'cart_layout_method'
|
|
23186
|
+
from public.logistics_rule_configs
|
|
23187
|
+
where is_active
|
|
23188
|
+
order by updated_at desc limit 1), 'belading') <> 'afmetingen' then
|
|
23189
|
+
delete from public.order_cart_layer_positions where cart_id = p_cart_id;
|
|
23190
|
+
return 0;
|
|
23191
|
+
end if;
|
|
24863
23192
|
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
23193
|
+
select * into v_lc from public.load_carrier_types
|
|
23194
|
+
where (v_cart.carrier_type_id is not null and id = v_cart.carrier_type_id)
|
|
23195
|
+
or (v_cart.carrier_type_id is null and code = v_cart.carrier_type)
|
|
23196
|
+
limit 1;
|
|
23197
|
+
if v_lc.id is null then
|
|
23198
|
+
select * into v_lc from public.load_carrier_types where is_active and is_default order by sort_order limit 1;
|
|
23199
|
+
end if;
|
|
24867
23200
|
|
|
24868
|
-
|
|
23201
|
+
v_layer_w := nullif(v_lc.layer_width_cm, 0) * 10;
|
|
23202
|
+
v_layer_h := nullif(v_lc.layer_length_cm, 0) * 10;
|
|
23203
|
+
v_max_layers := greatest(1, coalesce(v_cart.max_layers, v_lc.layers_per_carrier, 1));
|
|
24869
23204
|
|
|
24870
|
-
|
|
24871
|
-
|
|
24872
|
-
|
|
24873
|
-
|
|
24874
|
-
v_cart_uuid := NULL;
|
|
24875
|
-
END;
|
|
24876
|
-
IF v_cart_uuid IS NOT NULL THEN
|
|
24877
|
-
v_barcode := public.logistics_ensure_cart_barcode(v_cart_uuid);
|
|
24878
|
-
selected_cart := selected_cart || jsonb_build_object('barcode', v_barcode);
|
|
24879
|
-
END IF;
|
|
24880
|
-
END IF;
|
|
24881
|
-
END IF;
|
|
23205
|
+
if v_layer_w is null or v_layer_h is null then
|
|
23206
|
+
delete from public.order_cart_layer_positions where cart_id = p_cart_id;
|
|
23207
|
+
return 0;
|
|
23208
|
+
end if;
|
|
24882
23209
|
|
|
24883
|
-
|
|
24884
|
-
|
|
24885
|
-
|
|
24886
|
-
|
|
24887
|
-
|
|
24888
|
-
|
|
24889
|
-
|
|
24890
|
-
|
|
23210
|
+
-- handmatige plaatsingen bewaren vóór het vervangen
|
|
23211
|
+
for v_ov in
|
|
23212
|
+
select keg_id, layer, x, y, width, height, rotation, manual_overridden_at, manual_overridden_by
|
|
23213
|
+
from public.order_cart_layer_positions
|
|
23214
|
+
where cart_id = p_cart_id and manual_override
|
|
23215
|
+
loop
|
|
23216
|
+
v_overrides := v_overrides || jsonb_build_object(v_ov.keg_id, jsonb_build_object(
|
|
23217
|
+
'layer', v_ov.layer, 'x', v_ov.x, 'y', v_ov.y,
|
|
23218
|
+
'w', v_ov.width, 'h', v_ov.height,
|
|
23219
|
+
'at', v_ov.manual_overridden_at, 'by', v_ov.manual_overridden_by));
|
|
23220
|
+
end loop;
|
|
24891
23221
|
|
|
24892
|
-
|
|
24893
|
-
|
|
24894
|
-
|
|
24895
|
-
|
|
24896
|
-
|
|
24897
|
-
|
|
24898
|
-
|
|
24899
|
-
|
|
23222
|
+
-- 1. fustlijst opbouwen (stabiele volgorde, stabiele keg-namen)
|
|
23223
|
+
for it in
|
|
23224
|
+
select ci.id, ci.order_item_id, ci.product_id,
|
|
23225
|
+
coalesce(ci.product_name, p.product) as product_name,
|
|
23226
|
+
greatest(0, coalesce(ci.crates, 0)) as crates,
|
|
23227
|
+
d.fust_width_mm as fw, d.fust_length_mm as fl, d.fust_name as fust_name
|
|
23228
|
+
from logistics_active.order_cart_items ci
|
|
23229
|
+
left join public.logistics_product_dimensions d on d.product_id = ci.product_id
|
|
23230
|
+
left join public.products p on p.id = ci.product_id
|
|
23231
|
+
where ci.cart_id = p_cart_id
|
|
23232
|
+
order by coalesce(ci.layer_index, 999), ci.id
|
|
23233
|
+
loop
|
|
23234
|
+
v_n := it.crates;
|
|
23235
|
+
if v_n <= 0 then continue; end if;
|
|
23236
|
+
if it.fw is null or it.fl is null or it.fw <= 0 or it.fl <= 0 then continue; end if;
|
|
24900
23237
|
|
|
24901
|
-
|
|
24902
|
-
|
|
24903
|
-
|
|
24904
|
-
|
|
23238
|
+
v_fit_a := floor(v_layer_w / it.fw) * floor(v_layer_h / it.fl);
|
|
23239
|
+
v_fit_b := floor(v_layer_w / it.fl) * floor(v_layer_h / it.fw);
|
|
23240
|
+
if v_fit_a >= v_fit_b then
|
|
23241
|
+
v_w := it.fw; v_h := it.fl;
|
|
23242
|
+
else
|
|
23243
|
+
v_w := it.fl; v_h := it.fw;
|
|
23244
|
+
end if;
|
|
23245
|
+
if v_w > v_layer_w or v_h > v_layer_h then continue; end if;
|
|
24905
23246
|
|
|
24906
|
-
|
|
24907
|
-
|
|
24908
|
-
|
|
23247
|
+
for i in 1..v_n loop
|
|
23248
|
+
v_seq := v_seq + 1;
|
|
23249
|
+
v_kegs := v_kegs || jsonb_build_array(jsonb_build_object(
|
|
23250
|
+
'keg', 'F' || v_seq,
|
|
23251
|
+
'product_id', it.product_id,
|
|
23252
|
+
'order_item_id', it.order_item_id,
|
|
23253
|
+
'label', coalesce(it.product_name, 'Fust') || coalesce(' - ' || it.fust_name, ''),
|
|
23254
|
+
'w', v_w, 'h', v_h));
|
|
23255
|
+
end loop;
|
|
23256
|
+
end loop;
|
|
24909
23257
|
|
|
24910
|
-
|
|
23258
|
+
-- 2. beschikbare plekken berekenen in dezelfde volgorde
|
|
23259
|
+
for v_k in 0 .. jsonb_array_length(v_kegs) - 1 loop
|
|
23260
|
+
v_keg := v_kegs -> v_k;
|
|
23261
|
+
v_w := (v_keg->>'w')::numeric; v_h := (v_keg->>'h')::numeric;
|
|
23262
|
+
if v_x + v_w > v_layer_w + 0.001 then
|
|
23263
|
+
v_x := 0; v_y := v_y + v_row_h; v_row_h := 0;
|
|
23264
|
+
end if;
|
|
23265
|
+
if v_y + v_h > v_layer_h + 0.001 then
|
|
23266
|
+
v_layer := v_layer + 1; v_x := 0; v_y := 0; v_row_h := 0;
|
|
23267
|
+
if v_layer > v_max_layers then
|
|
23268
|
+
v_full := true;
|
|
23269
|
+
exit;
|
|
23270
|
+
end if;
|
|
23271
|
+
end if;
|
|
23272
|
+
v_slots := v_slots || jsonb_build_array(jsonb_build_object(
|
|
23273
|
+
'layer', v_layer, 'x', v_x, 'y', v_y, 'w', v_w, 'h', v_h));
|
|
23274
|
+
v_used := v_used || false;
|
|
23275
|
+
v_x := v_x + v_w;
|
|
23276
|
+
v_row_h := greatest(v_row_h, v_h);
|
|
23277
|
+
end loop;
|
|
24911
23278
|
|
|
24912
|
-
|
|
24913
|
-
|
|
24914
|
-
|
|
24915
|
-
|
|
24916
|
-
|
|
24917
|
-
|
|
24918
|
-
|
|
24919
|
-
|
|
23279
|
+
-- 3. handmatige plekken eerst vastzetten
|
|
23280
|
+
for v_k in 0 .. greatest(jsonb_array_length(v_kegs) - 1, -1) loop
|
|
23281
|
+
exit when jsonb_array_length(v_kegs) = 0;
|
|
23282
|
+
v_keg := v_kegs -> v_k;
|
|
23283
|
+
v_pos := v_overrides -> (v_keg->>'keg');
|
|
23284
|
+
if v_pos is null then continue; end if;
|
|
23285
|
+
if (v_pos->>'w')::numeric is distinct from (v_keg->>'w')::numeric
|
|
23286
|
+
or (v_pos->>'h')::numeric is distinct from (v_keg->>'h')::numeric then
|
|
23287
|
+
insert into public.logistics_layer_override_log(cart_id, keg_id, product_id, reason, details)
|
|
23288
|
+
values (p_cart_id, v_keg->>'keg', nullif(v_keg->>'product_id','')::uuid,
|
|
23289
|
+
'afmeting_gewijzigd', jsonb_build_object('override', v_pos, 'nieuw', v_keg));
|
|
23290
|
+
v_overrides := v_overrides - (v_keg->>'keg');
|
|
23291
|
+
continue;
|
|
23292
|
+
end if;
|
|
23293
|
+
v_s := null;
|
|
23294
|
+
for i in 0 .. jsonb_array_length(v_slots) - 1 loop
|
|
23295
|
+
v_slot := v_slots -> i;
|
|
23296
|
+
if not v_used[i+1]
|
|
23297
|
+
and (v_slot->>'layer')::int = (v_pos->>'layer')::int
|
|
23298
|
+
and (v_slot->>'x')::numeric = (v_pos->>'x')::numeric
|
|
23299
|
+
and (v_slot->>'y')::numeric = (v_pos->>'y')::numeric then
|
|
23300
|
+
v_s := i; exit;
|
|
23301
|
+
end if;
|
|
23302
|
+
end loop;
|
|
23303
|
+
if v_s is null then
|
|
23304
|
+
insert into public.logistics_layer_override_log(cart_id, keg_id, product_id, reason, details)
|
|
23305
|
+
values (p_cart_id, v_keg->>'keg', nullif(v_keg->>'product_id','')::uuid,
|
|
23306
|
+
'plek_vervallen', jsonb_build_object('override', v_pos));
|
|
23307
|
+
v_overrides := v_overrides - (v_keg->>'keg');
|
|
23308
|
+
continue;
|
|
23309
|
+
end if;
|
|
23310
|
+
v_used[v_s+1] := true;
|
|
23311
|
+
v_placed := v_placed || jsonb_build_array(v_keg || jsonb_build_object(
|
|
23312
|
+
'layer', (v_pos->>'layer')::int, 'x', (v_pos->>'x')::numeric, 'y', (v_pos->>'y')::numeric,
|
|
23313
|
+
'manual', true, 'at', v_pos->>'at', 'by', v_pos->>'by'));
|
|
23314
|
+
end loop;
|
|
24920
23315
|
|
|
24921
|
-
|
|
24922
|
-
|
|
24923
|
-
|
|
24924
|
-
|
|
24925
|
-
|
|
23316
|
+
-- overrides van fusten die niet meer in de kar zitten
|
|
23317
|
+
for v_ov in select key from jsonb_each(v_overrides) as t(key, value) loop
|
|
23318
|
+
if not exists (
|
|
23319
|
+
select 1 from jsonb_array_elements(v_placed) e where e->>'keg' = v_ov.key
|
|
23320
|
+
) then
|
|
23321
|
+
insert into public.logistics_layer_override_log(cart_id, keg_id, reason, details)
|
|
23322
|
+
values (p_cart_id, v_ov.key, 'fust_niet_meer_in_kar', v_overrides -> v_ov.key);
|
|
23323
|
+
end if;
|
|
23324
|
+
end loop;
|
|
24926
23325
|
|
|
24927
|
-
|
|
24928
|
-
|
|
24929
|
-
|
|
23326
|
+
-- 4. overige fusten om de vaste plekken heen indelen
|
|
23327
|
+
v_s := 0;
|
|
23328
|
+
for v_k in 0 .. greatest(jsonb_array_length(v_kegs) - 1, -1) loop
|
|
23329
|
+
exit when jsonb_array_length(v_kegs) = 0;
|
|
23330
|
+
v_keg := v_kegs -> v_k;
|
|
23331
|
+
if exists (select 1 from jsonb_array_elements(v_placed) e where e->>'keg' = v_keg->>'keg') then
|
|
23332
|
+
continue;
|
|
23333
|
+
end if;
|
|
23334
|
+
while v_s < jsonb_array_length(v_slots) and v_used[v_s+1] loop
|
|
23335
|
+
v_s := v_s + 1;
|
|
23336
|
+
end loop;
|
|
23337
|
+
exit when v_s >= jsonb_array_length(v_slots);
|
|
23338
|
+
v_slot := v_slots -> v_s;
|
|
23339
|
+
v_used[v_s+1] := true;
|
|
23340
|
+
v_placed := v_placed || jsonb_build_array(v_keg || jsonb_build_object(
|
|
23341
|
+
'layer', (v_slot->>'layer')::int, 'x', (v_slot->>'x')::numeric, 'y', (v_slot->>'y')::numeric,
|
|
23342
|
+
'manual', false));
|
|
23343
|
+
end loop;
|
|
24930
23344
|
|
|
24931
|
-
--
|
|
24932
|
-
|
|
24933
|
-
v_sleutel := 'pakbon:' || item.id::text || ':' || _cart_id || ':'
|
|
24934
|
-
|| coalesce(target_layout::text, '-') || ':' || coalesce(target_printer::text, '-');
|
|
24935
|
-
END IF;
|
|
23345
|
+
-- 5. atomair vervangen inclusief teruggeschreven handmatige vlaggen
|
|
23346
|
+
delete from public.order_cart_layer_positions where cart_id = p_cart_id;
|
|
24936
23347
|
|
|
24937
|
-
|
|
24938
|
-
|
|
24939
|
-
|
|
24940
|
-
|
|
24941
|
-
|
|
24942
|
-
|
|
24943
|
-
|
|
24944
|
-
|
|
24945
|
-
|
|
24946
|
-
|
|
24947
|
-
|
|
24948
|
-
|
|
24949
|
-
|
|
24950
|
-
|
|
24951
|
-
|
|
24952
|
-
|
|
24953
|
-
|
|
24954
|
-
|
|
24955
|
-
|
|
24956
|
-
|
|
24957
|
-
|
|
24958
|
-
'is_herprint', COALESCE(_is_herprint, false),
|
|
24959
|
-
'document_number', item.document_number,
|
|
24960
|
-
'document_type_code', COALESCE(nullif(doc_code, ''), dt.code),
|
|
24961
|
-
'report_key', dt.report_key,
|
|
24962
|
-
'print_template', dt.print_template,
|
|
24963
|
-
'order_number', COALESCE(selected_cart->>'orderNumber', item.order_number),
|
|
24964
|
-
'customer_name', item.customer_name,
|
|
24965
|
-
'reference', item.reference,
|
|
24966
|
-
'layout_id', target_layout,
|
|
24967
|
-
'layout_variant', CASE WHEN v_is_partial THEN 'partial_order' ELSE 'full_cart' END,
|
|
24968
|
-
'barcode', CASE WHEN v_barcode_on THEN COALESCE(v_barcode, item.barcode) ELSE item.barcode END,
|
|
24969
|
-
'country_code', item.country_code,
|
|
24970
|
-
'cart_id', _cart_id,
|
|
24971
|
-
'cart', selected_cart,
|
|
24972
|
-
'data', COALESCE(item.payload, '{}'::jsonb) || jsonb_build_object(
|
|
24973
|
-
'print_plek_id', target_plek,
|
|
24974
|
-
'cart_id', _cart_id,
|
|
24975
|
-
'cart', selected_cart,
|
|
24976
|
-
'orderId', COALESCE(selected_cart->>'orderId', item.payload->>'orderId'),
|
|
24977
|
-
'orderNumber', COALESCE(selected_cart->>'orderNumber', item.order_number)
|
|
24978
|
-
)
|
|
24979
|
-
),
|
|
24980
|
-
'Pickstation',
|
|
24981
|
-
pdf_url,
|
|
24982
|
-
pdf_b64,
|
|
24983
|
-
herkomst,
|
|
24984
|
-
COALESCE(_is_herprint, false),
|
|
24985
|
-
v_sleutel
|
|
24986
|
-
)
|
|
24987
|
-
RETURNING id INTO job_id;
|
|
23348
|
+
for v_k in 0 .. greatest(jsonb_array_length(v_placed) - 1, -1) loop
|
|
23349
|
+
exit when jsonb_array_length(v_placed) = 0;
|
|
23350
|
+
v_keg := v_placed -> v_k;
|
|
23351
|
+
insert into public.order_cart_layer_positions
|
|
23352
|
+
(cart_id, layer, keg_id, x, y, width, height, rotation,
|
|
23353
|
+
layer_width, layer_height, product_id, order_item_id, label,
|
|
23354
|
+
source, algorithm_version, manual_override, manual_overridden_at, manual_overridden_by)
|
|
23355
|
+
values
|
|
23356
|
+
(p_cart_id, (v_keg->>'layer')::int, v_keg->>'keg',
|
|
23357
|
+
(v_keg->>'x')::numeric, (v_keg->>'y')::numeric,
|
|
23358
|
+
(v_keg->>'w')::numeric, (v_keg->>'h')::numeric, 0,
|
|
23359
|
+
v_layer_w, v_layer_h,
|
|
23360
|
+
nullif(v_keg->>'product_id','')::uuid,
|
|
23361
|
+
nullif(v_keg->>'order_item_id','')::uuid,
|
|
23362
|
+
v_keg->>'label',
|
|
23363
|
+
'sql-grid-v5', 5,
|
|
23364
|
+
coalesce((v_keg->>'manual')::boolean, false),
|
|
23365
|
+
nullif(v_keg->>'at','')::timestamptz,
|
|
23366
|
+
nullif(v_keg->>'by','')::uuid);
|
|
23367
|
+
v_written := v_written + 1;
|
|
23368
|
+
end loop;
|
|
24988
23369
|
|
|
24989
|
-
|
|
24990
|
-
|
|
23370
|
+
-- 6. karregels volgen de werkelijke posities
|
|
23371
|
+
update public.order_cart_items ci
|
|
23372
|
+
set layer_index = s.min_layer,
|
|
23373
|
+
crates_in_layer = s.max_per_layer
|
|
23374
|
+
from (
|
|
23375
|
+
select order_item_id,
|
|
23376
|
+
min(layer) as min_layer,
|
|
23377
|
+
max(cnt) as max_per_layer
|
|
23378
|
+
from (
|
|
23379
|
+
select order_item_id, layer, count(*) as cnt
|
|
23380
|
+
from public.order_cart_layer_positions
|
|
23381
|
+
where cart_id = p_cart_id and order_item_id is not null
|
|
23382
|
+
group by order_item_id, layer
|
|
23383
|
+
) g
|
|
23384
|
+
group by order_item_id
|
|
23385
|
+
) s
|
|
23386
|
+
where ci.cart_id = p_cart_id and ci.order_item_id = s.order_item_id;
|
|
24991
23387
|
|
|
24992
|
-
|
|
24993
|
-
|
|
23388
|
+
return v_written;
|
|
23389
|
+
end;
|
|
24994
23390
|
$function$
|
|
24995
23391
|
$fsdef$;
|
|
24996
23392
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
24997
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
23393
|
+
RAISE NOTICE 'logistiek-engine: functie public.logistics_write_cart_layer_positions overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
23394
|
+
END $fsdo$;
|
|
23395
|
+
|
|
23396
|
+
DO $fsdo$ BEGIN
|
|
23397
|
+
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.pick_cart_breakdown(_order_id uuid)
|
|
23398
|
+
RETURNS jsonb
|
|
23399
|
+
LANGUAGE plpgsql
|
|
23400
|
+
STABLE SECURITY DEFINER
|
|
23401
|
+
SET search_path TO 'public'
|
|
23402
|
+
AS $function$
|
|
23403
|
+
DECLARE
|
|
23404
|
+
v_orders uuid[]; v_ref text; v_status jsonb;
|
|
23405
|
+
v_ready boolean := false; v_released boolean := false;
|
|
23406
|
+
v_total integer := 0; v_full integer := 0; v_partial integer := 0;
|
|
23407
|
+
v_shared integer := 0; v_crates integer := 0;
|
|
23408
|
+
BEGIN
|
|
23409
|
+
v_orders := public.pick_buffer_order_ids(_order_id);
|
|
23410
|
+
IF v_orders IS NULL OR cardinality(v_orders) = 0 THEN v_orders := ARRAY[_order_id]; END IF;
|
|
23411
|
+
SELECT o.order_number INTO v_ref FROM public.orders o WHERE o.id = _order_id;
|
|
23412
|
+
v_status := public.logistics_cart_plan_status(v_ref);
|
|
23413
|
+
v_ready := COALESCE((v_status->>'ready')::boolean, false);
|
|
23414
|
+
v_released := COALESCE((v_status->>'released')::boolean, false);
|
|
23415
|
+
IF v_ready THEN
|
|
23416
|
+
v_total := COALESCE((v_status->>'cartTotal')::integer, (v_status->>'totalCarts')::integer, 0);
|
|
23417
|
+
SELECT
|
|
23418
|
+
count(*) FILTER (WHERE COALESCE((c->>'isFullCart')::boolean, false)),
|
|
23419
|
+
count(*) FILTER (WHERE NOT COALESCE((c->>'isFullCart')::boolean, false)),
|
|
23420
|
+
count(*) FILTER (WHERE COALESCE((c->>'isShared')::boolean, false))
|
|
23421
|
+
INTO v_full, v_partial, v_shared
|
|
23422
|
+
FROM jsonb_array_elements(COALESCE(v_status->'carts', '[]'::jsonb)) c;
|
|
23423
|
+
IF v_total = 0 THEN v_total := v_full + v_partial; END IF;
|
|
23424
|
+
IF v_total > 0 AND v_full + v_partial <> v_total THEN
|
|
23425
|
+
v_partial := GREATEST(v_total - v_full, 0);
|
|
23426
|
+
END IF;
|
|
23427
|
+
END IF;
|
|
23428
|
+
SELECT COALESCE(sum(ci.crates), 0)::integer INTO v_crates
|
|
23429
|
+
FROM public.order_cart_items ci
|
|
23430
|
+
JOIN logistics_active.order_items oi ON oi.id = ci.order_item_id
|
|
23431
|
+
WHERE oi.order_id = ANY(v_orders);
|
|
23432
|
+
RETURN jsonb_build_object(
|
|
23433
|
+
'totalCarts', COALESCE(v_total, 0),
|
|
23434
|
+
'fullCarts', COALESCE(v_full, 0),
|
|
23435
|
+
'partialCarts', COALESCE(v_partial, 0),
|
|
23436
|
+
'sharedCarts', COALESCE(v_shared, 0),
|
|
23437
|
+
'crates', COALESCE(v_crates, 0),
|
|
23438
|
+
'cartPlanReady', v_ready,
|
|
23439
|
+
'cartPlanReleased', v_released,
|
|
23440
|
+
'cartPlanReason', v_status->>'reason'
|
|
23441
|
+
) || public.logistics_pick_mode();
|
|
23442
|
+
END; $function$
|
|
23443
|
+
$fsdef$;
|
|
23444
|
+
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
23445
|
+
RAISE NOTICE 'logistiek-engine: functie public.pick_cart_breakdown overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
24998
23446
|
END $fsdo$;
|
|
24999
23447
|
|
|
23448
|
+
|
|
23449
|
+
|
|
25000
23450
|
DO $fsdo$ BEGIN
|
|
25001
23451
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.pick_queue_apply_cart_breakdown()
|
|
25002
23452
|
RETURNS trigger
|
|
@@ -25056,311 +23506,22 @@ BEGIN
|
|
|
25056
23506
|
r := public.pick_queue_cart_plan_v152(_queue_item_id);
|
|
25057
23507
|
IF nullif(r->>'rowCartId','') IS NOT NULL THEN
|
|
25058
23508
|
SELECT e INTO v_own FROM jsonb_array_elements(r->'carts') e WHERE e->>'cartId' = r->>'rowCartId' LIMIT 1;
|
|
25059
|
-
END IF;
|
|
25060
|
-
RETURN r || jsonb_build_object(
|
|
25061
|
-
'cartCrates', CASE WHEN v_own IS NOT NULL THEN v_own->'cartCrates' END,
|
|
25062
|
-
'bufferCrates', CASE WHEN v_own IS NOT NULL THEN v_own->'bufferCrates' END,
|
|
25063
|
-
'departureAt', CASE WHEN v_own IS NOT NULL THEN v_own->'departureAt' END,
|
|
25064
|
-
'pickStartsAt', CASE WHEN v_own IS NOT NULL THEN v_own->'pickStartsAt' END,
|
|
25065
|
-
'releaseAt', CASE WHEN v_own IS NOT NULL THEN v_own->'releaseAt' END,
|
|
25066
|
-
'releaseReason', CASE WHEN v_own IS NOT NULL THEN v_own->'releaseReason' END);
|
|
25067
|
-
END $function$
|
|
25068
|
-
$fsdef$;
|
|
25069
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
25070
|
-
RAISE NOTICE 'logistiek-engine: functie public.pick_queue_cart_plan overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
25071
|
-
END $fsdo$;
|
|
25072
|
-
|
|
25073
|
-
DO $fsdo$ BEGIN
|
|
25074
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.recompute_all_reserved_stock()
|
|
25075
|
-
RETURNS void
|
|
25076
|
-
LANGUAGE plpgsql
|
|
25077
|
-
SECURITY DEFINER
|
|
25078
|
-
SET search_path TO 'public'
|
|
25079
|
-
AS $function$
|
|
25080
|
-
DECLARE
|
|
25081
|
-
oi_rec record; part record; member_rec record;
|
|
25082
|
-
v_key text; v_last_key text; v_remaining numeric; v_available numeric; v_take numeric; v_err text;
|
|
25083
|
-
v_skipped jsonb := '[]'::jsonb; v_skipped_qty numeric := 0;
|
|
25084
|
-
v_struct jsonb := '[]'::jsonb; v_struct_qty numeric := 0;
|
|
25085
|
-
v_frozen_ids uuid[];
|
|
25086
|
-
BEGIN
|
|
25087
|
-
IF current_setting('app.recomputing_reserved', true) = 'on' THEN RETURN; END IF;
|
|
25088
|
-
PERFORM set_config('app.recomputing_reserved', 'on', true);
|
|
25089
|
-
|
|
25090
|
-
DROP TABLE IF EXISTS _reserved_keys;
|
|
25091
|
-
DROP TABLE IF EXISTS _reserved_demand;
|
|
25092
|
-
DROP TABLE IF EXISTS _reserved_line;
|
|
25093
|
-
DROP TABLE IF EXISTS _reserved_alloc;
|
|
25094
|
-
DROP TABLE IF EXISTS _reserved_frozen;
|
|
25095
|
-
DROP TABLE IF EXISTS _reserved_double;
|
|
25096
|
-
CREATE TEMP TABLE _reserved_keys (raw_key text PRIMARY KEY, canon_key text) ON COMMIT DROP;
|
|
25097
|
-
CREATE TEMP TABLE _reserved_demand (trade_item_key text PRIMARY KEY, qty numeric NOT NULL DEFAULT 0) ON COMMIT DROP;
|
|
25098
|
-
CREATE TEMP TABLE _reserved_line (kind text, ref text, qty numeric, note text) ON COMMIT DROP;
|
|
25099
|
-
CREATE TEMP TABLE _reserved_alloc (order_item_id uuid, trade_item_key text, qty numeric, source text, group_id uuid) ON COMMIT DROP;
|
|
25100
|
-
CREATE TEMP TABLE _reserved_frozen (order_item_id uuid PRIMARY KEY) ON COMMIT DROP;
|
|
25101
|
-
CREATE TEMP TABLE _reserved_double (order_item_id uuid PRIMARY KEY) ON COMMIT DROP;
|
|
25102
|
-
|
|
25103
|
-
INSERT INTO _reserved_double SELECT DISTINCT d.order_item_id FROM public.logistics_double_group_lines(NULL) d;
|
|
25104
|
-
|
|
25105
|
-
IF public.logistics_plan_setting('verdeling_bevriezen_actief', 0) = 1 THEN
|
|
25106
|
-
INSERT INTO _reserved_frozen
|
|
25107
|
-
SELECT oi.id
|
|
25108
|
-
FROM logistics_active.order_items oi
|
|
25109
|
-
JOIN public.orders o ON o.id = oi.order_id
|
|
25110
|
-
WHERE o.status = 'Nog te picken' AND NOT public.logistics_reserved_order_excluded(o.id)
|
|
25111
|
-
AND COALESCE(oi.quantity, 0) > 0
|
|
25112
|
-
AND oi.product_id IS NOT NULL
|
|
25113
|
-
AND NOT EXISTS (SELECT 1 FROM _reserved_double x WHERE x.order_item_id = oi.id)
|
|
25114
|
-
AND NOT EXISTS (SELECT 1 FROM public.stock_mutation_log sml WHERE sml.order_item_id = oi.id AND sml.mutation_type = 'consumption')
|
|
25115
|
-
AND EXISTS (SELECT 1 FROM public.logistics_reservation_allocations a WHERE a.order_item_id = oi.id AND a.source <> 'error')
|
|
25116
|
-
AND public.logistics_allocation_frozen(oi.order_id)
|
|
25117
|
-
ON CONFLICT DO NOTHING;
|
|
25118
|
-
|
|
25119
|
-
-- Bevroren verdeling eerst, naar rato van het huidige aantal (verlaging geeft reservering vrij).
|
|
25120
|
-
INSERT INTO _reserved_alloc
|
|
25121
|
-
SELECT f.order_item_id, s.trade_item_key, s.qty, s.source, s.group_id
|
|
25122
|
-
FROM _reserved_frozen f
|
|
25123
|
-
JOIN logistics_active.order_items oi ON oi.id = f.order_item_id
|
|
25124
|
-
CROSS JOIN LATERAL public.logistics_frozen_allocation_scaled(f.order_item_id, COALESCE(oi.quantity, 0)::numeric) s;
|
|
25125
|
-
INSERT INTO _reserved_demand AS d
|
|
25126
|
-
SELECT trade_item_key, SUM(qty) FROM _reserved_alloc GROUP BY trade_item_key
|
|
25127
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
25128
|
-
END IF;
|
|
25129
|
-
|
|
25130
|
-
FOR oi_rec IN
|
|
25131
|
-
SELECT oi.id, oi.product_id, COALESCE(oi.quantity, 0)::numeric AS quantity
|
|
25132
|
-
FROM logistics_active.order_items oi
|
|
25133
|
-
JOIN public.orders o ON o.id = oi.order_id
|
|
25134
|
-
WHERE o.status = 'Nog te picken' AND NOT public.logistics_reserved_order_excluded(o.id)
|
|
25135
|
-
AND COALESCE(oi.quantity, 0) > 0
|
|
25136
|
-
AND oi.product_id IS NOT NULL
|
|
25137
|
-
AND NOT EXISTS (SELECT 1 FROM public.stock_mutation_log sml WHERE sml.order_item_id = oi.id AND sml.mutation_type = 'consumption')
|
|
25138
|
-
AND NOT EXISTS (SELECT 1 FROM _reserved_frozen f WHERE f.order_item_id = oi.id)
|
|
25139
|
-
AND NOT EXISTS (SELECT 1 FROM _reserved_double x WHERE x.order_item_id = oi.id)
|
|
25140
|
-
ORDER BY o.created_at, oi.id
|
|
25141
|
-
LOOP
|
|
25142
|
-
DELETE FROM _reserved_line WHERE true; -- safeupdate: nooit DELETE zonder WHERE
|
|
25143
|
-
INSERT INTO _reserved_line SELECT * FROM public.logistics_expand_line(oi_rec.product_id, oi_rec.quantity);
|
|
25144
|
-
|
|
25145
|
-
SELECT string_agg(l.note, '; ') INTO v_err FROM _reserved_line l WHERE l.kind = 'error';
|
|
25146
|
-
IF v_err IS NOT NULL THEN
|
|
25147
|
-
v_struct := v_struct || jsonb_build_object('order_item_id', oi_rec.id, 'product_id', oi_rec.product_id, 'reden', v_err);
|
|
25148
|
-
v_struct_qty := v_struct_qty + oi_rec.quantity;
|
|
25149
|
-
CONTINUE;
|
|
25150
|
-
END IF;
|
|
25151
|
-
|
|
25152
|
-
FOR part IN SELECT l.kind, l.ref, l.qty FROM _reserved_line l LOOP
|
|
25153
|
-
IF part.kind = 'item' THEN
|
|
25154
|
-
IF NOT EXISTS (SELECT 1 FROM _reserved_keys WHERE raw_key = part.ref) THEN
|
|
25155
|
-
INSERT INTO _reserved_keys VALUES (part.ref, public.logistics_reserved_key(part.ref));
|
|
25156
|
-
END IF;
|
|
25157
|
-
SELECT canon_key INTO v_key FROM _reserved_keys WHERE raw_key = part.ref;
|
|
25158
|
-
IF v_key IS NULL THEN
|
|
25159
|
-
v_skipped := v_skipped || to_jsonb(part.ref);
|
|
25160
|
-
v_skipped_qty := v_skipped_qty + part.qty;
|
|
25161
|
-
ELSE
|
|
25162
|
-
INSERT INTO _reserved_demand AS d VALUES (v_key, part.qty)
|
|
25163
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
25164
|
-
INSERT INTO _reserved_alloc VALUES (oi_rec.id, v_key, part.qty, 'item', NULL);
|
|
25165
|
-
END IF;
|
|
25166
|
-
ELSE
|
|
25167
|
-
v_remaining := part.qty;
|
|
25168
|
-
v_last_key := NULL;
|
|
25169
|
-
FOR member_rec IN
|
|
25170
|
-
SELECT public.resolve_group_member_stock_key(pgi.trade_item_id) AS raw_key
|
|
25171
|
-
FROM public.product_group_items pgi
|
|
25172
|
-
WHERE pgi.product_group_id = part.ref::uuid
|
|
25173
|
-
AND public.resolve_group_member_stock_key(pgi.trade_item_id) IS NOT NULL
|
|
25174
|
-
AND public.resolve_group_member_stock_key(pgi.trade_item_id) NOT LIKE 'group:%'
|
|
25175
|
-
ORDER BY pgi.sort_order ASC NULLS LAST, pgi.created_at ASC, pgi.id ASC
|
|
25176
|
-
LOOP
|
|
25177
|
-
IF NOT EXISTS (SELECT 1 FROM _reserved_keys WHERE raw_key = member_rec.raw_key) THEN
|
|
25178
|
-
INSERT INTO _reserved_keys VALUES (member_rec.raw_key, public.logistics_reserved_key(member_rec.raw_key));
|
|
25179
|
-
END IF;
|
|
25180
|
-
SELECT canon_key INTO v_key FROM _reserved_keys WHERE raw_key = member_rec.raw_key;
|
|
25181
|
-
IF v_key IS NULL THEN CONTINUE; END IF;
|
|
25182
|
-
v_last_key := v_key;
|
|
25183
|
-
IF v_remaining <= 0 THEN CONTINUE; END IF;
|
|
25184
|
-
|
|
25185
|
-
SELECT GREATEST(COALESCE(MAX(s.physical_stock), 0)
|
|
25186
|
-
- COALESCE((SELECT d.qty FROM _reserved_demand d WHERE d.trade_item_key = v_key), 0), 0)
|
|
25187
|
-
INTO v_available
|
|
25188
|
-
FROM public.trade_item_stock s
|
|
25189
|
-
WHERE s.trade_item_key = v_key;
|
|
25190
|
-
|
|
25191
|
-
IF COALESCE(v_available, 0) <= 0 THEN CONTINUE; END IF;
|
|
25192
|
-
v_take := LEAST(v_available, v_remaining);
|
|
25193
|
-
INSERT INTO _reserved_demand AS d VALUES (v_key, v_take)
|
|
25194
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
25195
|
-
INSERT INTO _reserved_alloc VALUES (oi_rec.id, v_key, v_take, 'group', part.ref::uuid);
|
|
25196
|
-
v_remaining := v_remaining - v_take;
|
|
25197
|
-
END LOOP;
|
|
25198
|
-
|
|
25199
|
-
IF v_remaining > 0 THEN
|
|
25200
|
-
IF v_last_key IS NULL THEN
|
|
25201
|
-
v_skipped := v_skipped || to_jsonb('group:' || part.ref);
|
|
25202
|
-
v_skipped_qty := v_skipped_qty + v_remaining;
|
|
25203
|
-
ELSE
|
|
25204
|
-
INSERT INTO _reserved_demand AS d VALUES (v_last_key, v_remaining)
|
|
25205
|
-
ON CONFLICT (trade_item_key) DO UPDATE SET qty = d.qty + EXCLUDED.qty;
|
|
25206
|
-
INSERT INTO _reserved_alloc VALUES (oi_rec.id, v_last_key, v_remaining, 'group', part.ref::uuid);
|
|
25207
|
-
END IF;
|
|
25208
|
-
END IF;
|
|
25209
|
-
END IF;
|
|
25210
|
-
END LOOP;
|
|
25211
|
-
END LOOP;
|
|
25212
|
-
|
|
25213
|
-
DELETE FROM public.logistics_reservation_allocations a
|
|
25214
|
-
WHERE a.order_item_id IN (
|
|
25215
|
-
SELECT oi.id FROM logistics_active.order_items oi
|
|
25216
|
-
JOIN public.orders o ON o.id = oi.order_id
|
|
25217
|
-
WHERE o.status = 'Nog te picken' AND NOT public.logistics_reserved_order_excluded(o.id)
|
|
25218
|
-
AND NOT EXISTS (SELECT 1 FROM public.stock_mutation_log sml
|
|
25219
|
-
WHERE sml.order_item_id = oi.id AND sml.mutation_type = 'consumption'));
|
|
25220
|
-
INSERT INTO public.logistics_reservation_allocations (order_item_id, trade_item_key, qty, source, group_id, line_qty)
|
|
25221
|
-
SELECT r.order_item_id, r.trade_item_key, SUM(r.qty), r.source, r.group_id, MAX(COALESCE(oi.quantity, 0))::numeric
|
|
25222
|
-
FROM _reserved_alloc r
|
|
25223
|
-
LEFT JOIN logistics_active.order_items oi ON oi.id = r.order_item_id
|
|
25224
|
-
WHERE r.qty > 0
|
|
25225
|
-
GROUP BY r.order_item_id, r.trade_item_key, r.source, r.group_id;
|
|
25226
|
-
DELETE FROM public.logistics_reservation_allocations WHERE computed_at < now() - interval '90 days';
|
|
25227
|
-
|
|
25228
|
-
PERFORM set_config('stock.change_source', 'RESERVATION_RECOMPUTE', true);
|
|
25229
|
-
UPDATE public.trade_item_stock s
|
|
25230
|
-
SET reserved_stock = CEIL(COALESCE(d.qty, 0))::integer,
|
|
25231
|
-
change_source = 'RESERVATION_RECOMPUTE',
|
|
25232
|
-
updated_at = now()
|
|
25233
|
-
FROM public.trade_item_stock s2
|
|
25234
|
-
LEFT JOIN _reserved_demand d ON d.trade_item_key = s2.trade_item_key
|
|
25235
|
-
WHERE s2.id = s.id
|
|
25236
|
-
AND s.reserved_stock IS DISTINCT FROM CEIL(COALESCE(d.qty, 0))::integer;
|
|
25237
|
-
|
|
25238
|
-
IF jsonb_array_length(v_skipped) > 0 THEN
|
|
25239
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
25240
|
-
'phase', 'reservering', 'step', 'reservering herberekenen', 'status', 'waarschuwing',
|
|
25241
|
-
'actor', 'recompute_all_reserved_stock', 'errorClass', 'ontbrekende_gegevens',
|
|
25242
|
-
'reason', 'Geen voorraadrij en geen actieve Floriday-koppeling om die aan te maken; reservering voor deze artikelen niet berekend.',
|
|
25243
|
-
'values', jsonb_build_object(
|
|
25244
|
-
'aantal_sleutels', (SELECT count(DISTINCT x) FROM jsonb_array_elements_text(v_skipped) x),
|
|
25245
|
-
'sleutels', (SELECT jsonb_agg(DISTINCT x) FROM jsonb_array_elements_text(v_skipped) x),
|
|
25246
|
-
'gemiste_vraag_stuks', v_skipped_qty)));
|
|
25247
|
-
END IF;
|
|
25248
|
-
|
|
25249
|
-
IF jsonb_array_length(v_struct) > 0 THEN
|
|
25250
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
25251
|
-
'phase', 'reservering', 'step', 'reservering herberekenen', 'status', 'waarschuwing',
|
|
25252
|
-
'actor', 'recompute_all_reserved_stock', 'errorClass', 'structuur',
|
|
25253
|
-
'reason', 'Samenstelling met een lus of te diepe nesting; voor deze bestelregels is niets gereserveerd.',
|
|
25254
|
-
'values', jsonb_build_object('aantal_regels', jsonb_array_length(v_struct), 'regels', v_struct, 'gemiste_vraag_stuks', v_struct_qty)));
|
|
25255
|
-
END IF;
|
|
25256
|
-
|
|
25257
|
-
SELECT array_agg(order_item_id) INTO v_frozen_ids FROM _reserved_frozen;
|
|
25258
|
-
PERFORM public.logistics_report_frozen_shortage(v_frozen_ids);
|
|
25259
|
-
PERFORM public.logistics_allocation_check_changes(NULL);
|
|
25260
|
-
|
|
25261
|
-
PERFORM set_config('app.recomputing_reserved', 'off', true);
|
|
25262
|
-
END;
|
|
25263
|
-
$function$
|
|
25264
|
-
$fsdef$;
|
|
25265
|
-
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
25266
|
-
RAISE NOTICE 'logistiek-engine: functie public.recompute_all_reserved_stock overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
25267
|
-
END $fsdo$;
|
|
25268
|
-
|
|
25269
|
-
DO $fsdo$ BEGIN
|
|
25270
|
-
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.recompute_reserved_stock(p_trade_item_key text)
|
|
25271
|
-
RETURNS void
|
|
25272
|
-
LANGUAGE plpgsql
|
|
25273
|
-
SECURITY DEFINER
|
|
25274
|
-
SET search_path TO 'public'
|
|
25275
|
-
AS $function$
|
|
25276
|
-
DECLARE
|
|
25277
|
-
v_key text;
|
|
25278
|
-
v_sum integer;
|
|
25279
|
-
v_products uuid[];
|
|
25280
|
-
v_pid uuid;
|
|
25281
|
-
BEGIN
|
|
25282
|
-
IF p_trade_item_key IS NULL OR btrim(p_trade_item_key) = '' THEN RETURN; END IF;
|
|
25283
|
-
IF current_setting('app.recomputing_reserved', true) = 'on' THEN RETURN; END IF;
|
|
25284
|
-
|
|
25285
|
-
-- B1: nieuwe of losse sleutel zonder orderregels, toewijzing of set-/groepsrelatie en reservering 0: niets te doen.
|
|
25286
|
-
v_key := public.logistics_reserved_key(p_trade_item_key);
|
|
25287
|
-
IF public.logistics_reserved_fast_skip(p_trade_item_key, v_key) THEN RETURN; END IF;
|
|
25288
|
-
|
|
25289
|
-
-- Set of groepshoofdproduct: gericht herberekenen op de onderdelen en leden (M7).
|
|
25290
|
-
SELECT array_agg(p.id) INTO v_products
|
|
25291
|
-
FROM public.products p
|
|
25292
|
-
WHERE (p.trade_item_key = btrim(p_trade_item_key)
|
|
25293
|
-
OR p.floriday_trade_item_id = btrim(p_trade_item_key)
|
|
25294
|
-
OR p.id::text = btrim(p_trade_item_key))
|
|
25295
|
-
AND (EXISTS (SELECT 1 FROM public.product_bom_items b WHERE b.parent_product_id = p.id)
|
|
25296
|
-
OR EXISTS (SELECT 1 FROM public.product_groups pg
|
|
25297
|
-
WHERE pg.is_active = true AND (pg.id = p.id OR pg.head_product_id = p.id)));
|
|
25298
|
-
IF v_products IS NOT NULL THEN
|
|
25299
|
-
FOREACH v_pid IN ARRAY v_products LOOP
|
|
25300
|
-
PERFORM public.logistics_recompute_reserved_targeted(v_pid);
|
|
25301
|
-
END LOOP;
|
|
25302
|
-
RETURN;
|
|
25303
|
-
END IF;
|
|
25304
|
-
|
|
25305
|
-
IF v_key IS NULL THEN
|
|
25306
|
-
PERFORM public.logistics_trace(jsonb_build_object(
|
|
25307
|
-
'phase', 'reservering',
|
|
25308
|
-
'step', 'reservering herberekenen',
|
|
25309
|
-
'status', 'waarschuwing',
|
|
25310
|
-
'actor', 'recompute_reserved_stock',
|
|
25311
|
-
'errorClass', 'ontbrekende_gegevens',
|
|
25312
|
-
'reason', 'Geen voorraadrij en geen actieve Floriday-koppeling om die aan te maken; reservering niet berekend.',
|
|
25313
|
-
'values', jsonb_build_object('sleutel', btrim(p_trade_item_key))));
|
|
25314
|
-
RETURN;
|
|
25315
|
-
END IF;
|
|
25316
|
-
|
|
25317
|
-
-- Sleutel hoort bij een groep of samenstelling: de toewijzing hangt van andere
|
|
25318
|
-
-- regels af, dus volledig herberekenen.
|
|
25319
|
-
IF v_key LIKE 'group:%'
|
|
25320
|
-
OR EXISTS (SELECT 1 FROM public.logistics_reservation_allocations a
|
|
25321
|
-
WHERE a.trade_item_key = v_key AND a.source = 'group')
|
|
25322
|
-
OR EXISTS (SELECT 1 FROM public.product_group_items pgi
|
|
25323
|
-
JOIN public.product_groups pg ON pg.id = pgi.product_group_id AND pg.is_active = true
|
|
25324
|
-
WHERE public.resolve_group_member_stock_key(pgi.trade_item_id) IN (v_key, btrim(p_trade_item_key)))
|
|
25325
|
-
OR EXISTS (SELECT 1 FROM public.product_bom_items b
|
|
25326
|
-
JOIN public.products p ON p.id = b.component_product_id
|
|
25327
|
-
WHERE COALESCE(NULLIF(btrim(COALESCE(p.floriday_trade_item_id, '')), ''),
|
|
25328
|
-
NULLIF(btrim(COALESCE(p.trade_item_key, '')), ''), p.id::text) = v_key
|
|
25329
|
-
OR p.trade_item_key = btrim(p_trade_item_key))
|
|
25330
|
-
THEN
|
|
25331
|
-
PERFORM public.recompute_all_reserved_stock();
|
|
25332
|
-
RETURN;
|
|
25333
|
-
END IF;
|
|
25334
|
-
|
|
25335
|
-
SELECT CEIL(COALESCE(SUM(COALESCE(oi.quantity, 0)), 0))::integer INTO v_sum
|
|
25336
|
-
FROM logistics_active.order_items oi
|
|
25337
|
-
JOIN public.orders o ON o.id = oi.order_id
|
|
25338
|
-
JOIN public.products p ON p.id = oi.product_id
|
|
25339
|
-
WHERE COALESCE(NULLIF(btrim(COALESCE(p.floriday_trade_item_id, '')), ''),
|
|
25340
|
-
NULLIF(btrim(COALESCE(p.trade_item_key, '')), ''), p.id::text) = v_key
|
|
25341
|
-
AND o.status = 'Nog te picken' AND NOT public.logistics_reserved_order_excluded(o.id)
|
|
25342
|
-
AND NOT EXISTS (SELECT 1 FROM public.product_bom_items b WHERE b.parent_product_id = p.id)
|
|
25343
|
-
AND NOT EXISTS (SELECT 1 FROM public.product_groups pg
|
|
25344
|
-
WHERE pg.is_active = true AND (pg.id = p.id OR pg.head_product_id = p.id))
|
|
25345
|
-
AND NOT EXISTS (
|
|
25346
|
-
SELECT 1 FROM public.stock_mutation_log sml
|
|
25347
|
-
WHERE sml.order_item_id = oi.id
|
|
25348
|
-
AND sml.mutation_type = 'consumption');
|
|
25349
|
-
|
|
25350
|
-
PERFORM set_config('stock.change_source', 'RESERVATION_RECOMPUTE', true);
|
|
25351
|
-
UPDATE public.trade_item_stock
|
|
25352
|
-
SET reserved_stock = v_sum,
|
|
25353
|
-
change_source = 'RESERVATION_RECOMPUTE',
|
|
25354
|
-
updated_at = now()
|
|
25355
|
-
WHERE trade_item_key = v_key
|
|
25356
|
-
AND reserved_stock IS DISTINCT FROM v_sum;
|
|
25357
|
-
END
|
|
25358
|
-
$function$
|
|
23509
|
+
END IF;
|
|
23510
|
+
RETURN r || jsonb_build_object(
|
|
23511
|
+
'cartCrates', CASE WHEN v_own IS NOT NULL THEN v_own->'cartCrates' END,
|
|
23512
|
+
'bufferCrates', CASE WHEN v_own IS NOT NULL THEN v_own->'bufferCrates' END,
|
|
23513
|
+
'departureAt', CASE WHEN v_own IS NOT NULL THEN v_own->'departureAt' END,
|
|
23514
|
+
'pickStartsAt', CASE WHEN v_own IS NOT NULL THEN v_own->'pickStartsAt' END,
|
|
23515
|
+
'releaseAt', CASE WHEN v_own IS NOT NULL THEN v_own->'releaseAt' END,
|
|
23516
|
+
'releaseReason', CASE WHEN v_own IS NOT NULL THEN v_own->'releaseReason' END);
|
|
23517
|
+
END $function$
|
|
25359
23518
|
$fsdef$;
|
|
25360
23519
|
EXCEPTION WHEN undefined_object OR undefined_table OR undefined_function OR invalid_schema_name THEN
|
|
25361
|
-
RAISE NOTICE 'logistiek-engine: functie public.
|
|
23520
|
+
RAISE NOTICE 'logistiek-engine: functie public.pick_queue_cart_plan overgeslagen (onderdeel van andere module ontbreekt): %', SQLERRM;
|
|
25362
23521
|
END $fsdo$;
|
|
25363
23522
|
|
|
23523
|
+
|
|
23524
|
+
|
|
25364
23525
|
DO $fsdo$ BEGIN
|
|
25365
23526
|
EXECUTE $fsdef$CREATE OR REPLACE FUNCTION public.logistics_register_tick_apikey(p_key text)
|
|
25366
23527
|
RETURNS jsonb
|
|
@@ -28323,78 +26484,6 @@ AS $function$
|
|
|
28323
26484
|
$function$;
|
|
28324
26485
|
|
|
28325
26486
|
-- 4. Centrale beslisregel.
|
|
28326
|
-
CREATE OR REPLACE FUNCTION public.logistics_document_for_order(p_order_id uuid, p_documenttype text)
|
|
28327
|
-
RETURNS jsonb
|
|
28328
|
-
LANGUAGE plpgsql
|
|
28329
|
-
STABLE SECURITY DEFINER
|
|
28330
|
-
SET search_path TO 'public'
|
|
28331
|
-
AS $function$
|
|
28332
|
-
DECLARE
|
|
28333
|
-
v_soort text := lower(btrim(coalesce(p_documenttype, '')));
|
|
28334
|
-
v_floriday boolean;
|
|
28335
|
-
v_bron text;
|
|
28336
|
-
v_type text;
|
|
28337
|
-
v_res jsonb;
|
|
28338
|
-
v_n int; v_std int; v_id uuid;
|
|
28339
|
-
v_l public.document_layouts%ROWTYPE;
|
|
28340
|
-
BEGIN
|
|
28341
|
-
IF v_soort = '' THEN
|
|
28342
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'reden', 'Geen documentsoort opgegeven.');
|
|
28343
|
-
END IF;
|
|
28344
|
-
|
|
28345
|
-
IF to_regprocedure('public.layout_voor_document(uuid,text)') IS NOT NULL THEN
|
|
28346
|
-
EXECUTE 'SELECT to_jsonb(public.layout_voor_document($1, $2))' INTO v_res USING p_order_id, v_soort;
|
|
28347
|
-
IF jsonb_typeof(v_res) <> 'object' THEN
|
|
28348
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'layouts',
|
|
28349
|
-
'reden', 'Layouts gaf geen bruikbaar antwoord voor ' || v_soort || '.');
|
|
28350
|
-
END IF;
|
|
28351
|
-
RETURN v_res || jsonb_build_object('keuze', 'layouts',
|
|
28352
|
-
'ok', coalesce((v_res->>'ok')::boolean, nullif(v_res->>'layout_id', '') IS NOT NULL));
|
|
28353
|
-
END IF;
|
|
28354
|
-
|
|
28355
|
-
-- Automatische keuze (Layouts nog niet bijgewerkt).
|
|
28356
|
-
SELECT o.order_source = 'floriday' INTO v_floriday FROM public.orders o WHERE o.id = p_order_id;
|
|
28357
|
-
IF v_floriday IS NULL THEN
|
|
28358
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch', 'reden', 'Order niet gevonden.');
|
|
28359
|
-
END IF;
|
|
28360
|
-
|
|
28361
|
-
v_type := CASE
|
|
28362
|
-
WHEN v_soort IN ('eigen_sticker', 'sticker', 'etiket') THEN 'sticker'
|
|
28363
|
-
WHEN v_soort IN ('verzenddocument', 'verzendbrief', 'afleverbrief', 'afleverbon') THEN 'afleverbrief'
|
|
28364
|
-
WHEN v_soort IN ('veilingbrief', 'veilingbon') THEN 'veilingbrief'
|
|
28365
|
-
WHEN v_soort LIKE '%pakbon%' THEN 'pakbon'
|
|
28366
|
-
WHEN v_soort LIKE '%productie%' THEN 'productiebon'
|
|
28367
|
-
ELSE v_soort END;
|
|
28368
|
-
v_bron := CASE
|
|
28369
|
-
WHEN v_floriday AND v_soort <> 'eigen_sticker' AND v_type IN ('sticker', 'traysticker', 'afleverbrief', 'veilingbrief') THEN 'floriday'
|
|
28370
|
-
ELSE 'eigen' END;
|
|
28371
|
-
IF v_bron = 'eigen' AND v_type = 'veilingbrief' THEN
|
|
28372
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch',
|
|
28373
|
-
'reden', 'Een veilingbrief hoort alleen bij een Floriday-order; voor een eigen order wordt de afleverbrief gebruikt.');
|
|
28374
|
-
END IF;
|
|
28375
|
-
|
|
28376
|
-
SELECT count(*), count(*) FILTER (WHERE is_standaard IS TRUE) INTO v_n, v_std
|
|
28377
|
-
FROM public.document_layouts
|
|
28378
|
-
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type;
|
|
28379
|
-
IF v_n = 1 THEN
|
|
28380
|
-
SELECT * INTO v_l FROM public.document_layouts
|
|
28381
|
-
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type;
|
|
28382
|
-
ELSIF v_n > 1 THEN
|
|
28383
|
-
SELECT * INTO v_l FROM public.document_layouts
|
|
28384
|
-
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type
|
|
28385
|
-
ORDER BY is_standaard DESC NULLS LAST, updated_at DESC LIMIT 1;
|
|
28386
|
-
END IF;
|
|
28387
|
-
IF v_l.id IS NULL THEN
|
|
28388
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch', 'bron', v_bron, 'documenttype', v_type,
|
|
28389
|
-
'reden', CASE WHEN v_bron = 'floriday'
|
|
28390
|
-
THEN 'Geen actieve ' || v_type || '-layout met bron Floriday. Activeer de Floriday-systeemlayout in Layouts en printers.'
|
|
28391
|
-
ELSE 'Maak of activeer een ' || v_type || 'layout in Layouts en printers.' END);
|
|
28392
|
-
END IF;
|
|
28393
|
-
RETURN jsonb_build_object('ok', true, 'layout_id', v_l.id, 'keuze', 'automatisch', 'bron', v_bron,
|
|
28394
|
-
'documenttype', v_type, 'breedte_mm', v_l.breedte_mm, 'hoogte_mm', v_l.hoogte_mm, 'reden', NULL);
|
|
28395
|
-
END;
|
|
28396
|
-
$function$;
|
|
28397
|
-
|
|
28398
26487
|
-- 5. Eigen stickers (HO/MO/AO): één per klant+product, aantal = planten van regels met needs_sticker.
|
|
28399
26488
|
CREATE OR REPLACE FUNCTION public.logistics_own_sticker_count(p_unit text, p_quantity numeric, p_ppc_regel numeric, p_ppc_product numeric)
|
|
28400
26489
|
RETURNS integer LANGUAGE sql IMMUTABLE SET search_path = public AS $cnt$
|
|
@@ -28436,271 +26525,95 @@ BEGIN
|
|
|
28436
26525
|
AND oi.quarantined_at IS NULL
|
|
28437
26526
|
AND oi.product_id IS NOT NULL
|
|
28438
26527
|
AND coalesce(o.order_source, '') <> 'floriday'
|
|
28439
|
-
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
28440
|
-
AND coalesce(o.status, '') <> 'geannuleerd'
|
|
28441
|
-
AND o.delivery_date >= current_date - 1
|
|
28442
|
-
GROUP BY o.id, o.order_number, o.customer_id, oi.product_id
|
|
28443
|
-
LIMIT greatest(1, p_limit)
|
|
28444
|
-
LOOP
|
|
28445
|
-
v_bron := r.order_id::text || ':' || r.product_id::text;
|
|
28446
|
-
SELECT count(*), (array_agg(s.id))[1] INTO v_n, v_sticker
|
|
28447
|
-
FROM public.customer_product_stickers s
|
|
28448
|
-
JOIN public.customers c ON c.id = r.customer_id
|
|
28449
|
-
WHERE s.trade_item_key = r.product_id::text
|
|
28450
|
-
AND s.customer_key IN (c.id::text, 'tf:' || coalesce(c.twinfield_code, '-'), 'cn:' || coalesce(c.customer_number, '-'));
|
|
28451
|
-
v_status := 'wacht_op_moment'; v_reden := NULL;
|
|
28452
|
-
IF r.onbekend THEN
|
|
28453
|
-
v_status := 'geblokkeerd'; v_reden := 'Aantal stickers onbekend: regel in fust zonder planten per fust (niet op de regel en niet bij het product). Vul planten per fust in.';
|
|
28454
|
-
ELSIF coalesce(r.planten, 0) < 1 THEN
|
|
28455
|
-
v_status := 'geblokkeerd'; v_reden := 'Aantal planten is 0; geen sticker te printen.';
|
|
28456
|
-
ELSIF v_n = 0 THEN
|
|
28457
|
-
v_status := 'geblokkeerd'; v_reden := 'Geen eigen sticker gevonden voor deze klant en dit product. Voeg hem toe bij de klant.';
|
|
28458
|
-
ELSIF v_n > 1 THEN
|
|
28459
|
-
v_status := 'geblokkeerd'; v_reden := 'Meer dan één eigen sticker voor deze klant en dit product; er mag er maar één zijn.';
|
|
28460
|
-
END IF;
|
|
28461
|
-
|
|
28462
|
-
UPDATE public.logistics_sticker_prints
|
|
28463
|
-
SET kopieen = greatest(coalesce(r.planten, 0), 1),
|
|
28464
|
-
eigen_sticker_id = CASE WHEN v_n = 1 THEN v_sticker ELSE NULL END,
|
|
28465
|
-
status = CASE WHEN status = 'geblokkeerd' AND v_status = 'wacht_op_moment' THEN 'wacht_op_moment'
|
|
28466
|
-
WHEN status = 'niet_printen' THEN v_status
|
|
28467
|
-
WHEN status = 'wacht_op_moment' THEN v_status ELSE status END,
|
|
28468
|
-
reden = CASE WHEN status IN ('wacht_op_moment', 'geblokkeerd', 'niet_printen') THEN v_reden ELSE reden END,
|
|
28469
|
-
updated_at = now()
|
|
28470
|
-
WHERE soort = 'eigen_sticker' AND bron_id = v_bron
|
|
28471
|
-
AND status IN ('wacht_op_moment', 'geblokkeerd', 'niet_printen');
|
|
28472
|
-
IF NOT FOUND AND NOT EXISTS (SELECT 1 FROM public.logistics_sticker_prints WHERE soort = 'eigen_sticker' AND bron_id = v_bron) THEN
|
|
28473
|
-
INSERT INTO public.logistics_sticker_prints (soort, bron_id, order_id, order_number, kopieen, status, reden, eigen_sticker_id)
|
|
28474
|
-
VALUES ('eigen_sticker', v_bron, r.order_id, r.order_number, greatest(coalesce(r.planten, 0), 1), v_status, v_reden,
|
|
28475
|
-
CASE WHEN v_n = 1 THEN v_sticker ELSE NULL END);
|
|
28476
|
-
END IF;
|
|
28477
|
-
v_bijgewerkt := v_bijgewerkt + 1;
|
|
28478
|
-
END LOOP;
|
|
28479
|
-
|
|
28480
|
-
-- Vinkje uitgezet (of order vervallen) vóór het printen: niet printen.
|
|
28481
|
-
UPDATE public.logistics_sticker_prints p
|
|
28482
|
-
SET status = 'niet_printen', reden = 'Sticker uitgezet op de orderregel of order vervallen.', updated_at = now()
|
|
28483
|
-
WHERE p.soort = 'eigen_sticker' AND p.status IN ('wacht_op_moment', 'geblokkeerd', 'klaar')
|
|
28484
|
-
AND NOT EXISTS (
|
|
28485
|
-
SELECT 1 FROM public.order_items oi JOIN public.orders o ON o.id = oi.order_id
|
|
28486
|
-
WHERE oi.order_id = p.order_id AND p.bron_id = oi.order_id::text || ':' || oi.product_id::text
|
|
28487
|
-
AND oi.needs_sticker IS TRUE AND oi.quarantined_at IS NULL
|
|
28488
|
-
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.status, '') <> 'geannuleerd');
|
|
28489
|
-
GET DIAGNOSTICS v_uit = ROW_COUNT;
|
|
28490
|
-
|
|
28491
|
-
-- Vrijgeven met de pakbon: kar en printplek van de geprinte pakbonrij, formaat uit sticker of layout.
|
|
28492
|
-
WITH vrij AS (
|
|
28493
|
-
SELECT p.id,
|
|
28494
|
-
(SELECT public.logistics_try_uuid(q.payload->>'cartId')
|
|
28495
|
-
FROM public.pick_queue q
|
|
28496
|
-
WHERE q.cancelled_at IS NULL AND q.print_job_id IS NOT NULL
|
|
28497
|
-
AND (q.payload->>'orderId' = p.order_id::text OR q.payload->'orderIds' ? p.order_id::text)
|
|
28498
|
-
ORDER BY q.created_at LIMIT 1) AS kar,
|
|
28499
|
-
(SELECT k.print_plek_id::text
|
|
28500
|
-
FROM public.pick_queue q
|
|
28501
|
-
JOIN public.print_plek_koppelingen k ON k.bron IN ('pickstation', 'pick_station') AND k.bron_id = q.station_id::text
|
|
28502
|
-
WHERE q.cancelled_at IS NULL AND q.print_job_id IS NOT NULL
|
|
28503
|
-
AND (q.payload->>'orderId' = p.order_id::text OR q.payload->'orderIds' ? p.order_id::text)
|
|
28504
|
-
ORDER BY q.created_at, k.created_at LIMIT 1) AS plek,
|
|
28505
|
-
s.width_mm, s.height_mm,
|
|
28506
|
-
public.logistics_document_for_order(p.order_id, 'eigen_sticker') AS lay
|
|
28507
|
-
FROM public.logistics_sticker_prints p
|
|
28508
|
-
LEFT JOIN public.customer_product_stickers s ON s.id = p.eigen_sticker_id
|
|
28509
|
-
WHERE p.soort = 'eigen_sticker' AND p.status = 'wacht_op_moment'
|
|
28510
|
-
AND EXISTS (SELECT 1 FROM public.pick_queue q
|
|
28511
|
-
WHERE q.cancelled_at IS NULL AND q.print_job_id IS NOT NULL
|
|
28512
|
-
AND (q.payload->>'orderId' = p.order_id::text OR q.payload->'orderIds' ? p.order_id::text))
|
|
28513
|
-
)
|
|
28514
|
-
UPDATE public.logistics_sticker_prints p
|
|
28515
|
-
SET status = 'klaar', cart_id = vrij.kar, print_plek_id = vrij.plek,
|
|
28516
|
-
breedte_mm = coalesce(vrij.width_mm, (vrij.lay->>'breedte_mm')::numeric),
|
|
28517
|
-
hoogte_mm = coalesce(vrij.height_mm, (vrij.lay->>'hoogte_mm')::numeric),
|
|
28518
|
-
updated_at = now()
|
|
28519
|
-
FROM vrij
|
|
28520
|
-
WHERE p.id = vrij.id;
|
|
28521
|
-
GET DIAGNOSTICS v_vrij = ROW_COUNT;
|
|
28522
|
-
|
|
28523
|
-
RETURN jsonb_build_object('regels', v_bijgewerkt, 'vrijgegeven', v_vrij, 'niet_printen', v_uit);
|
|
28524
|
-
END;
|
|
28525
|
-
$function$;
|
|
28526
|
-
|
|
28527
|
-
-- 6. Pakbon van het pickstation: alleen de centrale beslisregel (geen layout uit payload of werkwijze).
|
|
28528
|
-
CREATE OR REPLACE FUNCTION public.pick_enqueue_print_job(_queue_item_id uuid, _printer_id uuid, _session_id text, _is_herprint boolean, _cart_id text)
|
|
28529
|
-
RETURNS uuid
|
|
28530
|
-
LANGUAGE plpgsql
|
|
28531
|
-
SECURITY DEFINER
|
|
28532
|
-
SET search_path TO 'public'
|
|
28533
|
-
AS $function$
|
|
28534
|
-
DECLARE
|
|
28535
|
-
item public.pick_queue;
|
|
28536
|
-
dt public.pick_document_types;
|
|
28537
|
-
doc_code text;
|
|
28538
|
-
target_printer uuid;
|
|
28539
|
-
target_layout uuid;
|
|
28540
|
-
target_plek uuid;
|
|
28541
|
-
layout_meta jsonb;
|
|
28542
|
-
layout_reden text;
|
|
28543
|
-
v_types public.doc_layout_type[];
|
|
28544
|
-
doc_type public.doc_layout_type := 'vrij';
|
|
28545
|
-
layout_type public.doc_layout_type;
|
|
28546
|
-
pdf_url text;
|
|
28547
|
-
pdf_b64 text;
|
|
28548
|
-
herkomst text;
|
|
28549
|
-
job_id uuid;
|
|
28550
|
-
cart_plan jsonb := NULL;
|
|
28551
|
-
selected_cart jsonb := NULL;
|
|
28552
|
-
v_cart_uuid uuid;
|
|
28553
|
-
v_barcode text;
|
|
28554
|
-
v_barcode_on boolean := public.logistics_pick_barcode_enabled();
|
|
28555
|
-
v_is_partial boolean := false;
|
|
28556
|
-
v_sleutel text;
|
|
28557
|
-
v_order uuid;
|
|
28558
|
-
BEGIN
|
|
28559
|
-
SELECT * INTO item FROM public.pick_queue WHERE id = _queue_item_id;
|
|
28560
|
-
IF NOT FOUND THEN RAISE EXCEPTION 'Dit document bestaat niet meer.'; END IF;
|
|
28561
|
-
|
|
28562
|
-
SELECT * INTO dt FROM public.pick_document_types WHERE id = item.document_type_id;
|
|
28563
|
-
|
|
28564
|
-
doc_code := lower(btrim(coalesce(
|
|
28565
|
-
nullif(item.payload->>'documentType', ''),
|
|
28566
|
-
nullif(dt.code, ''),
|
|
28567
|
-
''
|
|
28568
|
-
)));
|
|
28569
|
-
|
|
28570
|
-
v_types := public.logistics_document_type_map(doc_code);
|
|
28571
|
-
|
|
28572
|
-
IF _cart_id IS NOT NULL THEN
|
|
28573
|
-
cart_plan := public.pick_queue_cart_plan(_queue_item_id);
|
|
28574
|
-
SELECT c INTO selected_cart
|
|
28575
|
-
FROM jsonb_array_elements(COALESCE(cart_plan->'carts', '[]'::jsonb)) AS c
|
|
28576
|
-
WHERE c->>'cartId' = _cart_id
|
|
28577
|
-
LIMIT 1;
|
|
28578
|
-
|
|
28579
|
-
IF selected_cart IS NULL THEN
|
|
28580
|
-
RAISE EXCEPTION 'De gekozen kar bestaat niet meer in het actuele karplan.';
|
|
28581
|
-
END IF;
|
|
28582
|
-
|
|
28583
|
-
v_is_partial := NOT COALESCE((selected_cart->>'isFullCart')::boolean, false);
|
|
28584
|
-
|
|
28585
|
-
IF v_barcode_on THEN
|
|
28586
|
-
BEGIN
|
|
28587
|
-
v_cart_uuid := nullif(_cart_id, '')::uuid;
|
|
28588
|
-
EXCEPTION WHEN invalid_text_representation THEN
|
|
28589
|
-
v_cart_uuid := NULL;
|
|
28590
|
-
END;
|
|
28591
|
-
IF v_cart_uuid IS NOT NULL THEN
|
|
28592
|
-
v_barcode := public.logistics_ensure_cart_barcode(v_cart_uuid);
|
|
28593
|
-
selected_cart := selected_cart || jsonb_build_object('barcode', v_barcode);
|
|
28594
|
-
END IF;
|
|
28595
|
-
END IF;
|
|
28596
|
-
END IF;
|
|
28597
|
-
|
|
28598
|
-
-- 1.0.176: het document wordt automatisch bepaald uit de order.
|
|
28599
|
-
v_order := public.logistics_try_uuid(COALESCE(selected_cart->>'orderId', item.payload->>'orderId', item.payload->>'order_id'));
|
|
28600
|
-
IF doc_code <> '' AND v_order IS NOT NULL THEN
|
|
28601
|
-
layout_meta := public.logistics_document_for_order(v_order, doc_code);
|
|
28602
|
-
target_layout := public.logistics_try_uuid(layout_meta->>'layout_id');
|
|
28603
|
-
layout_reden := nullif(layout_meta->>'reden', '');
|
|
28604
|
-
ELSIF doc_code <> '' THEN
|
|
28605
|
-
layout_meta := public.logistics_document_layout_v2(doc_code, v_is_partial);
|
|
28606
|
-
target_layout := public.logistics_try_uuid(layout_meta->>'layout_id');
|
|
28607
|
-
END IF;
|
|
28608
|
-
|
|
28609
|
-
SELECT l.documenttype INTO layout_type
|
|
28610
|
-
FROM public.document_layouts l
|
|
28611
|
-
WHERE l.id = target_layout
|
|
28612
|
-
AND l.actief IS TRUE;
|
|
28613
|
-
|
|
28614
|
-
IF layout_type IS NULL THEN
|
|
28615
|
-
target_layout := NULL;
|
|
28616
|
-
END IF;
|
|
28617
|
-
|
|
28618
|
-
doc_type := COALESCE(layout_type, v_types[1], 'vrij');
|
|
28619
|
-
|
|
28620
|
-
IF item.station_id IS NOT NULL THEN
|
|
28621
|
-
SELECT k.print_plek_id INTO target_plek
|
|
28622
|
-
FROM public.print_plek_koppelingen k
|
|
28623
|
-
WHERE k.bron IN ('pickstation', 'pick_station')
|
|
28624
|
-
AND k.bron_id = item.station_id::text
|
|
28625
|
-
ORDER BY k.created_at
|
|
28626
|
-
LIMIT 1;
|
|
28627
|
-
END IF;
|
|
28628
|
-
|
|
28629
|
-
SELECT p.id INTO target_printer
|
|
28630
|
-
FROM public.printers p
|
|
28631
|
-
WHERE p.id = _printer_id
|
|
28632
|
-
AND p.actief
|
|
28633
|
-
AND nullif(p.extern_printer_id, '') IS NOT NULL;
|
|
26528
|
+
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
26529
|
+
AND coalesce(o.status, '') <> 'geannuleerd'
|
|
26530
|
+
AND o.delivery_date >= current_date - 1
|
|
26531
|
+
GROUP BY o.id, o.order_number, o.customer_id, oi.product_id
|
|
26532
|
+
LIMIT greatest(1, p_limit)
|
|
26533
|
+
LOOP
|
|
26534
|
+
v_bron := r.order_id::text || ':' || r.product_id::text;
|
|
26535
|
+
SELECT count(*), (array_agg(s.id))[1] INTO v_n, v_sticker
|
|
26536
|
+
FROM public.customer_product_stickers s
|
|
26537
|
+
JOIN public.customers c ON c.id = r.customer_id
|
|
26538
|
+
WHERE s.trade_item_key = r.product_id::text
|
|
26539
|
+
AND s.customer_key IN (c.id::text, 'tf:' || coalesce(c.twinfield_code, '-'), 'cn:' || coalesce(c.customer_number, '-'));
|
|
26540
|
+
v_status := 'wacht_op_moment'; v_reden := NULL;
|
|
26541
|
+
IF r.onbekend THEN
|
|
26542
|
+
v_status := 'geblokkeerd'; v_reden := 'Aantal stickers onbekend: regel in fust zonder planten per fust (niet op de regel en niet bij het product). Vul planten per fust in.';
|
|
26543
|
+
ELSIF coalesce(r.planten, 0) < 1 THEN
|
|
26544
|
+
v_status := 'geblokkeerd'; v_reden := 'Aantal planten is 0; geen sticker te printen.';
|
|
26545
|
+
ELSIF v_n = 0 THEN
|
|
26546
|
+
v_status := 'geblokkeerd'; v_reden := 'Geen eigen sticker gevonden voor deze klant en dit product. Voeg hem toe bij de klant.';
|
|
26547
|
+
ELSIF v_n > 1 THEN
|
|
26548
|
+
v_status := 'geblokkeerd'; v_reden := 'Meer dan één eigen sticker voor deze klant en dit product; er mag er maar één zijn.';
|
|
26549
|
+
END IF;
|
|
28634
26550
|
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
26551
|
+
UPDATE public.logistics_sticker_prints
|
|
26552
|
+
SET kopieen = greatest(coalesce(r.planten, 0), 1),
|
|
26553
|
+
eigen_sticker_id = CASE WHEN v_n = 1 THEN v_sticker ELSE NULL END,
|
|
26554
|
+
status = CASE WHEN status = 'geblokkeerd' AND v_status = 'wacht_op_moment' THEN 'wacht_op_moment'
|
|
26555
|
+
WHEN status = 'niet_printen' THEN v_status
|
|
26556
|
+
WHEN status = 'wacht_op_moment' THEN v_status ELSE status END,
|
|
26557
|
+
reden = CASE WHEN status IN ('wacht_op_moment', 'geblokkeerd', 'niet_printen') THEN v_reden ELSE reden END,
|
|
26558
|
+
updated_at = now()
|
|
26559
|
+
WHERE soort = 'eigen_sticker' AND bron_id = v_bron
|
|
26560
|
+
AND status IN ('wacht_op_moment', 'geblokkeerd', 'niet_printen');
|
|
26561
|
+
IF NOT FOUND AND NOT EXISTS (SELECT 1 FROM public.logistics_sticker_prints WHERE soort = 'eigen_sticker' AND bron_id = v_bron) THEN
|
|
26562
|
+
INSERT INTO public.logistics_sticker_prints (soort, bron_id, order_id, order_number, kopieen, status, reden, eigen_sticker_id)
|
|
26563
|
+
VALUES ('eigen_sticker', v_bron, r.order_id, r.order_number, greatest(coalesce(r.planten, 0), 1), v_status, v_reden,
|
|
26564
|
+
CASE WHEN v_n = 1 THEN v_sticker ELSE NULL END);
|
|
26565
|
+
END IF;
|
|
26566
|
+
v_bijgewerkt := v_bijgewerkt + 1;
|
|
26567
|
+
END LOOP;
|
|
28638
26568
|
|
|
28639
|
-
|
|
28640
|
-
|
|
28641
|
-
|
|
28642
|
-
|
|
26569
|
+
-- Vinkje uitgezet (of order vervallen) vóór het printen: niet printen.
|
|
26570
|
+
UPDATE public.logistics_sticker_prints p
|
|
26571
|
+
SET status = 'niet_printen', reden = 'Sticker uitgezet op de orderregel of order vervallen.', updated_at = now()
|
|
26572
|
+
WHERE p.soort = 'eigen_sticker' AND p.status IN ('wacht_op_moment', 'geblokkeerd', 'klaar')
|
|
26573
|
+
AND NOT EXISTS (
|
|
26574
|
+
SELECT 1 FROM public.order_items oi JOIN public.orders o ON o.id = oi.order_id
|
|
26575
|
+
WHERE oi.order_id = p.order_id AND p.bron_id = oi.order_id::text || ':' || oi.product_id::text
|
|
26576
|
+
AND oi.needs_sticker IS TRUE AND oi.quarantined_at IS NULL
|
|
26577
|
+
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL AND coalesce(o.status, '') <> 'geannuleerd');
|
|
26578
|
+
GET DIAGNOSTICS v_uit = ROW_COUNT;
|
|
28643
26579
|
|
|
28644
|
-
|
|
28645
|
-
|
|
28646
|
-
|
|
28647
|
-
|
|
28648
|
-
|
|
28649
|
-
|
|
28650
|
-
|
|
28651
|
-
|
|
28652
|
-
|
|
28653
|
-
|
|
28654
|
-
|
|
28655
|
-
|
|
28656
|
-
|
|
28657
|
-
|
|
28658
|
-
|
|
28659
|
-
|
|
28660
|
-
|
|
28661
|
-
|
|
28662
|
-
|
|
28663
|
-
|
|
28664
|
-
|
|
28665
|
-
|
|
28666
|
-
'document_number', item.document_number,
|
|
28667
|
-
'document_type_code', COALESCE(nullif(doc_code, ''), dt.code),
|
|
28668
|
-
'report_key', dt.report_key,
|
|
28669
|
-
'print_template', dt.print_template,
|
|
28670
|
-
'order_number', COALESCE(selected_cart->>'orderNumber', item.order_number),
|
|
28671
|
-
'customer_name', item.customer_name,
|
|
28672
|
-
'reference', item.reference,
|
|
28673
|
-
'layout_id', target_layout,
|
|
28674
|
-
'layout_keuze', layout_meta->>'keuze',
|
|
28675
|
-
'layout_variant', CASE WHEN v_is_partial THEN 'partial_order' ELSE 'full_cart' END,
|
|
28676
|
-
'barcode', CASE WHEN v_barcode_on THEN COALESCE(v_barcode, item.barcode) ELSE item.barcode END,
|
|
28677
|
-
'country_code', item.country_code,
|
|
28678
|
-
'cart_id', _cart_id,
|
|
28679
|
-
'cart', selected_cart,
|
|
28680
|
-
'data', COALESCE(item.payload, '{}'::jsonb) || jsonb_build_object(
|
|
28681
|
-
'print_plek_id', target_plek,
|
|
28682
|
-
'cart_id', _cart_id,
|
|
28683
|
-
'cart', selected_cart,
|
|
28684
|
-
'orderId', COALESCE(selected_cart->>'orderId', item.payload->>'orderId'),
|
|
28685
|
-
'orderNumber', COALESCE(selected_cart->>'orderNumber', item.order_number)
|
|
28686
|
-
)
|
|
28687
|
-
),
|
|
28688
|
-
'Pickstation',
|
|
28689
|
-
pdf_url,
|
|
28690
|
-
pdf_b64,
|
|
28691
|
-
herkomst,
|
|
28692
|
-
COALESCE(_is_herprint, false),
|
|
28693
|
-
v_sleutel
|
|
26580
|
+
-- Vrijgeven met de pakbon: kar en printplek van de geprinte pakbonrij, formaat uit sticker of layout.
|
|
26581
|
+
WITH vrij AS (
|
|
26582
|
+
SELECT p.id,
|
|
26583
|
+
(SELECT public.logistics_try_uuid(q.payload->>'cartId')
|
|
26584
|
+
FROM public.pick_queue q
|
|
26585
|
+
WHERE q.cancelled_at IS NULL AND q.print_job_id IS NOT NULL
|
|
26586
|
+
AND (q.payload->>'orderId' = p.order_id::text OR q.payload->'orderIds' ? p.order_id::text)
|
|
26587
|
+
ORDER BY q.created_at LIMIT 1) AS kar,
|
|
26588
|
+
(SELECT k.print_plek_id::text
|
|
26589
|
+
FROM public.pick_queue q
|
|
26590
|
+
JOIN public.print_plek_koppelingen k ON k.bron IN ('pickstation', 'pick_station') AND k.bron_id = q.station_id::text
|
|
26591
|
+
WHERE q.cancelled_at IS NULL AND q.print_job_id IS NOT NULL
|
|
26592
|
+
AND (q.payload->>'orderId' = p.order_id::text OR q.payload->'orderIds' ? p.order_id::text)
|
|
26593
|
+
ORDER BY q.created_at, k.created_at LIMIT 1) AS plek,
|
|
26594
|
+
s.width_mm, s.height_mm,
|
|
26595
|
+
public.logistics_document_for_order(p.order_id, 'eigen_sticker') AS lay
|
|
26596
|
+
FROM public.logistics_sticker_prints p
|
|
26597
|
+
LEFT JOIN public.customer_product_stickers s ON s.id = p.eigen_sticker_id
|
|
26598
|
+
WHERE p.soort = 'eigen_sticker' AND p.status = 'wacht_op_moment'
|
|
26599
|
+
AND EXISTS (SELECT 1 FROM public.pick_queue q
|
|
26600
|
+
WHERE q.cancelled_at IS NULL AND q.print_job_id IS NOT NULL
|
|
26601
|
+
AND (q.payload->>'orderId' = p.order_id::text OR q.payload->'orderIds' ? p.order_id::text))
|
|
28694
26602
|
)
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
26603
|
+
UPDATE public.logistics_sticker_prints p
|
|
26604
|
+
SET status = 'klaar', cart_id = vrij.kar, print_plek_id = vrij.plek,
|
|
26605
|
+
breedte_mm = coalesce(vrij.width_mm, (vrij.lay->>'breedte_mm')::numeric),
|
|
26606
|
+
hoogte_mm = coalesce(vrij.height_mm, (vrij.lay->>'hoogte_mm')::numeric),
|
|
26607
|
+
updated_at = now()
|
|
26608
|
+
FROM vrij
|
|
26609
|
+
WHERE p.id = vrij.id;
|
|
26610
|
+
GET DIAGNOSTICS v_vrij = ROW_COUNT;
|
|
28699
26611
|
|
|
28700
|
-
RETURN
|
|
26612
|
+
RETURN jsonb_build_object('regels', v_bijgewerkt, 'vrijgegeven', v_vrij, 'niet_printen', v_uit);
|
|
28701
26613
|
END;
|
|
28702
26614
|
$function$;
|
|
28703
26615
|
|
|
26616
|
+
-- 6. Pakbon van het pickstation: alleen de centrale beslisregel (geen layout uit payload of werkwijze).
|
|
28704
26617
|
REVOKE EXECUTE ON FUNCTION public.logistics_own_sticker_sync(integer) FROM PUBLIC, anon, authenticated;
|
|
28705
26618
|
GRANT EXECUTE ON FUNCTION public.logistics_own_sticker_sync(integer) TO service_role;
|
|
28706
26619
|
REVOKE EXECUTE ON FUNCTION public.logistics_document_for_order(uuid, text) FROM PUBLIC, anon;
|
|
@@ -29468,243 +27381,76 @@ BEGIN
|
|
|
29468
27381
|
v_soort := v_ship->>'documenttype';
|
|
29469
27382
|
v_extra := jsonb_build_object('verzenddocument_bepaald', v_soort,
|
|
29470
27383
|
'fulfillment_order_id', v_ship->>'fulfillment_order_id');
|
|
29471
|
-
ELSE
|
|
29472
|
-
v_soort := 'afleverbrief';
|
|
29473
|
-
v_extra := jsonb_build_object('verzenddocument_bepaald', 'afleverbrief');
|
|
29474
|
-
END IF;
|
|
29475
|
-
END IF;
|
|
29476
|
-
|
|
29477
|
-
IF to_regprocedure('public.layout_voor_document(uuid,text)') IS NOT NULL THEN
|
|
29478
|
-
EXECUTE 'SELECT to_jsonb(public.layout_voor_document($1, $2))' INTO v_res USING p_order_id, v_soort;
|
|
29479
|
-
IF jsonb_typeof(v_res) IS DISTINCT FROM 'object' THEN
|
|
29480
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'layouts',
|
|
29481
|
-
'reden', 'Layouts gaf geen bruikbaar antwoord voor ' || v_soort || '.') || v_extra;
|
|
29482
|
-
END IF;
|
|
29483
|
-
RETURN v_res || jsonb_build_object('keuze', 'layouts',
|
|
29484
|
-
'ok', coalesce((v_res->>'ok')::boolean, nullif(v_res->>'layout_id', '') IS NOT NULL)) || v_extra;
|
|
29485
|
-
END IF;
|
|
29486
|
-
SELECT o.order_source = 'floriday' INTO v_floriday FROM public.orders o WHERE o.id = p_order_id;
|
|
29487
|
-
IF v_floriday IS NULL THEN
|
|
29488
|
-
SELECT EXISTS (SELECT 1 FROM public.orders WHERE id = p_order_id) INTO v_floriday;
|
|
29489
|
-
IF NOT v_floriday THEN
|
|
29490
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch', 'reden', 'Order niet gevonden.');
|
|
29491
|
-
END IF;
|
|
29492
|
-
v_floriday := false;
|
|
29493
|
-
END IF;
|
|
29494
|
-
v_type := CASE
|
|
29495
|
-
WHEN v_soort IN ('eigen_sticker', 'sticker', 'etiket') THEN 'sticker'
|
|
29496
|
-
WHEN v_soort IN ('verzenddocument', 'verzendbrief', 'afleverbrief', 'afleverbon') THEN 'afleverbrief'
|
|
29497
|
-
WHEN v_soort IN ('veilingbrief', 'veilingbon') THEN 'veilingbrief'
|
|
29498
|
-
WHEN v_soort LIKE '%pakbon%' THEN 'pakbon'
|
|
29499
|
-
WHEN v_soort LIKE '%productie%' THEN 'productiebon'
|
|
29500
|
-
ELSE v_soort END;
|
|
29501
|
-
v_bron := CASE
|
|
29502
|
-
WHEN v_floriday AND v_soort <> 'eigen_sticker' AND v_type IN ('sticker', 'traysticker', 'afleverbrief', 'veilingbrief') THEN 'floriday'
|
|
29503
|
-
ELSE 'eigen' END;
|
|
29504
|
-
IF v_bron = 'eigen' AND v_type = 'veilingbrief' THEN
|
|
29505
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch',
|
|
29506
|
-
'reden', 'Een veilingbrief hoort alleen bij een Floriday-order; voor een eigen order wordt de afleverbrief gebruikt.');
|
|
29507
|
-
END IF;
|
|
29508
|
-
SELECT count(*), count(*) FILTER (WHERE is_standaard IS TRUE) INTO v_n, v_std
|
|
29509
|
-
FROM public.document_layouts
|
|
29510
|
-
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type;
|
|
29511
|
-
IF v_n >= 1 THEN
|
|
29512
|
-
SELECT * INTO v_l FROM public.document_layouts
|
|
29513
|
-
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type
|
|
29514
|
-
ORDER BY is_standaard DESC NULLS LAST, updated_at DESC LIMIT 1;
|
|
29515
|
-
END IF;
|
|
29516
|
-
IF v_l.id IS NULL THEN
|
|
29517
|
-
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch', 'bron', v_bron, 'documenttype', v_type,
|
|
29518
|
-
'reden', CASE WHEN v_bron = 'floriday'
|
|
29519
|
-
THEN 'Geen actieve ' || v_type || '-layout met bron Floriday. Activeer de Floriday-systeemlayout in Layouts en printers.'
|
|
29520
|
-
ELSE 'Maak of activeer een ' || v_type || 'layout in Layouts en printers.' END) || v_extra;
|
|
29521
|
-
END IF;
|
|
29522
|
-
RETURN jsonb_build_object('ok', true, 'layout_id', v_l.id, 'keuze', 'automatisch', 'bron', v_bron,
|
|
29523
|
-
'documenttype', v_type, 'breedte_mm', v_l.breedte_mm, 'hoogte_mm', v_l.hoogte_mm, 'reden', NULL) || v_extra;
|
|
29524
|
-
END;
|
|
29525
|
-
$function$;
|
|
29526
|
-
|
|
29527
|
-
|
|
29528
|
-
-- ===== 1.0.178: fusten en land per kar, eigen traystickers =====
|
|
29529
|
-
-- 1.0.178 A: fusten en land per kar in control_get_todays_carts (achteraan toegevoegd)
|
|
29530
|
-
DO $m$ BEGIN
|
|
29531
|
-
IF pg_get_function_result('public.control_get_todays_carts()'::regprocedure) NOT LIKE '%crates_on_cart%' THEN
|
|
29532
|
-
DROP FUNCTION public.control_get_todays_carts();
|
|
29533
|
-
END IF;
|
|
29534
|
-
END $m$;
|
|
29535
|
-
|
|
29536
|
-
CREATE OR REPLACE FUNCTION public.control_get_todays_carts()
|
|
29537
|
-
RETURNS TABLE(cart_number_id uuid, cart_number text, order_source text, order_id text, cart_index integer, order_number text, pick_date date, status text, printed_at timestamp with time zone, printed_today boolean, crates_on_cart integer, country_code text)
|
|
29538
|
-
LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
29539
|
-
AS $function$
|
|
29540
|
-
WITH vandaag AS (
|
|
29541
|
-
SELECT (now() AT TIME ZONE public.logistics_tz())::date AS d
|
|
29542
|
-
),
|
|
29543
|
-
idx AS (
|
|
29544
|
-
SELECT DISTINCT ON (i.cart_id) i.*
|
|
29545
|
-
FROM public.logistics_cart_index((SELECT d FROM vandaag), (SELECT d FROM vandaag)) i
|
|
29546
|
-
ORDER BY i.cart_id, i.order_number
|
|
29547
|
-
),
|
|
29548
|
-
gecontroleerd AS (
|
|
29549
|
-
SELECT cci.cart_number_id, cci.order_source, cci.order_id, cci.cart_index
|
|
29550
|
-
FROM public.cart_control_items cci
|
|
29551
|
-
JOIN public.cart_control_sessions ccs ON ccs.id = cci.session_id
|
|
29552
|
-
WHERE ccs.control_date = (SELECT d FROM vandaag)
|
|
29553
|
-
AND cci.action = 'checked'
|
|
29554
|
-
)
|
|
29555
|
-
SELECT
|
|
29556
|
-
i.cart_id,
|
|
29557
|
-
COALESCE(cn.cart_number, i.cart_label),
|
|
29558
|
-
i.order_source,
|
|
29559
|
-
i.order_uuid::text,
|
|
29560
|
-
i.cart_index,
|
|
29561
|
-
i.order_number,
|
|
29562
|
-
i.pick_date,
|
|
29563
|
-
COALESCE(cn.status, 'pending'),
|
|
29564
|
-
i.printed_at,
|
|
29565
|
-
(i.printed_at >= (SELECT d FROM vandaag)::timestamptz),
|
|
29566
|
-
(SELECT sum(ci.crates)::int FROM public.order_cart_items ci WHERE ci.cart_id = i.cart_id),
|
|
29567
|
-
(SELECT CASE WHEN upper(btrim(l.country)) ~ '^[A-Z]{2}$' THEN upper(btrim(l.country)) END
|
|
29568
|
-
FROM public.orders o
|
|
29569
|
-
JOIN public.customer_delivery_locations l
|
|
29570
|
-
ON l.id = public.logistics_try_uuid(o.custom_fields->>'delivery_location')
|
|
29571
|
-
WHERE o.id = i.order_uuid
|
|
29572
|
-
LIMIT 1)
|
|
29573
|
-
FROM idx i
|
|
29574
|
-
LEFT JOIN public.cart_numbers cn
|
|
29575
|
-
ON cn.order_source = i.order_source
|
|
29576
|
-
AND cn.order_id = i.order_uuid::text
|
|
29577
|
-
AND cn.cart_index = i.cart_index
|
|
29578
|
-
LEFT JOIN gecontroleerd g1 ON g1.cart_number_id = i.cart_id
|
|
29579
|
-
LEFT JOIN gecontroleerd g2
|
|
29580
|
-
ON g2.order_source = i.order_source
|
|
29581
|
-
AND g2.order_id = i.order_uuid::text
|
|
29582
|
-
AND g2.cart_index = i.cart_index
|
|
29583
|
-
WHERE COALESCE(cn.status, 'pending') <> 'delivered'
|
|
29584
|
-
AND g1.cart_number_id IS NULL
|
|
29585
|
-
AND g2.order_id IS NULL
|
|
29586
|
-
ORDER BY i.order_number, i.cart_index;
|
|
29587
|
-
$function$;
|
|
29588
|
-
REVOKE ALL ON FUNCTION public.control_get_todays_carts() FROM PUBLIC, anon;
|
|
29589
|
-
GRANT EXECUTE ON FUNCTION public.control_get_todays_carts() TO authenticated, service_role;
|
|
29590
|
-
|
|
29591
|
-
-- 1.0.178 B: eigen traystickers
|
|
29592
|
-
ALTER TABLE public.logistics_sticker_prints DROP CONSTRAINT IF EXISTS logistics_sticker_prints_soort_check;
|
|
29593
|
-
ALTER TABLE public.logistics_sticker_prints ADD CONSTRAINT logistics_sticker_prints_soort_check
|
|
29594
|
-
CHECK (soort = ANY (ARRAY['sticker','traysticker','eigen_sticker','eigen_traysticker']));
|
|
29595
|
-
|
|
29596
|
-
CREATE OR REPLACE FUNCTION public.logistics_own_traysticker_sync(p_limit integer DEFAULT 200)
|
|
29597
|
-
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
29598
|
-
AS $function$
|
|
29599
|
-
DECLARE
|
|
29600
|
-
s jsonb; v_tray text; v_rel text; v_station text;
|
|
29601
|
-
r record; v_bron text; v_keep text[] := '{}'; n int := 0; n_geblokkeerd int := 0; n_vrij int := 0; n_uit int := 0;
|
|
29602
|
-
BEGIN
|
|
29603
|
-
SELECT settings INTO s FROM public.logistics_rule_configs
|
|
29604
|
-
ORDER BY is_active DESC, (status = 'actief') DESC, updated_at DESC LIMIT 1;
|
|
29605
|
-
v_tray := public.logistics_rule_text(s, 'pickstations', 'traysticker_release', 'uit');
|
|
29606
|
-
IF v_tray = 'uit' THEN
|
|
29607
|
-
RETURN jsonb_build_object('trayRelease', v_tray, 'regels', 0);
|
|
27384
|
+
ELSE
|
|
27385
|
+
v_soort := 'afleverbrief';
|
|
27386
|
+
v_extra := jsonb_build_object('verzenddocument_bepaald', 'afleverbrief');
|
|
27387
|
+
END IF;
|
|
29608
27388
|
END IF;
|
|
29609
|
-
v_rel := public.logistics_rule_text(s, 'pickstations', 'sticker_release', 'with_pick_release');
|
|
29610
|
-
v_station := CASE WHEN v_rel = 'with_packing_slip'
|
|
29611
|
-
THEN public.logistics_rule_text(s, 'pickstations', 'packing_slip_station', '')
|
|
29612
|
-
ELSE public.logistics_rule_text(s, 'pickstations', 'sticker_station', '') END;
|
|
29613
27389
|
|
|
29614
|
-
|
|
29615
|
-
SELECT
|
|
29616
|
-
|
|
29617
|
-
|
|
29618
|
-
|
|
29619
|
-
JOIN public.order_items oi ON oi.order_id = o.id
|
|
29620
|
-
JOIN public.order_cart_items ci ON ci.order_item_id = oi.id
|
|
29621
|
-
WHERE coalesce(o.order_source, '') <> 'floriday'
|
|
29622
|
-
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
29623
|
-
AND coalesce(o.status, '') <> 'geannuleerd'
|
|
29624
|
-
AND oi.quarantined_at IS NULL
|
|
29625
|
-
AND o.delivery_date >= current_date - 1
|
|
29626
|
-
GROUP BY o.id, o.order_number, ci.cart_id
|
|
29627
|
-
LIMIT greatest(1, p_limit)
|
|
29628
|
-
LOOP
|
|
29629
|
-
IF r.zonder_indeling OR r.lagen IS NULL THEN
|
|
29630
|
-
v_bron := r.order_id::text || ':' || r.cart_id::text || ':geen-indeling';
|
|
29631
|
-
v_keep := v_keep || v_bron;
|
|
29632
|
-
INSERT INTO public.logistics_sticker_prints (soort, bron_id, order_id, order_number, cart_id, kopieen, status, reden)
|
|
29633
|
-
VALUES ('eigen_traysticker', v_bron, r.order_id, r.order_number, r.cart_id, 1, 'geblokkeerd',
|
|
29634
|
-
'Trayindeling ontbreekt voor deze kar: niet elke orderregel heeft een tray (laag). Deel de kar opnieuw in; de rest van de order gaat door.')
|
|
29635
|
-
ON CONFLICT DO NOTHING;
|
|
29636
|
-
n_geblokkeerd := n_geblokkeerd + 1;
|
|
29637
|
-
CONTINUE;
|
|
27390
|
+
IF to_regprocedure('public.layout_voor_document(uuid,text)') IS NOT NULL THEN
|
|
27391
|
+
EXECUTE 'SELECT to_jsonb(public.layout_voor_document($1, $2))' INTO v_res USING p_order_id, v_soort;
|
|
27392
|
+
IF jsonb_typeof(v_res) IS DISTINCT FROM 'object' THEN
|
|
27393
|
+
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'layouts',
|
|
27394
|
+
'reden', 'Layouts gaf geen bruikbaar antwoord voor ' || v_soort || '.') || v_extra;
|
|
29638
27395
|
END IF;
|
|
29639
|
-
|
|
29640
|
-
|
|
29641
|
-
|
|
29642
|
-
|
|
29643
|
-
|
|
29644
|
-
|
|
29645
|
-
|
|
29646
|
-
|
|
29647
|
-
END
|
|
29648
|
-
|
|
27396
|
+
RETURN v_res || jsonb_build_object('keuze', 'layouts',
|
|
27397
|
+
'ok', coalesce((v_res->>'ok')::boolean, nullif(v_res->>'layout_id', '') IS NOT NULL)) || v_extra;
|
|
27398
|
+
END IF;
|
|
27399
|
+
SELECT o.order_source = 'floriday' INTO v_floriday FROM public.orders o WHERE o.id = p_order_id;
|
|
27400
|
+
IF v_floriday IS NULL THEN
|
|
27401
|
+
SELECT EXISTS (SELECT 1 FROM public.orders WHERE id = p_order_id) INTO v_floriday;
|
|
27402
|
+
IF NOT v_floriday THEN
|
|
27403
|
+
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch', 'reden', 'Order niet gevonden.');
|
|
27404
|
+
END IF;
|
|
27405
|
+
v_floriday := false;
|
|
27406
|
+
END IF;
|
|
27407
|
+
v_type := CASE
|
|
27408
|
+
WHEN v_soort IN ('eigen_sticker', 'sticker', 'etiket') THEN 'sticker'
|
|
27409
|
+
WHEN v_soort IN ('verzenddocument', 'verzendbrief', 'afleverbrief', 'afleverbon') THEN 'afleverbrief'
|
|
27410
|
+
WHEN v_soort IN ('veilingbrief', 'veilingbon') THEN 'veilingbrief'
|
|
27411
|
+
WHEN v_soort LIKE '%pakbon%' THEN 'pakbon'
|
|
27412
|
+
WHEN v_soort LIKE '%productie%' THEN 'productiebon'
|
|
27413
|
+
ELSE v_soort END;
|
|
27414
|
+
v_bron := CASE
|
|
27415
|
+
WHEN v_floriday AND v_soort <> 'eigen_sticker' AND v_type IN ('sticker', 'traysticker', 'afleverbrief', 'veilingbrief') THEN 'floriday'
|
|
27416
|
+
ELSE 'eigen' END;
|
|
27417
|
+
IF v_bron = 'eigen' AND v_type = 'veilingbrief' THEN
|
|
27418
|
+
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch',
|
|
27419
|
+
'reden', 'Een veilingbrief hoort alleen bij een Floriday-order; voor een eigen order wordt de afleverbrief gebruikt.');
|
|
27420
|
+
END IF;
|
|
27421
|
+
SELECT count(*), count(*) FILTER (WHERE is_standaard IS TRUE) INTO v_n, v_std
|
|
27422
|
+
FROM public.document_layouts
|
|
27423
|
+
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type;
|
|
27424
|
+
IF v_n >= 1 THEN
|
|
27425
|
+
SELECT * INTO v_l FROM public.document_layouts
|
|
27426
|
+
WHERE actief IS TRUE AND coalesce(bron, 'eigen') = v_bron AND documenttype::text = v_type
|
|
27427
|
+
ORDER BY is_standaard DESC NULLS LAST, updated_at DESC LIMIT 1;
|
|
27428
|
+
END IF;
|
|
27429
|
+
IF v_l.id IS NULL THEN
|
|
27430
|
+
RETURN jsonb_build_object('ok', false, 'layout_id', NULL, 'keuze', 'automatisch', 'bron', v_bron, 'documenttype', v_type,
|
|
27431
|
+
'reden', CASE WHEN v_bron = 'floriday'
|
|
27432
|
+
THEN 'Geen actieve ' || v_type || '-layout met bron Floriday. Activeer de Floriday-systeemlayout in Layouts en printers.'
|
|
27433
|
+
ELSE 'Maak of activeer een ' || v_type || 'layout in Layouts en printers.' END) || v_extra;
|
|
27434
|
+
END IF;
|
|
27435
|
+
RETURN jsonb_build_object('ok', true, 'layout_id', v_l.id, 'keuze', 'automatisch', 'bron', v_bron,
|
|
27436
|
+
'documenttype', v_type, 'breedte_mm', v_l.breedte_mm, 'hoogte_mm', v_l.hoogte_mm, 'reden', NULL) || v_extra;
|
|
27437
|
+
END;
|
|
27438
|
+
$function$;
|
|
29649
27439
|
|
|
29650
|
-
-- Indeling hersteld of tray vervallen: niet meer printen (alleen nog niet geprinte rijen).
|
|
29651
|
-
UPDATE public.logistics_sticker_prints p
|
|
29652
|
-
SET status = 'niet_printen', reden = 'Tray hoort niet meer bij deze kar of order vervallen.', updated_at = now()
|
|
29653
|
-
WHERE p.soort = 'eigen_traysticker' AND p.status IN ('wacht_op_moment', 'geblokkeerd', 'klaar')
|
|
29654
|
-
AND NOT (p.bron_id = ANY (v_keep))
|
|
29655
|
-
AND p.order_id IN (SELECT o.id FROM public.orders o WHERE o.delivery_date >= current_date - 1);
|
|
29656
|
-
GET DIAGNOSTICS n_uit = ROW_COUNT;
|
|
29657
27440
|
|
|
29658
|
-
|
|
29659
|
-
|
|
29660
|
-
|
|
29661
|
-
|
|
29662
|
-
|
|
29663
|
-
|
|
29664
|
-
|
|
29665
|
-
GET DIAGNOSTICS n_vrij = ROW_COUNT;
|
|
27441
|
+
-- ===== 1.0.178: fusten en land per kar, eigen traystickers =====
|
|
27442
|
+
-- 1.0.178 A: fusten en land per kar in control_get_todays_carts (achteraan toegevoegd)
|
|
27443
|
+
DO $m$ BEGIN
|
|
27444
|
+
IF pg_get_function_result('public.control_get_todays_carts()'::regprocedure) NOT LIKE '%crates_on_cart%' THEN
|
|
27445
|
+
DROP FUNCTION public.control_get_todays_carts();
|
|
27446
|
+
END IF;
|
|
27447
|
+
END $m$;
|
|
29666
27448
|
|
|
29667
|
-
|
|
29668
|
-
|
|
29669
|
-
|
|
29670
|
-
|
|
27449
|
+
-- 1.0.178 B: eigen traystickers
|
|
27450
|
+
ALTER TABLE public.logistics_sticker_prints DROP CONSTRAINT IF EXISTS logistics_sticker_prints_soort_check;
|
|
27451
|
+
ALTER TABLE public.logistics_sticker_prints ADD CONSTRAINT logistics_sticker_prints_soort_check
|
|
27452
|
+
CHECK (soort = ANY (ARRAY['sticker','traysticker','eigen_sticker','eigen_traysticker']));
|
|
29671
27453
|
|
|
29672
|
-
CREATE OR REPLACE FUNCTION public.logistics_own_traysticker_payload(p_id uuid)
|
|
29673
|
-
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
29674
|
-
AS $function$
|
|
29675
|
-
DECLARE p record; o record; v_laag int; v_nr int; v_tot int; v_loc text; v_prod jsonb;
|
|
29676
|
-
BEGIN
|
|
29677
|
-
SELECT * INTO p FROM public.logistics_sticker_prints WHERE id = p_id AND soort = 'eigen_traysticker';
|
|
29678
|
-
IF p.id IS NULL THEN RETURN jsonb_build_object('ok', false, 'reden', 'Traysticker niet gevonden.'); END IF;
|
|
29679
|
-
v_laag := nullif(split_part(p.bron_id, ':', 3), '')::int;
|
|
29680
|
-
SELECT * INTO o FROM public.orders WHERE id = p.order_id;
|
|
29681
|
-
SELECT count(DISTINCT ci.layer_index),
|
|
29682
|
-
count(DISTINCT ci.layer_index) FILTER (WHERE ci.layer_index <= v_laag)
|
|
29683
|
-
INTO v_tot, v_nr
|
|
29684
|
-
FROM public.order_cart_items ci JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
29685
|
-
WHERE oi.order_id = p.order_id AND ci.cart_id = p.cart_id AND ci.layer_index IS NOT NULL;
|
|
29686
|
-
SELECT coalesce(jsonb_agg(jsonb_build_object(
|
|
29687
|
-
'artikelnummer', prd.article_number,
|
|
29688
|
-
'naam', coalesce(ci.product_name, oi.product_name),
|
|
29689
|
-
'aantal', coalesce(ci.crates_in_layer, ci.crates)) ORDER BY coalesce(ci.product_name, oi.product_name)), '[]'::jsonb)
|
|
29690
|
-
INTO v_prod
|
|
29691
|
-
FROM public.order_cart_items ci JOIN public.order_items oi ON oi.id = ci.order_item_id
|
|
29692
|
-
LEFT JOIN public.products prd ON prd.id = coalesce(ci.product_id, oi.product_id)
|
|
29693
|
-
WHERE oi.order_id = p.order_id AND ci.cart_id = p.cart_id AND ci.layer_index = v_laag;
|
|
29694
|
-
SELECT nullif(btrim(concat_ws(', ', nullif(btrim(l.name), ''), nullif(btrim(l.city), ''), nullif(btrim(l.country), ''))), '')
|
|
29695
|
-
INTO v_loc
|
|
29696
|
-
FROM public.customer_delivery_locations l
|
|
29697
|
-
WHERE l.id = public.logistics_try_uuid(o.custom_fields->>'delivery_location');
|
|
29698
|
-
IF v_tot IS NULL OR v_tot = 0 OR jsonb_array_length(v_prod) = 0 THEN
|
|
29699
|
-
RETURN jsonb_build_object('ok', false, 'reden', 'Trayindeling ontbreekt voor deze tray. Deel de kar opnieuw in.');
|
|
29700
|
-
END IF;
|
|
29701
|
-
RETURN jsonb_build_object('ok', true, 'payload', jsonb_build_object(
|
|
29702
|
-
'order_id', o.id, 'order_number', o.order_number, 'ordernummer', o.order_number,
|
|
29703
|
-
'klantnaam', o.customer_name, 'leverdatum', o.delivery_date, 'afleverlocatie', v_loc,
|
|
29704
|
-
'cart_id', p.cart_id, 'tray_nummer', v_nr, 'tray_totaal', v_tot, 'tray_producten', v_prod));
|
|
29705
|
-
END; $function$;
|
|
29706
|
-
REVOKE ALL ON FUNCTION public.logistics_own_traysticker_payload(uuid) FROM PUBLIC, anon, authenticated;
|
|
29707
|
-
GRANT EXECUTE ON FUNCTION public.logistics_own_traysticker_payload(uuid) TO service_role;
|
|
29708
27454
|
-- ===== 1.0.178 correctie: eigen traysticker per fust =====
|
|
29709
27455
|
-- 1.0.178 correctie: eigen traysticker per FUST (niet per laag).
|
|
29710
27456
|
-- Sleutel: order:kar:karregel:fustnummer. Crates onbekend: één geblokkeerde rij per karregel.
|
|
@@ -29719,79 +27465,6 @@ RETURNS integer LANGUAGE sql IMMUTABLE SET search_path = public AS $tp$
|
|
|
29719
27465
|
END
|
|
29720
27466
|
$tp$;
|
|
29721
27467
|
|
|
29722
|
-
CREATE OR REPLACE FUNCTION public.logistics_own_traysticker_sync(p_limit integer DEFAULT 200)
|
|
29723
|
-
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
29724
|
-
AS $function$
|
|
29725
|
-
DECLARE
|
|
29726
|
-
s jsonb; v_tray text; v_rel text; v_station text;
|
|
29727
|
-
r record; v_bron text; v_keep text[] := '{}'; n int := 0; n_geblokkeerd int := 0; n_vrij int := 0; n_uit int := 0;
|
|
29728
|
-
BEGIN
|
|
29729
|
-
SELECT settings INTO s FROM public.logistics_rule_configs
|
|
29730
|
-
ORDER BY is_active DESC, (status = 'actief') DESC, updated_at DESC LIMIT 1;
|
|
29731
|
-
v_tray := public.logistics_rule_text(s, 'pickstations', 'traysticker_release', 'uit');
|
|
29732
|
-
IF v_tray = 'uit' THEN
|
|
29733
|
-
RETURN jsonb_build_object('trayRelease', v_tray, 'regels', 0);
|
|
29734
|
-
END IF;
|
|
29735
|
-
v_rel := public.logistics_rule_text(s, 'pickstations', 'sticker_release', 'with_pick_release');
|
|
29736
|
-
v_station := CASE WHEN v_rel = 'with_packing_slip'
|
|
29737
|
-
THEN public.logistics_rule_text(s, 'pickstations', 'packing_slip_station', '')
|
|
29738
|
-
ELSE public.logistics_rule_text(s, 'pickstations', 'sticker_station', '') END;
|
|
29739
|
-
|
|
29740
|
-
FOR r IN
|
|
29741
|
-
SELECT o.id AS order_id, o.order_number, ci.cart_id, ci.id AS ci_id, ci.crates
|
|
29742
|
-
FROM public.orders o
|
|
29743
|
-
JOIN public.order_items oi ON oi.order_id = o.id
|
|
29744
|
-
JOIN public.order_cart_items ci ON ci.order_item_id = oi.id
|
|
29745
|
-
WHERE coalesce(o.order_source, '') <> 'floriday'
|
|
29746
|
-
AND o.deleted_at IS NULL AND o.cancelled_at IS NULL
|
|
29747
|
-
AND coalesce(o.status, '') <> 'geannuleerd'
|
|
29748
|
-
AND oi.quarantined_at IS NULL
|
|
29749
|
-
AND o.delivery_date >= current_date - 1
|
|
29750
|
-
ORDER BY o.order_number, ci.cart_id, ci.created_at, ci.id
|
|
29751
|
-
LIMIT greatest(1, p_limit)
|
|
29752
|
-
LOOP
|
|
29753
|
-
IF r.crates IS NULL OR r.crates <= 0 THEN
|
|
29754
|
-
v_bron := r.order_id::text || ':' || r.cart_id::text || ':' || r.ci_id::text || ':onbekend';
|
|
29755
|
-
v_keep := v_keep || v_bron;
|
|
29756
|
-
INSERT INTO public.logistics_sticker_prints (soort, bron_id, order_id, order_number, cart_id, kopieen, status, reden)
|
|
29757
|
-
VALUES ('eigen_traysticker', v_bron, r.order_id, r.order_number, r.cart_id, 1, 'geblokkeerd',
|
|
29758
|
-
'Aantal fusten onbekend voor deze regel op de kar. De rest van de order gaat door.')
|
|
29759
|
-
ON CONFLICT DO NOTHING;
|
|
29760
|
-
n_geblokkeerd := n_geblokkeerd + 1;
|
|
29761
|
-
CONTINUE;
|
|
29762
|
-
END IF;
|
|
29763
|
-
FOR k IN 1 .. r.crates LOOP
|
|
29764
|
-
v_bron := r.order_id::text || ':' || r.cart_id::text || ':' || r.ci_id::text || ':' || k::text;
|
|
29765
|
-
v_keep := v_keep || v_bron;
|
|
29766
|
-
INSERT INTO public.logistics_sticker_prints (soort, bron_id, order_id, order_number, cart_id, kopieen, print_plek_id, status, reden)
|
|
29767
|
-
VALUES ('eigen_traysticker', v_bron, r.order_id, r.order_number, r.cart_id, 1,
|
|
29768
|
-
public.logistics_sticker_cart_plek(r.cart_id, v_station), 'wacht_op_moment', 'Wacht op de pakbon van deze kar.')
|
|
29769
|
-
ON CONFLICT DO NOTHING;
|
|
29770
|
-
n := n + 1;
|
|
29771
|
-
END LOOP;
|
|
29772
|
-
END LOOP;
|
|
29773
|
-
|
|
29774
|
-
-- Oude laagsleutels, vervallen fusten of orders: niet meer printen (alleen nog niet geprinte rijen, geen DELETE).
|
|
29775
|
-
UPDATE public.logistics_sticker_prints p
|
|
29776
|
-
SET status = 'niet_printen', reden = 'Fust hoort niet meer bij deze kar of order vervallen.', updated_at = now()
|
|
29777
|
-
WHERE p.soort = 'eigen_traysticker' AND p.status IN ('wacht_op_moment', 'geblokkeerd', 'klaar')
|
|
29778
|
-
AND NOT (p.bron_id = ANY (v_keep))
|
|
29779
|
-
AND p.order_id IN (SELECT o.id FROM public.orders o WHERE o.delivery_date >= current_date - 1);
|
|
29780
|
-
GET DIAGNOSTICS n_uit = ROW_COUNT;
|
|
29781
|
-
|
|
29782
|
-
UPDATE public.logistics_sticker_prints p
|
|
29783
|
-
SET status = 'klaar', reden = NULL,
|
|
29784
|
-
print_plek_id = coalesce(p.print_plek_id, public.logistics_sticker_cart_plek(p.cart_id, v_station)),
|
|
29785
|
-
updated_at = now()
|
|
29786
|
-
WHERE p.soort = 'eigen_traysticker' AND p.status = 'wacht_op_moment'
|
|
29787
|
-
AND p.cart_id IS NOT NULL AND public.logistics_cart_slip_queued(p.cart_id);
|
|
29788
|
-
GET DIAGNOSTICS n_vrij = ROW_COUNT;
|
|
29789
|
-
|
|
29790
|
-
RETURN jsonb_build_object('trayRelease', v_tray, 'fusten', n, 'geblokkeerd', n_geblokkeerd, 'vrijgegeven', n_vrij, 'niet_printen', n_uit);
|
|
29791
|
-
END; $function$;
|
|
29792
|
-
REVOKE ALL ON FUNCTION public.logistics_own_traysticker_sync(integer) FROM PUBLIC, anon, authenticated;
|
|
29793
|
-
GRANT EXECUTE ON FUNCTION public.logistics_own_traysticker_sync(integer) TO service_role;
|
|
29794
|
-
|
|
29795
27468
|
CREATE OR REPLACE FUNCTION public.logistics_own_traysticker_payload(p_id uuid)
|
|
29796
27469
|
RETURNS jsonb LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO 'public'
|
|
29797
27470
|
AS $function$
|
|
@@ -31388,30 +29061,6 @@ BEGIN
|
|
|
31388
29061
|
END $function$;
|
|
31389
29062
|
|
|
31390
29063
|
-- Handmatig kiezen: de enige manier. NULL = terug naar automatisch. Verstuurt nooit een mail.
|
|
31391
|
-
CREATE OR REPLACE FUNCTION public.logistics_set_order_carrier(p_order_id uuid, p_carrier_id uuid)
|
|
31392
|
-
RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public'
|
|
31393
|
-
AS $function$
|
|
31394
|
-
DECLARE v_uid uuid := auth.uid(); o jsonb; v_skip text; r jsonb;
|
|
31395
|
-
BEGIN
|
|
31396
|
-
IF v_uid IS NULL AND coalesce(auth.role(), '') <> 'service_role' THEN RAISE EXCEPTION 'Niet ingelogd'; END IF;
|
|
31397
|
-
SELECT to_jsonb(x) INTO o FROM public.orders x WHERE x.id = p_order_id AND x.deleted_at IS NULL FOR UPDATE;
|
|
31398
|
-
IF o IS NULL THEN RAISE EXCEPTION 'Order niet gevonden.'; END IF;
|
|
31399
|
-
IF p_carrier_id IS NOT NULL THEN
|
|
31400
|
-
v_skip := public.logistics_carrier_skip_reason(p_carrier_id);
|
|
31401
|
-
IF v_skip IS NOT NULL THEN RAISE EXCEPTION 'Deze vervoerder kan niet gekozen worden: %.', v_skip; END IF;
|
|
31402
|
-
r := public.logistics_carrier_result(p_carrier_id, 'handmatig', 'Handmatig gekozen op de order.', '{}'::text[]);
|
|
31403
|
-
ELSE
|
|
31404
|
-
r := public.logistics_resolve_carrier_core(o, true);
|
|
31405
|
-
END IF;
|
|
31406
|
-
PERFORM set_config('logistics.carrier_writer', 'engine', true);
|
|
31407
|
-
UPDATE public.orders
|
|
31408
|
-
SET carrier_id = public.logistics_try_uuid(r->>'carrier_id'), carrier_source = r->>'bron',
|
|
31409
|
-
carrier_reason = r->>'reden', carrier_resolved_at = now(), carrier_set_by = v_uid, carrier_set_at = now()
|
|
31410
|
-
WHERE id = p_order_id;
|
|
31411
|
-
PERFORM set_config('logistics.carrier_writer', '', true);
|
|
31412
|
-
RETURN r || jsonb_build_object('bevroren', public.logistics_carrier_frozen_reason(p_order_id));
|
|
31413
|
-
END $function$;
|
|
31414
|
-
|
|
31415
29064
|
-- Lijst F: wat de regel per bestaande open order zou opslaan (alleen lezen).
|
|
31416
29065
|
CREATE OR REPLACE FUNCTION public.logistics_carrier_preview_existing(p_limit integer DEFAULT 1000)
|
|
31417
29066
|
RETURNS TABLE(order_id uuid, order_number text, order_source text, delivery_date text, huidig_custom_carrier text,
|
|
@@ -31918,10 +29567,21 @@ AS $function$
|
|
|
31918
29567
|
OR session_user::text <> 'authenticator'
|
|
31919
29568
|
$function$;
|
|
31920
29569
|
|
|
29570
|
+
CREATE OR REPLACE FUNCTION public.logistics_acc_entry()
|
|
29571
|
+
RETURNS text LANGUAGE sql STABLE SET search_path TO 'public'
|
|
29572
|
+
AS $function$
|
|
29573
|
+
SELECT nullif(current_setting('request.path', true), '')
|
|
29574
|
+
$function$;
|
|
29575
|
+
REVOKE ALL ON FUNCTION public.logistics_acc_entry() FROM PUBLIC, anon;
|
|
29576
|
+
GRANT EXECUTE ON FUNCTION public.logistics_acc_entry() TO authenticated, service_role;
|
|
29577
|
+
COMMENT ON FUNCTION public.logistics_acc_entry() IS 'Logistiek Engine: het API-adres van het lopende verzoek (request.path), voor de ketenherkenning.';
|
|
29578
|
+
|
|
31921
29579
|
CREATE OR REPLACE FUNCTION public.logistics_acc_direct(p_fn text)
|
|
31922
29580
|
RETURNS boolean LANGUAGE sql STABLE SET search_path TO 'public'
|
|
31923
29581
|
AS $function$
|
|
31924
|
-
|
|
29582
|
+
-- Rechtstreeks = het API-adres van dit verzoek is deze functie zelf, of onbekend (fail closed).
|
|
29583
|
+
-- Een ander /rpc/-adres: aangeroepen vanuit een functie die de API mocht uitvoeren (keten).
|
|
29584
|
+
SELECT coalesce(lower(public.logistics_acc_entry()) = '/rpc/' || lower(p_fn), true)
|
|
31925
29585
|
$function$;
|
|
31926
29586
|
|
|
31927
29587
|
CREATE OR REPLACE FUNCTION public.logistics_acc_guard(p_level text, p_fn text)
|
|
@@ -32099,4 +29759,60 @@ BEGIN
|
|
|
32099
29759
|
v_def := regexp_replace(v_def, 'END \$function\$\s*$', E' RETURN QUERY SELECT * FROM public.logistics_access_check();\nEND $function$');
|
|
32100
29760
|
EXECUTE v_def;
|
|
32101
29761
|
END IF;
|
|
32102
|
-
END $ic$;
|
|
29762
|
+
END $ic$;
|
|
29763
|
+
|
|
29764
|
+
-- 1.0.186: pickschermlijst verwerkt. Alleen de 16 functies uit tabel C blijven open;
|
|
29765
|
+
-- de rest krijgt het niveau 'ingelogd' met ketenherkenning via request.path.
|
|
29766
|
+
DO $lv$
|
|
29767
|
+
DECLARE v_def text;
|
|
29768
|
+
BEGIN
|
|
29769
|
+
v_def := pg_get_functiondef('public.logistics_acc_levels()'::regprocedure);
|
|
29770
|
+
IF position('wacht op pickschermlijst' IN v_def) > 0 AND position('SELECT * FROM (' IN v_def) > 0 THEN
|
|
29771
|
+
v_def := replace(v_def, 'SELECT * FROM (',
|
|
29772
|
+
'SELECT v.functie, CASE WHEN v.niveau = ''wacht op pickschermlijst'' THEN CASE WHEN v.functie = ANY (ARRAY[''logistics_auto_send_status'',''logistics_barcode_lookup'',''logistics_cart_plan_status'',''logistics_cart_slip_plan'',''logistics_cart_sticker_state'',''logistics_complete_task'',''logistics_document_for_order'',''logistics_is_pick_workday'',''logistics_order_released'',''logistics_order_sticker_meldingen'',''logistics_pick_mode'',''logistics_scan_resolve'',''logistics_shipping_note_from_barcode'',''logistics_shipping_note_status'',''logistics_working_hours_status'',''pick_queue_cart_plan'']) THEN ''open (pickscherm/scanner zonder inlog)'' ELSE ''ingelogd'' END ELSE v.niveau END AS niveau FROM (');
|
|
29773
|
+
v_def := replace(v_def, ') v(functie, niveau)', ') v(functie, niveau)');
|
|
29774
|
+
EXECUTE v_def;
|
|
29775
|
+
END IF;
|
|
29776
|
+
END $lv$;
|
|
29777
|
+
|
|
29778
|
+
DO $acc$
|
|
29779
|
+
DECLARE r record; v_def text; v_new text; v_pos int; v_fail text[] := '{}'::text[]; n int := 0;
|
|
29780
|
+
BEGIN
|
|
29781
|
+
FOR r IN
|
|
29782
|
+
SELECT p.oid, p.proname, l.lanname, p.prosrc, x.lvl
|
|
29783
|
+
FROM public.logistics_acc_levels() x(fn, lvl)
|
|
29784
|
+
JOIN pg_proc p ON p.proname = x.fn AND p.pronamespace = 'public'::regnamespace
|
|
29785
|
+
JOIN pg_language l ON l.oid = p.prolang
|
|
29786
|
+
WHERE x.lvl IN ('server', 'ingelogd', 'beheer')
|
|
29787
|
+
AND p.prorettype <> 'trigger'::regtype AND coalesce(p.prosrc, '') <> ''
|
|
29788
|
+
AND p.prosrc NOT LIKE '%logistics_acc_guard(%'
|
|
29789
|
+
AND (p.proname <> 'pick_enqueue_print_job'
|
|
29790
|
+
OR pg_get_function_identity_arguments(p.oid) IN (
|
|
29791
|
+
'_queue_item_id uuid, _printer_id uuid, _session_id text, _is_herprint boolean',
|
|
29792
|
+
'_queue_item_id uuid, _printer_id uuid, _session_id text, _is_herprint boolean, _cart_id text'))
|
|
29793
|
+
LOOP
|
|
29794
|
+
BEGIN
|
|
29795
|
+
v_def := pg_get_functiondef(r.oid);
|
|
29796
|
+
IF r.lanname = 'plpgsql' THEN
|
|
29797
|
+
v_pos := regexp_instr(r.prosrc, '\mBEGIN\M', 1, 1, 1, 'i');
|
|
29798
|
+
IF v_pos = 0 THEN RAISE EXCEPTION 'geen BEGIN gevonden'; END IF;
|
|
29799
|
+
v_new := left(r.prosrc, v_pos - 1) || E'\n PERFORM public.logistics_acc_guard(' || quote_literal(r.lvl) || ', '
|
|
29800
|
+
|| quote_literal(r.proname) || ');' || substr(r.prosrc, v_pos);
|
|
29801
|
+
ELSIF r.lanname = 'sql' THEN
|
|
29802
|
+
v_new := E'\n SELECT public.logistics_acc_guard(' || quote_literal(r.lvl) || ', ' || quote_literal(r.proname) || ');' || r.prosrc;
|
|
29803
|
+
ELSE
|
|
29804
|
+
RAISE EXCEPTION 'taal % niet ondersteund', r.lanname;
|
|
29805
|
+
END IF;
|
|
29806
|
+
v_pos := position(r.prosrc IN v_def);
|
|
29807
|
+
IF v_pos = 0 THEN RAISE EXCEPTION 'definitie niet te herschrijven'; END IF;
|
|
29808
|
+
v_def := overlay(v_def placing v_new from v_pos for length(r.prosrc));
|
|
29809
|
+
EXECUTE v_def;
|
|
29810
|
+
n := n + 1;
|
|
29811
|
+
EXCEPTION WHEN OTHERS THEN
|
|
29812
|
+
v_fail := v_fail || (r.proname || ': ' || SQLERRM);
|
|
29813
|
+
END;
|
|
29814
|
+
END LOOP;
|
|
29815
|
+
RAISE NOTICE 'pickschermlijst: % functies voorzien; mislukt: %', n, array_to_string(v_fail, ' | ');
|
|
29816
|
+
END $acc$;
|
|
29817
|
+
|
|
29818
|
+
ALTER FUNCTION public.logistics_cart_barcode_value(uuid) SET search_path TO 'public';
|