"""模拟交易网关写侧(PRD FR-1;FRAMEWORK §3 例外条款)。 仅本类可 INSERT jinrong_core.core_trade;core_ro 仍只读。生产环境由真实 交易系统回调替代,本类随 app/gateway/ 退役。 """ from __future__ import annotations from datetime import datetime from decimal import Decimal from typing import Any from sqlalchemy import text from sqlalchemy.engine import Engine from app.config.settings import settings from app.utils.db import get_engine class GatewayRepository: """core_trade 唯一写入口;仅 INSERT,不改不删(模拟网关语义)。 D20(T-0b):绑定 `role="rw"`(账号 `xh_core_rw`,仅限 4 张表的 SELECT/INSERT/UPDATE,**无 DELETE、无 DDL**)。注意 gateway 的**读**走 `role="ro"`(`CoreReadOnlyRepository`),两个 engine 并存——这是「最小 权限」能否成立的关键边界(架构 §11.1)。 """ def __init__(self, engine: Engine | None = None) -> None: self._engine = engine or get_engine(settings.mysql_core_database, "rw") def insert_trade( self, trade_id: str, customer_id: str, product_id: str, trade_type: str, amount: Decimal, traded_at: datetime, trade_status: str = "confirmed", ) -> None: sql = text( """ INSERT INTO core_trade (trade_id, customer_id, product_id, trade_type, amount, trade_status, traded_at) VALUES (:tid, :cid, :pid, :ttype, :amount, :status, :at) """ ) with self._engine.begin() as conn: conn.execute( sql, { "tid": trade_id, "cid": customer_id, "pid": product_id, "ttype": trade_type, # str 无损传递:MySQL DECIMAL 隐式转换;sqlite text SQL 不支持 Decimal 绑定 "amount": str(amount), "status": trade_status, "at": traded_at, }, )