UC-CRM-018. Несколько сделок из одной одобренной фиксации (по разным объектам застройщика)
Назначение
Показывает связь «фиксация → сделки = 1:N»: одна одобренная фиксация авторизует агента работать с
клиентом по проектам застройщика и создать по ней сколько угодно сделок — по разным объектам этого
застройщика. Одобрение фиксации не создаёт сделку и не привязано к объекту (пара «клиент × застройщик»);
дедуп сделок обеспечивает не фиксация, а инвариант «одно активное намерение на (LeadId, PropertyObjectId)»
(INV-INTENT-1). Поэтому FixationRequestId на сделке не уникален. Дома полей —
../domain/fixation-request.md и ../domain/deal.md.
Metadata
| Поле | Значение |
|---|---|
| ID | UC-CRM-018 |
| Контекст | crm (см. docs/06-services/crm/) |
| Тип | основной |
| Статус | draft |
Актор
| Поле | Значение |
|---|---|
| Роль | Агент-исполнитель лида (Executor) или Менеджер ПИН |
| Permissions / scope | crm.deals.manage; агент — record-level по членству лида (ADR-0071); Менеджер ПИН — platform-scope (кросс-tenant, ADR-0052) |
| Tenant | Лид TenantId = AgencyCompanyId; каждая создаваемая сделка TenantId = DeveloperCompanyId объекта (тот же застройщик у всех сделок этой фиксации) |
| Record-level | Агент — активный участник лида; Менеджер ПИН — любой |
Предусловие
- Лид существует и
Status = Active(INV-LEAD-2). - Для пары «инвестор × застройщик» есть одобренная фиксация
(../domain/fixation-request.md;
Status = Approved). - Несколько объектов этого застройщика — предмет намерений инвестора (
ConfirmedByInvestor = true) либо выбираются агентом при создании сделок; по каждой паре (LeadId,PropertyObjectId) нет другой активной сделки/намерения (INV-INTENT-1).
Триггер
| Поле | Значение |
|---|---|
| Источник | UI-действие → вызов API (повторяется на каждый объект) |
| Триггерящий элемент | Кнопка «Создать сделку» на карточке лида для каждого объекта → POST /api/agent/crm/deals |
Основной Поток
- Контекст. У агента есть активный лид и одна одобренная фиксация для пары «инвестор × застройщик». Инвестор рассматривает несколько объектов этого застройщика (намерения по ним — Flow A/UC-CRM-016).
- Создание первой сделки. Агент создаёт сделку по объекту №1. Так как для пары есть одобренная фиксация
и объект — подтверждённое намерение инвестора, гейт INV-DEAL-11 выполнен → сделка сразу
Application: составExecutor+InvestorPrimary+SellManager+ авто-PinManager,FixationRequestId= одобренная фиксация,IntentId= намерение объекта №1,IntentConfirmedAtпроставлен,TenantId = DeveloperCompanyId. - Создание последующих сделок. По объектам №2, №3, … агент повторяет создание сделки, ссылаясь на ту же
фиксацию. Каждая новая сделка получает тот же
FixationRequestId(значение не уникально среди сделок) и собственныйIntentId/PropertyObjectId. Одобренную фиксацию повторно оформлять не нужно — она авторизует все объекты застройщика в рамках пары. - Дедуп по объекту (INV-INTENT-1). Уникальность на пару (
LeadId,PropertyObjectId) не даёт завести вторую активную сделку по тому же объекту: повтор по уже занятому объекту — конфликт активного намеренияCRM_INTENT_ACTIVE_OBJECT_EXISTS; разные объекты — независимые сделки. - Что меняется. На каждый вызов — новая
DealEntity(+ участники, таймлайнDealCreated, запись ленты лидаDealCreated) в одном согласованном изменении вместе с записью в outbox. Фиксация не меняется — только читается как основание авторизации. - Публикация. На каждую сделку —
pin.crm.deal-created.v1(Status = Application, участники соSellManager). Все сделки попадают на канбан застройщика (одна пара «инвестор × застройщик», один застройщик, разные объекты). - Результат. В лиде — несколько активных сделок к одному застройщику по разным объектам, все с общим
FixationRequestId. Агент видит их в списке сделок лида; инвестор — в «Мои сделки». - Завершение/отмена независимы. Каждая сделка проходит свой жизненный цикл. Завершение одной сделки
(
Completed) не влияет на остальные; отмена одной (Cancelled) освобождает её объект, прочие сделки фиксации остаются активными.
Диаграмма
Альтернативные Потоки
- Агент создаёт сделку по объекту той же фиксации, но объект ещё не подтверждён инвестором (нет намерения
или
ConfirmedByInvestor = false). - Гейт INV-DEAL-11 не выполнен по намерению → сделка заводится в
Draft(см. Flow B, UC-CRM-017); фиксация уже одобрена, но условие намерения не снято. После подтверждения инвестором — вовлечение застройщика.
- По паре (
LeadId,PropertyObjectId) уже есть активная сделка/намерение. CRM_INTENT_ACTIVE_OBJECT_EXISTS(409); вторая активная сделка по тому же объекту не создаётся.
Возврат: работать с существующей сделкой объекта либо выбрать другой объект.
- Фиксация для пары не
Approved(на рассмотрении, отклонена, истекла). CRM_DEAL_FIXATION_REQUIRED(409) при попытке сразуApplication(или сделка остаётсяDraftдо выполнения гейта).
Возврат: дождаться одобрения (UC-FIX-002) или повторно отправить заявку на фиксацию.
- Лид
Expired/Archived. CRM_LEAD_NOT_ACTIVE(409); сделки не создаются.
Возврат: продлить/реактивировать лид (INV-LEAD-3).
Постусловие
- В лиде — несколько активных
DealEntityк одному застройщику по разным объектам; у всех общийFixationRequestId(не уникален среди сделок), у каждой собственныйIntentId/PropertyObjectId. - Ни по одному объекту нет двух активных сделок (INV-INTENT-1); фиксация не изменена (используется как основание авторизации).
- На каждую созданную сделку опубликован
pin.crm.deal-created.v1; всеApplication-сделки видны застройщику. - Завершение/отмена любой из сделок не затрагивает остальные сделки той же фиксации.
Возможные Ошибки
| Код | HTTP | Условие | Поведение клиента |
|---|---|---|---|
CRM_INTENT_ACTIVE_OBJECT_EXISTS | 409 | По паре (LeadId, PropertyObjectId) уже есть активная сделка/намерение (INV-INTENT-1) | Работать с существующей сделкой объекта или выбрать другой |
CRM_DEAL_FIXATION_REQUIRED | 409 | Для пары «инвестор × застройщик» нет одобренной фиксации (создание сразу в Application / гейт INV-DEAL-11) | Дождаться одобрения фиксации; иначе сделка заводится в Draft |
CRM_DEAL_INTENT_NOT_CONFIRMED | 409 | Объект без подтверждённого инвестором намерения — сразу в Application нельзя | Сделка заводится в Draft; подтвердить намерение, затем вовлечь застройщика |
CRM_DEAL_PAYMENT_METHOD_REQUIRED | 422 | Создание сразу в Application без PaymentMethod (INV-DEAL-1) | Форма требует выбрать способ оплаты |
CRM_LEAD_NOT_ACTIVE | 409 | Лид Expired/Archived (INV-LEAD-2) | Предложить продлить/реактивировать лид |
Доменные События
| Событие | Когда поднимается | Subscribers |
|---|---|---|
DealCreated / DealMemberAdded | Каждое создание сделки по объекту фиксации | Таймлайн сделки DealCreated, запись ленты лида LeadEventEntity(DealCreated) |
Kafka Интеграционные События
| Событие | Topic | Когда публикуется | Consumers |
|---|---|---|---|
DealCreatedEvent | pin.crm.deal-created.v1 | На каждую созданную сделку (одна фиксация → N сделок), через outbox атомарно | messenger (чат сделки + участники), notifications (участникам) — контракт ../events/deal-created.md |
Последующие изменения каждой сделки независимы — ../events/deal-stage-changed.md, ../events/deal-completed.md, ../events/deal-cancelled.md.
Acceptance Criteria
| # | Критерий | Проверка |
|---|---|---|
| AC1 | По одной одобренной фиксации агент создаёт сделки по объектам №1 и №2 → две сделки Application с общим FixationRequestId и разными IntentId/PropertyObjectId | Интеграционный тест: 2× POST /api/agent/crm/deals; FixationRequestId совпадает, объекты разные |
| AC2 | FixationRequestId не уникален среди сделок — вторая сделка с той же фиксацией создаётся успешно | Тест: отсутствует unique-конфликт по FixationRequestId |
| AC3 | Повтор по уже занятому объекту → CRM_INTENT_ACTIVE_OBJECT_EXISTS (409), вторая активная сделка по объекту не создаётся | Негативный тест INV-INTENT-1 |
| AC4 | Объект без подтверждённого намерения → сделка заводится в Draft (гейт по намерению не выполнен), не в Application | Тест A1 |
| AC5 | Все Application-сделки одной фиксации видны застройщику на канбане; пара «инвестор × застройщик» одна | Тест видимости застройщика |
| AC6 | Завершение одной сделки (Completed) не влияет на остальные; отмена одной освобождает её объект, прочие активны | Тест независимости жизненных циклов |
| AC7 | Фиксация используется только как основание — её состояние (Approved) не меняется при создании сделок | Тест: FixationRequestEntity без изменений |
Обратные ссылки
Автоссылки: где используется этот документ.
- Use Cases (2): UC-CRM-016. Инвестор добавляет намерения бронирования (много объектов), UC-CRM-017. Flow B: агент предлагает объект → Draft-сделка → подтверждение инвестором → вовлечение застройщика
- registries (1): Реестр use cases и user stories PIN
Связанные Документы
- API метод: ../api/agent/create-deal.md;
вовлечение застройщика для
Draft— ../api/agent/engage-developer.md. - Domain entity: ../domain/deal.md (
FixationRequestIdне unique, связь 1:N, INV-DEAL-1/11), ../domain/fixation-request.md (пара «клиент × застройщик»,Approved), ../domain/lead.md (INV-INTENT-1, намерения). - Kafka событие: ../events/deal-created.md.
- Смежные UC: UC-CRM-016-investor-adds-booking-intents.md, UC-CRM-017-draft-deal-investor-confirmation.md, UC-CRM-002-agent-creates-deal-from-lead.md, UC-FIX-002-developer-approves-fixation.md.
- ADR: 0052 tenancy, 0071 crm-ownership-and-participant-model.