Инструменты пользователя

Инструменты сайта


sharixopen:knowledge:scenarios:service_request_declined

SERVICE_REQUEST в DECLINED: возврат в BOOKED и резервное закрытие

Назначение: Сценарий процесса. Продукт: ShariX Open.

Для кого: Разработчик · Интегратор · Поддержка · Рецензент и приёмщик · Нейросеть.

Темы: Заказы → Жизненный цикл · Заказы → Назначение · Обработчики → Runtime.

Область: ShariX Open. Обработчик: open_service_request_declined, тип SERVICE_REQUEST (2), статус DECLINED. На 31.10.2026 обе опубликованные Python-копии побайтово совпали с генерацией Blockly workspace. Это проверка исходников, а не запуск операций над заказами.

Назначение и границы

Обработчик сопровождает заказ после зафиксированного отказа исполнителя. Его первое действие — попытка возврата в BOOKED, чтобы дальнейший процесс продолжил соответствующий handler. Он не выбирает новых кандидатов, не рассылает предложения и не повторяет раунд подтверждения самостоятельно.

Закрытие по сроку — резервная ветка после обработанного неуспеха возврата. Это принципиально отличается от схемы «подождать после отказа, затем всегда закрыть заказ». BPMN описательные, isExecutable=false; исполняется выбранный проверенный Python, сгенерированный из Blockly.

Порядок решений (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_service_declined_logic" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="declined_Process_declined" name="DECLINED: сначала возврат к поиску, затем условный fallback закрытия" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN описательная, isExecutable=false; канонический Python получен из Blockly.", "Возврат BOOKED имеет приоритет над проверкой срока закрытия.", "declined_close_at в runtime считается от Ticket.updated_at, не от создания заказа."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_declined.py", "repository": "sharix-open-handlers-examples", "sha256": "94f135d86092ff98644b626724c4d50f48b9fcc61d23f733f9ee98f264a68657"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_declined.json", "repository": "sharix-open-handlers-examples", "sha256": "d8f754511eefb8381512f28cf8fcd499a67218be67be51e91fe4448698a75859"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}]}</bpmn:documentation>
    <bpmn:laneSet id="declined_Lanes_declined">
      <bpmn:lane id="declined_Lane_worker" name="Свой статус и scoped context; reason return_to_booked">
        <bpmn:flowNodeRef>declined_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_return</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_returned</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_booked</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_due</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_close</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_closed</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_defer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_return_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_close_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>declined_error</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="declined_start" name="DECLINED и context получен">
      <bpmn:outgoing>declined_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:serviceTask id="declined_return" name="return-declined-to-booked">
      <bpmn:incoming>declined_Flow_0</bpmn:incoming>
      <bpmn:outgoing>declined_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="declined_returned" name="Успех / stale?">
      <bpmn:incoming>declined_Flow_1</bpmn:incoming>
      <bpmn:outgoing>declined_Flow_2</bpmn:outgoing>
      <bpmn:outgoing>declined_Flow_3</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:endEvent id="declined_booked" name="Очередь освобождена; при успехе BOOKED">
      <bpmn:incoming>declined_Flow_2</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:exclusiveGateway id="declined_due" name="Срок fallback закрытия наступил?">
      <bpmn:incoming>declined_Flow_3</bpmn:incoming>
      <bpmn:outgoing>declined_Flow_4</bpmn:outgoing>
      <bpmn:outgoing>declined_Flow_6</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="declined_close" name="close-declined (strict result)">
      <bpmn:incoming>declined_Flow_4</bpmn:incoming>
      <bpmn:outgoing>declined_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="declined_closed" name="Успех/stale: очередь освобождена">
      <bpmn:incoming>declined_Flow_5</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="declined_defer" name="DECLINED_RECHECK_SECONDS">
      <bpmn:incoming>declined_Flow_6</bpmn:incoming>
      <bpmn:outgoing>declined_Flow_7</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="declined_wait" name="Worker свободен; повтор позже / по событию">
      <bpmn:incoming>declined_Flow_7</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:boundaryEvent id="declined_return_error" name="API исключение" attachedToRef="declined_return" cancelActivity="true">
      <bpmn:outgoing>declined_Flow_8</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:boundaryEvent id="declined_close_error" name="API/доменный неуспех" attachedToRef="declined_close" cancelActivity="true">
      <bpmn:outgoing>declined_Flow_9</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:endEvent id="declined_error" name="processing_error, общий defer">
      <bpmn:incoming>declined_Flow_8</bpmn:incoming>
      <bpmn:incoming>declined_Flow_9</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="declined_Flow_0" sourceRef="declined_start" targetRef="declined_return" name="" />
    <bpmn:sequenceFlow id="declined_Flow_1" sourceRef="declined_return" targetRef="declined_returned" name="" />
    <bpmn:sequenceFlow id="declined_Flow_2" sourceRef="declined_returned" targetRef="declined_booked" name="Да" />
    <bpmn:sequenceFlow id="declined_Flow_3" sourceRef="declined_returned" targetRef="declined_due" name="Нет" />
    <bpmn:sequenceFlow id="declined_Flow_4" sourceRef="declined_due" targetRef="declined_close" name="Да" />
    <bpmn:sequenceFlow id="declined_Flow_5" sourceRef="declined_close" targetRef="declined_closed" name="" />
    <bpmn:sequenceFlow id="declined_Flow_6" sourceRef="declined_due" targetRef="declined_defer" name="Нет" />
    <bpmn:sequenceFlow id="declined_Flow_7" sourceRef="declined_defer" targetRef="declined_wait" name="" />
    <bpmn:sequenceFlow id="declined_Flow_8" sourceRef="declined_return_error" targetRef="declined_error" name="" />
    <bpmn:sequenceFlow id="declined_Flow_9" sourceRef="declined_close_error" targetRef="declined_error" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_service_declined_logic">
    <bpmn:participant id="declined_Pool_declined" name="DECLINED: сначала возврат к поиску, затем условный fallback закрытия" processRef="declined_Process_declined" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_service_declined_logic">
    <bpmndi:BPMNPlane id="Plane_service_declined_logic" bpmnElement="Collaboration_service_declined_logic">
      <bpmndi:BPMNShape id="declined_DI_Pool_declined" bpmnElement="declined_Pool_declined" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1530" height="680" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_Lane_worker" bpmnElement="declined_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1500" height="680" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_start" bpmnElement="declined_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_return" bpmnElement="declined_return">
        <dc:Bounds x="365.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_returned" bpmnElement="declined_returned">
        <dc:Bounds x="725.0" y="75.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_booked" bpmnElement="declined_booked">
        <dc:Bounds x="1042.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_due" bpmnElement="declined_due">
        <dc:Bounds x="725.0" y="315.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_close" bpmnElement="declined_close">
        <dc:Bounds x="985.0" y="305.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_closed" bpmnElement="declined_closed">
        <dc:Bounds x="1352.0" y="322.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_defer" bpmnElement="declined_defer">
        <dc:Bounds x="675.0" y="545.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_wait" bpmnElement="declined_wait">
        <dc:Bounds x="1042.0" y="562.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_return_error" bpmnElement="declined_return_error">
        <dc:Bounds x="472.0" y="117.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_close_error" bpmnElement="declined_close_error">
        <dc:Bounds x="1092.0" y="357.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="declined_DI_error" bpmnElement="declined_error">
        <dc:Bounds x="1352.0" y="562.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="declined_DI_Flow_0" bpmnElement="declined_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="365.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_1" bpmnElement="declined_Flow_1">
        <di:waypoint x="515.0" y="100.0" />
        <di:waypoint x="725.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_2" bpmnElement="declined_Flow_2">
        <di:waypoint x="775.0" y="100.0" />
        <di:waypoint x="1042.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_3" bpmnElement="declined_Flow_3">
        <di:waypoint x="750.0" y="125.0" />
        <di:waypoint x="750.0" y="315.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_4" bpmnElement="declined_Flow_4">
        <di:waypoint x="775.0" y="340.0" />
        <di:waypoint x="985.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_5" bpmnElement="declined_Flow_5">
        <di:waypoint x="1135.0" y="340.0" />
        <di:waypoint x="1352.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_6" bpmnElement="declined_Flow_6">
        <di:waypoint x="750.0" y="365.0" />
        <di:waypoint x="750.0" y="545.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_7" bpmnElement="declined_Flow_7">
        <di:waypoint x="825.0" y="580.0" />
        <di:waypoint x="1042.0" y="580.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_8" bpmnElement="declined_Flow_8">
        <di:waypoint x="508.0" y="135.0" />
        <di:waypoint x="550.0" y="135.0" />
        <di:waypoint x="550.0" y="510.0" />
        <di:waypoint x="1370.0" y="510.0" />
        <di:waypoint x="1370.0" y="562.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="declined_DI_Flow_9" bpmnElement="declined_Flow_9">
        <di:waypoint x="1128.0" y="375.0" />
        <di:waypoint x="1170.0" y="375.0" />
        <di:waypoint x="1250.0" y="375.0" />
        <di:waypoint x="1250.0" y="510.0" />
        <di:waypoint x="1370.0" y="510.0" />
        <di:waypoint x="1370.0" y="562.0" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

После проверки своего статуса загружается scoped order context, записывается локальная причина return_to_booked, затем вызывается return-declined-to-booked.

  • Успех или stale освобождает текущую очередь и заканчивает проход. При успешном переходе далее работает BOOKED.
  • Обработанный доменный неуспех позволяет проверить declined_close_at.
  • Только при наступившем сроке предпринимается close-declined.
  • Если срок ещё не наступил, назначается defer по SERVICE_REQUEST_DECLINED_RECHECK_SECONDS.

Даже если срок закрытия уже прошёл, успешный возврат BOOKED имеет приоритет: проверка даты до него не выполняется. Исключение транспорта/API при возврате прерывает проход; fallback закрытия после исключения в том же проходе не вызывается.

Результаты API нужно различать:

  • У wrapper возврата разрешён обработанный доменный неуспех: после него можно проверить срок закрытия.
  • У close-declined результат строгий: отрицательный бизнес-ответ может перейти в общий processing_error.
  • Scoped 404 означает stale: локальное состояние очищается. Это не подтверждение перехода, выполненного именно данным вызовом.
  • Исключение транспорта, авторизации или разбора ответа прерывает проход; резервное закрытие вслед за таким исключением не вызывается.

Backend и передача следующему обработчику (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_service_declined_handoff" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="backend_Process_backend" name="Backend: транзакция канонического действия и wakeup после commit" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN описательная, isExecutable=false; канонический Python получен из Blockly.", "Возврат BOOKED имеет приоритет над проверкой срока закрытия.", "declined_close_at в runtime считается от Ticket.updated_at, не от создания заказа.", "Два narrow actions, не generic ticket.transition.", "Закрытие не выполняет платёжный gate DONE: это другая ветка жизненного цикла."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_declined.py", "repository": "sharix-open-handlers-examples", "sha256": "94f135d86092ff98644b626724c4d50f48b9fcc61d23f733f9ee98f264a68657"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_declined.json", "repository": "sharix-open-handlers-examples", "sha256": "d8f754511eefb8381512f28cf8fcd499a67218be67be51e91fe4448698a75859"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}]}</bpmn:documentation>
    <bpmn:laneSet id="backend_Lanes_backend">
      <bpmn:lane id="backend_Lane_worker" name="HasHandlerAPIKey + capability + текущий Ticket scope">
        <bpmn:flowNodeRef>backend_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_check</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_save</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_notify</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_close</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_scope</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_closed</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="backend_start" name="return-declined-to-booked">
      <bpmn:outgoing>backend_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="backend_check" name="Lock актуального Orders; проверить DECLINED">
      <bpmn:incoming>backend_Flow_0</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="backend_save" name="Канонический BOOKED; при успехе очистить provider">
      <bpmn:incoming>backend_Flow_1</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_2</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sendTask id="backend_notify" name="После commit: ticket.changed / ticket.moved">
      <bpmn:incoming>backend_Flow_2</bpmn:incoming>
      <bpmn:incoming>backend_Flow_6</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_3</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="backend_end" name="Новый handler отвечает за дальнейший процесс">
      <bpmn:incoming>backend_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:startEvent id="backend_close" name="Fallback close-declined после проверки времени в runtime">
      <bpmn:outgoing>backend_Flow_4</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="backend_scope" name="Lock + ожидаемый DECLINED; дату отдельно не проверяет">
      <bpmn:incoming>backend_Flow_4</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="backend_closed" name="Канонический CLOSED">
      <bpmn:incoming>backend_Flow_5</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_6</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sequenceFlow id="backend_Flow_0" sourceRef="backend_start" targetRef="backend_check" name="" />
    <bpmn:sequenceFlow id="backend_Flow_1" sourceRef="backend_check" targetRef="backend_save" name="" />
    <bpmn:sequenceFlow id="backend_Flow_2" sourceRef="backend_save" targetRef="backend_notify" name="" />
    <bpmn:sequenceFlow id="backend_Flow_3" sourceRef="backend_notify" targetRef="backend_end" name="" />
    <bpmn:sequenceFlow id="backend_Flow_4" sourceRef="backend_close" targetRef="backend_scope" name="" />
    <bpmn:sequenceFlow id="backend_Flow_5" sourceRef="backend_scope" targetRef="backend_closed" name="" />
    <bpmn:sequenceFlow id="backend_Flow_6" sourceRef="backend_closed" targetRef="backend_notify" name="" />
  </bpmn:process>
  <bpmn:process id="queue_Process_queue" name="Очереди handler: доставка события не является самим commit" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN описательная, isExecutable=false; канонический Python получен из Blockly.", "Возврат BOOKED имеет приоритет над проверкой срока закрытия.", "declined_close_at в runtime считается от Ticket.updated_at, не от создания заказа.", "Два narrow actions, не generic ticket.transition.", "Закрытие не выполняет платёжный gate DONE: это другая ветка жизненного цикла."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_declined.py", "repository": "sharix-open-handlers-examples", "sha256": "94f135d86092ff98644b626724c4d50f48b9fcc61d23f733f9ee98f264a68657"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_declined.json", "repository": "sharix-open-handlers-examples", "sha256": "d8f754511eefb8381512f28cf8fcd499a67218be67be51e91fe4448698a75859"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}]}</bpmn:documentation>
    <bpmn:laneSet id="queue_Lanes_queue">
      <bpmn:lane id="queue_Lane_worker" name="XMPP wakeup и периодическое восстановление">
        <bpmn:flowNodeRef>queue_event</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_sync</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_end</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="queue_event" name="Получить changed/moved либо reconcile">
      <bpmn:outgoing>queue_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="queue_sync" name="Следующий владелец ready; прежний удаляет локальное состояние">
      <bpmn:incoming>queue_Flow_0</bpmn:incoming>
      <bpmn:outgoing>queue_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="queue_end" name="BOOKED обрабатывает собственный handler; CLOSED без этого этапа">
      <bpmn:incoming>queue_Flow_1</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="queue_Flow_0" sourceRef="queue_event" targetRef="queue_sync" name="" />
    <bpmn:sequenceFlow id="queue_Flow_1" sourceRef="queue_sync" targetRef="queue_end" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_service_declined_handoff">
    <bpmn:participant id="backend_Pool_backend" name="Backend: транзакция канонического действия и wakeup после commit" processRef="backend_Process_backend" />
    <bpmn:participant id="queue_Pool_queue" name="Очереди handler: доставка события не является самим commit" processRef="queue_Process_queue" />
    <bpmn:messageFlow id="Message_service_declined_handoff_0" sourceRef="backend_notify" targetRef="queue_event" name="Потеря события компенсируется periodic reconciliation" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_service_declined_handoff">
    <bpmndi:BPMNPlane id="Plane_service_declined_handoff" bpmnElement="Collaboration_service_declined_handoff">
      <bpmndi:BPMNShape id="backend_DI_Pool_backend" bpmnElement="backend_Pool_backend" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1530" height="500" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_Lane_worker" bpmnElement="backend_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1500" height="500" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_start" bpmnElement="backend_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_check" bpmnElement="backend_check">
        <dc:Bounds x="365.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_save" bpmnElement="backend_save">
        <dc:Bounds x="675.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_notify" bpmnElement="backend_notify">
        <dc:Bounds x="985.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_end" bpmnElement="backend_end">
        <dc:Bounds x="1352.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_close" bpmnElement="backend_close">
        <dc:Bounds x="132.0" y="382.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_scope" bpmnElement="backend_scope">
        <dc:Bounds x="365.0" y="365.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_closed" bpmnElement="backend_closed">
        <dc:Bounds x="675.0" y="365.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="backend_DI_Flow_0" bpmnElement="backend_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="365.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_1" bpmnElement="backend_Flow_1">
        <di:waypoint x="515.0" y="100.0" />
        <di:waypoint x="675.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_2" bpmnElement="backend_Flow_2">
        <di:waypoint x="825.0" y="100.0" />
        <di:waypoint x="985.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_3" bpmnElement="backend_Flow_3">
        <di:waypoint x="1135.0" y="100.0" />
        <di:waypoint x="1352.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_4" bpmnElement="backend_Flow_4">
        <di:waypoint x="168.0" y="400.0" />
        <di:waypoint x="365.0" y="400.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_5" bpmnElement="backend_Flow_5">
        <di:waypoint x="515.0" y="400.0" />
        <di:waypoint x="675.0" y="400.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_6" bpmnElement="backend_Flow_6">
        <di:waypoint x="825.0" y="400.0" />
        <di:waypoint x="870.0" y="400.0" />
        <di:waypoint x="930.0" y="400.0" />
        <di:waypoint x="930.0" y="30.0" />
        <di:waypoint x="1060.0" y="30.0" />
        <di:waypoint x="1060.0" y="65.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="queue_DI_Pool_queue" bpmnElement="queue_Pool_queue" isHorizontal="true">
        <dc:Bounds x="0.0" y="720.0" width="910" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_Lane_worker" bpmnElement="queue_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="720.0" width="880" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_event" bpmnElement="queue_event">
        <dc:Bounds x="132.0" y="802.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_sync" bpmnElement="queue_sync">
        <dc:Bounds x="365.0" y="785.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_end" bpmnElement="queue_end">
        <dc:Bounds x="732.0" y="802.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="queue_DI_Flow_0" bpmnElement="queue_Flow_0">
        <di:waypoint x="168.0" y="820.0" />
        <di:waypoint x="365.0" y="820.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="queue_DI_Flow_1" bpmnElement="queue_Flow_1">
        <di:waypoint x="515.0" y="820.0" />
        <di:waypoint x="732.0" y="820.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_service_declined_handoff_0" bpmnElement="Message_service_declined_handoff_0">
        <di:waypoint x="1060" y="135" />
        <di:waypoint x="1060" y="640" />
        <di:waypoint x="150" y="640" />
        <di:waypoint x="150" y="802" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="200" y="600" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Оба действия проходят HasHandlerAPIKey, отдельный capability и текущий Ticket scope. Они не используют произвольный generic ticket.transition.

Возврат в BOOKED — return-declined-to-booked:

  • Требует capability order.return_declined_to_booked.
  • Блокирует актуальный Orders и проверяет ожидаемый DECLINED.
  • Выполняет канонический переход в BOOKED; при успехе очищает прежний provider.
  • Не ждёт grace, не проверяет дату резервного закрытия и не требует заранее пустого provider.

Резервное закрытие — close-declined:

  • Требует capability order.close_declined.
  • Под блокировкой проверяет DECLINED, затем выполняет канонический CLOSED.
  • Сам action не проверяет возраст заявки: срок проверяет вызывающий Python.
  • Платёжный gate закрытия DONE здесь не вызывается: это другая ветвь жизненного цикла.

После commit ticket.changed будит нового владельца, ticket.moved сообщает прежнему об уходе Ticket. Потерянная доставка не откатывает сохранённый статус; periodic reconciliation восстанавливает состав очередей. BOOKED далее самостоятельно решает вопрос входа в PENDING и пользовательских take/cancel. Этот handler не обещает мгновенного назначения нового исполнителя.

От какой даты считается fallback

Дата резервного закрытия рассчитывается так:

  1. Из order context берётся ticket.status_entered_at.
  2. В текущем backend это Ticket.updated_at, а не отдельная неизменяемая дата входа в DECLINED.
  3. К ней прибавляется SERVICE_REQUEST_DECLINED_CLOSE_AFTER_SECONDS с минимумом 0.
  4. При отсутствующей или некорректной дате helper не считает срок наступившим.

Следовательно, обновление Ticket может сдвинуть расчётную дату. При отсутствии status_entered_at или некорректной дате helper не считает срок наступившим. Не следует обещать точное закрытие через заданный интервал после исторического отказа, если дата в Ticket менялась.

Ожидание, ошибки и диагностика

Назначение Настройка
Обычный повтор после неуспешного возврата без закрытия SERVICE_REQUEST_DECLINED_RECHECK_SECONDS
Задержка резервного закрытия от context status_entered_at SERVICE_REQUEST_DECLINED_CLOSE_AFTER_SECONDS
Общее исключение DEFERRED_TICKET_RECHECK_SECONDS, processing_error
Восстановление состава очереди INTERVAL_TIME_BD_REQ

Defer освобождает worker; внешнее событие может сделать Ticket ready раньше. Локальная причина return_to_booked не означает, что возврат уже сохранился. Здесь нет собственного пользовательского сообщения с требованием ответа: источником изменения служит канонический backend action либо другое разрешённое внешнее действие, после которого handler замечает смену статуса.

Порядок диагностики:

  1. Перечитайте фактические Orders, Ticket и provider; проверьте ответ return-declined-to-booked.
  2. Если BOOKED уже сохранён, отсутствие последующего close ожидаемо: возврат имеет приоритет даже при прошедшем сроке.
  3. Если DECLINED сохранён, отдельно проверьте доменный ответ возврата, transport/auth error, расчёт даты и ответ close.
  4. Сопоставьте локальный reason/defer с каноническим статусом: return_to_booked обозначает намерение, а не сохранённый результат.
  5. Отсутствие XMPP-события само по себе не является основанием повторить прежнюю запись в API.

Проверенные источники

На 31.10.2026 повторно проверены закреплённые Git-файлы и каноническая генерация. В обновившихся репозиториях tickets исходные файлы не изменились; в backend изменился только urls.py — добавлены маршруты скачивания документов, маршруты этого сценария сохранены. BPMN сохранены вместе с историческими ссылками на исходники; актуальные commits приведены ниже. Общий автоматический hook обновления Wiki этой проверкой не подтверждается.

Связанные материалы

sharixopen/knowledge/scenarios/service_request_declined.txt · Последнее изменение: — sx_knowledge_api_open

© 2022 ShariX