12 KiB
Поток n8n для order_groups
Цель
Supabase хранит состояние доставки, генерирует ссылку для клиента и
сохраняет все временные отметки.
n8n отвечает за отправку SMS, повторные попытки и перевод зависших
групп в ручную обработку.
Короткая ссылка с нашей стороны не нужна. Мы храним полную delivery_link,
а сервис SMS сам сокращает ссылку при отправке.
Источник истины
Основная запись находится в public.order_groups.
Важные поля:
status- бизнес-готовность группыdelivery_status- состояние согласования доставки для клиента и логистаdelivery_link- полная публичная ссылка на/delivery/:tokendelivery_invitation_id- связанная запись приглашенияnotification_status- состояние SMS-оркестрации дляn8nsms_attempts- сколько было попыток отправки SMSfirst_sms_sent_at- время первой SMSsecond_sms_sent_at- время второй SMSlast_sms_error- текст последней ошибки провайдераnext_notification_check_at- когдаn8nдолжен вернуться к записиdelivery_dateиdelivery_time- выбранный слот после подтверждения клиентом
Окно отправки SMS
Чтобы не тревожить клиентов ночью, SMS отправляются только в местное окно:
09:00-20:00 Europe/Simferopol
Если запись стала готова к отправке вне этого окна, SMS не отправляется сразу.
Supabase должен поставить ближайшее разрешенное время в
next_notification_check_at:
- до
09:00- сегодня в09:00 - с
09:00до20:00- сразу - после
20:00- завтра в09:00
Для этого в SQL есть helper:
public.next_order_group_sms_check_at(start_from timestamptz, delay interval)
n8n не должен сам решать, можно ли сейчас тревожить клиента. Он просто выбирает
записи, где next_notification_check_at <= now().
Рекомендуемая модель статусов
delivery_status
pending_confirmation- клиент еще не выбрал слотagreed- клиент выбрал слот доставкиmanual_confirmation_required- автоматический поток не сработал, менеджер/логист должен продолжить вручнуюno_contact- менеджер/логист пытался связаться вручную, но связи с клиентом нетassigned_to_driver- доставка согласована и передана в планирование водителюout_for_delivery- водитель уже в работеdelivered- доставка завершенаcancelled- группу больше не нужно обрабатывать
notification_status
not_started- ссылка еще не подготовленаlink_ready-Supabaseсоздалdelivery_link,n8nможет отправлять первую SMSfirst_sms_sent- первая SMS принята провайдеромsecond_sms_sent- отправлено напоминаниеconfirmed- клиент выбрал слотmanual_required- после повторов подтверждения нетsend_failed- ошибка провайдера/API, можно повторить
Ответственность Supabase
1. Подготовка ссылки
Когда order_group попадает в поток согласования доставки:
status = 'ready_for_notification'delivery_status = 'pending_confirmation'
Триггер Supabase order_groups_ensure_delivery_link должен:
- создать запись
delivery_invitationsсorder_group_id - сгенерировать token и полную публичную ссылку
- подготовить слоты только на завтра и послезавтра
- записать
delivery_linkвorder_groups - установить
delivery_invitation_id - установить
notification_status = 'link_ready' - установить
next_notification_check_atчерезpublic.next_order_group_sms_check_at()
SQL для этого триггера лежит здесь:
docs/sql/order-groups-auto-delivery-link.sql
n8n больше не должен вызывать create-delivery-invitation для order_groups.
Ему нужно ждать, пока в строке уже будут
notification_status = 'link_ready' и delivery_link is not null.
2. Прием выбора клиента
Публичная страница использует token.
Когда клиент подтверждает слот, confirm-delivery-choice должен:
- сохранить
delivery_dateиdelivery_time - установить
delivery_status = 'agreed' - установить
notification_status = 'confirmed'
Это становится стоп-сигналом для всех напоминаний в n8n.
Потоки n8n
Поток 1. Отправка первой SMS
Триггер:
- Cron каждые 5-10 минут
- Опционально запасной webhook-триггер, если потом захочешь push-старт
Запрос:
status = 'ready_for_notification'delivery_status = 'pending_confirmation'notification_status = 'link_ready'delivery_link is not nullnext_notification_check_at <= now()
Действие:
- отправить SMS с
delivery_link
При успехе обновить order_groups:
notification_status = 'first_sms_sent'sms_attempts = 1first_sms_sent_at = now()sms_sent_at = now()last_sms_error = nullnext_notification_check_at = public.next_order_group_sms_check_at(now(), interval '3 hours')
Важно: если первая SMS ушла, например, в 18:30, проверка через 3 часа попала бы
на 21:30. Helper перенесет следующую проверку на завтра 09:00.
При ошибке обновить order_groups:
notification_status = 'send_failed'last_sms_error = <ошибка провайдера>next_notification_check_at = public.next_order_group_sms_check_at(now(), interval '10 minutes')
Поток 2. Наблюдатель доставки
Триггер:
- Cron каждые 10 минут
Назначение:
- найти записи, где первый поток не завершился корректно
- повторить неудачные первые отправки
Кандидаты для выбора:
notification_status = 'send_failed'delivery_status = 'pending_confirmation'next_notification_check_at <= now()
Поведение:
- повторить первую SMS
- если успех, перевести в
first_sms_sent - если повторные ошибки превысили выбранный порог, перевести в
manual_required - все новые значения
next_notification_check_atсчитать черезpublic.next_order_group_sms_check_at(...)
Поток 3. Напоминание по SMS
Триггер:
- Cron каждые 10 минут
Запрос:
delivery_status = 'pending_confirmation'notification_status = 'first_sms_sent'next_notification_check_at <= now()
Действие:
- отправить вторую SMS-напоминалку с той же
delivery_link
При успехе обновить:
notification_status = 'second_sms_sent'sms_attempts = 2second_sms_sent_at = now()last_sms_error = nullnext_notification_check_at = public.next_order_group_sms_check_at(now(), interval '3 hours')
При ошибке обновить:
notification_status = 'send_failed'last_sms_error = <ошибка провайдера>next_notification_check_at = public.next_order_group_sms_check_at(now(), interval '30 minutes')
Поток 4. Передача в ручную обработку
Триггер:
- Cron каждые 10 минут
Запрос:
delivery_status = 'pending_confirmation'notification_status = 'second_sms_sent'next_notification_check_at <= now()
Действие:
- остановить автоматические напоминания
- перевести группу в ручную обработку
Обновление:
delivery_status = 'manual_confirmation_required'notification_status = 'manual_required'
После этого автоматические SMS больше не отправляются. В ЛК менеджер/логист
должен вручную выбрать дату доставки или поставить результат no_contact, если
связаться с клиентом не удалось.
Поток 5. Условия остановки
Каждый поток должен игнорировать строки, где:
delivery_status in ('agreed', 'no_contact', 'assigned_to_driver', 'out_for_delivery', 'delivered', 'cancelled')notification_status in ('confirmed', 'manual_required')
Это не дает слать дублирующие SMS после ответа клиента или передачи кейса человеку.
Рекомендуемый текст SMS
Пример:
Ваш заказ готов к согласованию доставки.
Выберите удобные дату и время по ссылке:
{{delivery_link}}
Напоминание:
Напоминаем: нужно выбрать дату и время доставки вашего заказа.
Ссылка:
{{delivery_link}}
Что нужно фронтенду
Публичной странице нужны только:
- token из URL
get-delivery-invitationconfirm-delivery-choice
Никакой логики SMS на фронтенде быть не должно. Никакой генерации ссылок на фронтенде быть не должно.
Минимальный порядок внедрения
- Развернуть обновленную схему
Supabaseиdocs/sql/order-groups-auto-delivery-link.sql. - Проверить, что insert/update в
order_groupsпишетdelivery_linkиnotification_status = 'link_ready'. - Собрать поток
n8nдля первой SMS. - Собрать поток
n8nдля напоминаний. - Собрать поток
n8nдля ручной передачи. - Проверить полный цикл на одной реальной записи
order_group.
Сценарий проверки
- Пометить одну
order_groupкак готовую к клиентскому согласованию доставки. - Убедиться, что
delivery_linkпоявился вorder_groupsавтоматически. - Дать
n8nотправить первую SMS. - Открыть ссылку и подтвердить слот на клиентской странице.
- Убедиться, что
delivery_status = 'agreed'иnotification_status = 'confirmed'. - Убедиться, что потоки напоминаний больше не трогают эту группу.