-- 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.next_order_group_sms_check_at( start_from timestamptz default now(), delay interval default interval '0 minutes' ) returns timestamptz language plpgsql stable as $$ declare v_timezone text := 'Europe/Simferopol'; v_local_time timestamp; v_local_date date; v_work_start timestamp; v_work_end timestamp; v_candidate timestamp; begin v_local_time := (start_from at time zone v_timezone) + delay; v_local_date := v_local_time::date; v_work_start := v_local_date + time '09:00'; v_work_end := v_local_date + time '20:00'; if v_local_time < v_work_start then v_candidate := v_work_start; elsif v_local_time >= v_work_end then v_candidate := (v_local_date + 1) + time '09:00'; else v_candidate := v_local_time; end if; return v_candidate at time zone v_timezone; end; $$; 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 ((start_from at time zone 'Europe/Simferopol')::date + offset_days) as delivery_day from generate_series(1, 2) as offset_days ), 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 = public.next_order_group_sms_check_at(), 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;