-- 员工合同快照:一名正式员工的一份任务合同对应一条记录。 -- 常用字段独立存储用于筛选导出,VariablesJson 按 VariableCode 保存全部标准及自定义变量。 -- 适用数据库:MySQL 8.0+ SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS `ob_employee_contract_snapshot` ( `Id` BIGINT NOT NULL COMMENT '主键', `EmployeeId` BIGINT NOT NULL COMMENT '正式员工Id', `TaskId` BIGINT NOT NULL COMMENT '来源入职任务Id', `TaskContractId` BIGINT NOT NULL COMMENT '来源任务合同Id', `TemplateId` BIGINT NOT NULL COMMENT '合同模板Id', `TemplateVersionId` BIGINT NOT NULL COMMENT '合同模板版本Id', `ContractName` VARCHAR(300) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '合同名称快照', `ContractType` VARCHAR(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '合同类型快照', `ContractStartDate` DATE DEFAULT NULL COMMENT '合同开始日期', `ContractEndDate` DATE DEFAULT NULL COMMENT '合同结束日期', `ContractTerm` VARCHAR(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '合同期限原始文本', `ProbationStartDate` DATE DEFAULT NULL COMMENT '试用期开始日期', `ProbationEndDate` DATE DEFAULT NULL COMMENT '试用期结束日期', `ProbationTerm` VARCHAR(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '试用期期限原始文本', `ProbationSalary` DECIMAL(18,2) DEFAULT NULL COMMENT '试用薪资,对应hr.ProbationSalary,不自动推算', `BaseSalary` DECIMAL(18,2) DEFAULT NULL COMMENT '基本工资', `PositionSalary` DECIMAL(18,2) DEFAULT NULL COMMENT '岗位工资', `PerformanceAllowance` DECIMAL(18,2) DEFAULT NULL COMMENT '绩效津贴', `AttendanceBonus` DECIMAL(18,2) DEFAULT NULL COMMENT '全勤奖', `RegularSalary` DECIMAL(18,2) DEFAULT NULL COMMENT '转正后薪资', `WorkCity` VARCHAR(300) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '工作地点或城市', `PositionName` VARCHAR(300) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '合同岗位名称', `EmployeeNo` VARCHAR(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '合同员工工号', `VariablesJson` JSON NOT NULL COMMENT '按VariableCode索引的完整合同变量快照', `SnapshotVersion` INT NOT NULL DEFAULT 1 COMMENT '快照结构版本', `SnapshotAt` DATETIME(3) NOT NULL COMMENT '快照生成时间', `ExtJson` LONGTEXT COLLATE utf8mb4_unicode_ci COMMENT '扩展信息', `Status` VARCHAR(20) COLLATE utf8mb4_unicode_ci DEFAULT 'enable' COMMENT '记录状态', `CreateTime` DATETIME(3) DEFAULT NULL COMMENT '创建时间', `UpdateTime` DATETIME(3) DEFAULT NULL COMMENT '更新时间', `CreateUserId` BIGINT DEFAULT NULL COMMENT '创建者Id', `UpdateUserId` BIGINT DEFAULT NULL COMMENT '修改者Id', `CreateUser` VARCHAR(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建人', `UpdateUser` VARCHAR(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '更新人', `IsDelete` TINYINT(1) DEFAULT 0 COMMENT '软删除', PRIMARY KEY (`Id`), UNIQUE KEY `uk_ob_employee_contract_snapshot_contract` (`TaskContractId`), KEY `idx_ob_employee_contract_snapshot_employee` (`EmployeeId`, `IsDelete`), KEY `idx_ob_employee_contract_snapshot_task` (`TaskId`, `IsDelete`), KEY `idx_ob_employee_contract_snapshot_dates` (`ContractStartDate`, `ContractEndDate`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='正式员工合同业务快照'; -- 为已经审核建档且仍保留任务合同变量的员工补建快照。 INSERT IGNORE INTO `ob_employee_contract_snapshot` ( `Id`, `EmployeeId`, `TaskId`, `TaskContractId`, `TemplateId`, `TemplateVersionId`, `ContractName`, `ContractType`, `ContractStartDate`, `ContractEndDate`, `ContractTerm`, `ProbationStartDate`, `ProbationEndDate`, `ProbationTerm`, `ProbationSalary`, `BaseSalary`, `PositionSalary`, `PerformanceAllowance`, `AttendanceBonus`, `RegularSalary`, `WorkCity`, `PositionName`, `EmployeeNo`, `VariablesJson`, `SnapshotVersion`, `SnapshotAt`, `Status`, `CreateTime`, `CreateUserId`, `CreateUser`, `IsDelete` ) SELECT contract.`Id`, task.`EmployeeId`, task.`Id`, contract.`Id`, contract.`TemplateId`, contract.`TemplateVersionId`, contract.`ContractName`, contract.`ContractType`, CASE WHEN TRIM(variable.`ContractStartDateText`) REGEXP '^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$' THEN STR_TO_DATE(TRIM(variable.`ContractStartDateText`), '%Y-%m-%d') ELSE NULL END, CASE WHEN TRIM(variable.`ContractEndDateText`) REGEXP '^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$' THEN STR_TO_DATE(TRIM(variable.`ContractEndDateText`), '%Y-%m-%d') ELSE NULL END, variable.`ContractTerm`, CASE WHEN TRIM(variable.`ProbationStartDateText`) REGEXP '^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$' THEN STR_TO_DATE(TRIM(variable.`ProbationStartDateText`), '%Y-%m-%d') ELSE NULL END, CASE WHEN TRIM(variable.`ProbationEndDateText`) REGEXP '^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$' THEN STR_TO_DATE(TRIM(variable.`ProbationEndDateText`), '%Y-%m-%d') ELSE NULL END, variable.`ProbationTerm`, CASE WHEN TRIM(variable.`ProbationSalaryText`) REGEXP '^-?[0-9]+([.][0-9]+)?$' THEN CAST(TRIM(variable.`ProbationSalaryText`) AS DECIMAL(18,2)) ELSE NULL END, CASE WHEN TRIM(variable.`BaseSalaryText`) REGEXP '^-?[0-9]+([.][0-9]+)?$' THEN CAST(TRIM(variable.`BaseSalaryText`) AS DECIMAL(18,2)) ELSE NULL END, CASE WHEN TRIM(variable.`PositionSalaryText`) REGEXP '^-?[0-9]+([.][0-9]+)?$' THEN CAST(TRIM(variable.`PositionSalaryText`) AS DECIMAL(18,2)) ELSE NULL END, CASE WHEN TRIM(variable.`PerformanceAllowanceText`) REGEXP '^-?[0-9]+([.][0-9]+)?$' THEN CAST(TRIM(variable.`PerformanceAllowanceText`) AS DECIMAL(18,2)) ELSE NULL END, CASE WHEN TRIM(variable.`AttendanceBonusText`) REGEXP '^-?[0-9]+([.][0-9]+)?$' THEN CAST(TRIM(variable.`AttendanceBonusText`) AS DECIMAL(18,2)) ELSE NULL END, CASE WHEN TRIM(variable.`RegularSalaryText`) REGEXP '^-?[0-9]+([.][0-9]+)?$' THEN CAST(TRIM(variable.`RegularSalaryText`) AS DECIMAL(18,2)) ELSE NULL END, variable.`WorkCity`, variable.`PositionName`, variable.`EmployeeNo`, COALESCE(variable.`VariablesJson`, JSON_OBJECT()), 1, COALESCE(task.`AuditedAt`, employee.`CreateTime`, NOW(3)), 'enable', COALESCE(employee.`CreateTime`, NOW(3)), employee.`CreateUserId`, employee.`CreateUser`, 0 FROM `ob_onboarding_task` task INNER JOIN `ob_employee` employee ON employee.`Id` = task.`EmployeeId` INNER JOIN `ob_task_contract` contract ON contract.`TaskId` = task.`Id` LEFT JOIN ( SELECT row_value.`TaskContractId`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ContractStartDate' THEN row_value.`VariableValue` END) AS `ContractStartDateText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ContractEndDate' THEN row_value.`VariableValue` END) AS `ContractEndDateText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ContractTerm' THEN row_value.`VariableValue` END) AS `ContractTerm`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ProbationStartDate' THEN row_value.`VariableValue` END) AS `ProbationStartDateText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ProbationEndDate' THEN row_value.`VariableValue` END) AS `ProbationEndDateText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ProbationTerm' THEN row_value.`VariableValue` END) AS `ProbationTerm`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.ProbationSalary' THEN row_value.`VariableValue` END) AS `ProbationSalaryText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.BaseSalary' THEN row_value.`VariableValue` END) AS `BaseSalaryText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.PositionSalary' THEN row_value.`VariableValue` END) AS `PositionSalaryText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.PerformanceAllowance' THEN row_value.`VariableValue` END) AS `PerformanceAllowanceText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.AttendanceBonus' THEN row_value.`VariableValue` END) AS `AttendanceBonusText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.RegularSalary' THEN row_value.`VariableValue` END) AS `RegularSalaryText`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.WorkCity' THEN row_value.`VariableValue` END) AS `WorkCity`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.PositionName' THEN row_value.`VariableValue` END) AS `PositionName`, MAX(CASE WHEN row_value.`VariableCode` = 'hr.EmployeeNo' THEN row_value.`VariableValue` END) AS `EmployeeNo`, JSON_OBJECTAGG( row_value.`VariableCode`, JSON_OBJECT( 'variableName', row_value.`VariableName`, 'variableType', row_value.`VariableType`, 'dataType', row_value.`DataType`, 'variableValue', row_value.`VariableValue`, 'sourceType', row_value.`SourceType`, 'isManualOverride', row_value.`IsManualOverride`, 'sortCode', row_value.`SortCode` ) ) AS `VariablesJson` FROM `ob_task_contract_variable` row_value WHERE row_value.`IsDelete` = 0 GROUP BY row_value.`TaskContractId` ) variable ON variable.`TaskContractId` = contract.`Id` WHERE task.`EmployeeId` IS NOT NULL AND task.`IsDelete` = 0 AND employee.`IsDelete` = 0 AND contract.`IsDelete` = 0; SELECT COUNT(*) AS `员工合同快照数量`, COUNT(DISTINCT `EmployeeId`) AS `已归档员工数量`, COUNT(DISTINCT `TaskContractId`) AS `已归档合同数量` FROM `ob_employee_contract_snapshot` WHERE `IsDelete` = 0;