Files
backend/.ai/conventions/data.md
T
ksv741 e3ecb8c15e
Backend verify / commits (pull_request) Successful in 1m29s
Backend verify / security (pull_request) Successful in 1m5s
Backend verify / verify (pull_request) Successful in 6m13s
Backend verify / commits (push) Skipped
Backend verify / security (push) Successful in 1m11s
Backend verify / verify (push) Failing after 7m34s
refactor: enforce repository boundary in application (WealthLedger/backend#171)
2026-11-04 22:29:01 +03:00

6.8 KiB
Raw Blame History

Backend data

Ownership и выбор операции

PrismaService — существующий shared DB provider с lifecycle приложения. prisma/schema.prisma и migrations владеют persistence; generated/prisma создаётся Prisma и не редактируется вручную. Конфигурация URL находится в prisma.config.ts/validated environment; SQLite — текущая локальная база.

Ситуация Решение
Данные для use case Concrete repository; use case не импортирует PrismaService/Prisma и не строит queries
Несколько записей обязаны выполниться вместе Database transaction вокруг инварианта
Конкурентная смена одного значения Atomic conditional update/constraint с проверкой результата
Независимые reads Не добавляй transaction ради внешнего вида
Общая persistence abstraction Только при реальной общей ответственности; generic repository для одной Prisma реализации не нужен

Размещение repository определяется Architecture: в слоистом module это infrastructure/. Repository — конкретный класс *.repository.ts у business owner, без обязательных interface/port/adapter. Он владеет queries, includes/filtering, DB mapping и согласованным чтением. Суффиксы *.persistence.ts, *.store.ts, *.dao.ts для той же роли не используем. Nest module регистрирует repository приватно.

Новые business decisions (можно ли менять архивную карту, допустим ли перевод) принадлежат application/domain; repository сохраняет persistence и ownership ограничения. Existing checks/HTTP helpers в BankCardsRepository — migration candidate, не повод дублировать их при новом use case или разрывать transaction. BaseRepository<T>, GenericRepository<T> и RepositoryFactory поверх Prisma не нужны без отдельной общей ответственности.

BankCardsRepository.summaryData проверяет владельца карты и получает операции с категориями в одной read transaction. GetBankSummaryUseCase выбирает период, вызывает repository, затем чистый bankSummary и формирует ответ. Prisma records не становятся domain entities: расчёт получает только нужные ему значения.

Application-код не импортирует PrismaService и не строит Prisma queries. Репозиторий владеет запросом и CAS-проверкой результата, а application — правилами и формированием ответа. Типы Prisma допустимы только в type-only импортах для существующей транзакционной границы. Не создавай обёртку на каждый вызов Prisma без текущего потребителя. BankCardsRepository.write сохраняет retry/transaction boundary для банковских записей; callback с transaction client — локальная техническая граница, не API для domain.

Выбирай только нужные данные, сохраняй user/account ownership в запросах и application checks. Предварительный lookup не заменяет unique constraint при race. Пример: AuthRepository преобразует P2002 в результат регистрации и выполняет conditional updateMany для refresh rotation; AuthService сохраняет HTTP error contract. Сначала пойми invariant; не копируй его flow в другой use case.

Transaction не охватывает сетевой T-Bank вызов как будто это одна atomic DB операция. Планируй порядок и compensation по текущей задаче; не удерживай DB lock во время retry внешней сети. Access/cache generation semantics — у T-Bank integration.

Деньги и точность

Для денежных значений используй existing decimal helpers и строковый wire value, не JS floating-point арифметику для сумм. Currency — отдельная часть Money; разные валюты не складываются без явно заданного conversion contract. Источник формы — src/common/money.types.ts; пример точной арифметики: decimal.ts. Форматирование ответа не меняет доменную семантику и точность расчёта.

Schema и migration

Сначала определи, какие существующие данные/consumers должны сохраниться. Миграцию проверяй на disposable копии с representative existing data; generated client обновляй из schema. Не переписывай уже применённую migration ради нового состояния и не выполняй reset/drop реальной базы как шаг верификации. Для destructive или compatibility-sensitive изменения подготовь backup/restore, переход и проверку отката до его применения. SQLite/local MVP не означает disposable data.

Безопасный путь: additive изменение, заполнение/проверка данных и только затем удаление прежней формы, если задача этого требует. Примеры schema/migrations: Prisma source. SQLite — embedded storage текущего приложения; файл БД и encryption key требуют согласованного backup/restore.

Проверка

npx prisma validate; после schema change npx prisma generate и npm run typecheck:app. Invariants/atomicity/migration safety требуют tests на соответствующей boundary: mock Prisma не доказывает реальную transaction. Выбор integration/e2e и известные ограничения — в Testing.