feat: add monthly payroll center tables

This commit is contained in:
焦龙言 2026-06-18 14:23:11 +08:00
parent 99c7ba776f
commit a846ea5070
4 changed files with 528 additions and 0 deletions

View File

@ -441,6 +441,172 @@ class OvertimeRecordORM(Base):
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.utcnow, comment="创建时间")
class AttendanceSyncJobORM(Base):
"""钉钉或 Excel 考勤同步批次,用于实时看板和月度核算追踪。"""
__tablename__ = "attendance_sync_jobs"
__table_args__ = {
"comment": "考勤同步任务表记录钉钉实时同步或Excel导入的批次状态",
"mysql_charset": "utf8mb4",
"mysql_collate": "utf8mb4_unicode_ci",
}
id: Mapped[str] = mapped_column(String(32), primary_key=True, comment="同步任务IDUUID十六进制字符串")
source_type: Mapped[str] = mapped_column(String(32), nullable=False, index=True, comment="数据来源dingtalk钉钉、excel表格")
sync_mode: Mapped[str] = mapped_column(String(32), nullable=False, default="today", index=True, comment="同步模式today今日、month本月至今、range自定义范围")
attendance_date: Mapped[date | None] = mapped_column(Date, nullable=True, index=True, comment="实时看板对应考勤日期")
salary_month: Mapped[str] = mapped_column(String(7), nullable=False, default="", index=True, comment="工资月份格式YYYY-MM")
start_date: Mapped[date | None] = mapped_column(Date, nullable=True, comment="同步开始日期")
end_date: Mapped[date | None] = mapped_column(Date, nullable=True, comment="同步结束日期")
status: Mapped[str] = mapped_column(String(32), nullable=False, default="created", index=True, comment="任务状态created、running、completed、failed")
employee_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="本次同步涉及员工数量")
record_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="本次同步获得或解析的考勤记录数量")
error_message: Mapped[str] = mapped_column(Text, nullable=False, default="", comment="任务失败时的错误信息")
created_by: Mapped[str] = mapped_column(String(64), nullable=False, default="", comment="创建人用户名快照")
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.utcnow, comment="创建时间")
updated_at: Mapped[datetime] = mapped_column(
DateTime,
nullable=False,
default=datetime.utcnow,
onupdate=datetime.utcnow,
comment="更新时间",
)
class SalaryPreviewORM(Base):
"""本月进行中的薪资预估结果,不作为最终工资发放依据。"""
__tablename__ = "salary_preview"
__table_args__ = (
UniqueConstraint("sync_job_id", "employee_id", name="uq_salary_preview_sync_employee"),
{
"comment": "实时薪资预估表,保存当前同步批次下的员工级薪资预估",
"mysql_charset": "utf8mb4",
"mysql_collate": "utf8mb4_unicode_ci",
},
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="薪资预估主键ID")
sync_job_id: Mapped[str] = mapped_column(
ForeignKey("attendance_sync_jobs.id", ondelete="CASCADE"),
nullable=False,
index=True,
comment="关联考勤同步任务ID",
)
employee_id: Mapped[int | None] = mapped_column(
ForeignKey("employees.id", ondelete="SET NULL"),
nullable=True,
index=True,
comment="关联员工ID未匹配员工时为空",
)
employee_no: Mapped[str] = mapped_column(String(64), nullable=False, default="", index=True, comment="员工编号快照")
employee_name: Mapped[str] = mapped_column(String(128), nullable=False, index=True, comment="员工姓名快照")
department: Mapped[str] = mapped_column(String(128), nullable=False, default="", comment="部门名称快照")
position: Mapped[str] = mapped_column(String(128), nullable=False, default="", comment="岗位名称快照")
salary_month: Mapped[str] = mapped_column(String(7), nullable=False, default="", index=True, comment="工资月份格式YYYY-MM")
attendance_days: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="本月当前出勤天数")
actual_work_hours: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="本月当前实际工时")
punch_overtime_hours: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="打卡推算加班工时")
leave_hours: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="请假或调休工时")
remaining_overtime_hours: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="剩余加班工时")
late_deduction: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="当前迟到扣款")
missing_card_deduction: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="当前缺卡扣款")
commission_amount: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="当前已录入提成")
overtime_pay: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="当前加班费")
estimated_gross_salary: Mapped[float | None] = mapped_column(Float, nullable=True, comment="当前预估应发工资")
estimated_net_salary: Mapped[float | None] = mapped_column(Float, nullable=True, comment="当前预估实发工资")
status: Mapped[str] = mapped_column(String(32), nullable=False, default="estimated", index=True, comment="预估状态estimated已预估、warning有异常")
note: Mapped[str] = mapped_column(Text, nullable=False, default="", comment="预估备注或异常说明")
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.utcnow, comment="创建时间")
updated_at: Mapped[datetime] = mapped_column(
DateTime,
nullable=False,
default=datetime.utcnow,
onupdate=datetime.utcnow,
comment="更新时间",
)
sync_job: Mapped[AttendanceSyncJobORM] = relationship()
employee: Mapped[EmployeeORM | None] = relationship()
class MonthlyPayrollRunORM(Base):
"""月度正式核算批次,支持复核、锁定和导出。"""
__tablename__ = "monthly_payroll_runs"
__table_args__ = {
"comment": "月度工资核算批次表,记录每月工资计算、复核和锁定状态",
"mysql_charset": "utf8mb4",
"mysql_collate": "utf8mb4_unicode_ci",
}
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="月度核算批次主键ID")
salary_month: Mapped[str] = mapped_column(String(7), nullable=False, index=True, comment="工资月份格式YYYY-MM")
source_type: Mapped[str] = mapped_column(String(32), nullable=False, default="excel", comment="数据来源excel或dingtalk")
source_job_id: Mapped[str] = mapped_column(String(32), nullable=False, default="", index=True, comment="来源任务ID可关联工资任务或同步任务")
status: Mapped[str] = mapped_column(String(32), nullable=False, default="draft", index=True, comment="核算状态draft、calculated、reviewed、locked、failed")
employee_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="参与核算员工数量")
gross_total: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="应发工资合计")
net_total: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="实发工资合计")
deduction_total: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="扣款合计")
overtime_total: Mapped[float] = mapped_column(Float, nullable=False, default=0, comment="剩余加班工时合计")
locked_by: Mapped[str] = mapped_column(String(64), nullable=False, default="", comment="锁定人用户名快照")
locked_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="锁定时间")
created_by: Mapped[str] = mapped_column(String(64), nullable=False, default="", comment="创建人用户名快照")
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.utcnow, comment="创建时间")
updated_at: Mapped[datetime] = mapped_column(
DateTime,
nullable=False,
default=datetime.utcnow,
onupdate=datetime.utcnow,
comment="更新时间",
)
class PayrollExceptionORM(Base):
"""核算异常记录,例如缺员工、缺薪资档案、缺卡、请假无法识别。"""
__tablename__ = "payroll_exceptions"
__table_args__ = {
"comment": "工资核算异常表,保存月度核算或实时同步过程中发现的待处理问题",
"mysql_charset": "utf8mb4",
"mysql_collate": "utf8mb4_unicode_ci",
}
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="异常记录主键ID")
run_id: Mapped[int | None] = mapped_column(
ForeignKey("monthly_payroll_runs.id", ondelete="CASCADE"),
nullable=True,
index=True,
comment="关联月度核算批次ID",
)
sync_job_id: Mapped[str | None] = mapped_column(
ForeignKey("attendance_sync_jobs.id", ondelete="CASCADE"),
nullable=True,
index=True,
comment="关联考勤同步任务ID",
)
employee_id: Mapped[int | None] = mapped_column(
ForeignKey("employees.id", ondelete="SET NULL"),
nullable=True,
index=True,
comment="关联员工ID未匹配员工时为空",
)
employee_no: Mapped[str] = mapped_column(String(64), nullable=False, default="", index=True, comment="员工编号快照")
employee_name: Mapped[str] = mapped_column(String(128), nullable=False, default="", index=True, comment="员工姓名快照")
salary_month: Mapped[str] = mapped_column(String(7), nullable=False, default="", index=True, comment="工资月份格式YYYY-MM")
exception_type: Mapped[str] = mapped_column(String(64), nullable=False, index=True, comment="异常类型编码")
severity: Mapped[str] = mapped_column(String(32), nullable=False, default="warning", index=True, comment="严重级别info、warning、error")
message: Mapped[str] = mapped_column(Text, nullable=False, default="", comment="异常说明")
status: Mapped[str] = mapped_column(String(32), nullable=False, default="open", index=True, comment="处理状态open待处理、resolved已处理、ignored已忽略")
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.utcnow, comment="创建时间")
resolved_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="处理完成时间")
run: Mapped[MonthlyPayrollRunORM | None] = relationship()
sync_job: Mapped[AttendanceSyncJobORM | None] = relationship()
employee: Mapped[EmployeeORM | None] = relationship()
class CommissionRecordORM(Base):
"""月度提成或奖金记录,支持手工维护和 Excel 导入。"""

View File

@ -474,6 +474,125 @@ CREATE TABLE IF NOT EXISTS `overtime_record` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='加班记录表,保存每日加班工时、加班类型、单价和金额';
CREATE TABLE IF NOT EXISTS `attendance_sync_jobs` (
`id` VARCHAR(32) NOT NULL COMMENT '同步任务IDUUID十六进制字符串',
`source_type` VARCHAR(32) NOT NULL COMMENT '数据来源dingtalk钉钉、excel表格',
`sync_mode` VARCHAR(32) NOT NULL DEFAULT 'today' COMMENT '同步模式today今日、month本月至今、range自定义范围',
`attendance_date` DATE NULL COMMENT '实时看板对应考勤日期',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`start_date` DATE NULL COMMENT '同步开始日期',
`end_date` DATE NULL COMMENT '同步结束日期',
`status` VARCHAR(32) NOT NULL DEFAULT 'created' COMMENT '任务状态created、running、completed、failed',
`employee_count` INT NOT NULL DEFAULT 0 COMMENT '本次同步涉及员工数量',
`record_count` INT NOT NULL DEFAULT 0 COMMENT '本次同步获得或解析的考勤记录数量',
`error_message` TEXT NOT NULL COMMENT '任务失败时的错误信息',
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人用户名快照',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_attendance_sync_jobs_source_type` (`source_type`),
KEY `ix_attendance_sync_jobs_sync_mode` (`sync_mode`),
KEY `ix_attendance_sync_jobs_attendance_date` (`attendance_date`),
KEY `ix_attendance_sync_jobs_salary_month` (`salary_month`),
KEY `ix_attendance_sync_jobs_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='考勤同步任务表记录钉钉实时同步或Excel导入的批次状态';
CREATE TABLE IF NOT EXISTS `salary_preview` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '薪资预估主键ID',
`sync_job_id` VARCHAR(32) NOT NULL COMMENT '关联考勤同步任务ID',
`employee_id` INT NULL COMMENT '关联员工ID未匹配员工时为空',
`employee_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '员工编号快照',
`employee_name` VARCHAR(128) NOT NULL COMMENT '员工姓名快照',
`department` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '部门名称快照',
`position` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '岗位名称快照',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`attendance_days` FLOAT NOT NULL DEFAULT 0 COMMENT '本月当前出勤天数',
`actual_work_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '本月当前实际工时',
`punch_overtime_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '打卡推算加班工时',
`leave_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '请假或调休工时',
`remaining_overtime_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '剩余加班工时',
`late_deduction` FLOAT NOT NULL DEFAULT 0 COMMENT '当前迟到扣款',
`missing_card_deduction` FLOAT NOT NULL DEFAULT 0 COMMENT '当前缺卡扣款',
`commission_amount` FLOAT NOT NULL DEFAULT 0 COMMENT '当前已录入提成',
`overtime_pay` FLOAT NOT NULL DEFAULT 0 COMMENT '当前加班费',
`estimated_gross_salary` FLOAT NULL COMMENT '当前预估应发工资',
`estimated_net_salary` FLOAT NULL COMMENT '当前预估实发工资',
`status` VARCHAR(32) NOT NULL DEFAULT 'estimated' COMMENT '预估状态estimated已预估、warning有异常',
`note` TEXT NOT NULL COMMENT '预估备注或异常说明',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uq_salary_preview_sync_employee` (`sync_job_id`, `employee_id`),
KEY `ix_salary_preview_sync_job_id` (`sync_job_id`),
KEY `ix_salary_preview_employee_id` (`employee_id`),
KEY `ix_salary_preview_employee_no` (`employee_no`),
KEY `ix_salary_preview_employee_name` (`employee_name`),
KEY `ix_salary_preview_salary_month` (`salary_month`),
KEY `ix_salary_preview_status` (`status`),
CONSTRAINT `fk_salary_preview_sync_job_id`
FOREIGN KEY (`sync_job_id`) REFERENCES `attendance_sync_jobs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_salary_preview_employee_id`
FOREIGN KEY (`employee_id`) REFERENCES `employees` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='实时薪资预估表,保存当前同步批次下的员工级薪资预估';
CREATE TABLE IF NOT EXISTS `monthly_payroll_runs` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '月度核算批次主键ID',
`salary_month` VARCHAR(7) NOT NULL COMMENT '工资月份格式YYYY-MM',
`source_type` VARCHAR(32) NOT NULL DEFAULT 'excel' COMMENT '数据来源excel或dingtalk',
`source_job_id` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '来源任务ID可关联工资任务或同步任务',
`status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '核算状态draft、calculated、reviewed、locked、failed',
`employee_count` INT NOT NULL DEFAULT 0 COMMENT '参与核算员工数量',
`gross_total` FLOAT NOT NULL DEFAULT 0 COMMENT '应发工资合计',
`net_total` FLOAT NOT NULL DEFAULT 0 COMMENT '实发工资合计',
`deduction_total` FLOAT NOT NULL DEFAULT 0 COMMENT '扣款合计',
`overtime_total` FLOAT NOT NULL DEFAULT 0 COMMENT '剩余加班工时合计',
`locked_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '锁定人用户名快照',
`locked_at` DATETIME NULL COMMENT '锁定时间',
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人用户名快照',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_monthly_payroll_runs_salary_month` (`salary_month`),
KEY `ix_monthly_payroll_runs_source_job_id` (`source_job_id`),
KEY `ix_monthly_payroll_runs_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='月度工资核算批次表,记录每月工资计算、复核和锁定状态';
CREATE TABLE IF NOT EXISTS `payroll_exceptions` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '异常记录主键ID',
`run_id` INT NULL COMMENT '关联月度核算批次ID',
`sync_job_id` VARCHAR(32) NULL COMMENT '关联考勤同步任务ID',
`employee_id` INT NULL COMMENT '关联员工ID未匹配员工时为空',
`employee_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '员工编号快照',
`employee_name` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '员工姓名快照',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`exception_type` VARCHAR(64) NOT NULL COMMENT '异常类型编码',
`severity` VARCHAR(32) NOT NULL DEFAULT 'warning' COMMENT '严重级别info、warning、error',
`message` TEXT NOT NULL COMMENT '异常说明',
`status` VARCHAR(32) NOT NULL DEFAULT 'open' COMMENT '处理状态open待处理、resolved已处理、ignored已忽略',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`resolved_at` DATETIME NULL COMMENT '处理完成时间',
PRIMARY KEY (`id`),
KEY `ix_payroll_exceptions_run_id` (`run_id`),
KEY `ix_payroll_exceptions_sync_job_id` (`sync_job_id`),
KEY `ix_payroll_exceptions_employee_id` (`employee_id`),
KEY `ix_payroll_exceptions_employee_no` (`employee_no`),
KEY `ix_payroll_exceptions_employee_name` (`employee_name`),
KEY `ix_payroll_exceptions_salary_month` (`salary_month`),
KEY `ix_payroll_exceptions_exception_type` (`exception_type`),
KEY `ix_payroll_exceptions_severity` (`severity`),
KEY `ix_payroll_exceptions_status` (`status`),
CONSTRAINT `fk_payroll_exceptions_run_id`
FOREIGN KEY (`run_id`) REFERENCES `monthly_payroll_runs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_payroll_exceptions_sync_job_id`
FOREIGN KEY (`sync_job_id`) REFERENCES `attendance_sync_jobs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_payroll_exceptions_employee_id`
FOREIGN KEY (`employee_id`) REFERENCES `employees` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='工资核算异常表,保存月度核算或实时同步过程中发现的待处理问题';
CREATE TABLE IF NOT EXISTS `commission_record` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '提成记录主键ID',
`employee_id` INT NOT NULL COMMENT '关联员工ID',

View File

@ -384,6 +384,125 @@ CREATE TABLE IF NOT EXISTS `overtime_record` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='加班记录表,保存每日加班工时、加班类型、单价和金额';
CREATE TABLE IF NOT EXISTS `attendance_sync_jobs` (
`id` VARCHAR(32) NOT NULL COMMENT '同步任务IDUUID十六进制字符串',
`source_type` VARCHAR(32) NOT NULL COMMENT '数据来源dingtalk钉钉、excel表格',
`sync_mode` VARCHAR(32) NOT NULL DEFAULT 'today' COMMENT '同步模式today今日、month本月至今、range自定义范围',
`attendance_date` DATE NULL COMMENT '实时看板对应考勤日期',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`start_date` DATE NULL COMMENT '同步开始日期',
`end_date` DATE NULL COMMENT '同步结束日期',
`status` VARCHAR(32) NOT NULL DEFAULT 'created' COMMENT '任务状态created、running、completed、failed',
`employee_count` INT NOT NULL DEFAULT 0 COMMENT '本次同步涉及员工数量',
`record_count` INT NOT NULL DEFAULT 0 COMMENT '本次同步获得或解析的考勤记录数量',
`error_message` TEXT NOT NULL COMMENT '任务失败时的错误信息',
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人用户名快照',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_attendance_sync_jobs_source_type` (`source_type`),
KEY `ix_attendance_sync_jobs_sync_mode` (`sync_mode`),
KEY `ix_attendance_sync_jobs_attendance_date` (`attendance_date`),
KEY `ix_attendance_sync_jobs_salary_month` (`salary_month`),
KEY `ix_attendance_sync_jobs_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='考勤同步任务表记录钉钉实时同步或Excel导入的批次状态';
CREATE TABLE IF NOT EXISTS `salary_preview` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '薪资预估主键ID',
`sync_job_id` VARCHAR(32) NOT NULL COMMENT '关联考勤同步任务ID',
`employee_id` INT NULL COMMENT '关联员工ID未匹配员工时为空',
`employee_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '员工编号快照',
`employee_name` VARCHAR(128) NOT NULL COMMENT '员工姓名快照',
`department` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '部门名称快照',
`position` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '岗位名称快照',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`attendance_days` FLOAT NOT NULL DEFAULT 0 COMMENT '本月当前出勤天数',
`actual_work_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '本月当前实际工时',
`punch_overtime_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '打卡推算加班工时',
`leave_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '请假或调休工时',
`remaining_overtime_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '剩余加班工时',
`late_deduction` FLOAT NOT NULL DEFAULT 0 COMMENT '当前迟到扣款',
`missing_card_deduction` FLOAT NOT NULL DEFAULT 0 COMMENT '当前缺卡扣款',
`commission_amount` FLOAT NOT NULL DEFAULT 0 COMMENT '当前已录入提成',
`overtime_pay` FLOAT NOT NULL DEFAULT 0 COMMENT '当前加班费',
`estimated_gross_salary` FLOAT NULL COMMENT '当前预估应发工资',
`estimated_net_salary` FLOAT NULL COMMENT '当前预估实发工资',
`status` VARCHAR(32) NOT NULL DEFAULT 'estimated' COMMENT '预估状态estimated已预估、warning有异常',
`note` TEXT NOT NULL COMMENT '预估备注或异常说明',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uq_salary_preview_sync_employee` (`sync_job_id`, `employee_id`),
KEY `ix_salary_preview_sync_job_id` (`sync_job_id`),
KEY `ix_salary_preview_employee_id` (`employee_id`),
KEY `ix_salary_preview_employee_no` (`employee_no`),
KEY `ix_salary_preview_employee_name` (`employee_name`),
KEY `ix_salary_preview_salary_month` (`salary_month`),
KEY `ix_salary_preview_status` (`status`),
CONSTRAINT `fk_salary_preview_sync_job_id`
FOREIGN KEY (`sync_job_id`) REFERENCES `attendance_sync_jobs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_salary_preview_employee_id`
FOREIGN KEY (`employee_id`) REFERENCES `employees` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='实时薪资预估表,保存当前同步批次下的员工级薪资预估';
CREATE TABLE IF NOT EXISTS `monthly_payroll_runs` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '月度核算批次主键ID',
`salary_month` VARCHAR(7) NOT NULL COMMENT '工资月份格式YYYY-MM',
`source_type` VARCHAR(32) NOT NULL DEFAULT 'excel' COMMENT '数据来源excel或dingtalk',
`source_job_id` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '来源任务ID可关联工资任务或同步任务',
`status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '核算状态draft、calculated、reviewed、locked、failed',
`employee_count` INT NOT NULL DEFAULT 0 COMMENT '参与核算员工数量',
`gross_total` FLOAT NOT NULL DEFAULT 0 COMMENT '应发工资合计',
`net_total` FLOAT NOT NULL DEFAULT 0 COMMENT '实发工资合计',
`deduction_total` FLOAT NOT NULL DEFAULT 0 COMMENT '扣款合计',
`overtime_total` FLOAT NOT NULL DEFAULT 0 COMMENT '剩余加班工时合计',
`locked_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '锁定人用户名快照',
`locked_at` DATETIME NULL COMMENT '锁定时间',
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人用户名快照',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_monthly_payroll_runs_salary_month` (`salary_month`),
KEY `ix_monthly_payroll_runs_source_job_id` (`source_job_id`),
KEY `ix_monthly_payroll_runs_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='月度工资核算批次表,记录每月工资计算、复核和锁定状态';
CREATE TABLE IF NOT EXISTS `payroll_exceptions` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '异常记录主键ID',
`run_id` INT NULL COMMENT '关联月度核算批次ID',
`sync_job_id` VARCHAR(32) NULL COMMENT '关联考勤同步任务ID',
`employee_id` INT NULL COMMENT '关联员工ID未匹配员工时为空',
`employee_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '员工编号快照',
`employee_name` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '员工姓名快照',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`exception_type` VARCHAR(64) NOT NULL COMMENT '异常类型编码',
`severity` VARCHAR(32) NOT NULL DEFAULT 'warning' COMMENT '严重级别info、warning、error',
`message` TEXT NOT NULL COMMENT '异常说明',
`status` VARCHAR(32) NOT NULL DEFAULT 'open' COMMENT '处理状态open待处理、resolved已处理、ignored已忽略',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`resolved_at` DATETIME NULL COMMENT '处理完成时间',
PRIMARY KEY (`id`),
KEY `ix_payroll_exceptions_run_id` (`run_id`),
KEY `ix_payroll_exceptions_sync_job_id` (`sync_job_id`),
KEY `ix_payroll_exceptions_employee_id` (`employee_id`),
KEY `ix_payroll_exceptions_employee_no` (`employee_no`),
KEY `ix_payroll_exceptions_employee_name` (`employee_name`),
KEY `ix_payroll_exceptions_salary_month` (`salary_month`),
KEY `ix_payroll_exceptions_exception_type` (`exception_type`),
KEY `ix_payroll_exceptions_severity` (`severity`),
KEY `ix_payroll_exceptions_status` (`status`),
CONSTRAINT `fk_payroll_exceptions_run_id`
FOREIGN KEY (`run_id`) REFERENCES `monthly_payroll_runs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_payroll_exceptions_sync_job_id`
FOREIGN KEY (`sync_job_id`) REFERENCES `attendance_sync_jobs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_payroll_exceptions_employee_id`
FOREIGN KEY (`employee_id`) REFERENCES `employees` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='工资核算异常表,保存月度核算或实时同步过程中发现的待处理问题';
CREATE TABLE IF NOT EXISTS `commission_record` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '提成记录主键ID',
`employee_id` INT NOT NULL COMMENT '关联员工ID',

View File

@ -0,0 +1,124 @@
-- 2026-06-18 月度核算中心与实时考勤看板升级脚本。
-- Execute with:
-- mysql -h localhost -P 3306 -u root -p12345678 financial_system < financial_system/database/sql/upgrade_20260618_monthly_payroll_center.sql
USE `financial_system`;
CREATE TABLE IF NOT EXISTS `attendance_sync_jobs` (
`id` VARCHAR(32) NOT NULL COMMENT '同步任务IDUUID十六进制字符串',
`source_type` VARCHAR(32) NOT NULL COMMENT '数据来源dingtalk钉钉、excel表格',
`sync_mode` VARCHAR(32) NOT NULL DEFAULT 'today' COMMENT '同步模式today今日、month本月至今、range自定义范围',
`attendance_date` DATE NULL COMMENT '实时看板对应考勤日期',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`start_date` DATE NULL COMMENT '同步开始日期',
`end_date` DATE NULL COMMENT '同步结束日期',
`status` VARCHAR(32) NOT NULL DEFAULT 'created' COMMENT '任务状态created、running、completed、failed',
`employee_count` INT NOT NULL DEFAULT 0 COMMENT '本次同步涉及员工数量',
`record_count` INT NOT NULL DEFAULT 0 COMMENT '本次同步获得或解析的考勤记录数量',
`error_message` TEXT NOT NULL COMMENT '任务失败时的错误信息',
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人用户名快照',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_attendance_sync_jobs_source_type` (`source_type`),
KEY `ix_attendance_sync_jobs_sync_mode` (`sync_mode`),
KEY `ix_attendance_sync_jobs_attendance_date` (`attendance_date`),
KEY `ix_attendance_sync_jobs_salary_month` (`salary_month`),
KEY `ix_attendance_sync_jobs_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='考勤同步任务表记录钉钉实时同步或Excel导入的批次状态';
CREATE TABLE IF NOT EXISTS `salary_preview` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '薪资预估主键ID',
`sync_job_id` VARCHAR(32) NOT NULL COMMENT '关联考勤同步任务ID',
`employee_id` INT NULL COMMENT '关联员工ID未匹配员工时为空',
`employee_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '员工编号快照',
`employee_name` VARCHAR(128) NOT NULL COMMENT '员工姓名快照',
`department` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '部门名称快照',
`position` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '岗位名称快照',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`attendance_days` FLOAT NOT NULL DEFAULT 0 COMMENT '本月当前出勤天数',
`actual_work_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '本月当前实际工时',
`punch_overtime_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '打卡推算加班工时',
`leave_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '请假或调休工时',
`remaining_overtime_hours` FLOAT NOT NULL DEFAULT 0 COMMENT '剩余加班工时',
`late_deduction` FLOAT NOT NULL DEFAULT 0 COMMENT '当前迟到扣款',
`missing_card_deduction` FLOAT NOT NULL DEFAULT 0 COMMENT '当前缺卡扣款',
`commission_amount` FLOAT NOT NULL DEFAULT 0 COMMENT '当前已录入提成',
`overtime_pay` FLOAT NOT NULL DEFAULT 0 COMMENT '当前加班费',
`estimated_gross_salary` FLOAT NULL COMMENT '当前预估应发工资',
`estimated_net_salary` FLOAT NULL COMMENT '当前预估实发工资',
`status` VARCHAR(32) NOT NULL DEFAULT 'estimated' COMMENT '预估状态estimated已预估、warning有异常',
`note` TEXT NOT NULL COMMENT '预估备注或异常说明',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uq_salary_preview_sync_employee` (`sync_job_id`, `employee_id`),
KEY `ix_salary_preview_sync_job_id` (`sync_job_id`),
KEY `ix_salary_preview_employee_id` (`employee_id`),
KEY `ix_salary_preview_employee_no` (`employee_no`),
KEY `ix_salary_preview_employee_name` (`employee_name`),
KEY `ix_salary_preview_salary_month` (`salary_month`),
KEY `ix_salary_preview_status` (`status`),
CONSTRAINT `fk_salary_preview_sync_job_id`
FOREIGN KEY (`sync_job_id`) REFERENCES `attendance_sync_jobs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_salary_preview_employee_id`
FOREIGN KEY (`employee_id`) REFERENCES `employees` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='实时薪资预估表,保存当前同步批次下的员工级薪资预估';
CREATE TABLE IF NOT EXISTS `monthly_payroll_runs` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '月度核算批次主键ID',
`salary_month` VARCHAR(7) NOT NULL COMMENT '工资月份格式YYYY-MM',
`source_type` VARCHAR(32) NOT NULL DEFAULT 'excel' COMMENT '数据来源excel或dingtalk',
`source_job_id` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '来源任务ID可关联工资任务或同步任务',
`status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '核算状态draft、calculated、reviewed、locked、failed',
`employee_count` INT NOT NULL DEFAULT 0 COMMENT '参与核算员工数量',
`gross_total` FLOAT NOT NULL DEFAULT 0 COMMENT '应发工资合计',
`net_total` FLOAT NOT NULL DEFAULT 0 COMMENT '实发工资合计',
`deduction_total` FLOAT NOT NULL DEFAULT 0 COMMENT '扣款合计',
`overtime_total` FLOAT NOT NULL DEFAULT 0 COMMENT '剩余加班工时合计',
`locked_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '锁定人用户名快照',
`locked_at` DATETIME NULL COMMENT '锁定时间',
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人用户名快照',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_monthly_payroll_runs_salary_month` (`salary_month`),
KEY `ix_monthly_payroll_runs_source_job_id` (`source_job_id`),
KEY `ix_monthly_payroll_runs_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='月度工资核算批次表,记录每月工资计算、复核和锁定状态';
CREATE TABLE IF NOT EXISTS `payroll_exceptions` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '异常记录主键ID',
`run_id` INT NULL COMMENT '关联月度核算批次ID',
`sync_job_id` VARCHAR(32) NULL COMMENT '关联考勤同步任务ID',
`employee_id` INT NULL COMMENT '关联员工ID未匹配员工时为空',
`employee_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '员工编号快照',
`employee_name` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '员工姓名快照',
`salary_month` VARCHAR(7) NOT NULL DEFAULT '' COMMENT '工资月份格式YYYY-MM',
`exception_type` VARCHAR(64) NOT NULL COMMENT '异常类型编码',
`severity` VARCHAR(32) NOT NULL DEFAULT 'warning' COMMENT '严重级别info、warning、error',
`message` TEXT NOT NULL COMMENT '异常说明',
`status` VARCHAR(32) NOT NULL DEFAULT 'open' COMMENT '处理状态open待处理、resolved已处理、ignored已忽略',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`resolved_at` DATETIME NULL COMMENT '处理完成时间',
PRIMARY KEY (`id`),
KEY `ix_payroll_exceptions_run_id` (`run_id`),
KEY `ix_payroll_exceptions_sync_job_id` (`sync_job_id`),
KEY `ix_payroll_exceptions_employee_id` (`employee_id`),
KEY `ix_payroll_exceptions_employee_no` (`employee_no`),
KEY `ix_payroll_exceptions_employee_name` (`employee_name`),
KEY `ix_payroll_exceptions_salary_month` (`salary_month`),
KEY `ix_payroll_exceptions_exception_type` (`exception_type`),
KEY `ix_payroll_exceptions_severity` (`severity`),
KEY `ix_payroll_exceptions_status` (`status`),
CONSTRAINT `fk_payroll_exceptions_run_id`
FOREIGN KEY (`run_id`) REFERENCES `monthly_payroll_runs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_payroll_exceptions_sync_job_id`
FOREIGN KEY (`sync_job_id`) REFERENCES `attendance_sync_jobs` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_payroll_exceptions_employee_id`
FOREIGN KEY (`employee_id`) REFERENCES `employees` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='工资核算异常表,保存月度核算或实时同步过程中发现的待处理问题';