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

Entity / Aggregate: BankEntity

Дом полей сущности «Банк» контекста chessboard. Проекции (вкладка «Финансирование» проекта в catalog, банк сделки/эскроу в crm) ссылаются сюда и описывают только дельту.

Назначение

BankEntity — платформенный справочник банков (идентификатор, название, логотип). На банки ссылаются проекты застройщиков (эскроу-банки, банк проектного финансирования, ипотечные банки в ProjectFinancingDocument — см. project.md) и контекст crm (банк эскроу-счёта сделки). Справочником управляет администратор платформы (admin API: создание, список/поиск, получение по id, изменение, удаление, lookup); застройщикам и агентам доступны только lookup-методы.

Классификация

ПолеЗначение
Контекстchessboard
KindСправочник (Entity — CRUD, доменной логики нет)
Source of truthchessboard
Таблицаchessboard.banks
Tenant isolationНе tenanted — платформенный справочник (ADR-0052 п.3: platform-level данные); видимость определяется правами

Поля

ПолеТипОбязательностьОграничения (PK/FK/index/constraint)ИсточникОписание
IdGuidДаPKappИдентификатор банка.
NamestringДаvarchar(256), min 1; unique ux_banks_name (lower(name)) where deleted_at is nullapp (admin API)Название банка. Уникально среди активных (INV-BNK-1).
LogoFileIdGuid?Нетбез FK (внешний storage/CDN)app (admin API)Файл логотипа; выдача ссылок — граница storage/CDN.
CreatedAtDateTimeOffsetДаindex ix_banks_created_atappДата создания.
CreatedByUserIdGuid?НетappКто создал (администратор).
UpdatedAtDateTimeOffsetДаappДата изменения.
UpdatedByUserIdGuid?НетappПоследний изменивший.
DeletedAtDateTimeOffset?Нетpartial-index filterappАрхив — операция «удаление» admin API выполняется как soft-delete (на банк ссылаются jsonb проектов и сделки crm).
DeletedByUserIdGuid?НетappКто архивировал.
VersionlongДа>= 1appВерсия записи (инкремент при каждом изменении).

Связи

СвязьТипКлючDelete behavior
ProjectEntity (финансирование)логическая (id в Financing jsonb проекта, без FK)Project.Financing.EscrowBankIds[] / MortgageBankIds[] / ProjectFinancingBankIdархив банка не ломает проекты: проекции фильтруют архивные (INV-BNK-2)
Сделка crm (банк эскроу)логическая (чужой контекст, по lookup-API)crm хранит BankId

Инварианты и переходы состояний

ИнвариантУсловиеКогда проверяетсяОшибка
INV-BNK-1 UniqueNameName уникально среди не удалённых банковпри создании и переименованииCHESSBOARD_BANK_NAME_TAKEN
INV-BNK-2 ArchiveKeepsReferencesАрхив не каскадирует: ссылки из Project.Financing и crm остаются валидными; lookup-списки и public-проекции исключают архивныепри чтении/выдаче списков и проекций
State-машины нет

Активен → архив через soft-delete. В отличие от hotelier.md, где архив блокируется FK-ссылками INV-HTL-2, банк ссылается логически, без FK — архивируется свободно, ссылки переживают архив (INV-BNK-2).

Жизненный цикл и операции

ОперацияАкторПредусловиеЭффектОтказ
CreateадминистраторName свободно среди активныхновая запись, Version = 1CHESSBOARD_BANK_NAME_TAKEN (INV-BNK-1)
Renameадминистраторновое Name свободно среди активных (кроме себя)Name обновлён, Version += 1CHESSBOARD_BANK_NAME_TAKEN; конкурентный rename проигравший — тот же код (гонка сериализуется unique-индексом ux_banks_name)
Update logoадминистраторзапись активнаLogoFileId обновлён, Version += 1
Archive (soft-delete)администраторзапись активнаDeletedAt/DeletedByUserId проставлены; исчезает из lookup и public-проекций; ссылки из Project.Financing/crm остаются валидны (INV-BNK-2); повторный архив — идемпотентный no-op
Restore (возврат из архива)администраторName снова свободно среди активныхDeletedAt = null, снова в lookupCHESSBOARD_BANK_NAME_TAKEN (имя занято другим активным за время архива)
Lookup (list/search/by-id)застройщик / агент / public-карточкаактивные банки в списках; by-id резолвит и архивные — для исторических проекций уже сохранённых Financing

Постусловие любой мутации: Version монотонно растёт, UpdatedAt/UpdatedByUserId обновлены; событий в шину нет (потребители читают синхронно, см. ниже).

Доменные и интеграционные события

Событий нет

Справочник читается потребителями через lookup-API синхронно (банков десятки, изменения редки). Если у catalog появится потребность в реплике — добавляется BankUpsertedKafkaEvent отдельным изменением контракта.

Кросс-контекстный контракт (lookup)

Справочник предоставляет синхронное чтение, а не событийную реплику. Что гарантируется потребителям:

  • Что предоставляет. catalog (вкладка «Финансирование» карточки проекта) и crm (банк эскроу-счёта сделки) получают по BankId пару Name + LogoFileId через lookup-API; актуальность — read-time (никакого окна eventual-consistency, реплики нет).
  • Обработка архивных. by-id резолвит и архивные банки (INV-BNK-2), чтобы уже сохранённый в Project.Financing или в сделке crm BankId продолжал отображаться исторически; списки/пикеры активных банков архивные исключают — переиспользовать архивный банк в новой конфигурации нельзя.
  • Что ожидается от потребителей. Хранить только BankId (не денормализовать Name/лого); при отсутствии резолва (id не найден вовсе — возможно лишь при рассогласовании данных, hard-delete не бывает) — проекция опускает банк без ошибки чтения карточки.
  • Валидация ссылок на записи. При записи Project.Financing каждый BankId проверяется на существование (INV-PRJ-7, project.md); ответственность за целостность ссылки — на записывающей операции, не на справочнике.

Индексы, хранение, безопасность

АспектЗначение
ИндексыPK pk_banks; ux_banks_name unique (lower(name)) where deleted_at is null; ix_banks_created_at
Партиционирование / retentionnone — десятки строк; retention бессрочный
Concurrencyоптимистическая блокировка (правка не должна затирать чужую)
Permissions / PIICRUD — только admin API (chessboard.banks.manage, ADR-0053); lookup (list/by-id) — Developers/Agents API (chessboard.references.lookup) и public-проекция карточки проекта (название+лого). PII нет
Auditверсия записи + отметки кто/когда; soft-delete

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

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

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