docs: 品牌全量口径统一为「南方基金」+ 作废文档清理
1) 客服 Agent 四份交付文档 + 构建脚手架:品牌由包装占位 XX科技 / 旧名 南方财富 统一为南方基金(热线 400-889-8899 / 官网 nffund.com),系统名改为「智能服务系统」; 同步追加 §0.4 修订记录行,工程记录行保留原占位字面以支撑硬编码扫描验收。 2) 开发文档:清理 28 份已作废/残留文档(14 份移出归档 + 14 份仓库副本), 新增《文档规整方案与开发前待决事项-2026-09-17》。 3) 客服agent 四份交付文档首次纳入本分支。
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""风控查询所需的补充只读 ORM 映射。
|
||||
|
||||
第二版 `app/model/fund.py` 已覆盖多数 `fin_*` 表;本模块只补充风控查询需要、
|
||||
但当前尚未映射的三张已有表,不负责建表、迁移或写入。
|
||||
|
||||
安全边界:
|
||||
|
||||
1. 只声明列映射,不提供写入方法。
|
||||
2. `sys_user.password_hash` 和 `email` 不进入风控只读模型。
|
||||
3. 不声明 ForeignKey,避免 ORM 写入时产生级联语义。
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import JSON, Numeric, String, Text
|
||||
from sqlalchemy.dialects.mysql import BIGINT, DATETIME, TINYINT
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.model.base import Base
|
||||
|
||||
__all__ = ["RiskLoginRecord", "RiskUser", "RiskWorkOrder"]
|
||||
|
||||
|
||||
class RiskUser(Base):
|
||||
"""统一身份表中的风控只读字段(sys_user)。"""
|
||||
|
||||
__tablename__ = "sys_user"
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True)
|
||||
user_no: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
username: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
user_type: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
employee_role: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
||||
customer_tier: Mapped[str | None] = mapped_column(String(16), nullable=True)
|
||||
investor_type: Mapped[str | None] = mapped_column(String(8), nullable=True)
|
||||
investor_type_assessed_at: Mapped[datetime | None] = mapped_column(
|
||||
DATETIME(fsp=0), nullable=True
|
||||
)
|
||||
is_professional_investor: Mapped[int] = mapped_column(
|
||||
TINYINT(display_width=1), nullable=False
|
||||
)
|
||||
professional_investor_status: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
professional_investor_certified_at: Mapped[datetime | None] = mapped_column(
|
||||
DATETIME(fsp=0), nullable=True
|
||||
)
|
||||
fund_account_status: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
fund_account_opened_at: Mapped[datetime | None] = mapped_column(
|
||||
DATETIME(fsp=0), nullable=True
|
||||
)
|
||||
status: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
created_at: Mapped[datetime] = mapped_column(DATETIME(fsp=0), nullable=False)
|
||||
updated_at: Mapped[datetime] = mapped_column(DATETIME(fsp=0), nullable=False)
|
||||
|
||||
|
||||
class RiskLoginRecord(Base):
|
||||
"""登录记录只读映射(sys_login_record)。"""
|
||||
|
||||
__tablename__ = "sys_login_record"
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), nullable=False)
|
||||
login_at: Mapped[datetime] = mapped_column(DATETIME(fsp=0), nullable=False)
|
||||
login_result: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
ip_region: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||||
device_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
is_common_device: Mapped[int] = mapped_column(TINYINT(display_width=1), nullable=False)
|
||||
failure_reason: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DATETIME(fsp=0), nullable=False)
|
||||
|
||||
|
||||
class RiskWorkOrder(Base):
|
||||
"""风险处置及交易申请兼容工单只读映射(biz_work_order)。"""
|
||||
|
||||
__tablename__ = "biz_work_order"
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True)
|
||||
work_order_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
customer_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), nullable=False)
|
||||
order_type: Mapped[str | None] = mapped_column(String(16), nullable=True)
|
||||
product_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True), nullable=True)
|
||||
amount: Mapped[Decimal | None] = mapped_column(Numeric(18, 2), nullable=True)
|
||||
channel: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
||||
advisor_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True), nullable=True)
|
||||
risk_rule_hits: Mapped[Any | None] = mapped_column(JSON, nullable=True)
|
||||
risk_disclosure_ack_at: Mapped[datetime | None] = mapped_column(
|
||||
DATETIME(fsp=0), nullable=True
|
||||
)
|
||||
second_confirmation_at: Mapped[datetime | None] = mapped_column(
|
||||
DATETIME(fsp=0), nullable=True
|
||||
)
|
||||
recording_reference: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||||
ops_handler_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True), nullable=True)
|
||||
ops_handled_at: Mapped[datetime | None] = mapped_column(DATETIME(fsp=0), nullable=True)
|
||||
compliance_handler_id: Mapped[int | None] = mapped_column(
|
||||
BIGINT(unsigned=True), nullable=True
|
||||
)
|
||||
compliance_handled_at: Mapped[datetime | None] = mapped_column(
|
||||
DATETIME(fsp=0), nullable=True
|
||||
)
|
||||
reject_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
alert_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True), nullable=True)
|
||||
work_order_type: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
||||
submitter_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True), nullable=True)
|
||||
handler_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True), nullable=True)
|
||||
priority: Mapped[str | None] = mapped_column(String(8), nullable=True)
|
||||
status: Mapped[str] = mapped_column(String(24), nullable=False)
|
||||
request_detail: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||
handle_result: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||
submitted_at: Mapped[datetime | None] = mapped_column(DATETIME(fsp=0), nullable=True)
|
||||
accepted_at: Mapped[datetime | None] = mapped_column(DATETIME(fsp=0), nullable=True)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(DATETIME(fsp=0), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DATETIME(fsp=0), nullable=False)
|
||||
updated_at: Mapped[datetime] = mapped_column(DATETIME(fsp=0), nullable=False)
|
||||
Reference in New Issue
Block a user