ee642e5eaa
PostgreSQL-репозиторий для m2m_core.deals — реальное хранилище сделок вместо in-memory. Выбор Repository происходит автоматически в lkgateway.NewServer: если в runtime-конфиге задан Postgres DSN, поднимается pgxpool и используется PostgresRepository; иначе fallback на MemoryRepository. internal/m2mcore/pgrepo.go: - PostgresRepository: Create (идемпотентный по guid через ON CONFLICT DO NOTHING), GetByGUID, GetByID, Update, List (с фильтрами state/investor/created_*), AppendEvent для журнала deal_events - request_xml/response_xml/decision_xml хранятся как windows-1251 XML через nsdxml, на чтении парсятся обратно в m2m.M2M* структуры - stages — jsonb с историей FSM-переходов migrations/m2m-core/002__stages.sql: - ALTER TABLE deals ADD COLUMN stages jsonb DEFAULT '[]' internal/lkgateway/server.go: - При NewServer проверяется runtime-config: если есть DSN → PostgresRepository, иначе MemoryRepository; ошибка подключения логируется с fallback на in-memory - Тесты используют tempdir SetupPath для изоляции от реальной БД internal/lkgateway/setup.go: - tryPingPostgres переписан с database/sql (требует регистрации драйвера) на pgx.Connect — теперь форма /admin/setup/postgres реально проверяет подключение перед сохранением DSN Проверено сквозным smoke-тестом: введение DSN через UI → сохранение в ~/.bj/setup.json → перезапуск lk-gateway → лог "PostgresRepository подключён (m2m_core.deals)" → сделки реально пишутся в БД. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
internal/m2mcore — ядро бизнес-логики M2M
Конечный автомат сделки, репозиторий, идемпотентность по GUID,
сборка M2MTransferRequest из заявки ЛК + данных Fansy, метрики SLA.
Состав
fsm.go— состояния FSM и матрица разрешённых переходов (Draft → Validated → SubmittedToNSD → AwaitingDecision → Confirmed → AwaitingSUB16 → Done, веткиRejected,TimedOut,ManualApproval).deal.go— доменная модельDealс явными методами переходов (Validate,Submit,ReceiveDecision,Timeout,SendToManualApproval,ApproveManually,RejectManually,CompleteSUB16). Каждый переход проверяет текущее состояние, пишет историю вStagesи фиксирует событие в журнале.uuid.go— генератор UUID v4 без внешних зависимостей.repo.go— портRepository+ in-memory реализацияMemoryRepositoryс идемпотентнымCreate(по GUID возвращает существующую сделку). PostgreSQL-реализация — задача M2 (миграция лежит вmigrations/m2m-core/001__deals.sql).ports.go— порты к внешним системам (NSDSender,LKCallbackClient,CryptoVerifier,FansyStore) с no-op заглушками для M1.enrich.go— функцияEnrichRequest: изClaimInput(заявка ЛК)- данных Fansy собирает валидный
M2MTransferRequest, генерируетGUIDиReferenceIDпо каждой ЦБ.
- данных Fansy собирает валидный
metrics.go— портRecorder+MemoryRecorder, отдающий Prometheus text-format. В M2 заменим наprometheus/client_golang, когда прокси откроет Go-модули.
Зависимости
Только stdlib и собственные пакеты internal/m2m, internal/nsdxml.
Никаких внешних модулей.
Тесты
fsm_test.go— переходы и терминальные состояния.repo_test.go— идемпотентность по GUID, фильтры вList.uuid_test.go— формат UUID v4 иReferenceID.metrics_test.go— Prometheus-текст.
Сервис cmd/m2m-core
cmd/m2m-core/main.go — HTTP-сервер с /healthz и /metrics,
in-memory репозиторий, no-op порты. Адрес из BJ_HTTP_ADDR
(по умолчанию :8081). В M2 будет заменено на реальные клиенты НРД
и crypto-service.