supersam/docs/sql/order-groups-auto-delivery-...

160 lines
4.4 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Auto-create public delivery links for rows imported into public.order_groups.
-- Run this in Supabase SQL Editor after the order_groups delivery columns exist.
create extension if not exists pgcrypto with schema extensions;
create or replace function public.build_order_group_default_available_slots(
start_from timestamptz default now()
)
returns text[]
language sql
stable
as $$
with candidate_days as (
select day::date as delivery_day
from generate_series(
(start_from at time zone 'Europe/Simferopol')::date + 1,
(start_from at time zone 'Europe/Simferopol')::date + 21,
interval '1 day'
) as day
where extract(isodow from day) between 1 and 5
order by day
limit 5
),
slots as (
select format('%s, %s', delivery_day, half_day) as slot_name
from candidate_days
cross join (
values ('Первая половина дня'), ('Вторая половина дня')
) as halves(half_day)
)
select coalesce(array_agg(slot_name order by slot_name), array[]::text[])
from slots;
$$;
create or replace function public.ensure_order_group_delivery_link()
returns trigger
language plpgsql
security definer
set search_path = public, extensions
as $$
declare
v_customer_name text;
v_customer_phone text;
v_order_number text;
v_token text;
v_token_hash text;
v_delivery_link text;
v_invitation_id uuid;
v_base_url text := 'https://dost.supersamsev.ru';
begin
if pg_trigger_depth() > 1 then
return new;
end if;
if coalesce(new.status, '') <> 'ready_for_notification' then
return new;
end if;
if coalesce(new.delivery_status, 'pending_confirmation') <> 'pending_confirmation' then
return new;
end if;
if coalesce(new.notification_status, 'not_started') not in ('not_started', 'send_failed') then
return new;
end if;
if new.delivery_link is not null or new.delivery_invitation_id is not null then
return new;
end if;
v_customer_name := nullif(
coalesce(new.customer_name, new.customer ->> 'name'),
''
);
v_customer_phone := nullif(
coalesce(
new.customer_phone_normalized,
new.customer_phone,
new.customer ->> 'phone_normalized',
new.customer ->> 'phone',
split_part(new.group_key, '|', 1)
),
''
);
v_order_number := coalesce(new.group_key::text, new.order_numbers[1]::text);
if v_customer_phone is null then
update public.order_groups
set
notification_status = 'manual_required',
last_sms_error = 'Не найден телефон клиента для формирования SMS-ссылки',
next_notification_check_at = null,
updated_at = timezone('utc', now())
where id = new.id;
return new;
end if;
v_token := replace(gen_random_uuid()::text, '-', '') || replace(gen_random_uuid()::text, '-', '');
v_token_hash := encode(digest(v_token, 'sha256'), 'hex');
v_delivery_link := v_base_url || '/delivery/' || v_token;
insert into public.delivery_invitations (
order_id,
order_group_id,
token_hash,
state,
order_number,
customer_name,
customer_phone,
available_slots,
expires_at,
sent_at
)
values (
null,
new.id,
v_token_hash,
'awaiting_choice',
v_order_number,
v_customer_name,
v_customer_phone,
public.build_order_group_default_available_slots(),
timezone('utc', now()) + interval '7 days',
null
)
returning id into v_invitation_id;
update public.order_groups
set
delivery_invitation_id = v_invitation_id,
delivery_link = v_delivery_link,
notification_status = 'link_ready',
last_sms_error = null,
next_notification_check_at = timezone('utc', now()),
updated_at = timezone('utc', now())
where id = new.id;
return new;
end;
$$;
drop trigger if exists order_groups_ensure_delivery_link on public.order_groups;
create trigger order_groups_ensure_delivery_link
after insert or update of status, delivery_status, notification_status, delivery_link, delivery_invitation_id
on public.order_groups
for each row
execute function public.ensure_order_group_delivery_link();
-- Backfill links for already imported groups that are still waiting for SMS.
update public.order_groups
set
notification_status = notification_status,
updated_at = timezone('utc', now())
where status = 'ready_for_notification'
and delivery_status = 'pending_confirmation'
and notification_status in ('not_started', 'send_failed')
and delivery_link is null
and delivery_invitation_id is null;