""" 异常项模型 存储对账过程中检测到的异常 """ from datetime import datetime from enum import Enum from typing import Optional from sqlalchemy import ForeignKey, Integer, String, Text, DateTime, JSON, Float from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import BaseModel class ExceptionType(str, Enum): """异常类型""" # 第一阶段:工资表内部异常 MISSING_EMPLOYEE = "MISSING_EMPLOYEE" # 员工缺失(三个表之一缺失该员工) AMOUNT_MISMATCH = "AMOUNT_MISMATCH" # 金额不匹配 ZERO_AMOUNT = "ZERO_AMOUNT" # 金额为零 NEGATIVE_AMOUNT = "NEGATIVE_AMOUNT" # 负数金额 UNUSUAL_AMOUNT = "UNUSUAL_AMOUNT" # 金额异常(过大或过小) DUPLICATE_EMPLOYEE = "DUPLICATE_EMPLOYEE" # 重复员工 # 第二阶段:银行实发对账(预留) BANK_MISMATCH = "BANK_MISMATCH" # 银行实发与工资表不匹配 BANK_MISSING = "BANK_MISSING" # 银行记录缺失 BANK_EXTRA = "BANK_EXTRA" # 银行多余记录 class ExceptionStatus(str, Enum): """异常状态""" PENDING = "PENDING" # 待处理 CONFIRMED = "CONFIRMED" # 已确认 IGNORED = "IGNORED" # 已忽略 RESOLVED = "RESOLVED" # 已解决 class ExceptionSeverity(str, Enum): """异常严重程度""" LOW = "LOW" # 低 MEDIUM = "MEDIUM" # 中 HIGH = "HIGH" # 高 CRITICAL = "CRITICAL" # 严重 class ExceptionItem(BaseModel): """ 异常项模型 记录对账过程中检测到的各类异常 """ __tablename__ = "exception_items" company_id: Mapped[int] = mapped_column(Integer, ForeignKey("companies.id"), nullable=False, index=True) task_id: Mapped[int] = mapped_column(Integer, ForeignKey("reconciliation_tasks.id"), nullable=False, index=True) # 异常基本信息 exception_type: Mapped[str] = mapped_column(String(50), nullable=False, index=True, comment="异常类型") severity: Mapped[str] = mapped_column(String(20), nullable=False, default=ExceptionSeverity.MEDIUM.value, comment="严重程度") status: Mapped[str] = mapped_column(String(20), nullable=False, default=ExceptionStatus.PENDING.value, index=True, comment="状态") # 关联的员工信息 employee_id: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, index=True, comment="员工ID") employee_name: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment="员工姓名") # 异常详情 description: Mapped[str] = mapped_column(Text, nullable=False, comment="异常描述") detail: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="详细信息") # 涉及的金额 salary_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="工资表金额") social_security_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="社保表金额") tax_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="个税表金额") bank_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="银行实发金额") # 差异金额 difference_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="差异金额") # 建议处理方式 suggested_action: Mapped[Optional[str]] = mapped_column(String(200), nullable=True, comment="建议处理方式") ai_suggestion: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="AI 分析建议") # 处理信息 handled_by: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("users.id"), nullable=True) handled_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) handling_note: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="处理备注") # 关系 company = relationship("Company", backref="exceptions") task = relationship("ReconciliationTask", backref="exceptions") handler = relationship("User", foreign_keys=[handled_by]) def __repr__(self) -> str: return f""