feat: 迁移奶龙风控业务模块与演示文档
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