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

POST /api/agent/crm/clients/{clientId}/archive — Архивировать клиента

Перевод карточки клиентской базы агента Active → Archived: карточка убирается из рабочего списка /crm/clients, но история лидов, фиксаций и сделок сохраняется (клиент — «адресная книга + агрегатор», client.md). Операция разрешена только для клиента без незакрытых связей (инвариант INV-CLI-4). Восстановление (Restore, Archived → Active) и полное soft-удаление (SoftDelete) — companion-операции того же агрегата (см. state-diagram в client.md); здесь не описываются.

Назначение

Дать агенту/руководителю агентства «прибраться» в клиентской базе — скрыть неактуальные карточки (клиент отказался, ушёл к другому агенту, дубль) без потери истории.

Metadata

ПолеЗначение
Сервис/контекстcrm
API areaagent
Feature groupclients
Статусdraft
Документdocs/06-services/crm/api/agent/archive-client.md

Актор и доступ

ПроверкаЗначение
Actor typeUser (Агент — участник процессов клиента; Руководитель агентства; Менеджер ПИН)
Auth policy / Permissionscrm.clients.manage
Scope (RBAC)организация (TenantId = AgencyCompanyId); Менеджер ПИН — platform-scope
Record-levelагент: активный участник процессов клиента (лид/фиксация/сделка); руководитель агентства: любой клиент своего TenantId; Менеджер ПИН — сквозной доступ (ADR-0052)
Tenant isolationTenantId в каждом запросе; загрузка и проверки связей — строго в рамках TenantId
Auditupdate (переход статуса Active → Archived, actor-stamping UpdatedByUserId)
Доступ

Рядовой агент архивирует только карточки, в процессах которых он — активный участник (лид/фиксация/ сделка); руководитель агентства — любую карточку своего TenantId; Менеджер ПИН — сквозной доступ вне привязки к TenantId (ADR-0052).

HTTP-контракт

ПолеЗначение
MethodPOST
Route/api/agent/crm/clients/{clientId}/archive
Success status204 (No Content); повтор на уже Archived клиенте — идемпотентный 204
Idempotency headerне применяется (идемпотентность по целевому статусу)
Correlationсквозной trace через заголовок traceparent

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
TenantIdidentity claimsGuidДаRequired, != Guid.EmptyTenant isolation (AgencyCompanyId)
ClientIdrouteGuidДа!= Guid.Empty; существующая живая карточка
ActorUserIdidentity claimsGuidДаRequired; проверка record-levelстемпится в UpdatedByUserId
Тело запроса

Тело запроса пустое: причина архивации у ClientEntity не хранится (поля Reason в доме карточки нет, client.md).

Модель ответа

Тела ответа нет: результат — HTTP 204 No Content. Идентификаторы дочерних сущностей наружу не возвращаются (внутренние данные агентства). Ошибочные исходы — ProblemDetails с кодом из таблицы ниже.

Алгоритм

  1. Контекст и доступ. Операцию выполняет агент/руководитель агентства/Менеджер ПИН (permission crm.clients.manage) в рамках TenantId.
  2. Проверка входа и предусловий.
    • формат: ClientId != Guid.Empty, TenantId != Guid.Empty — иначе ошибка валидации;
    • карточка существует в TenantId и не soft-deleted — иначе CRM_CLIENT_NOT_FOUND;
    • record-level: если actor не Менеджер ПИН и не руководитель агентства, требуется членство в процессах клиента (актор — активный участник лида/фиксации/сделки) — иначе CRM_CLIENT_FORBIDDEN.
  3. Что читаем. Карточку клиента (единственный мутируемый агрегат; на время проверки связей строка блокируется, чтобы конкурентное создание лида/сделки не проскочило между проверкой и записью).
  4. Бизнес-правила и переходы (INV-CLI-4). Идемпотентность: если уже Archived — вернуть 204, событие не поднимается. Иначе целевой статус только из Active. Проверка «нет незакрытых связей» по клиенту:
    • активные лиды (Status = Active, enum LeadStatus, lead.md);
    • ожидающие фиксации (Status = Pending, enum FixationStatus, fixation-request.md);
    • незавершённые сделки (Status NOT IN {Completed, Cancelled}, enum DealStatus, deal.md). Любая незакрытая связь → CRM_CLIENT_HAS_ACTIVE_RELATIONS. Иначе переход Active → Archived (ActiveLeadId уже null по INV-CLI-2), стемпинг UpdatedByUserId = actor.
  5. Что меняется. Статус клиента переводится в Archived; дочерние строки не изменяются.
  6. События. Доменное ClientArchived — внутреннее (in-process). Интеграционных (Kafka) событий нет: клиентская база — внутренние данные агентства, внешние контексты реагируют на события лидов/сделок (client.md; список публикуемых топиков — README).
  7. Результат. HTTP 204 No Content. Провалы правил — из таблицы ошибок.

Диаграмма

Предусловия и постусловия

Предусловия. Актор с crm.clients.manage и доступом к карточке по членству агентства (активный участник процессов клиента / руководитель агентства / Менеджер ПИН). Карточка живая (не soft-deleted). Для перехода — нет незакрытых связей (INV-CLI-4): активных лидов, Pending-фиксаций, незавершённых сделок.

Постусловие (успех). Status = Archived, UpdatedByUserId = actor; дочерние агрегаты (лиды/фиксации/ сделки) не изменены; карточка выпадает из рабочего списка /crm/clients (фильтр Active). Поднято доменное ClientArchived (in-process); интеграционных событий нет. Повтор на уже Archived карточке — идемпотентный 204 без события.

Постусловие (отказ по связям/доступу). Статус клиента не изменён, событие не поднято.

Побочные эффекты

ТипДетали
Интеграционные событияnone (Kafka-события клиент не публикует)
Доменные событияClientArchived (in-process; консюмеров-хендлеров в CRM на текущем слое нет)
Внешние вызовыnone
Проекции / поискпроекция клиентов (ClientSearchDocument) обновляется (Status = Archived); выпадение из списка /crm/clients — за счёт фильтра Status = Active в query-методах
Уведомленияnone (архивация — тихая операция агента)

Ошибки и failure modes

Ошибки

Главный гейт — INV-CLI-4: архивация невозможна, пока у клиента есть незакрытый лид, Pending-фиксация или незавершённая сделка (CRM_CLIENT_HAS_ACTIVE_RELATIONS).

КодHTTP statusУсловиеСообщениеRetry
VALIDATION_FAILED400пустой ClientId/TenantId«Некорректный идентификатор клиента»no retry
CRM_CLIENT_NOT_FOUND404карточки нет в TenantId либо уже soft-deleted«Клиент не найден»no retry
CRM_CLIENT_FORBIDDEN403actor не участник процессов клиента и не руководитель/Менеджер ПИН«Нет доступа к карточке клиента»no retry
CRM_CLIENT_HAS_ACTIVE_RELATIONS409есть активный лид, Pending-фиксация или незавершённая сделка (INV-CLI-4)«Нельзя архивировать клиента с активными лидами, заявками на фиксацию или сделками»no retry (сначала закрыть связи)
CONCURRENCY_CONFLICT409гонка с созданием связи после проверки«Данные изменились, повторите»retry (перечитка)
Идемпотентность и гонки

Уже Archived клиент — не ошибка: идемпотентный 204. Гонка «создание лида/сделки во время архивации» ограничена блокировкой строки клиента: команды создания связей трогают клиента (LastActivityAt/ActiveLeadId) и сериализуются с архивацией.

Совместимость и наблюдаемость

  • Метод — новый (write-only, тело пустое); аддитивен к карте agent-области (README). Companion-операции restore (Archived → Active) и soft-delete добавляются отдельными endpoint-ами того же агрегата — без breaking change к этому контракту.
  • Logs: client archived (ClientId, TenantId, ActorUserId; PII не пишется) и client archive rejected (reason = has-active-relations); metrics: crm_client_archive_total{result}; traces — сквозной trace через traceparent; dashboard pin-crm; runbook — docs/06-services/crm/runbooks/.

Acceptance Criteria

  • Happy path. Given Active-клиент без незакрытых связей; When archive; Then 204, Status = Archived, карточка исчезла из рабочего списка.
  • Идемпотентность. Given клиент уже Archived; When archive; Then 204, событие ClientArchived не поднимается.
  • Незакрытые связи (INV-CLI-4). Given активный лид, Pending-фиксация или незавершённая сделка; When archive; Then 409 CRM_CLIENT_HAS_ACTIVE_RELATIONS, статус не меняется.
  • Гонка. Given параллельное создание лида/сделки во время архивации; When обе операции трогают клиента; Then побеждает одна; проигравшая — 409 CONCURRENCY_CONFLICT (перечитать состояние).
  • Доступ. Given клиент, в процессах которого рядовой актор не участвует (и он не руководитель); When archive; Then 403 CRM_CLIENT_FORBIDDEN.

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

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

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