Docs: sync Back#61 specialist_id + trial/402 (no auto-start). Fixes EventHub/EventHubSpec#14

This commit is contained in:
2026-07-27 21:24:09 +03:00
parent 546f888487
commit 644ded803c
3 changed files with 31 additions and 16 deletions
+21 -12
View File
@@ -78,14 +78,17 @@ EventHub — платформа для управления событиями
слоты освобождаются;
- уже `confirmed`**оставляем**;
- owner: просмотр/редактирование своих событий и настроек, CRUD specialists — **разрешены**;
- create нового commercial / upgrade type → `402`.
- create нового commercial / upgrade type → `402` (нужна **уже active** подписка
или trial; auto-start trial при create **нет** — см. ниже и §2.9).
Периодический job (например раз в 60 с): помечает просроченные подписки `expired`, отменяет
pending владельца, **не** меняет `calendar.type`. Legacy `downgrade_user_calendars/1`
(type → personal) — удалить/не использовать.
Первое создание commercial без подписки: **auto-start trial** (один раз, `trial_used`);
повтор без подписки → `402`. Планы/цены — §2.9.
Create / upgrade `commercial` без **уже active** подписки или trial → **`402`**.
Trial стартует **только** явным `POST /v1/subscription` с `action=start_trial`
(один раз, `trial_used`); при create commercial auto-start trial **нет**.
Планы/цены — §2.9.
В ответах календаря (user API): `booking_open` (boolean) — производное от
`type=commercial` ∧ calendar `active` ∧ подписка владельца active.
@@ -173,8 +176,9 @@ Legacy: прямой `POST /v1/calendars/:id/specialists` **не использ
допускается только как внутренний/тестовый путь или удаляется после миграции на invite.
Продуктовый путь: invite → accept → specialist.
- `event.specialist_id` опционален; если задан — только `active` specialist этого календаря
(иначе `400`).
- `event.specialist_id` опционален на `POST`/`PUT` события; если задан — персистится
и валидируется: только `active` specialist этого календаря (иначе `400`
`Invalid specialist_id for this calendar`).
- **Confirm/decline booking:** владелец — любые booking календаря; `active` specialist — только
booking на событиях, где `event.specialist_id` = его `user_id`.
- **Inbox к подтверждению:** `GET /v1/user/booking-requests` агрегирует **actionable** pending
@@ -339,8 +343,9 @@ Legacy: прямой `POST /v1/calendars/:id/specialists` **не использ
- Цены (`logic_subscription:plan_price/1`, minor units): monthly **999**, quarterly **2499**,
biannual **4499**, annual **7999**; trial — 0. Платёжный шлюз — заглушка (`process_payment` → ok).
- Статус подписки: `active`, `expired`, `cancelled`.
- Отслеживание использования пробного периода (`trial_used`); trial стартует автоматически при
первой попытке создать/апгрейднуть commercial (§2.1.2).
- Отслеживание использования пробного периода (`trial_used`); trial стартует **только**
явным `POST /v1/subscription` (`action=start_trial`), не при create/upgrade commercial
(§2.1.2). Create/upgrade commercial без уже active sub/trial → `402`.
- Истечение: периодический job → `expired`; commercial-календари **не** меняют type —
переходят в restricted; после `activate` / новой active подписки функционал восстанавливается
(§2.1.2). Не использовать legacy downgrade type → personal.
@@ -480,9 +485,11 @@ src/
В calendar-результатах — `image_url` (если задан на календаре). Upload/multipart
**не** входит в контракт: поле URL.
- `GET /v1/calendars` — список календарей.
- `POST /v1/calendars` — создать календарь (`commercial`подписка/trial; иначе `402`).
- `POST /v1/calendars` — создать календарь (`commercial`нужна уже active sub/trial;
иначе `402`; auto-start trial нет).
- `GET /v1/calendars/:id` — календарь (`following`, `booking_open` для текущего контекста).
- `PUT /v1/calendars/:id` — обновить календарь (`personal→commercial`gate подписки).
- `PUT /v1/calendars/:id` — обновить календарь (`personal→commercial`нужна уже
active sub/trial, иначе `402`).
- `DELETE /v1/calendars/:id` — удалить календарь.
- `POST /v1/calendars/:id/follow` — отслеживать чужой календарь.
- `DELETE /v1/calendars/:id/follow` — снять follow.
@@ -495,9 +502,10 @@ src/
- `POST /v1/specialist-invites/:id/accept` | `…/decline` — ответ invitee.
- `POST /v1/specialist-invites/accept` `{ token }` — accept по email deep-link.
- `GET /v1/calendars/:calendar_id/events` — события календаря.
- `POST /v1/calendars/:calendar_id/events` — создать событие.
- `POST /v1/calendars/:calendar_id/events` — создать событие (тело может включать
опциональный `specialist_id`; invalid → `400`).
- `GET /v1/events/:id` — событие.
- `PUT /v1/events/:id` — обновить событие.
- `PUT /v1/events/:id` — обновить событие (в т.ч. `specialist_id`; invalid → `400`).
- `DELETE /v1/events/:id` — удалить событие.
- `GET /v1/events/:id/occurrences` — вхождения повторяющегося события.
- `DELETE /v1/events/:id/occurrences/:start_time` — отменить вхождение серии.
@@ -522,7 +530,8 @@ src/
- `POST /v1/tickets` — создать или обновить тикет (дедуп по `error_hash`): body `{ error_message, stacktrace?, context?, source?: frontend|manual }`; ответ 201 (или 429 при rate-limit новых).
- `GET /v1/tickets/:id` — статус тикета.
- `GET /v1/subscription` — подписка пользователя.
- `POST /v1/subscription`активировать подписку.
- `POST /v1/subscription``action=start_trial` | `activate` (+ `plan`, опционально
`payment_info`). Trial — только через `start_trial`, не через create commercial.
- `GET /v1/calendars/:calendar_id/view?month=YYYY-MM` — HTML-календарь (владелец), включая архив.
### WebSocket (порт 8081)