Entity / Aggregate: BankEntity
Дом полей сущности «Банк» контекста chessboard. Проекции (вкладка «Финансирование» проекта в catalog,
банк сделки/эскроу в crm) ссылаются сюда и описывают только дельту.
Назначение
BankEntity — платформенный справочник банков (идентификатор, название, логотип). На банки ссылаются
проекты застройщиков (эскроу-банки, банк проектного финансирования, ипотечные банки в
ProjectFinancingDocument — см. project.md) и контекст crm (банк эскроу-счёта сделки).
Справочником управляет администратор платформы (admin API: создание, список/поиск, получение по id,
изменение, удаление, lookup); застройщикам и агентам доступны только lookup-методы.
Классификация
| Поле | Значение |
|---|---|
| Контекст | chessboard |
| Kind | Справочник (Entity — CRUD, доменной логики нет) |
| Source of truth | chessboard |
| Таблица | chessboard.banks |
| Tenant isolation | Не tenanted — платформенный справочник (ADR-0052 п.3: platform-level данные); видимость определяется правами |
Поля
| Поле | Тип | Обязательность | Ограничения (PK/FK/index/constraint) | Источник | Описание |
|---|---|---|---|---|---|
Id | Guid | Да | PK | app | Идентификатор банка. |
Name | string | Да | varchar(256), min 1; unique ux_banks_name (lower(name)) where deleted_at is null | app (admin API) | Название банка. Уникально среди активных (INV-BNK-1). |
LogoFileId | Guid? | Нет | без FK (внешний storage/CDN) | app (admin API) | Файл логотипа; выдача ссылок — граница storage/CDN. |
CreatedAt | DateTimeOffset | Да | index ix_banks_created_at | app | Дата создания. |
CreatedByUserId | Guid? | Нет | — | app | Кто создал (администратор). |
UpdatedAt | DateTimeOffset | Да | — | app | Дата изменения. |
UpdatedByUserId | Guid? | Нет | — | app | Последний изменивший. |
DeletedAt | DateTimeOffset? | Нет | partial-index filter | app | Архив — операция «удаление» admin API выполняется как soft-delete (на банк ссылаются jsonb проектов и сделки crm). |
DeletedByUserId | Guid? | Нет | — | app | Кто архивировал. |
Version | long | Да | >= 1 | app | Версия записи (инкремент при каждом изменении). |
Связи
| Связь | Тип | Ключ | Delete behavior |
|---|---|---|---|
ProjectEntity (финансирование) | логическая (id в Financing jsonb проекта, без FK) | Project.Financing.EscrowBankIds[] / MortgageBankIds[] / ProjectFinancingBankId | архив банка не ломает проекты: проекции фильтруют архивные (INV-BNK-2) |
Сделка crm (банк эскроу) | логическая (чужой контекст, по lookup-API) | crm хранит BankId | — |
Инварианты и переходы состояний
| Инвариант | Условие | Когда проверяется | Ошибка |
|---|---|---|---|
| INV-BNK-1 UniqueName | Name уникально среди не удалённых банков | при создании и переименовании | CHESSBOARD_BANK_NAME_TAKEN |
| INV-BNK-2 ArchiveKeepsReferences | Архив не каскадирует: ссылки из Project.Financing и crm остаются валидными; lookup-списки и public-проекции исключают архивные | при чтении/выдаче списков и проекций | — |
Активен → архив через soft-delete. В отличие от hotelier.md, где архив блокируется FK-ссылками INV-HTL-2, банк ссылается логически, без FK — архивируется свободно, ссылки переживают архив (INV-BNK-2).
Жизненный цикл и операции
| Операция | Актор | Предусловие | Эффект | Отказ |
|---|---|---|---|---|
| Create | администратор | Name свободно среди активных | новая запись, Version = 1 | CHESSBOARD_BANK_NAME_TAKEN (INV-BNK-1) |
| Rename | администратор | новое Name свободно среди активных (кроме себя) | Name обновлён, Version += 1 | CHESSBOARD_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, снова в lookup | CHESSBOARD_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или в сделкеcrmBankIdпродолжал отображаться исторически; списки/пикеры активных банков архивные исключают — переиспользовать архивный банк в новой конфигурации нельзя. - Что ожидается от потребителей. Хранить только
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 |
| Партиционирование / retention | none — десятки строк; retention бессрочный |
| Concurrency | оптимистическая блокировка (правка не должна затирать чужую) |
| Permissions / PII | CRUD — только admin API (chessboard.banks.manage, ADR-0053); lookup (list/by-id) — Developers/Agents API (chessboard.references.lookup) и public-проекция карточки проекта (название+лого). PII нет |
| Audit | версия записи + отметки кто/когда; soft-delete |
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (2): Entity / Aggregate: HotelierEntity, Entity / Aggregate: ProjectEntity
- API (5): Admin CRUD банков — создание / список / карточка / правка / архив / lookup, Chessboard API — реестр операций областей Developers и Admin, GET /api/v1/developers/lookup/{banks,hoteliers} — Lookup справочников банков/отельеров, GET /api/v1/public/projects/{projectId} — Карточка проекта (ограниченная/полная), POST /api/v1/developers/projects — Создание проекта
- Use Cases (2): UC-CHS-001. Создание и публикация проекта застройщиком, UC-CHS-007. Администратор ведёт справочники банков и отельеров
- index.md (1): Chessboard Service (Pin.Chessboard)
- registries (2): Реестр инвариантов PIN, Реестр сущностей PIN
Связанные документы
- project.md — использование в
ProjectFinancingDocument; hotelier.md — парный справочник той же формы. - Admin API CRUD: ../api/admin/banks-crud.md; lookup: ../api/developers/references-lookup.md.