SpexTaxi — мобильный маркетплейс для поиска и заказа спецтехники.
Платформа поддерживает три пользовательских сценария в рамках одной учетной записи:
Один пользователь имеет один аккаунт и может переключаться между ролями клиент и исполнитель. Поток заказа у частного и бизнес-клиента одинаковый. Режим интерфейса — одно поле current_mode.
Полные шаги — в USER_SCENARIOS.md. Кратко:
Фильтр: тип, тариф (набор зависит от типа транспорта — часы/смены/месяцы или километры/рейсы), количество, срочный (без даты) или плановый (дата и время начала, справочно для исполнителя), точка, опционально потолок цены. Список ближайших машин, карта с кластерами. Цена на карточке = ставка × количество. Календаря занятости нет: по срочным показываются только исполнители с включённым флагом «принимаю срочные заказы». Контакты после «принять запрос». Один ожидающий запрос на заказ. Черновик можно сохранить без отправки. Подробности — SEARCH_ALGORITHM.md.
Тарифы на единицу из списка категории. Тип транспорта — строка machinery_categories (code, категория прав, текст UI). Лицензия — одна на категорию, без approve админа машина не в поиске. Флаг «принимаю срочные заказы» — ручной чекбокс в профиле. Подписка исполнителя спрятана под executor_subscription_enabled.
«Принять запрос» открывает контакты (срок подтверждения условий — 1 сутки). «Подтвердить условия» фиксирует посчитанную сумму. Сделка → оплата 1 сутки, иначе возврат в поиск; прямая → сразу работа. Пока не in_progress, срыв матча возвращает заказ к поиску; полную отмену делает только клиент, исполнитель только отклоняет партнёра. Из in_progress отмена только спором (исключение — плановый до даты начала); completed когда обе стороны подтвердили исполнение. Заказ без найденного исполнителя система снимает сама (срочный — 24 ч без действий клиента, плановый — дата начала).
current_mode; UI от текущего режима.SEARCH_ALGORITHM.md), черновики заказов.assigned нет.in_progress до подтверждения обеими или спора; отмена начатой работы только спором (плановый до даты начала — отмена с причиной).executor_subscription_enabled (в MVP выключен).other (SERVICE_RULES.md, API_CONTRACT_MVP.md раздел 9).Company, CompanyMember, CompanyProject) до подтвержденной потребности.Каждый заказ должен поддерживать два режима расчета:
direct_payment — условия и оплата согласуются напрямую между сторонами;secure_deal — опциональная оплата через платежного провайдера.Каталожные тарифы живут на единице транспорта и задаются исполнителем. Типы: час, смена, сутки, месяц, рейс, километр — какие доступны, зависит от категории (TARIFF_TYPES.md).
Стоимость заказа считает система: ставка выбранного тарифа машины × количество. Заказчик сумму не вводит. Исполнитель подтверждает эти условия отдельной кнопкой после первого «принять» (1 сутки).
Запрос на ожидании ответа — только одному исполнителю. Клиент может снять его до принятия/отказа и выбрать другого. Исполнитель, который отказал или не ответил 5 минут, по этому заказу в выдаче не показывается.
Оплата через приложение не является обязательной для MVP, но архитектура должна быть готова к интеграции платежей.
Нужен абстрактный платежный слой:
PaymentProvider (адаптер провайдера);PaymentService (прикладные сценарии);Функции, которые должны поддерживаться архитектурно:
Источник истины по реальным денежным средствам — внешний платежный провайдер, а не баланс в базе данных.
После captured платформа деньги больше не двигает (админ — только санкции).
«Безопасная сделка» включается по выбору клиента и не должна быть обязательной по умолчанию.
Целевой поток:
awaiting_payment, форма оплаты, 1 сутки;in_progress;expires_at провайдера → disputed только если холд уже был (authorized);Если клиент не создал платёж — провайдер ничего не возвращает; наш таймаут возвращает заказ в поиск исполнителя.
Правка деталей на awaiting_payment — вернуть/отменить платёж, снова переговоры.
executor_subscription_enabled)В MVP флаг выключен.
Когда включён — без активной подписки исполнитель не в поиске и не принимает заказы.
Автоактивация после оплаты (целевой вариант под флагом): отдельный платёж (не холд заказа), webhook → active + срок, по истечении expired и скрытие из поиска. Нужны: продукт подписки в ЮKassa, POST /executor/subscription/pay, идемпотентный webhook, джоба expiry.
Через админку: админ ставит active / срок вручную (оплата вне приложения или без оплаты). Нужны: экран очереди, аудит. Медленнее, зато без рекуррента.
Лицензии подтверждает админ отдельно, не смешивать с оплатой подписки.
Модуль должен быть изолирован так, чтобы MVP можно было запустить без него и безопасно подключить позже.
На ожидании первого ответа — один исполнитель. Не ответил за 5 минут = отказ, повторно на этот заказ нельзя.
Первое «принять» открывает контакты. Если принят срочный заказ — остальные ожидающие срочные запросы этого исполнителя закрываются автоотказом, клиенты получают уведомление, их заказы остаются в поиске; плановые запросы висят до ответа. «Подтвердить условия» (1 сутки) → direct_payment сразу in_progress, secure_deal → awaiting_payment → холд → in_progress. completed — когда обе стороны подтвердили исполнение. На этом заказе после начала работы нового поиска нет.
Минимальные технические гарантии:
User, ExecutorProfile, ExecutorLicenseMachineryUnit, MachineryPhoto, MachineryPricingRule, MachineryCategory, PricingType, CategoryPricingTypeOrder, OrderPricing, OrderCandidate, OrderAssignment, OrderStatusEvent, ContactExchangeEventDispute, DisputeMessage, Review, RatingEvent, NotificationPaymentRecord, PaymentWebhookEventСущности позже:
Company, CompanyMember, CompanyProjectdraft — сохранён без запросаpublished — поиск исполнителя (в том числе после срыва матча до работы)in_negotiation — контакты, правки, «подтвердить условия»awaiting_payment — ждём холд (secure_deal)in_progress — работа, пока обе не подтвердят исполнение или спорcompleted — обе подтвердилиdisputed — спорcancelled — отмена клиентом до работы, отмена планового до даты начала, «исполнитель не найден», отмена админом или исход спораsecure_deal)not_requiredpendingauthorizedcapturedfailedcancelledrefundedНужно проверить минимум три варианта:
В MVP можно стартовать с подписки (или бесплатного периода), а «Безопасную сделку» подключить после подтверждения базовой гипотезы и юридической модели.
Перед запуском «Безопасной сделки» отдельно проверить:
month или большому количеству day длится дольше стандартного холда провайдера; по текущей модели истечение холда переводит заказ в disputed. Нужно выяснить, позволяет ли ЮKassa задавать срок холда под заказ. До ответа ограничений по тарифу не вводим; если нельзя — варианты: ограничить безопасную сделку короткими заказами или перейти к списанию при старте работы (эскроу, другая юридическая модель).Этап 1 (быстрая проверка гипотезы):
Этап 2:
completed);Этап 3:
current_mode.in_progress срыв матча возвращает тот же заказ в поиск; полную отмену до работы делает только клиент.Текст правил — SERVICE_RULES.md: