feat: 添加线索引擎、NLQ、场景检测、前端界面等核心功能模块
This commit is contained in:
@@ -41,6 +41,10 @@ class RelationshipType(str, Enum):
|
||||
SUPPLIES = "supplies" # 供应商 —供货→ 合同/工单
|
||||
HANDLED_BY = "handled_by" # 工单 —处理人→ 员工
|
||||
SETTLES = "settles" # 结算单 —结算→ 合同
|
||||
EMPLOYED_BY = "employed_by" # 员工 —任职于→ 客户/供应商(组织)
|
||||
OPERATES = "operates" # 员工 —操作→ 号码/账户(R15 越权检测)
|
||||
SUBSCRIBES = "subscribes" # 号码 —订购→ 合同(R9/R10 订购关联)
|
||||
BIDS_FOR = "bids_for" # 供应商 —投标→ 工单(R12 招投标关联)
|
||||
|
||||
|
||||
# 关系的合法 (源实体类型, 目标实体类型) 约束,用于校验图谱写入
|
||||
@@ -72,6 +76,16 @@ RELATIONSHIP_DOMAIN: dict[RelationshipType, tuple[set[EntityType], set[EntityTyp
|
||||
),
|
||||
RelationshipType.HANDLED_BY: ({EntityType.WORK_ORDER}, {EntityType.EMPLOYEE}),
|
||||
RelationshipType.SETTLES: ({EntityType.SETTLEMENT}, {EntityType.CONTRACT}),
|
||||
RelationshipType.EMPLOYED_BY: (
|
||||
{EntityType.EMPLOYEE},
|
||||
{EntityType.CUSTOMER, EntityType.SUPPLIER},
|
||||
),
|
||||
RelationshipType.OPERATES: (
|
||||
{EntityType.EMPLOYEE},
|
||||
{EntityType.MSISDN, EntityType.ACCOUNT},
|
||||
),
|
||||
RelationshipType.SUBSCRIBES: ({EntityType.MSISDN}, {EntityType.CONTRACT}),
|
||||
RelationshipType.BIDS_FOR: ({EntityType.SUPPLIER}, {EntityType.WORK_ORDER}),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
"""源明细落地层(Staging / Raw)。
|
||||
|
||||
保存数据中心按 `数据要求.md` 提供的原始明细,作为"原始证据"留存;
|
||||
再由接入适配器(app/ingest)映射/投影到通用本体(entity/relationship/metric_event)。
|
||||
两层并存:源明细可回溯原始数据,本体支撑关联穿透与时序分析。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime as dt
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import Date, DateTime, Float, Index, Integer, String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.db import Base
|
||||
|
||||
|
||||
def _uuid() -> uuid.UUID:
|
||||
return uuid.uuid4()
|
||||
|
||||
|
||||
def _now() -> dt.datetime:
|
||||
return dt.datetime.now(dt.timezone.utc)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R8 · 政企收入全链路穿透 / 拆单规避(§4.1)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcContract(Base):
|
||||
"""源明细:政企合同(对应数据要求 §4.1 / R8)。"""
|
||||
|
||||
__tablename__ = "src_contract"
|
||||
__table_args__ = (Index("ix_src_contract_customer", "customer_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
contract_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
customer_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
customer_name: Mapped[str | None] = mapped_column(String(256))
|
||||
amount: Mapped[float] = mapped_column(Float, nullable=False)
|
||||
sign_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
approval_threshold: Mapped[float | None] = mapped_column(Float)
|
||||
approval_level: Mapped[str | None] = mapped_column(String(32))
|
||||
legal_person: Mapped[str | None] = mapped_column(String(128))
|
||||
register_address: Mapped[str | None] = mapped_column(String(256))
|
||||
pay_account: Mapped[str | None] = mapped_column(String(64))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcContractApproval(Base):
|
||||
"""源明细:合同审批流水(对应 R8 补充)。"""
|
||||
|
||||
__tablename__ = "src_contract_approval"
|
||||
__table_args__ = (Index("ix_src_approval_contract", "contract_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
contract_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
approval_step: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
approver: Mapped[str | None] = mapped_column(String(128))
|
||||
approval_result: Mapped[str | None] = mapped_column(String(32)) # approved/rejected
|
||||
approval_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
remark: Mapped[str | None] = mapped_column(Text)
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcPayment(Base):
|
||||
"""源明细:回款流水(对应 R8 回款时序违约)。"""
|
||||
|
||||
__tablename__ = "src_payment"
|
||||
__table_args__ = (Index("ix_src_payment_contract", "contract_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
contract_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
pay_account: Mapped[str | None] = mapped_column(String(64))
|
||||
pay_amount: Mapped[float] = mapped_column(Float, nullable=False)
|
||||
pay_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
pay_type: Mapped[str | None] = mapped_column(String(32)) # 预付/尾款/全款
|
||||
overdue_flag: Mapped[str | None] = mapped_column(String(8)) # Y/N
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R9 · 市场业务真实性 / 养卡骗补(§4.2)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcChannelMonthly(Base):
|
||||
"""源明细:渠道用户月度留存与佣金/活跃(对应数据要求 §4.2 / R9)。"""
|
||||
|
||||
__tablename__ = "src_channel_monthly"
|
||||
__table_args__ = (Index("ix_src_channel_key", "channel_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
channel_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
cohort_label: Mapped[str] = mapped_column(String(32), nullable=False) # 新增批次(如 2025-01)
|
||||
month_index: Mapped[int] = mapped_column(Integer, nullable=False) # 第N月
|
||||
cohort_size: Mapped[int] = mapped_column(Integer, default=0)
|
||||
retained: Mapped[int] = mapped_column(Integer, default=0)
|
||||
commission_paid: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
active_ratio: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
zero_usage_ratio: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcSubscription(Base):
|
||||
"""源明细:用户订购与退订流水(对应 R9 订购退订分析)。"""
|
||||
|
||||
__tablename__ = "src_subscription"
|
||||
__table_args__ = (Index("ix_src_sub_msisdn", "msisdn"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
msisdn: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
channel_key: Mapped[str | None] = mapped_column(String(64))
|
||||
product_code: Mapped[str | None] = mapped_column(String(64))
|
||||
subscribe_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
unsubscribe_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
region: Mapped[str | None] = mapped_column(String(64))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R10 · 收入与成本跨期匹配(§4.3)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcRevenueRecognition(Base):
|
||||
"""源明细:收入确认凭证与明细(对应 R10)。"""
|
||||
|
||||
__tablename__ = "src_revenue_recognition"
|
||||
__table_args__ = (Index("ix_src_rev_contract", "contract_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
voucher_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
contract_no: Mapped[str | None] = mapped_column(String(64))
|
||||
recognition_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
recognition_amount: Mapped[float] = mapped_column(Float, nullable=False)
|
||||
billing_mode: Mapped[str | None] = mapped_column(String(32)) # 按量/包年/趸交
|
||||
period_start: Mapped[dt.date | None] = mapped_column(Date)
|
||||
period_end: Mapped[dt.date | None] = mapped_column(Date)
|
||||
prepaid_flag: Mapped[str | None] = mapped_column(String(8)) # Y/N 预收/趸交
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcCostAmortization(Base):
|
||||
"""源明细:成本摊销明细(对应 R10)。"""
|
||||
|
||||
__tablename__ = "src_cost_amortization"
|
||||
__table_args__ = (Index("ix_src_cost_contract", "contract_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
voucher_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
contract_no: Mapped[str | None] = mapped_column(String(64))
|
||||
cost_type: Mapped[str | None] = mapped_column(String(64)) # 设备/安装/维护
|
||||
amortization_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
amortization_amount: Mapped[float] = mapped_column(Float, nullable=False)
|
||||
total_periods: Mapped[int | None] = mapped_column(Integer)
|
||||
current_period: Mapped[int | None] = mapped_column(Integer)
|
||||
delivery_date: Mapped[dt.date | None] = mapped_column(Date) # 交付/上架日期
|
||||
acceptance_date: Mapped[dt.date | None] = mapped_column(Date) # 验收日期
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R11 · 渠道佣金与代理商套利(§4.4)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcTerminalBinding(Base):
|
||||
"""源明细:终端 IMEI 与号码绑定 / 补贴发放(对应 R11)。"""
|
||||
|
||||
__tablename__ = "src_terminal_binding"
|
||||
__table_args__ = (
|
||||
Index("ix_src_terminal_imei", "imei"),
|
||||
Index("ix_src_terminal_msisdn", "msisdn"),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
imei: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
msisdn: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
brand_model: Mapped[str | None] = mapped_column(String(128))
|
||||
activate_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
subsidy_amount: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
commission_amount: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
online_days: Mapped[int | None] = mapped_column(Integer) # 在网天数
|
||||
post_activate_traffic_mb: Mapped[float | None] = mapped_column(Float) # 激活后流量
|
||||
region: Mapped[str | None] = mapped_column(String(64)) # 归属地
|
||||
cross_province_flag: Mapped[str | None] = mapped_column(String(8)) # 跨省入网 Y/N
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R12 · 网络建设与工程采购(§4.5)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcBidding(Base):
|
||||
"""源明细:招投标记录(对应 R12)。"""
|
||||
|
||||
__tablename__ = "src_bidding"
|
||||
__table_args__ = (Index("ix_src_bidding_project", "project_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
project_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
project_name: Mapped[str | None] = mapped_column(String(256))
|
||||
bidder_key: Mapped[str] = mapped_column(String(64), nullable=False) # 投标人/供应商编号
|
||||
bidder_name: Mapped[str | None] = mapped_column(String(256))
|
||||
bid_amount: Mapped[float | None] = mapped_column(Float)
|
||||
bid_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
win_flag: Mapped[str | None] = mapped_column(String(8)) # 中标 Y/N
|
||||
technical_score: Mapped[float | None] = mapped_column(Float)
|
||||
legal_person: Mapped[str | None] = mapped_column(String(128))
|
||||
shareholder_info: Mapped[str | None] = mapped_column(Text) # JSON or 描述
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcProjectSignoff(Base):
|
||||
"""源明细:工程量签证与施工(对应 R12)。"""
|
||||
|
||||
__tablename__ = "src_project_signoff"
|
||||
__table_args__ = (Index("ix_src_signoff_project", "project_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
project_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
work_order_no: Mapped[str | None] = mapped_column(String(64))
|
||||
signoff_quantity: Mapped[float | None] = mapped_column(Float) # 签证工程量
|
||||
unit: Mapped[str | None] = mapped_column(String(32))
|
||||
resource_consumed: Mapped[float | None] = mapped_column(Float) # 实际资源消耗
|
||||
contractor_key: Mapped[str | None] = mapped_column(String(64)) # 施工队
|
||||
signoff_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
inspection_lat: Mapped[float | None] = mapped_column(Float) # 巡检 GPS 纬度
|
||||
inspection_lng: Mapped[float | None] = mapped_column(Float) # 巡检 GPS 经度
|
||||
inspection_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R13 · 互联互通与网间结算(§4.6)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcCdr(Base):
|
||||
"""源明细:话单 CDR(对应 R13,大数据量增量接入)。"""
|
||||
|
||||
__tablename__ = "src_cdr"
|
||||
__table_args__ = (
|
||||
Index("ix_src_cdr_caller", "caller"),
|
||||
Index("ix_src_cdr_time", "start_time"),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
caller: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
callee: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
start_time: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
||||
duration_sec: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
call_type: Mapped[str | None] = mapped_column(String(16)) # voice/sms/data
|
||||
peer_operator: Mapped[str | None] = mapped_column(String(32)) # 对端运营商
|
||||
route_info: Mapped[str | None] = mapped_column(String(128)) # 路由信息
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcInterconnectSettlement(Base):
|
||||
"""源明细:网间结算单(对应 R13)。"""
|
||||
|
||||
__tablename__ = "src_interconnect_settlement"
|
||||
__table_args__ = (Index("ix_src_ics_period", "settle_period"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
settlement_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
peer_operator: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
settle_period: Mapped[str] = mapped_column(String(16), nullable=False) # 如 2025-06
|
||||
settle_type: Mapped[str | None] = mapped_column(String(32)) # 语音/短信/SP/CP
|
||||
volume: Mapped[float] = mapped_column(Float, default=0.0) # 结算量(分钟/条)
|
||||
unit_price: Mapped[float | None] = mapped_column(Float)
|
||||
settle_amount: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
sms_delivery_rate: Mapped[float | None] = mapped_column(Float) # 短信到达率
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R14 · 云业务 / IDC 与新兴业务(§4.7)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcCloudUsage(Base):
|
||||
"""源明细:云资源用量(对应 R14)。"""
|
||||
|
||||
__tablename__ = "src_cloud_usage"
|
||||
__table_args__ = (Index("ix_src_cloud_contract", "contract_no"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
contract_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
customer_key: Mapped[str | None] = mapped_column(String(64))
|
||||
resource_type: Mapped[str | None] = mapped_column(String(32)) # CPU/存储/带宽
|
||||
usage_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
actual_usage: Mapped[float] = mapped_column(Float, default=0.0) # 实际用量
|
||||
contracted_quota: Mapped[float | None] = mapped_column(Float) # 合同约定量
|
||||
billed_usage: Mapped[float | None] = mapped_column(Float) # 计费量
|
||||
unit: Mapped[str | None] = mapped_column(String(16)) # vCPU/GB/Mbps
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcIdcCabinet(Base):
|
||||
"""源明细:IDC 机柜出租与电力消耗(对应 R14)。"""
|
||||
|
||||
__tablename__ = "src_idc_cabinet"
|
||||
__table_args__ = (Index("ix_src_idc_cabinet_id", "cabinet_id"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
cabinet_id: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
customer_key: Mapped[str | None] = mapped_column(String(64))
|
||||
contract_no: Mapped[str | None] = mapped_column(String(64))
|
||||
report_month: Mapped[str | None] = mapped_column(String(16)) # 如 2025-06
|
||||
occupancy_rate: Mapped[float | None] = mapped_column(Float) # 出租率
|
||||
power_kwh: Mapped[float | None] = mapped_column(Float) # 电力消耗 kWh
|
||||
revenue_amount: Mapped[float | None] = mapped_column(Float) # 收入金额
|
||||
acceptance_date: Mapped[dt.date | None] = mapped_column(Date) # 验收日期
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# R15 · 员工内部舞弊与资源滥用(§4.8)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcEmployeeOperation(Base):
|
||||
"""源明细:员工权限与操作日志(对应 R15)。"""
|
||||
|
||||
__tablename__ = "src_employee_operation"
|
||||
__table_args__ = (
|
||||
Index("ix_src_emp_op_employee", "employee_key"),
|
||||
Index("ix_src_emp_op_time", "operation_time"),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
employee_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
employee_name: Mapped[str | None] = mapped_column(String(128))
|
||||
position: Mapped[str | None] = mapped_column(String(64))
|
||||
role_permissions: Mapped[str | None] = mapped_column(Text) # 岗位-权限
|
||||
operation_type: Mapped[str | None] = mapped_column(String(64))
|
||||
operation_target: Mapped[str | None] = mapped_column(String(256)) # 操作对象
|
||||
operation_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
department: Mapped[str | None] = mapped_column(String(128))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcInternalMsisdn(Base):
|
||||
"""源明细:内部测试号及用量(对应 R15)。"""
|
||||
|
||||
__tablename__ = "src_internal_msisdn"
|
||||
__table_args__ = (Index("ix_src_int_msisdn", "msisdn"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
msisdn: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
assigned_employee: Mapped[str | None] = mapped_column(String(64))
|
||||
purpose: Mapped[str | None] = mapped_column(String(128)) # 测试/演示/其他
|
||||
traffic_mb: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
voice_min: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
revenue_attributed: Mapped[float] = mapped_column(Float, default=0.0) # 收入归属
|
||||
report_month: Mapped[str | None] = mapped_column(String(16))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcPointsTransaction(Base):
|
||||
"""源明细:积分/电子券发放与兑换流水(对应 R15)。"""
|
||||
|
||||
__tablename__ = "src_points_transaction"
|
||||
__table_args__ = (Index("ix_src_points_employee", "operator_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
transaction_no: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
operator_key: Mapped[str] = mapped_column(String(64), nullable=False) # 操作人工号
|
||||
target_account: Mapped[str | None] = mapped_column(String(64)) # 受益账户
|
||||
transaction_type: Mapped[str | None] = mapped_column(String(32)) # 发放/兑换/变现
|
||||
points_amount: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
cash_value: Mapped[float | None] = mapped_column(Float) # 变现金额
|
||||
transaction_time: Mapped[dt.datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 主数据源明细(§3 实体级原始数据)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SrcCustomer(Base):
|
||||
"""源明细:客户主数据(§3 Customer)。"""
|
||||
|
||||
__tablename__ = "src_customer"
|
||||
__table_args__ = (Index("ix_src_cust_key", "customer_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
customer_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
customer_name: Mapped[str] = mapped_column(String(256), nullable=False)
|
||||
customer_type: Mapped[str | None] = mapped_column(String(32)) # 政企/公众
|
||||
register_address: Mapped[str | None] = mapped_column(String(256))
|
||||
legal_person: Mapped[str | None] = mapped_column(String(128))
|
||||
uscc: Mapped[str | None] = mapped_column(String(32)) # 统一社会信用代码
|
||||
open_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcSupplier(Base):
|
||||
"""源明细:供应商主数据(§3 Supplier)。"""
|
||||
|
||||
__tablename__ = "src_supplier"
|
||||
__table_args__ = (Index("ix_src_supplier_key", "supplier_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
supplier_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
supplier_name: Mapped[str] = mapped_column(String(256), nullable=False)
|
||||
legal_person: Mapped[str | None] = mapped_column(String(128))
|
||||
shareholder_info: Mapped[str | None] = mapped_column(Text)
|
||||
register_address: Mapped[str | None] = mapped_column(String(256))
|
||||
uscc: Mapped[str | None] = mapped_column(String(32))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcEmployee(Base):
|
||||
"""源明细:员工主数据(§3 Employee)。"""
|
||||
|
||||
__tablename__ = "src_employee"
|
||||
__table_args__ = (Index("ix_src_emp_key", "employee_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
employee_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
employee_name: Mapped[str | None] = mapped_column(String(128))
|
||||
position: Mapped[str | None] = mapped_column(String(64))
|
||||
department: Mapped[str | None] = mapped_column(String(128))
|
||||
role_permissions: Mapped[str | None] = mapped_column(Text)
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcChannel(Base):
|
||||
"""源明细:渠道/代理商主数据(§3 Channel)。"""
|
||||
|
||||
__tablename__ = "src_channel"
|
||||
__table_args__ = (Index("ix_src_chan_key", "channel_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
channel_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
channel_name: Mapped[str | None] = mapped_column(String(256))
|
||||
commission_policy: Mapped[str | None] = mapped_column(Text) # 佣金政策描述
|
||||
region: Mapped[str | None] = mapped_column(String(64))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcMsisdn(Base):
|
||||
"""源明细:号码主数据(§3 MSISDN)。"""
|
||||
|
||||
__tablename__ = "src_msisdn"
|
||||
__table_args__ = (Index("ix_src_msisdn_no", "msisdn"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
msisdn: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
customer_key: Mapped[str | None] = mapped_column(String(64))
|
||||
region: Mapped[str | None] = mapped_column(String(64))
|
||||
activate_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
deactivate_date: Mapped[dt.date | None] = mapped_column(Date)
|
||||
status: Mapped[str | None] = mapped_column(String(16)) # active/suspended/cancelled
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
|
||||
|
||||
class SrcAccount(Base):
|
||||
"""源明细:账户主数据(§3 Account)。"""
|
||||
|
||||
__tablename__ = "src_account"
|
||||
__table_args__ = (Index("ix_src_acct_key", "account_key"),)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=_uuid)
|
||||
account_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
account_name: Mapped[str | None] = mapped_column(String(256))
|
||||
owner_key: Mapped[str | None] = mapped_column(String(64)) # 所属主体编号
|
||||
owner_type: Mapped[str | None] = mapped_column(String(32)) # customer/supplier/legal_person
|
||||
bank_name: Mapped[str | None] = mapped_column(String(128))
|
||||
branch_name: Mapped[str | None] = mapped_column(String(128))
|
||||
data_version_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
|
||||
ingested_at: Mapped[dt.datetime] = mapped_column(DateTime(timezone=True), default=_now)
|
||||
Reference in New Issue
Block a user