| |
| sharixopen:knowledge:scenarios:st_request_assigned [2026/10/28 18:19] – [sharixknowledge] approved package sx_knowledge_api_open | sharixopen:knowledge:scenarios:st_request_assigned [2026/10/31 13:21] (текущий) – [sharixknowledge] approved package sx_knowledge_api_open |
|---|
| "ShariXKnowledgeOpenKnowledgeOperationsRuntimehealth", | "ShariXKnowledgeOpenKnowledgeOperationsRuntimehealth", |
| "ShariXKnowledgeScenarios" | "ShariXKnowledgeScenarios" |
| | ], |
| | "depends_on": [ |
| | "ShariXKnowledgeOpenKnowledgeModulesHandlers" |
| | ], |
| | "verified_by": [ |
| | "ShariXKnowledgeVerification" |
| ] | ] |
| }, | }, |
| "domain": "business_processes", | "domain": "business_processes", |
| "lifecycle": "implemented", | "lifecycle": "implemented", |
| "component": "handlers", | "component": "handlers_examples, handlers_backend, tickets", |
| "parents": [ | "parents": [ |
| "ShariXKnowledgeScenarios" | "ShariXKnowledgeScenarios" |
| ], | ], |
| "terms": [ | "terms": [ |
| "ST_REQUEST", | "audience_developer", |
| "ASSIGNED", | "audience_support", |
| "BPMN" | "audience_reviewer", |
| | "audience_ai", |
| | "product_sharix_open", |
| | "material_scenario", |
| | "topic_handlers_support", |
| | "topic_handlers_runtime", |
| | "st_request", |
| | "ticket_assigned", |
| | "bpmn", |
| | "ticket", |
| | "blockly", |
| | "generated_python" |
| ] | ] |
| }, | }, |
| "path": "lib/tickets.py", | "path": "lib/tickets.py", |
| "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883" | "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883" |
| | }, |
| | { |
| | "repository": "sharix-open-tickets", |
| | "commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", |
| | "path": "models/ticket.py", |
| | "sha256": "4768d9ef47b61bf3ae98bf2749ed142adc477978b44de29177363ba9664baa43" |
| } | } |
| ], | ], |
| "cleanup": "f88cb3844123482c917a759e6b31c82894cd156acbd652a75a883997cfc33715" | "cleanup": "f88cb3844123482c917a759e6b31c82894cd156acbd652a75a883997cfc33715" |
| } | } |
| | }, |
| | "classification": { |
| | "schema": "sharix.knowledge.classification.v1", |
| | "products": [ |
| | "sharix_open" |
| | ], |
| | "audiences": [ |
| | "developer", |
| | "support", |
| | "reviewer", |
| | "ai" |
| | ], |
| | "material": "scenario", |
| | "topics": [ |
| | "handlers/support", |
| | "handlers/runtime" |
| | ], |
| | "tag_terms": [ |
| | "audience_developer", |
| | "audience_support", |
| | "audience_reviewer", |
| | "audience_ai", |
| | "product_sharix_open", |
| | "material_scenario", |
| | "topic_handlers_support", |
| | "topic_handlers_runtime", |
| | "st_request", |
| | "ticket_assigned", |
| | "bpmn", |
| | "ticket", |
| | "blockly", |
| | "generated_python" |
| | ], |
| | "registry_document": "ShariXKnowledgeClassification", |
| | "state_meaning": "implemented — описана проверенная реализация исходников; серверный runtime отдельно; review — состояние текста" |
| | }, |
| | "editorial_review": { |
| | "date": "2026-10-31", |
| | "scope": "Конкретизация действий, условий, результатов и диагностики; перечисления; исходные BPMN сохранены", |
| | "current_source_records_verified": 15, |
| | "original_source_evidence_recheck": "После git fetch все исходные commits/SHA-256 совпали; дополнительные функциональные источники включены в source_evidence", |
| | "canonical_regeneration": { |
| | "kind": "ticket", |
| | "compared_python_paths": [ |
| | "handlers/open_st_request_assigned.py", |
| | "generated_handlers/open_st_request_assigned.py" |
| | ], |
| | "generator_sources_verified": 11, |
| | "handler_executed": false |
| | }, |
| | "runtime_checked": false |
| } | } |
| }, | }, |
| "content_sha256": "df75f4237c679f85d74cd0732271fa7b951eddf5af29a0eaa04f97a1ae1fc2aa", | "content_sha256": "ff828567f52cfb9fcadb207cda4b0effa0072889852b3f404c8c8468977f7a9f", |
| "schema": 1 | "schema": 1 |
| } | } |
| ~~NOCACHE~~ | ~~NOCACHE~~ |
| |
| **Область:** ShariX Open. **Обработчик:** ''open_st_request_assigned'', тип ''ST_REQUEST'' (1), рабочий статус ''ASSIGNED''. Описана опубликованная встроенная реализация и проверенные внешние контракты на 28.10.2026. Python побайтово сверен с каноническим render его Blockly workspace. На конкретном сервере дополнительно имеют значение выбранная локальная версия, настройки и готовность runtime. | **Назначение:** [[sharixopen:knowledge:classification:materials#scenarij_processa|Сценарий процесса]]. **Продукт:** [[sharixopen:knowledge:classification:products#sharix_open|ShariX Open]]. |
| | |
| | **Для кого:** [[sharixopen:knowledge:classification:audiences#razrabotchik|Разработчик]] · [[sharixopen:knowledge:classification:audiences#podderzhka|Поддержка]] · [[sharixopen:knowledge:classification:audiences#recenzent_i_prijomschik|Рецензент и приёмщик]] · [[sharixopen:knowledge:classification:audiences#nejroset|Нейросеть]]. |
| | |
| | **Темы:** [[sharixopen:knowledge:classification:topics#st_request|Обработчики → ST_REQUEST]] · [[sharixopen:knowledge:classification:topics#runtime|Обработчики → Runtime]]. |
| | |
| | |
| | |
| | **Область:** ShariX Open. **Обработчик:** ''open_st_request_assigned'', тип ''ST_REQUEST'' (1), рабочий статус ''ASSIGNED''. 31.10.2026 исходники повторно получены из Git. Обе Python-копии совпали с новой канонической генерацией Blockly; проверены 11 исходников генераторов. Сам обработчик и его внешние действия не запускались. Выбранная версия, настройки и доступность подключений конкретной установки проверяются отдельно. |
| |
| ===== Назначение и границы ===== | ===== Назначение и границы ===== |
| Обработчик обслуживает уже назначенную стадию заявки. Он не выбирает сотрудника, не заполняет ''assigned_to'', не проверяет наличие назначенного человека и сам не выполняет содержание обращения. При ручном режиме он освобождает worker и ждёт дальнейшего действия; при автоматическом — запрашивает следующий статус и передаёт Ticket следующему обработчику. | Обработчик сопровождает уже назначенную стадию: |
| | |
| | * при ручном режиме освобождает worker и ждёт действия пользователя; |
| | * при автоматическом режиме запрашивает IN_PROCESS и передаёт Ticket следующему handler; |
| | * не выбирает сотрудника и не заполняет assigned_to; |
| | * не проверяет наличие назначенного человека; |
| | * не выполняет содержание обращения. |
| |
| Статус ''ASSIGNED'' и заполненное поле ''assigned_to'' — разные факты. Автоматическое продвижение статуса не назначает исполнителя задним числом. Техническая причина ''support_execution'' — локальная отметка runtime, а не комментарий в карточке, не поручение пользователю и не сообщение об успешно выполненной работе. | Статус ''ASSIGNED'' и заполненное поле ''assigned_to'' — разные факты. Автоматическое продвижение статуса не назначает исполнителя задним числом. Техническая причина ''support_execution'' — локальная отметка runtime, а не комментарий в карточке, не поручение пользователю и не сообщение об успешно выполненной работе. |
| Сначала проверяется статус локального authoritative-снимка, который очередь получила из backend или входящего Ticket. Отдельный API GET на каждом проходе здесь не выполняется. Если снимок уже не в ''ASSIGNED'', обработчик запрашивает исключение из своей очереди и удаление комнаты уведомлений; сам Ticket в backend этим не удаляется. | Сначала проверяется статус локального authoritative-снимка, который очередь получила из backend или входящего Ticket. Отдельный API GET на каждом проходе здесь не выполняется. Если снимок уже не в ''ASSIGNED'', обработчик запрашивает исключение из своей очереди и удаление комнаты уведомлений; сам Ticket в backend этим не удаляется. |
| |
| При выключенном ''STREQ_AUTOACCEPT'' записывается ''support_execution'' и назначается defer через ''ST_REQUEST_ASSIGNED_RECHECK_SECONDS''. Текущий worker освобождается. Срок делает Ticket пригодным для повторной постановки в ready FIFO; запуск зависит также от свободного worker и готовности XMPP. Новая подтверждённая ревизия снимка может снять defer раньше. Одинаковое повторное событие само по себе не является новым решением и не требует повторного бизнес-действия. | Ручной режим, STREQ_AUTOACCEPT выключен: |
| |
| При включённом ''STREQ_AUTOACCEPT'' выполняется узкая операция ''ticket.transition'' в ''IN_PROCESS''. Успех API предшествует ''send_to_handler'' в ''open_st_request_inprocess''. Затем текущая очередь освобождается с ''delete_room=False''. Это успешная попытка передачи, а не подтверждение выполнения следующей стадии. ''STREQ_AUTOACCEPT'' выбирается при создании HandlerContext; сохранение значения в файле не доказывает, что уже работающий процесс его перечитал. | - Записать локальную причину support_execution. |
| | - Назначить defer по ST_REQUEST_ASSIGNED_RECHECK_SECONDS. |
| | - Освободить текущий worker. |
| | - После срока Ticket снова может попасть в ready FIFO; новая подтверждённая ревизия может снять ожидание раньше. |
| | |
| | Фактический запуск зависит от worker и XMPP. Повтор одинакового снимка не является новым решением и не обнуляет defer. |
| | |
| | Автоматический режим: |
| | |
| | - Запросить IN_PROCESS через scoped ticket.transition. |
| | - После успешного ответа API выполнить send_to_handler в open_st_request_inprocess. |
| | - Убрать Ticket из текущей очереди с delete_room=False. |
| | |
| | Это передача следующей стадии, а не подтверждение выполнения заявки. Значение STREQ_AUTOACCEPT берётся при создании HandlerContext; сохранение нового значения в файле не доказывает его применения работающим процессом. |
| |
| Если scoped API вернул 404, runtime трактует снимок как больше не принадлежащий этому обработчику, запрашивает очистку и не делает handoff. Другие ошибки API и ошибки XMPP-отправки проходят через общий error recovery: фиксируется ''processing_error'', назначается defer по ''DEFERRED_TICKET_RECHECK_SECONDS'', ошибка попадает в диагностику. Если переход уже committed, ошибка отправки не возвращает статус в ''ASSIGNED''. | Если scoped API вернул 404, runtime трактует снимок как больше не принадлежащий этому обработчику, запрашивает очистку и не делает handoff. Другие ошибки API и ошибки XMPP-отправки проходят через общий error recovery: фиксируется ''processing_error'', назначается defer по ''DEFERRED_TICKET_RECHECK_SECONDS'', ошибка попадает в диагностику. Если переход уже committed, ошибка отправки не возвращает статус в ''ASSIGNED''. |
| Пользователь открывает карточку Ticket и выбирает ''IN_PROCESS'' среди доступных переходов. Страница публикуется по маршруту ''tickets/ticket/<id>/''; пользовательский API использует ''tickets/api/ticket/<id>/status''. Общий префикс установки определяется её URL-конфигурацией. Наличие видимой ссылки или знание id не заменяют доступ к Ticket и право смены статуса. | Пользователь открывает карточку Ticket и выбирает ''IN_PROCESS'' среди доступных переходов. Страница публикуется по маршруту ''tickets/ticket/<id>/''; пользовательский API использует ''tickets/api/ticket/<id>/status''. Общий префикс установки определяется её URL-конфигурацией. Наличие видимой ссылки или знание id не заменяют доступ к Ticket и право смены статуса. |
| |
| View проверяет объектный доступ и ''user_can_change_ticket_status''. Предикат допускает staff/superuser, участника группы списка тикета, назначенного пользователя и, в общем контракте Tickets, provider связанного Order. Сам факт создания Ticket не даёт права принять его или начать обработку. Затем ''change_ticket_status'' проверяет допустимость перехода; эта общая функция сама не проверяет объектные права — это обязанность вызывающего слоя. | Перед пользовательским переходом проверяются: |
| | |
| | * объектный доступ к Ticket; |
| | * user_can_change_ticket_status: staff/superuser, участник группы списка, назначенный пользователь либо provider связанного заказа в общем контракте Tickets; |
| | * допустимость выбранного перехода в change_ticket_status. |
| | |
| | Создание Ticket само по себе не даёт права начать обработку. Change_ticket_status проверяет lifecycle, а объектные права обязан проверить вызывающий слой. Для связанного заказа действуют его доменные ограничения. |
| |
| У автоматического обработчика другой вход: ''tickets/api/handler/ticket/<id>/transition'', identity API-ключа, capability ''ticket.transition'', рабочая область статуса и блокировка строки. Пользовательский и handler API нельзя считать взаимозаменяемыми по доступу. | У автоматического обработчика другой вход: ''tickets/api/handler/ticket/<id>/transition'', identity API-ключа, capability ''ticket.transition'', рабочая область статуса и блокировка строки. Пользовательский и handler API нельзя считать взаимозаменяемыми по доступу. |
| |
| При успешном каноническом переходе backend сохраняет статус и Event. После commit планируются **два разных события**: | После сохранения статуса и Event и завершения commit направляются два события: |
| * ''ticket.changed'' с новым статусом ''IN_PROCESS'' направляется в ''open_st_request_inprocess''; | |
| * ''ticket.moved'' с прежним ''ASSIGNED'' и новым статусом направляется в ''open_st_request_assigned'', чтобы прежняя очередь исключила свой снимок. | * **ticket.changed:** новый IN_PROCESS адресуется open_st_request_inprocess. |
| | * **ticket.moved:** прежний ASSIGNED и новый статус адресуются open_st_request_assigned для исключения старого снимка. |
| |
| Это не две команды повторно выполнить одно действие. Прежний обработчик получает сигнал о смене владельца, новый — повод получить свой scoped Ticket и начать собственную стадию. Передача идёт через ejabberd; failed delivery не откатывает сохранённый Ticket. При автоматической ветке дополнительно возможен прямой XMPP Ticket snapshot от ''send_to_handler''. Runtime сопоставляет ревизии и объединяет повторные сигналы; постоянная гарантия exactly-once здесь не заявляется. | Это не две команды повторно выполнить одно действие. Прежний обработчик получает сигнал о смене владельца, новый — повод получить свой scoped Ticket и начать собственную стадию. Передача идёт через ejabberd; failed delivery не откатывает сохранённый Ticket. При автоматической ветке дополнительно возможен прямой XMPP Ticket snapshot от ''send_to_handler''. Runtime сопоставляет ревизии и объединяет повторные сигналы; постоянная гарантия exactly-once здесь не заявляется. |
| </sharix-bpmn> | </sharix-bpmn> |
| |
| При ''ticket.moved'' текущая XMPP-обработка ставит запрос на discard без синхронного API GET. Если Ticket сейчас выполняется, исключение откладывается до завершения worker; параллельный второй проход для него не создаётся. Если он не in-flight, runtime сразу убирает локальный снимок и запрашивает удаление комнаты. Конкретная очистка комнаты зависит от ветки: успешная явная передача текущего handler сохраняет её. | Уборка при ticket.moved: |
| | |
| | - XMPP-обработка ставит запрос discard без синхронного API GET. |
| | - Для in-flight Ticket удаление откладывается до завершения worker. |
| | - Для свободного Ticket локальный снимок исключается сразу, запрашивается удаление комнаты. |
| | |
| | Успешная явная передача текущего handler сохраняет комнату. Очистка локальной очереди не удаляет Ticket из backend. |
| | |
| | Периодическая scoped сверка по INTERVAL_TIME_BD_REQ: |
| | |
| | * успешный список без Ticket позволяет исключить прежний снимок сразу либо после in-flight прохода; |
| | * новая ревизия обновляет снимок и снимает defer; |
| | * неизменившийся снимок сохраняет ожидание; |
| | * ошибка API сохраняет локальное состояние, логируется и оставляет следующий повтор. |
| |
| Независимо от доставки сообщений очередь периодически получает scoped список по ''INTERVAL_TIME_BD_REQ''. Ticket, отсутствующий в успешно полученном списке ''ASSIGNED'', исключается сразу либо после in-flight прохода. При новой ревизии сохраняется свежий снимок и снимается defer; неизменившийся снимок не обнуляет ожидание без причины. Если API недоступен, неизвестность не трактуется как удаление Ticket: локальный снимок сохраняется, ошибка логируется, следующая сверка назначается обычным циклом. | Недоступность API не является подтверждённым удалением заявки. |
| |
| Отсрочки, причины ожидания, coalescing событий и локальная очередь живут в памяти процесса. После restart authoritative-состав восстанавливается из backend; прежний deadline не является долговечным SLA-обязательством. ''deferred_until'' и ''next_reconciliation_at'' в BPMN — символические значения сроков, не новые env-ключи и не фиксированное число секунд. Служебные startup/stop-пути общего runtime не развёрнуты здесь в отдельный бизнес-процесс. | Отсрочки, причины ожидания, coalescing событий и локальная очередь живут в памяти процесса. После restart authoritative-состав восстанавливается из backend; прежний deadline не является долговечным SLA-обязательством. ''deferred_until'' и ''next_reconciliation_at'' в BPMN — символические значения сроков, не новые env-ключи и не фиксированное число секунд. Служебные startup/stop-пути общего runtime не развёрнуты здесь в отдельный бизнес-процесс. |