feat: document product and wire real client flow
This commit is contained in:
parent
b147d632e8
commit
ca72a4e662
31
README.md
31
README.md
|
|
@ -1,6 +1,6 @@
|
|||
# Construction Delivery Control
|
||||
|
||||
React-приложение для управления заказами, производством, логистикой и чатбот-коммуникацией через VK, Telegram и Messenger Max.
|
||||
React-приложение для управления заказами, доставкой, ролями сотрудников и публичным согласованием доставки с клиентом.
|
||||
|
||||
## Запуск
|
||||
|
||||
|
|
@ -9,26 +9,25 @@ npm install
|
|||
npm run dev
|
||||
```
|
||||
|
||||
## Что реализовано
|
||||
## Главный документ
|
||||
|
||||
- OTP-вход по email через Supabase Auth с demo-режимом без backend-конфига.
|
||||
- Installable PWA-режим: приложение можно добавить на домашний экран и открыть как отдельное окно.
|
||||
- Offline demo flow: после первого запуска дашборд и локальные demo-данные доступны без интернета.
|
||||
- Role-based dashboard для менеджера, производства, логиста и администратора.
|
||||
- Форма создания и редактирования заказов с автоназначением логиста.
|
||||
- Карточка заказа с историей статусов, действий, чата и слотов доставки.
|
||||
- Панели очереди производства и администраторского обзора пользователей.
|
||||
- Светлая и тёмная тема, адаптивный минималистичный UI.
|
||||
- Supabase SQL-схема с RLS, аудитом и расширением под нескольких логистов.
|
||||
- Тестируемый сервисный слой для фильтрации, смены статусов и генерации новых заказов.
|
||||
- Документация по архитектуре, ботам и пользовательским сценариям.
|
||||
- [Обзор системы](/Users/mihailkucer/Documents/super-sam/docs/product-overview.md) — назначение приложения, роли, сценарии, клиентский flow и подготовка к показу.
|
||||
|
||||
## Что уже есть
|
||||
|
||||
- OTP-вход по email через Supabase Auth.
|
||||
- Role-based dashboard для менеджера, логиста, водителя и администратора.
|
||||
- Карточка заказа с историей, чатом и слотами доставки.
|
||||
- Публичная страница `/delivery/:token` для выбора даты и половины дня доставки.
|
||||
- Supabase SQL-схема, таблицы приглашений и Edge Functions для invitation flow.
|
||||
- Документация по архитектуре, сценариям и интеграциям.
|
||||
|
||||
## Структура
|
||||
|
||||
- `src/` — интерфейс и клиентская логика.
|
||||
- `public/` — PWA manifest, service worker и install icons.
|
||||
- `supabase/schema.sql` — структура БД, роли, индексы, RLS, триггеры.
|
||||
- `supabase/functions/` — заготовки Edge Functions для webhook и отправки сообщений в боты.
|
||||
- `supabase/functions/` — Edge Functions для приглашений, статусов и чат-коммуникаций.
|
||||
- `supabase/seed/stage-1-demo.sql` — рабочий набор seed-данных для показа.
|
||||
- `docs/architecture.md` — архитектура фронтенда и модулей.
|
||||
- `docs/chatbot-integration.md` — логика интеграции VK/Telegram/Messenger Max.
|
||||
- `docs/product-overview.md` — общий обзор продукта, ролей и сценариев.
|
||||
- `docs/scenarios.md` — сценарии жизненного цикла заказа.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
# SuperSam: Обзор системы
|
||||
|
||||
`SuperSam` — это система управления доставкой заказов, которая объединяет внутренние рабочие кабинеты сотрудников и публичную страницу для клиента. Приложение помогает пройти путь от готовности заказа к отгрузке до согласования доставки, назначения исполнителей, фиксации результата и контроля исключений.
|
||||
|
||||
## Задачи приложения
|
||||
|
||||
- собрать в одном месте информацию по заказам, доставке, истории действий и коммуникациям;
|
||||
- разделить рабочие зоны по ролям, чтобы каждый сотрудник видел только свой контур задач;
|
||||
- дать логисту инструмент для запуска и контроля согласования доставки;
|
||||
- дать клиенту простую ссылку, по которой он может выбрать дату и половину дня доставки;
|
||||
- сохранить в Supabase историю изменений, статусы и интеграционные события.
|
||||
|
||||
## Роли
|
||||
|
||||
### Менеджер
|
||||
|
||||
Менеджер работает с заказами на ранних этапах:
|
||||
- видит список заказов и карточки клиентов;
|
||||
- следит за составом заказа и комментариями;
|
||||
- передаёт заказ дальше по процессу после подтверждения.
|
||||
|
||||
### Логист
|
||||
|
||||
Логист отвечает за доставку:
|
||||
- видит готовые к запуску и проблемные заказы;
|
||||
- контролирует статусы согласования доставки;
|
||||
- назначает и корректирует слоты;
|
||||
- переводит заказ в ручную обработку, если клиент не ответил;
|
||||
- отслеживает историю и связанные сообщения.
|
||||
|
||||
### Водитель
|
||||
|
||||
Водитель работает только со своими доставками:
|
||||
- видит назначенные маршруты;
|
||||
- открывает карточку точки доставки;
|
||||
- фиксирует ход доставки и итоговый статус.
|
||||
|
||||
### Администратор
|
||||
|
||||
Администратор видит всю систему:
|
||||
- пользователей и роли;
|
||||
- общие списки заказов и событий;
|
||||
- состояние интеграций и служебные данные.
|
||||
|
||||
### Клиент
|
||||
|
||||
Клиент не входит во внутренний кабинет. Он получает публичную ссылку вида `/delivery/:token` и по ней:
|
||||
- видит номер заказа;
|
||||
- выбирает удобную дату;
|
||||
- выбирает половину дня: `До обеда` или `После обеда`;
|
||||
- подтверждает выбор.
|
||||
|
||||
## Основные сценарии
|
||||
|
||||
### Внутренний сценарий
|
||||
|
||||
1. Заказ попадает в систему.
|
||||
2. Менеджер и внутренние сотрудники ведут заказ по этапам.
|
||||
3. Когда заказ готов к доставке, логист запускает приглашение клиенту.
|
||||
4. Клиент выбирает слот по публичной ссылке.
|
||||
5. Система переводит заказ в `Доставка согласована`.
|
||||
6. Логист и водитель доводят доставку до результата.
|
||||
|
||||
### Сценарий клиента
|
||||
|
||||
Клиентская страница работает по token из таблицы `public.delivery_invitations`. Для рабочего показа используется заранее загруженный seed-набор данных.
|
||||
|
||||
После загрузки seed можно открыть ссылку:
|
||||
|
||||
`/delivery/client-flow-1001`
|
||||
|
||||
Эта ссылка должна показывать:
|
||||
- заказ `CD-240031`;
|
||||
- четыре варианта слота;
|
||||
- две даты;
|
||||
- две половины дня: `До обеда` и `После обеда`.
|
||||
|
||||
После подтверждения выбора:
|
||||
- invitation переводится в состояние `agreed`;
|
||||
- заказ переводится в `Доставка согласована`;
|
||||
- в `order_history` появляется запись о подтверждении;
|
||||
- в `delivery_slots` фиксируется подтверждённый слот.
|
||||
|
||||
## Что хранится в Supabase
|
||||
|
||||
### Основные таблицы
|
||||
|
||||
- `public.users` — пользователи и роли;
|
||||
- `public.orders` — заказы и текущие статусы;
|
||||
- `public.order_history` — история изменений;
|
||||
- `public.delivery_slots` — возможные и подтверждённые слоты доставки;
|
||||
- `public.delivery_invitations` — публичные invitation token и состояние клиентского flow;
|
||||
- `public.integration_events` — технические и интеграционные события.
|
||||
|
||||
### Важные поля для клиентского flow
|
||||
|
||||
- `delivery_invitations.token_hash` — хеш публичного токена;
|
||||
- `delivery_invitations.state` — состояние приглашения;
|
||||
- `delivery_invitations.available_slots` — список доступных вариантов для клиента;
|
||||
- `delivery_invitations.delivery_date` и `delivery_invitations.delivery_time` — выбранный или основной слот;
|
||||
- `orders.status` — текущий рабочий статус заказа;
|
||||
- `orders.delivery_agreement_status` — статус согласования доставки.
|
||||
|
||||
## Как подготовить систему к показу
|
||||
|
||||
1. Загрузить схему `supabase/schema.sql`.
|
||||
2. Создать нужных пользователей в `auth.users`.
|
||||
3. Выполнить `supabase/seed/stage-1-demo.sql`.
|
||||
4. Убедиться, что Edge Functions развернуты:
|
||||
- `get-delivery-invitation`
|
||||
- `confirm-delivery-choice`
|
||||
- `create-delivery-invitation`
|
||||
5. Открыть внутренний кабинет.
|
||||
6. Открыть клиентскую ссылку `/delivery/client-flow-1001`.
|
||||
|
||||
## Что показывать на встрече
|
||||
|
||||
- вход во внутренний кабинет;
|
||||
- список заказов для менеджера, логиста и водителя;
|
||||
- карточку заказа и статусы;
|
||||
- клиентскую ссылку с выбором даты и половины дня;
|
||||
- изменение статуса заказа после подтверждения клиентом.
|
||||
|
||||
## Полезные документы
|
||||
|
||||
- [README](/Users/mihailkucer/Documents/super-sam/README.md)
|
||||
- [Архитектура](/Users/mihailkucer/Documents/super-sam/docs/architecture.md)
|
||||
- [Сценарии](/Users/mihailkucer/Documents/super-sam/docs/scenarios.md)
|
||||
- [Edge Functions](/Users/mihailkucer/Documents/super-sam/supabase/functions/README.md)
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
# Product Docs And Real Client Flow Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Создать один общий документ по приложению и ролям, подготовить рабочие Supabase seed-данные для клиентского приглашения и довести `/delivery/:token` до реального flow.
|
||||
|
||||
**Architecture:** Документация собирается в одном основном продуктово-ориентированном документе, на который начинает ссылаться `README`. Клиентский flow остаётся построен на `delivery_invitations` и Edge Functions, но приводится к фактическому фронтенд-контракту: фронтенд вызывает functions через Supabase invoke, а seed поднимает один реальный invitation token с рабочими слотами.
|
||||
|
||||
**Tech Stack:** React 18, Vite, Supabase SQL, Supabase Edge Functions, Vitest.
|
||||
|
||||
---
|
||||
|
||||
## Chunk 1: Real Client Invitation Contract
|
||||
|
||||
### Task 1: Зафиксировать тестами рабочий invitation contract
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/services/deliveryInvitationApi.test.js`
|
||||
- Modify or Create: client page test if needed
|
||||
|
||||
- [ ] **Step 1: Add failing tests for real token flow**
|
||||
- [ ] **Step 2: Run targeted tests and confirm failure**
|
||||
- [ ] **Step 3: Cover returned delivery date/time and real slot format**
|
||||
|
||||
### Task 2: Привести Edge Function и frontend API к одному контракту
|
||||
|
||||
**Files:**
|
||||
- Modify: `supabase/functions/get-delivery-invitation/index.ts`
|
||||
- Modify: `supabase/functions/confirm-delivery-choice/index.ts`
|
||||
- Modify: `src/services/deliveryInvitationApi.js`
|
||||
- Modify: `src/pages/ClientDeliveryPage.jsx`
|
||||
|
||||
- [ ] **Step 1: Support frontend invoke contract in get-delivery-invitation**
|
||||
- [ ] **Step 2: Return invitation delivery date/time fields**
|
||||
- [ ] **Step 3: Keep confirm-delivery-choice compatible with selected slot data**
|
||||
- [ ] **Step 4: Re-run targeted tests and confirm pass**
|
||||
|
||||
## Chunk 2: Supabase Seed For Demoable Client Flow
|
||||
|
||||
### Task 3: Подготовить реальный invitation token и слоты в seed
|
||||
|
||||
**Files:**
|
||||
- Modify: `supabase/seed/stage-1-demo.sql`
|
||||
|
||||
- [ ] **Step 1: Add one known invitation token**
|
||||
- [ ] **Step 2: Store stable slot values for tomorrow/after-tomorrow style choices**
|
||||
- [ ] **Step 3: Keep seed re-runnable**
|
||||
- [ ] **Step 4: Ensure order status matches awaiting client choice**
|
||||
|
||||
## Chunk 3: One General Product Document
|
||||
|
||||
### Task 4: Собрать единый общий документ по системе
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/product-overview.md`
|
||||
- Modify: `README.md`
|
||||
|
||||
- [ ] **Step 1: Write the main product document**
|
||||
- [ ] **Step 2: Cover goals, roles, scenarios, client flow and Supabase entities**
|
||||
- [ ] **Step 3: Link README to the new main document**
|
||||
|
||||
## Chunk 4: Final Verification
|
||||
|
||||
### Task 5: Проверить итоговый сценарий
|
||||
|
||||
**Files:**
|
||||
- Reference: `src/pages/ClientDeliveryPage.jsx`
|
||||
- Reference: `supabase/seed/stage-1-demo.sql`
|
||||
- Reference: `docs/product-overview.md`
|
||||
|
||||
- [ ] **Step 1: Run targeted tests**
|
||||
|
||||
Run: `npm test -- src/services/deliveryInvitationApi.test.js src/components/client/DeliveryChoiceFlow.test.jsx src/components/client/DeliverySlotsPicker.test.jsx`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 2: Run auth/order regression tests**
|
||||
|
||||
Run: `npm test -- src/context/AuthContext.test.js src/components/auth/OtpLoginForm.test.jsx src/services/orderService.test.js src/components/orders/OrdersTable.test.jsx src/components/orders/OrderDetailPanel.test.jsx src/components/orders/OrderFilters.test.jsx`
|
||||
Expected: PASS
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# Product Docs And Real Client Flow Design
|
||||
|
||||
**Goal:** Подготовить один общий документ по приложению с описанием задач, ролей и пользовательских сценариев, а также довести публичную клиентскую страницу до рабочего Supabase flow на реальном invitation token и seed-данных.
|
||||
|
||||
## What We Are Building
|
||||
|
||||
Нужен один основной документ, который можно открыть первым и понять:
|
||||
- зачем существует приложение;
|
||||
- какие роли в нём есть;
|
||||
- что видит каждая роль после входа;
|
||||
- как проходит согласование доставки с клиентом;
|
||||
- какие данные должны быть подготовлены в Supabase для показа.
|
||||
|
||||
Параллельно нужно довести клиентскую страницу `/delivery/:token` до реально работающего сценария на базе `delivery_invitations`, `orders` и `delivery_slots`, чтобы можно было показать не showcase-заглушку, а настоящий flow.
|
||||
|
||||
## Product Documentation Shape
|
||||
|
||||
Главный документ должен быть продуктовым, а не набором технических заметок. Рекомендованная структура:
|
||||
|
||||
1. Назначение системы
|
||||
2. Основные задачи приложения
|
||||
3. Роли и зоны ответственности
|
||||
4. Ключевые рабочие сценарии
|
||||
5. Сценарий клиента по публичной ссылке
|
||||
6. Какие данные живут в Supabase
|
||||
7. Как подготовить систему к показу
|
||||
8. Полезные ссылки на более глубокие технические документы
|
||||
|
||||
Этот документ должен стать основной точкой входа из `README`.
|
||||
|
||||
## Real Client Flow
|
||||
|
||||
Клиентская страница должна работать на реальном token из `delivery_invitations`, без локального fallback как основного сценария.
|
||||
|
||||
Для этого:
|
||||
- `get-delivery-invitation` должен корректно работать с тем способом вызова, который использует фронтенд;
|
||||
- ответ invitation должен возвращать все данные, нужные клиентскому экрану: заказ, клиент, state, доступные слоты, выбранные `delivery_date` и `delivery_time`;
|
||||
- `confirm-delivery-choice` должен фиксировать выбор клиента и обновлять заказ/историю;
|
||||
- seed должен создавать один рабочий invitation token, который можно открыть в браузере и пройти до подтверждения.
|
||||
|
||||
## Seed Strategy
|
||||
|
||||
Нужен один понятный рабочий пример для показа:
|
||||
- заказ в статусе `Ожидает ответа клиента`;
|
||||
- invitation с известным токеном;
|
||||
- слоты на две даты и две половины дня;
|
||||
- логист и менеджер уже привязаны;
|
||||
- после подтверждения выбор уходит в историю и переводит заказ в `Доставка согласована`.
|
||||
|
||||
Вместо текстовых слотов вида `14 апреля, первая половина дня` лучше хранить технически стабильный формат, который фронтенд однозначно разбирает, например `YYYY-MM-DD, До обеда`.
|
||||
|
||||
## UX Decisions
|
||||
|
||||
- В клиентском экране главное действие — выбор даты и половины дня без лишнего текста.
|
||||
- Тексты должны звучать как рабочий сервис доставки.
|
||||
- В документе роли описываются через задачи и результат, а не через внутреннюю реализацию интерфейса.
|
||||
|
||||
## Validation
|
||||
|
||||
- Тесты API/клиента фиксируют рабочий invitation flow.
|
||||
- После seed известный токен должен открываться на `/delivery/:token`.
|
||||
- Общий документ должен быть связан с `README` как основной обзор проекта.
|
||||
|
|
@ -9,7 +9,7 @@ import {
|
|||
fetchDeliveryInvitation,
|
||||
} from "../services/deliveryInvitationApi";
|
||||
|
||||
const groupSlotsFromInvitation = (invitation) => {
|
||||
export const groupSlotsFromInvitation = (invitation) => {
|
||||
if (!invitation) {
|
||||
return [];
|
||||
}
|
||||
|
|
@ -49,6 +49,15 @@ const groupSlotsFromInvitation = (invitation) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const buildDeliveryConfirmationPayload = ({
|
||||
slot,
|
||||
invitation,
|
||||
searchDate,
|
||||
}) => ({
|
||||
deliveryDate: slot?.date || searchDate || invitation?.deliveryDate || undefined,
|
||||
deliveryTime: slot?.time || invitation?.deliveryTime || undefined,
|
||||
});
|
||||
|
||||
export const ClientDeliveryPage = () => {
|
||||
const { token } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
|
@ -103,7 +112,7 @@ export const ClientDeliveryPage = () => {
|
|||
const invitationState = invitation?.state || "awaiting_choice";
|
||||
|
||||
const handleConfirmChoice = React.useCallback(
|
||||
async (deliveryTime) => {
|
||||
async ({ deliveryDate, deliveryTime }) => {
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -114,7 +123,7 @@ export const ClientDeliveryPage = () => {
|
|||
await confirmDeliveryChoice({
|
||||
token,
|
||||
deliveryTime,
|
||||
deliveryDate: searchParams.get("date") || invitation?.deliveryDate || undefined,
|
||||
deliveryDate,
|
||||
});
|
||||
const loadedInvitation = await fetchDeliveryInvitation(token);
|
||||
setInvitation(loadedInvitation);
|
||||
|
|
@ -124,15 +133,21 @@ export const ClientDeliveryPage = () => {
|
|||
setError(confirmError instanceof Error ? confirmError.message : "Не удалось сохранить выбор");
|
||||
}
|
||||
},
|
||||
[searchParams, token, invitation],
|
||||
[token, invitation],
|
||||
);
|
||||
|
||||
const handleSlotSelect = React.useCallback(
|
||||
(slot) => {
|
||||
setSelectedSlotId(slot.id);
|
||||
handleConfirmChoice(slot.time);
|
||||
handleConfirmChoice(
|
||||
buildDeliveryConfirmationPayload({
|
||||
slot,
|
||||
invitation,
|
||||
searchDate: searchParams.get("date"),
|
||||
}),
|
||||
);
|
||||
},
|
||||
[handleConfirmChoice],
|
||||
[handleConfirmChoice, invitation, searchParams],
|
||||
);
|
||||
|
||||
const handleRequestNewLink = React.useCallback(() => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildDeliveryConfirmationPayload,
|
||||
groupSlotsFromInvitation,
|
||||
} from "./ClientDeliveryPage";
|
||||
|
||||
describe("ClientDeliveryPage helpers", () => {
|
||||
it("maps invitation slots in YYYY-MM-DD format to UI slots", () => {
|
||||
expect(
|
||||
groupSlotsFromInvitation({
|
||||
availableSlots: [
|
||||
"2026-04-15, До обеда",
|
||||
"2026-04-15, После обеда",
|
||||
],
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
id: "slot-0-2026-04-15, До обеда",
|
||||
date: "2026-04-15",
|
||||
time: "До обеда",
|
||||
},
|
||||
{
|
||||
id: "slot-1-2026-04-15, После обеда",
|
||||
date: "2026-04-15",
|
||||
time: "После обеда",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("builds confirmation payload from the selected slot date and time", () => {
|
||||
expect(
|
||||
buildDeliveryConfirmationPayload({
|
||||
slot: {
|
||||
id: "slot-1",
|
||||
date: "2026-04-16",
|
||||
time: "После обеда",
|
||||
},
|
||||
invitation: {
|
||||
deliveryDate: "2026-04-15",
|
||||
},
|
||||
searchDate: "2026-04-14",
|
||||
}),
|
||||
).toEqual({
|
||||
deliveryDate: "2026-04-16",
|
||||
deliveryTime: "После обеда",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -15,7 +15,7 @@ Deno.serve(async (request) => {
|
|||
return new Response("ok", { headers: corsHeaders });
|
||||
}
|
||||
|
||||
if (request.method !== "GET") {
|
||||
if (!["GET", "POST"].includes(request.method)) {
|
||||
return new Response(JSON.stringify({ error: "Method not allowed" }), {
|
||||
status: 405,
|
||||
headers: {
|
||||
|
|
@ -27,7 +27,9 @@ Deno.serve(async (request) => {
|
|||
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const token = url.searchParams.get("token") || "";
|
||||
const token = request.method === "POST"
|
||||
? ((await request.json()) as { token?: string })?.token || ""
|
||||
: url.searchParams.get("token") || "";
|
||||
if (!token) {
|
||||
return new Response(JSON.stringify({ error: "token is required" }), {
|
||||
status: 400,
|
||||
|
|
@ -96,6 +98,8 @@ Deno.serve(async (request) => {
|
|||
customerName: order.customer?.name || invitation.customer_name || null,
|
||||
customerPhone: order.customer?.phone || invitation.customer_phone || null,
|
||||
availableSlots: invitation.available_slots || [],
|
||||
deliveryDate: invitation.delivery_date || null,
|
||||
deliveryTime: invitation.delivery_time || null,
|
||||
orderStatus: order.status,
|
||||
deliveryAgreementStatus: order.delivery_agreement_status,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -564,12 +564,19 @@ insert into public.delivery_slots (
|
|||
)
|
||||
select
|
||||
o.id,
|
||||
'2026-04-14'::date,
|
||||
'Первая половина дня',
|
||||
slot.delivery_date,
|
||||
slot.delivery_time,
|
||||
(select id from public.users where email = 'mk7029953@yandex.ru' limit 1),
|
||||
'pending_confirmation',
|
||||
null
|
||||
from public.orders o
|
||||
cross join (
|
||||
values
|
||||
((current_date + 1), 'До обеда'),
|
||||
((current_date + 1), 'После обеда'),
|
||||
((current_date + 2), 'До обеда'),
|
||||
((current_date + 2), 'После обеда')
|
||||
) as slot(delivery_date, delivery_time)
|
||||
where o.order_number = 'CD-240031';
|
||||
|
||||
insert into public.delivery_slots (
|
||||
|
|
@ -607,22 +614,22 @@ insert into public.delivery_invitations (
|
|||
)
|
||||
select
|
||||
o.id,
|
||||
encode(digest('demo-invite-1001', 'sha256'), 'hex'),
|
||||
encode(digest('client-flow-1001', 'sha256'), 'hex'),
|
||||
'awaiting_choice',
|
||||
o.order_number,
|
||||
o.customer ->> 'name',
|
||||
o.customer ->> 'phone',
|
||||
o.customer ->> 'messenger',
|
||||
array[
|
||||
'14 апреля, первая половина дня',
|
||||
'14 апреля, вторая половина дня',
|
||||
'15 апреля, первая половина дня',
|
||||
'15 апреля, вторая половина дня'
|
||||
to_char(current_date + 1, 'YYYY-MM-DD') || ', До обеда',
|
||||
to_char(current_date + 1, 'YYYY-MM-DD') || ', После обеда',
|
||||
to_char(current_date + 2, 'YYYY-MM-DD') || ', До обеда',
|
||||
to_char(current_date + 2, 'YYYY-MM-DD') || ', После обеда'
|
||||
],
|
||||
'2026-04-14'::date,
|
||||
'Первая половина дня',
|
||||
'2026-04-13T09:00:00Z',
|
||||
'2026-04-13T09:10:00Z',
|
||||
(current_date + 1),
|
||||
'До обеда',
|
||||
timezone('utc', now()),
|
||||
null,
|
||||
null
|
||||
from public.orders o
|
||||
where o.order_number = 'CD-240031'
|
||||
|
|
@ -657,12 +664,12 @@ select
|
|||
'seed',
|
||||
'success',
|
||||
jsonb_build_object(
|
||||
'token', 'demo-invite-1001',
|
||||
'token', 'client-flow-1001',
|
||||
'availableSlots', array[
|
||||
'14 апреля, первая половина дня',
|
||||
'14 апреля, вторая половина дня',
|
||||
'15 апреля, первая половина дня',
|
||||
'15 апреля, вторая половина дня'
|
||||
to_char(current_date + 1, 'YYYY-MM-DD') || ', До обеда',
|
||||
to_char(current_date + 1, 'YYYY-MM-DD') || ', После обеда',
|
||||
to_char(current_date + 2, 'YYYY-MM-DD') || ', До обеда',
|
||||
to_char(current_date + 2, 'YYYY-MM-DD') || ', После обеда'
|
||||
]
|
||||
),
|
||||
null
|
||||
|
|
|
|||
Loading…
Reference in New Issue