Содержание
SERVICE_REQUEST в ACCEPTED: подготовка, подтверждение и платёжное ожидание
Назначение: Сценарий процесса. Продукт: ShariX Open.
Для кого: Разработчик · Интегратор · Поддержка · Рецензент и приёмщик · Нейросеть.
Темы: Заказы → Жизненный цикл · Заказы → Финализация оплаты · Заказы → Назначение.
Область: ShariX Open. Обработчик: open_service_request_accepted, тип SERVICE_REQUEST (2), статус ACCEPTED. 31.10.2026 исходники повторно получены из Git. Обе Python-копии совпали с новой канонической генерацией Blockly. Сам обработчик и его внешние действия при анализе не запускались. Выбранная версия, настройки и работоспособность конкретной установки проверяются отдельно.
Назначение и границы
Вход — заказ с назначенным исполнителем, который уже принял его. Handler сопровождает ACCEPTED → PRE_START:
- ждёт доступности подготовки;
- при ручном режиме предлагает подтвердить подготовку;
- по контрольной дате предпринимает обязательную попытку подготовки;
- во всех ветвях сохраняет проверки исполнителя, одновременных заказов и оплаты через prepare-accepted.
Отдельно обрабатывается необходимость привязки карты клиентом сервиса. Ожидание клиентского платёжного действия не приравнивается к отказу исполнителя. BPMN описательные, isExecutable=false; runtime исполняет выбранный проверенный Python из Blockly, а не схему Wiki.
Приоритет ветвей (BPMN)
После проверки своего статуса handler каждый проход загружает context и записывает локальную причину provider_preparation. Чужой статус запрашивает очистку Ticket/комнаты. 404 текущего scope очищает устаревшее локальное состояние; неоднозначность/отсутствие связанного Orders — ошибка API.
1. Привязка карты имеет приоритет
Признак привязки карты строится по customer_action платёжного состояния:
- required=true;
- code=bind_card;
- target=client.
При payment_requires_card_binding handler сразу вызывает prepare-accepted, до проверки времени и auto-режима. Успех/stale освобождает очередь; доменный неуспех ведёт к SERVICE_REQUEST_ACCEPTED_RECHECK_SECONDS.
В этой ветке нет проверки порога неуспехов и автоматического decline-provider, хотя wrapper prepare учитывает доменные неуспехи в общем счётчике. Нельзя описывать ожидание карты как «после нескольких попыток исполнитель автоматически откажется». Вызов проходит реальный payment hook: сам диагностический флаг не является отдельным запретом перехода или разрешением его обойти. Если hook уже допускает подготовку, вызов может завершиться раньше обычной временной ветки.
Платёжная диагностика context ловит исключение и возвращает пустое состояние; отсутствие флага ещё не доказывает отсутствие платёжного ограничения. Решающий hook вызывается при prepare заново.
2. Обязательная попытка по pre_start_at
Когда особой card-ветки нет и pre_start_at наступил:
- Попробовать prepare независимо от AUTO_PRE_START и ответа исполнителя.
- При успехе/stale закончить обработку текущей стадии.
- При доменном неуспехе проверить отдельный счётчик prepare.
- При достижении порога попробовать decline-provider; если порог не достигнут или decline неуспешен — назначить RECHECK.
Обязательна попытка, а не гарантированный PRE_START. Платёжное ограничение или конфликт активных заказов может сохранить ACCEPTED.
«Обязательная» означает обязательную попытку, а не гарантированный PRE_START: конфликт активных заказов или платёжное условие могут оставить ACCEPTED. Если дата отсутствует/некорректна, timing helper не считает её наступившей; это повод проверить исходные даты, а не ждать гарантированного автоматического перехода.
3. Необязательное раннее подтверждение
До pre_start_at включённый SERVICE_REQUEST_ACCEPTED_AUTO_PRE_START пропускает приглашение исполнителю и ждёт RECHECK. Выключенный auto-режим начинает ручной раунд после prepare_available_at. Раньше этого окна тоже только RECHECK.
Порядок ручного раунда:
- Проверить уже сохранённый winner/no_winner.
- Проверить предусмотренное исчерпание попыток.
- Если терминального решения нет — отправить попытку и разобрать queued web intents.
- Снова проверить winner/no_winner.
- Winner ведёт к prepare, no_winner и предусмотренное исчерпание — к decline; иной исход ждёт интервала уведомлений.
Исполнитель, сообщение и срок ответа (BPMN)
Приглашение order.action.required адресуется текущему provider и содержит:
- prepare — подтвердить подготовку;
- decline — отказаться;
- available_from=prepare_available_at;
- due_at=pre_start_at;
- popup_policy=online_only.
Успешный XMPP-send не подтверждает показ интерфейса и прочтение человеком.
Используются SERVICE_REQUEST_ACCEPTED_ROUND_STRATEGY, …DELIVERY_POLICY, число попыток, интервал и окно ответа. Общий срок раунда от создания: (attempts−1) × notification_interval + response_window. Пустой JID/список получателей не даёт успешного раунда; handler остаётся на повторе. Попытка учитывается до I/O, неуспешный send также может расходовать лимит.
У single_confirmation accept/prepare даёт winner, decline — no_winner, timeout — no_winner. У first_accept положительный ответ даёт winner, все отрицательные — no_winner, timeout — timed_out. Этот Python не равняет timed_out и no_winner; закрытый раунд не считается активным для проверки исчерпания, и последующий send может создать новый. При этом проверка обязательной pre_start_at-ветки предшествует любому ручному раунду.
Прямой XMPP-ответ связывается с JID отправителя; web intent принимается через доверенный relay с сохранением actor. Валидатор проверяет актуальные round/order/ticket/status, участника, действие, offer при наличии, срок и повтор. Подтверждение приёма ответа не равно сохранённому PRE_START. Маршруты handler-intents и прямой пользовательский actions API различаются; HTTP 202 relay подтверждает транспорт, не переход заказа.
Backend и внешнее платёжное действие (BPMN)
Backend prepare-accepted:
- Проверяет capability order.prepare_accepted и scope.
- Под lock сверяет ACCEPTED, текущее назначение, provider/user и hard eligibility.
- Применяет concurrency policy.
- Вызывает handle_before_order_pre_start выбранного платёжного backend через facade.
- При допуске сохраняет PRE_START.
Runtime передаёт expected_provider_id, SERVICE_REQUEST_SINGLE_ACTIVE_ORDER, SERVICE_REQUEST_OFFLINE_ON_PRE_START и допустимые location-поля победителя, если они есть.
При допуске сохраняется PRE_START. По настройке предложения исполнителя переводятся offline, запускается предусмотренный prediction hook. Доменный отказ возвращает неуспех без обещания перехода. Даты prepare_available_at/pre_start_at этот narrow action отдельно не проверяет: время определяет текущий Python flow, а backend защищает бизнес-ограничения.
Клиент выполняет требуемую привязку в платёжном интерфейсе вне handler. Конкретный backend, gateway и набор условий зависят от установки; из одной facade нельзя вывести обязательный внешний платёжный сервис. После обновления состояния очередной context/hook заново оценивает готовность. Схема показывает эту зависимость, а не прямую команду от клиента перевести Ticket.
decline-provider — отдельный scoped action с собственным capability и expected provider. Он фиксирует DECLINED и очищает provider при успешном переходе, не возвращает заказ напрямую в BOOKED.
Настройки и диагностика
| Назначение | Настройка / источник |
|---|---|
| Начало подготовки | pre_start_at = planned_start − SERVICE_REQUEST_PRE_START_DURATION_SECONDS |
| Начало раннего приглашения | prepare_available_at = pre_start_at − SERVICE_REQUEST_ACCEPTED_REACTION_LEAD_SECONDS |
| Пропуск приглашения до обязательного срока | SERVICE_REQUEST_ACCEPTED_AUTO_PRE_START |
| Обычный повтор | SERVICE_REQUEST_ACCEPTED_RECHECK_SECONDS |
| Стратегия и доставка | SERVICE_REQUEST_ACCEPTED_ROUND_STRATEGY, SERVICE_REQUEST_ACCEPTED_DELIVERY_POLICY |
| Число попыток / порог доменных неуспехов prepare | SERVICE_REQUEST_ACCEPTED_NOTIFICATION_ATTEMPTS |
| Интервал и окно ответа | SERVICE_REQUEST_ACCEPTED_NOTIFICATION_INTERVAL_SECONDS, SERVICE_REQUEST_ACCEPTED_RESPONSE_WINDOW_SECONDS |
| Дополнительные backend-параметры | SERVICE_REQUEST_SINGLE_ACTIVE_ORDER, SERVICE_REQUEST_OFFLINE_ON_PRE_START |
Счётчик доменных неуспехов prepare отличается от счётчика send-попыток, хотя использует тот же порог NOTIFICATION_ATTEMPTS. Исключение транспорта/401/403/5xx не является автоматически зарегистрированным отрицательным ответом исполнителя: оно идёт в processing_error и общий DEFERRED_TICKET_RECHECK_SECONDS.
При диагностике проверить по порядку:
- Актуальные статус и provider.
- Card-флаг и реальное платёжное состояние.
- prepare_available_at и pre_start_at.
- Auto-настройку и outcome раунда.
- Ответ prepare-accepted/decline-provider и фактически сохранённый Ticket.
Доменный отказ, send failure, молчание человека и ожидание карты — разные причины. Локальный provider_preparation не доказывает отправки приглашения.
Round registry, ответы, send- и action-счётчики живут в памяти процесса и не восстанавливают старый round id после рестарта. Defer освобождает worker; backend event может сделать Ticket ready раньше. После commit перехода ticket.changed будит следующего владельца, ticket.moved очищает прежнего; periodic reconciliation по INTERVAL_TIME_BD_REQ восстанавливает состав при потере событий.
Проверенные источники
Git SHA/SHA-256 и модели закреплены в metadata/BPMN. Handler и бизнес-API при анализе не исполнялись. Сборщик повторно сверяет закреплённые источники; общий автоматический hook Wiki ещё не завершён.
- sharix-open-handlers-examples / handlers/open_service_request_accepted.py — Git 76e0c693b628ed4a1fa34515a3f8abdff26149bb.
- sharix-open-handlers-examples / generated_handler_blocks/open_service_request_accepted.json — Git 76e0c693b628ed4a1fa34515a3f8abdff26149bb.
- sharix-open-handlers-examples / catalog.py — Git 76e0c693b628ed4a1fa34515a3f8abdff26149bb.
- sharix-open-handlers-backend / core/blockly_runtime.py — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-handlers-backend / core/requesters.py — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-handlers-backend / core/order_action_messages.py — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-handlers-backend / ticket_blockly_codegen.py — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-handlers-backend / ticket_codegen_contract.json — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-tickets / lib/tickets.py — Git fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14.
- sharix-open-tickets / api/handler_auth.py — Git fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14.
- sharix-open-tickets / signals.py — Git fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14.
- sharix-open-tickets / services/handler_wakeup.py — Git fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14.
- sharix-open-backend / apiviews/handler_order_workflow.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / apiviews/open_api.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/order_handler_relay.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/handler_order_context.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/order_workflow_policy.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/order_actions.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/order_permissions.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / urls.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/order_lifecycle.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-backend / lib/order_provider_requirements.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.
- sharix-open-handlers-backend / core/order_rounds.py — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-handlers-backend / settings_schema.py — Git 50baf376e224d915a87d63240f3f339b3dda9afa.
- sharix-open-backend / lib/payments/facade.py — Git 778a3280cee115ba0efe3fdff7b0e708b0c10093.