Перейти к основному содержимому

Event Contract: pin.support.ticket-created (TicketCreatedKafkaEvent)

Версионируемый контракт интеграционного события «обращение (тикет) заведено». Consumer-документы ссылаются сюда, не переописывая payload. Событие фиксирует факт создания TicketEntity (ticket.md) — из веб-формы заявителя (create-ticket) или оператором (create-ticket-on-behalf) — и несёт минимальный маршрутный snapshot: очередь, категория, приоритет, канал, заявитель. Единственный потребитель — notifications (оповестить дежурных операторов очереди).

Назначение

Даёт notifications факт нового обращения, чтобы оповестить дежурных операторов очереди (QueueId) без синхронного запроса в support: маршрутизация уже вычислена producer-ом (INV-Q-5, ticket-queue.md), поэтому событие несёт готовый QueueId/Category/Priority, а не заставляет консюмера повторять правила. ФИО/телефон заявителя в payload не входят — потребитель берёт их из собственной реплики identity (pin.identity.users.v1); событие несёт только RequesterUserId/RequesterCompanyId. Публичное в границах платформы (m2m ACL Kafka), т.к. служит внутренней маршрутизации обращений.

Metadata

ПолеЗначение
Event typepin.support.ticket-created
Topicpin.support.ticket-created.v1
Partitions / key3 (низкий объём, ADR-0056) / ключ = TicketId (= AggregateId; per-ticket порядок)
ContractVersion1
Producersupport: create-ticket (веб-форма, ../api/public/create-ticket.md) и create-ticket-on-behalf (../api/support/create-ticket-on-behalf.md)
Статусdraft

Событие публикуется атомарно с созданием обращения в статусе New: пока изменение не зафиксировано, событие не отправляется потребителям; после фиксации — доставляется гарантированно (at-least-once). Метаданные события: MessageId (Guid v7, для дедупликации), AggregateId = TicketId (= Kafka key, per-ticket порядок), AggregateType = "Ticket".

Payload TicketCreatedKafkaEvent

Дом полей — entity: TicketEntity (раздел «Доменные и интеграционные события»); здесь перечислено только то, что реально в событии. Все поля — скаляры/enum-строки; вложенных моделей нет.

ПолеТипОбязательностьИсточник (TicketEntity)CompatibilityОписание
TicketIdGuidДаIdImmutableКлюч агрегата (= AggregateId, Kafka key).
NumberlongДаNumberImmutableЧеловекочитаемый номер (SUP-NNN) для текста уведомления/диплинка.
TenantIdGuidДаTenantIdImmutablePIN CompanyId (единый tenant платформы, ADR-0052).
QueueIdGuidДаQueueIdImmutableОчередь маршрутизации — адресат оповещения дежурных операторов.
Categorystring (enum TicketCategory)ДаCategoryAdditive only (новые значения)Тематика обращения (Account/Deal/Booking/Payment/Content/Technical/Complaint/Other).
Prioritystring (enum TicketPriority)ДаPriorityAdditive onlyПриоритет (Low/Normal/High/Urgent) — влияет на срочность оповещения.
Statusstring (enum TicketStatus)ДаStatusAdditive onlyВсегда New в момент создания (INV-TKT-1); включён для единообразия с ticket-status-changed.
Channelstring (enum TicketChannel)ДаChannelAdditive onlyКанал (WebForm/Operator/ExternalDesk).
RequesterUserIdGuidДаRequesterUserIdImmutableЗаявитель (id, не PII); ФИО/телефон — из реплики identity у потребителя.
RequesterCompanyIdGuid?НетRequesterCompanyIdAdditive onlyКомпания заявителя (контекст оповещения); null — инвестор.
RelatedDealIdGuid?НетRelatedDealIdAdditive onlyСвязанная сделка (crm), если указана при создании.
CreatedAtDateTimeOffsetДаCreatedAtImmutableМомент создания обращения.

Enum-значения не дублируются — дом ticket.md → «Enum TicketCategory/TicketPriority/TicketStatus/TicketChannel». Subject, тело первого сообщения, AssigneeUserId (при создании null), SLA-дедлайны и ФИО/телефон/email заявителя в payload не входят — потребителю (notifications) не нужны; текст обращения читается по API тикета, display-подпись — из реплики identity.

Когда публикуется

УсловиеПереход состоянияПубликация
create-ticket (веб-форма заявителя; Channel = WebForm, CreatedByUserId = null/заявитель)[*] → New (INV-TKT-1; QueueId по маршрутизации)атомарно со сменой состояния агрегата
create-ticket-on-behalf (оператор от лица заявителя; Channel = Operator)[*] → Newта же

Взятие в работу/смена статуса публикуются отдельным событием ticket-status-changed.md; публичный ответ оператора (reply-ticket, Visibility = Public) порождает ticket-message-posted.md (уведомление заявителя через notifications), а внутренняя переписка/заметки (Internal) и сообщения самого заявителя Kafka-события не порождают (внутренний тред, ticket-message.md).

Потребители (consumers)

Consumer-контекстSide effectsИдемпотентностьЗадержка (SLA)
notificationsОповещение дежурных операторов очереди QueueId о новом обращении (получатели — своя модель дежурств/подписок notifications)first-seen по MessageId< 1 мин

Список получателей событие сознательно не несёт: сопоставление QueueId → дежурные операторы инкапсулировано в notifications (собственная модель дежурств), support его не публикует.

Доставка и восстановление. At-least-once; потребитель дедуплицирует по MessageId (first-seen). Транзиентный сбой обработки — ретраи, исчерпание попыток → DLQ с алертом (без блокировки партиции). Порядок гарантирован только внутри этого топика (ключ TicketId); межтопикового порядка с ticket-status-changed/ticket-message-posted того же тикета нет — при опережающем status-changed консюмер обрабатывает событие как самодостаточное (Number/QueueId/Category уже в payload), см. README.md («Гарантии доставки, порядка и восстановления»).

Версионирование и совместимость

  • ContractVersion = 1; при Version != ContractVersion consumer логирует warning и продолжает обработку. Топик кодирует версию суффиксом .v1 по конвенции.
  • Additive-only для minor: новые optional-поля с безопасным default — без bump. Новые значения enum TicketCategory/TicketPriority/TicketChannel — additive.
  • Breaking (удаление/переименование/смена типа/смысла) — ContractVersion = 2 + новый топик pin.support.ticket-created.v2 + dual-publish на период миграции + deadline миграции consumers + sunset .v1.
  • Unknown enum (Category/Priority/Channel) — fallback: сохранить строку как есть, warning, не падать (оповещение с нейтральной формулировкой/приоритетом).

Безопасность

Событие несёт только идентификаторы, enum-значения и метку времени — прямого PII нет по построению: ФИО/телефон/email заявителя намеренно исключены (потребитель резолвит из своей реплики identity).

ПолеКласс данныхПравило
TicketId, Number, TenantId, QueueId, RequesterUserId, RequesterCompanyId, RelatedDealIdInternalinclude (id/номер, не PII)
Category, Priority, Status, ChannelInternalinclude (enum-строки)
CreatedAtInternalinclude

Событие НЕ содержит secrets, tokens, raw credentials, ФИО/телефон/email, тела обращения, вложений. Доступ к топику — m2m ACL Kafka (notifications).

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы