252 lines
6.9 KiB
Markdown
252 lines
6.9 KiB
Markdown
# n8n Flow For `order_groups`
|
|
|
|
## Goal
|
|
|
|
`Supabase` stores the delivery state, generates the client link, and saves all timestamps.
|
|
`n8n` is responsible for sending SMS, retrying, and moving stalled groups into manual handling.
|
|
|
|
The short link is not needed on our side. We store the full `delivery_link`, and the SMS provider shortens it during delivery.
|
|
|
|
## Source Of Truth
|
|
|
|
The main record is `public.order_groups`.
|
|
|
|
Important fields:
|
|
|
|
- `status` - business readiness of the group
|
|
- `delivery_status` - delivery coordination state for the client and logistics
|
|
- `delivery_link` - full public link to `/delivery/:token`
|
|
- `delivery_invitation_id` - related invitation record
|
|
- `notification_status` - SMS orchestration state for `n8n`
|
|
- `sms_attempts` - how many SMS attempts were made
|
|
- `first_sms_sent_at` - timestamp of the first SMS
|
|
- `second_sms_sent_at` - timestamp of the second SMS
|
|
- `last_sms_error` - last provider error text
|
|
- `next_notification_check_at` - when `n8n` should revisit the record
|
|
- `delivery_date` and `delivery_time` - selected slot after client confirmation
|
|
|
|
## Recommended Status Model
|
|
|
|
### `delivery_status`
|
|
|
|
- `pending_confirmation` - client has not selected a slot yet
|
|
- `agreed` - client selected a delivery slot
|
|
- `manual_confirmation_required` - automatic flow failed, manager/logistics must continue manually
|
|
- `assigned_to_driver` - delivery is approved and handed over to driver planning
|
|
- `out_for_delivery` - driver is already working on it
|
|
- `delivered` - delivery completed
|
|
- `cancelled` - group should no longer be processed
|
|
|
|
### `notification_status`
|
|
|
|
- `not_started` - link has not been prepared yet
|
|
- `link_ready` - Supabase created `delivery_link`, `n8n` can send the first SMS
|
|
- `first_sms_sent` - first SMS was accepted by provider
|
|
- `second_sms_sent` - reminder SMS was accepted by provider
|
|
- `confirmed` - client selected a slot
|
|
- `manual_required` - no confirmation after retries
|
|
- `send_failed` - provider/API error, retry allowed
|
|
|
|
## Supabase Responsibilities
|
|
|
|
### 1. Prepare the link
|
|
|
|
When an `order_group` is moved into the client-delivery flow:
|
|
|
|
- `status = 'ready_for_notification'`
|
|
- `delivery_status = 'pending_confirmation'`
|
|
|
|
Supabase trigger `order_groups_ensure_delivery_link` should:
|
|
|
|
- create `delivery_invitations` row with `order_group_id`
|
|
- generate token and full public URL
|
|
- write `delivery_link` into `order_groups`
|
|
- set `delivery_invitation_id`
|
|
- set `notification_status = 'link_ready'`
|
|
- set `next_notification_check_at = now()`
|
|
|
|
The SQL for this trigger lives in:
|
|
|
|
```text
|
|
docs/sql/order-groups-auto-delivery-link.sql
|
|
```
|
|
|
|
`n8n` no longer has to call `create-delivery-invitation` for `order_groups`. It should wait until the row already has `notification_status = 'link_ready'` and `delivery_link is not null`.
|
|
|
|
### 2. Accept client choice
|
|
|
|
The public client page uses the token.
|
|
When the client confirms a slot, `confirm-delivery-choice` should:
|
|
|
|
- store `delivery_date` and `delivery_time`
|
|
- set `delivery_status = 'agreed'`
|
|
- set `notification_status = 'confirmed'`
|
|
|
|
That change becomes the stop signal for all reminder workflows in `n8n`.
|
|
|
|
## n8n Workflows
|
|
|
|
### Workflow 1. First SMS sender
|
|
|
|
Trigger:
|
|
|
|
- Cron every 5-10 minutes
|
|
- Optional backup webhook trigger if you later want push-based start
|
|
|
|
Query:
|
|
|
|
- `status = 'ready_for_notification'`
|
|
- `delivery_status = 'pending_confirmation'`
|
|
- `notification_status = 'link_ready'`
|
|
- `delivery_link is not null`
|
|
|
|
Action:
|
|
|
|
- send SMS with `delivery_link`
|
|
|
|
On success update `order_groups`:
|
|
|
|
- `notification_status = 'first_sms_sent'`
|
|
- `sms_attempts = 1`
|
|
- `first_sms_sent_at = now()`
|
|
- `sms_sent_at = now()`
|
|
- `last_sms_error = null`
|
|
- `next_notification_check_at = now() + interval '1 hour'`
|
|
|
|
On failure update `order_groups`:
|
|
|
|
- `notification_status = 'send_failed'`
|
|
- `last_sms_error = <provider error>`
|
|
- `next_notification_check_at = now() + interval '10 minutes'`
|
|
|
|
## Workflow 2. Delivery watchdog
|
|
|
|
Trigger:
|
|
|
|
- Cron every 10 minutes
|
|
|
|
Purpose:
|
|
|
|
- find records where first workflow did not finish cleanly
|
|
- retry failed first sends
|
|
|
|
Query candidates:
|
|
|
|
- `notification_status = 'send_failed'`
|
|
- `delivery_status = 'pending_confirmation'`
|
|
- `next_notification_check_at <= now()`
|
|
|
|
Behavior:
|
|
|
|
- retry first SMS
|
|
- if success, move to `first_sms_sent`
|
|
- if repeated failures exceed your chosen threshold, move to `manual_required`
|
|
|
|
## Workflow 3. Reminder SMS
|
|
|
|
Trigger:
|
|
|
|
- Cron every 10 minutes
|
|
|
|
Query:
|
|
|
|
- `delivery_status = 'pending_confirmation'`
|
|
- `notification_status = 'first_sms_sent'`
|
|
- `next_notification_check_at <= now()`
|
|
|
|
Action:
|
|
|
|
- send second SMS reminder with the same `delivery_link`
|
|
|
|
On success update:
|
|
|
|
- `notification_status = 'second_sms_sent'`
|
|
- `sms_attempts = 2`
|
|
- `second_sms_sent_at = now()`
|
|
- `last_sms_error = null`
|
|
- `next_notification_check_at = now() + interval '3 hours'`
|
|
|
|
On failure update:
|
|
|
|
- `notification_status = 'send_failed'`
|
|
- `last_sms_error = <provider error>`
|
|
- `next_notification_check_at = now() + interval '30 minutes'`
|
|
|
|
## Workflow 4. Manual handoff
|
|
|
|
Trigger:
|
|
|
|
- Cron every 10 minutes
|
|
|
|
Query:
|
|
|
|
- `delivery_status = 'pending_confirmation'`
|
|
- `notification_status = 'second_sms_sent'`
|
|
- `next_notification_check_at <= now()`
|
|
|
|
Action:
|
|
|
|
- stop automatic reminders
|
|
- move the group into manual handling
|
|
|
|
Update:
|
|
|
|
- `delivery_status = 'manual_confirmation_required'`
|
|
- `notification_status = 'manual_required'`
|
|
|
|
## Workflow 5. Stop conditions
|
|
|
|
Every workflow must ignore rows where:
|
|
|
|
- `delivery_status in ('agreed', 'assigned_to_driver', 'out_for_delivery', 'delivered', 'cancelled')`
|
|
- `notification_status in ('confirmed', 'manual_required')`
|
|
|
|
This prevents duplicate SMS after the client already responded or the case was handed to a person.
|
|
|
|
## Suggested SMS Text
|
|
|
|
Example:
|
|
|
|
```text
|
|
Ваш заказ готов к согласованию доставки.
|
|
Выберите удобные дату и время по ссылке:
|
|
{{delivery_link}}
|
|
```
|
|
|
|
Reminder:
|
|
|
|
```text
|
|
Напоминаем: нужно выбрать дату и время доставки вашего заказа.
|
|
Ссылка:
|
|
{{delivery_link}}
|
|
```
|
|
|
|
## What Frontend Needs
|
|
|
|
The frontend public page only needs:
|
|
|
|
- token from URL
|
|
- `get-delivery-invitation`
|
|
- `confirm-delivery-choice`
|
|
|
|
No SMS logic should live in the frontend.
|
|
No link generation should live in the frontend.
|
|
|
|
## Minimal Rollout Order
|
|
|
|
1. Deploy updated `Supabase` schema and `docs/sql/order-groups-auto-delivery-link.sql`.
|
|
2. Verify that insert/update in `order_groups` writes `delivery_link` and `notification_status = 'link_ready'`.
|
|
3. Build `n8n` workflow for first SMS.
|
|
4. Build `n8n` reminder workflow.
|
|
5. Build `n8n` manual-handoff workflow.
|
|
6. Test full cycle on one real `order_group`.
|
|
|
|
## Test Scenario
|
|
|
|
1. Mark one `order_group` as ready for client delivery.
|
|
2. Confirm that `delivery_link` appeared in `order_groups` automatically.
|
|
4. Let `n8n` send the first SMS.
|
|
5. Open the link and confirm a slot on the client page.
|
|
6. Confirm that `delivery_status = 'agreed'` and `notification_status = 'confirmed'`.
|
|
7. Confirm that reminder workflows no longer touch this group.
|