-- 考勤设置独立保存与历史升级脚本
-- 执行日期：2026-03-23
-- 用途：
-- 1. 将考勤设置改为单条独立保存、编辑、逻辑删除
-- 2. 为各配置表补充版本号、最后修改人、最后修改时间、逻辑删除字段
-- 3. 新增考勤配置历史表
-- 4. 为考勤打卡记录补充规则快照字段，保证后续可追溯当时命中的规则
-- 说明：脚本已兼容“表已存在 / 字段已存在 / 索引已存在”的场景，可重复执行

SET @db_name = DATABASE();

DROP PROCEDURE IF EXISTS sp_add_column_if_not_exists;
DROP PROCEDURE IF EXISTS sp_add_index_if_not_exists;

DELIMITER $$
CREATE PROCEDURE sp_add_column_if_not_exists(
    IN p_table VARCHAR(64),
    IN p_column VARCHAR(64),
    IN p_definition TEXT
)
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM information_schema.COLUMNS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = p_table
          AND COLUMN_NAME = p_column
    ) THEN
        SET @ddl_sql = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition);
        PREPARE stmt FROM @ddl_sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END IF;
END$$

CREATE PROCEDURE sp_add_index_if_not_exists(
    IN p_table VARCHAR(64),
    IN p_index VARCHAR(64),
    IN p_definition TEXT
)
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM information_schema.STATISTICS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = p_table
          AND INDEX_NAME = p_index
    ) THEN
        SET @ddl_sql = CONCAT('ALTER TABLE `', p_table, '` ', p_definition);
        PREPARE stmt FROM @ddl_sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END IF;
END$$
DELIMITER ;

-- ========================================
-- 1. 新增考勤配置历史表
-- ========================================
CREATE TABLE IF NOT EXISTS `lq_attendance_config_history` (
  `F_Id` varchar(50) NOT NULL COMMENT '主键ID',
  `F_ModuleType` int NOT NULL COMMENT '模块类型',
  `F_BizId` varchar(50) NOT NULL COMMENT '业务主键ID',
  `F_VersionNo` int NOT NULL DEFAULT 1 COMMENT '版本号',
  `F_OperateType` int NOT NULL COMMENT '操作类型（1新增，2修改，3删除）',
  `F_Title` varchar(200) DEFAULT NULL COMMENT '配置标题',
  `F_SnapshotJson` longtext COMMENT '配置快照JSON',
  `F_ChangeReason` varchar(500) DEFAULT NULL COMMENT '变更原因',
  `F_OperateUserId` varchar(50) DEFAULT NULL COMMENT '操作人ID',
  `F_OperateUserName` varchar(100) DEFAULT NULL COMMENT '操作人姓名',
  `F_OperateTime` datetime NOT NULL COMMENT '操作时间',
  PRIMARY KEY (`F_Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='考勤配置历史记录表';

CALL sp_add_index_if_not_exists(
  'lq_attendance_config_history',
  'idx_attendance_config_history_biz',
  'ADD INDEX `idx_attendance_config_history_biz` (`F_ModuleType`, `F_BizId`, `F_VersionNo`)'
);

CALL sp_add_index_if_not_exists(
  'lq_attendance_config_history',
  'idx_attendance_config_history_time',
  'ADD INDEX `idx_attendance_config_history_time` (`F_OperateTime`)'
);

-- ========================================
-- 2. 考勤设置主表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_setting', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_setting', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_setting', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_setting', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_setting', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 3. 公休日期表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_holiday', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_holiday', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_holiday', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_holiday', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_holiday', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 4. 考勤分组表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_group', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_group', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_group', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_group', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_group', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 5. 免考勤人员表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_exempt_user', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_exempt_user', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_exempt_user', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_exempt_user', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_exempt_user', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 6. 额外假期表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_extra_leave', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_extra_leave', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_extra_leave', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_extra_leave', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_extra_leave', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 7. 婚假规则表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_marriage_leave_rule', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_marriage_leave_rule', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_marriage_leave_rule', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_marriage_leave_rule', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_marriage_leave_rule', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 8. 丧假规则表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_funeral_leave_rule', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_funeral_leave_rule', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_funeral_leave_rule', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_funeral_leave_rule', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_funeral_leave_rule', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 9. 年假规则表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_annual_leave_rule', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_annual_leave_rule', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_annual_leave_rule', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_annual_leave_rule', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_annual_leave_rule', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 10. 迟到早退规则表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_late_rule', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_late_rule', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_late_rule', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_late_rule', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_late_rule', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 11. 缺卡规则表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_missing_card_rule', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_missing_card_rule', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_missing_card_rule', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_missing_card_rule', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_missing_card_rule', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 12. 旷工规则表补字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_absenteeism_rule', 'F_DeleteMark', "int DEFAULT 0 COMMENT '逻辑删除标记（0-正常，1-已删除）' AFTER `F_CreateTime`");
CALL sp_add_column_if_not_exists('lq_attendance_absenteeism_rule', 'F_VersionNo', "int DEFAULT 0 COMMENT '当前版本号' AFTER `F_DeleteMark`");
CALL sp_add_column_if_not_exists('lq_attendance_absenteeism_rule', 'F_LastModifyUserId', "varchar(50) DEFAULT NULL COMMENT '最后修改人ID' AFTER `F_VersionNo`");
CALL sp_add_column_if_not_exists('lq_attendance_absenteeism_rule', 'F_LastModifyUserName', "varchar(100) DEFAULT NULL COMMENT '最后修改人姓名' AFTER `F_LastModifyUserId`");
CALL sp_add_column_if_not_exists('lq_attendance_absenteeism_rule', 'F_LastModifyTime', "datetime DEFAULT NULL COMMENT '最后修改时间' AFTER `F_LastModifyUserName`");

-- ========================================
-- 13. 打卡记录补规则快照字段
-- ========================================
CALL sp_add_column_if_not_exists('lq_attendance_record', 'F_RuleSnapshotJson', "longtext COMMENT '规则快照JSON' AFTER `F_Remark`");

DROP PROCEDURE IF EXISTS sp_add_column_if_not_exists;
DROP PROCEDURE IF EXISTS sp_add_index_if_not_exists;
