116 lines
5.8 KiB
Python
116 lines
5.8 KiB
Python
"""风控查询所需的补充只读 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)
|