spectaxi

Доменная модель и ERD (MVP)

1) Цель

Минимальная модель MVP: без обязательной безопасной сделки, без внутреннего кошелька, без календаря занятости. Выровнена с USER_SCENARIOS.md.

2) Сущности

users

Нет default_mode, is_client_enabled, is_executor_enabled.

Для создания и принятия заказа: непустой full_name и хотя бы один канал из contact_phone / telegram_url / whatsapp_url / max_url / непустого messengers_json.

executor_profiles

Создаётся при регистрации в режиме исполнителя или при первом переключении на исполнителя.

accepts_urgent_orders = false скрывает исполнителя только из выдачи по срочным заказам; по плановым он виден. Система этот флаг не переключает.

Пока executor_subscription_enabled = false, статус подписки не ограничивает поиск.

machinery_categories

Строка таблицы и есть конфиг типа транспорта. Отдельного JSON license_config нет.

Селект при создании машины — строки этой таблицы.

pricing_types

category_pricing_types

machinery_units

Лимита единиц нет. Флага занятости на единице нет.

machinery_photos

Файлы загружает исполнитель, в API с клиента URL не принимаются. У активной единицы минимум одно фото; последнее удалить нельзя. Аватар исполнителя — тоже файлом.

machinery_pricing_rules

Тариф принадлежит единице.

В поиске единица участвует только если: не удалена, подписка ок (если флаг), есть нужный тариф, лицензия категории approved либо license_category пустой, и для срочного поиска — accepts_urgent_orders.

executor_licenses

Одна лицензия на пару исполнитель + категория (не на каждую машину).

Уникально (executor_profile_id, category_id). Документы — executor_license_files (license_id, url, created_at).

Машину без approved сохранить можно, в поиске нет.

orders

Нет статуса assigned. Нет окна работ, окончания и полей занятости.

order_pricing

Один к заказу. Сумму считает сервер.

unit_rate копируется с машины при отправке запроса и при каждой правке заказчиком; смена ставок исполнителем на машине запись не меняет.

order_candidates

Статуса viewed нет. auto_declined — система закрыла запрос, потому что исполнитель принял другой срочный заказ; для клиента это отказ, штрафа исполнителю нет.

На заказ не более одного notified. Один исполнитель может одновременно быть notified по нескольким заказам. Assignment при «подтвердить условия»; при возврате на поиск снимается.

order_assignments

Появляется при «подтвердить условия». Снимается, если заказ вернулся в published (неоплата и т.п.) — на in_progress назначение уже не снимается.

order_status_events

contact_exchange_events

disputes

Одна запись на заказ (order_id unique).

Апелляция: та же строка снова open, appeal_used = true, сообщения продолжаются. Второго спора-строки нет.

dispute_messages / dispute_message_photos

Сообщения спора (author_kind: client executor admin) и фото к сообщению.

reviews

После completed, по одному отзыву каждой стороны.

Отзывы об исполнителе видны в поиске и профиле. Отзывы о клиенте — исполнителю в карточке входящего запроса как средняя оценка и число отзывов (без текста и контактов).

notifications

Прочтение не меняет статус кандидата.

rating_events

Правила — RATING_PLAN.md.

payment_records / payment_webhook_events

Холд только после создания платежа на awaiting_payment. Клиент сумму не задаёт.

subscription_payments (когда флаг подписки включён)

Платёж активации исполнителя, не холд заказа. Webhook → subscription_status = active.

3) ERD

erDiagram
    users ||--o| executor_profiles : has
    executor_profiles ||--o{ machinery_units : owns
    executor_profiles ||--o{ executor_licenses : licenses
    machinery_categories ||--o{ machinery_units : categorizes
    machinery_categories ||--o{ executor_licenses : requires
    machinery_categories ||--o{ category_pricing_types : allows
    pricing_types ||--o{ category_pricing_types : allowed_in
    pricing_types ||--o{ machinery_pricing_rules : used_by
    machinery_units ||--o{ machinery_photos : has
    machinery_units ||--o{ machinery_pricing_rules : priced_by
    executor_licenses ||--o{ executor_license_files : docs

    users ||--o{ orders : creates
    machinery_categories ||--o{ orders : requested_category
    orders ||--|| order_pricing : has
    orders ||--o{ order_candidates : request_one_at_a_time
    orders ||--o| order_assignments : assigned_to_one
    orders ||--o{ order_status_events : tracks
    orders ||--o{ contact_exchange_events : contact_shared
    orders ||--o| disputes : one_dispute
    disputes ||--o{ dispute_messages : has
    dispute_messages ||--o{ dispute_message_photos : photos
    orders ||--o{ reviews : public_stars
    orders ||--o| payment_records : payment_link
    users ||--o{ notifications : inbox
    users ||--o{ rating_events : score_changes
    users ||--o{ reviews : writes
    payment_records ||--o{ payment_webhook_events : updated_by

4) Инварианты

5) Индексы и ограничения

Обязательные:

Рекомендуемые:

6) Отложить