"""正式工资输入、分配过程与月度生成锁,和隔离预演分别留存。""" from datetime import datetime from decimal import Decimal from sqlalchemy import JSON, DateTime, Index, Integer, Numeric, String, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from app.models.base import BIGINT_UNSIGNED, Base, TimestampMixin, mysql_table_args class PayrollMonth(Base, TimestampMixin): """先锁月份行再修改方案或生成工资;生成标记不随审批退回清除。""" __tablename__ = "payroll_months" __table_args__ = mysql_table_args("工资月份控制表(首次生成即锁定分配,审批不解锁)") id: Mapped[int] = mapped_column( BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID" ) month: Mapped[str] = mapped_column(String(7), unique=True, comment="工资月份") maker_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="实际工资制作人账号ID") maker_name: Mapped[str] = mapped_column(String(64), comment="制作人用户名快照") generated_at: Mapped[datetime | None] = mapped_column( DateTime, comment="首次成功生成时间(不可解锁)" ) class PayrollInput(Base, TimestampMixin): """正式核算输入的版本:来源、成本、归属及期初均有依据,旧版本不覆盖。""" __tablename__ = "payroll_inputs" __table_args__ = mysql_table_args( "正式工资输入版本表", UniqueConstraint("business_id", "version", name="uk_payroll_inputs_business_version"), Index("idx_payroll_inputs_source_group", "source_database", "group_key"), ) id: Mapped[int] = mapped_column( BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID" ) business_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="正式业务ID") version: Mapped[int] = mapped_column(Integer, comment="输入版本") source_database: Mapped[str] = mapped_column(String(128), comment="源账套或人工来源") group_key: Mapped[str] = mapped_column(String(128), comment="独立业务平账组") fingerprint: Mapped[str] = mapped_column(String(64), comment="来源及事实指纹") data_json: Mapped[dict] = mapped_column(JSON, comment="经核实的源数据及人工事实快照") requested_by: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="录入人账号ID") class PayrollAllocation(Base, TimestampMixin): """一次正式计算的逐段过程;版本不可变,生效性由所属台账控制。""" __tablename__ = "payroll_allocations" __table_args__ = mysql_table_args( "正式FIFO分配明细表", UniqueConstraint("ledger_id", "line_no", name="uk_payroll_allocations_ledger_line"), Index("idx_payroll_allocations_business_id", "business_id"), ) id: Mapped[int] = mapped_column( BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID" ) ledger_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="所属正式台账ID") business_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="正式业务ID") line_no: Mapped[int] = mapped_column(Integer, comment="本台账稳定明细序号") input_id: Mapped[int] = mapped_column(BIGINT_UNSIGNED, comment="所用输入版本ID") amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), comment="分配回款金额") data_json: Mapped[dict] = mapped_column(JSON, comment="单据、成本、归属、参数和逐段计算依据")