tuqin
4 天以前 0d30e44d3cf4118222f6de88424a39a04d1642e9
fix(hrm): actual_days 改为可空,区分「未录考勤」与「实出0天」

问题:hrm_salary_calculation.actual_days 是 INT NOT NULL DEFAULT 0,
导致「该月未生成考勤汇总」和「实出 0 天」都存成 0,无法区分。
缺勤扣款逻辑于是把未录考勤当成实出 0 天,把整月工资扣光
(11 月重算时 132 人实发全部归零)。

修复:字段改为 NULL DEFAULT NULL,语义约定:
- actual_days IS NULL → 未生成考勤汇总,视为满勤,不扣旷工
- actual_days = 0 → 实出 0 天(人工填写),按 100% 扣旷工
- actual_days = N → 扣 应出-N 中超出请假单覆盖的部分

验证(基本1950/岗位11383.60/应出30):
- 实出 NULL → 缺勤0.00,实发13000.00
- 实出 0 → 缺勤13333.60(封顶),实发0.00
- 实出 20 → 缺勤4444.53,实发8684.32
- 实出 30 → 缺勤0.00,实发13128.85

另:11 月 132 条核算单已按「未录考勤」置 NULL 并重算,
实发恢复正常(合计 599521.74),撤销的确认状态已从备份表还原。
已添加1个文件
17 ■■■■■ 文件已修改
sql/mysql/hrm_salary_calculation_actual_days_nullable.sql 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/hrm_salary_calculation_actual_days_nullable.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
-- ============================================================
-- è–ªé…¬æ ¸ç®—:actual_days(实出天数)允许为空
--
-- èƒŒæ™¯ï¼š
--   åŽŸå­—æ®µæ˜¯ INT NOT NULL DEFAULT 0,导致「该月还没有考勤汇总」和
--   ã€Œå®žå‡º 0 å¤©ã€åœ¨æ•°æ®åº“里都存成 0,无法区分。
--   ç¼ºå‹¤æ‰£æ¬¾é€»è¾‘于是把「未录考勤」当成「实出 0 å¤©ã€ï¼ŒæŠŠæ•´æœˆå·¥èµ„扣光。
--
-- è¯­ä¹‰çº¦å®šï¼ˆä¸Ž HrmSalaryCalculationServiceImpl#calculateAttendanceDeduction å¯¹åº”):
--   actual_days IS NULL  â†’ è¯¥æœˆæœªç”Ÿæˆè€ƒå‹¤æ±‡æ€»ï¼Œè§†ä¸ºæ»¡å‹¤ï¼Œä¸åšæ—·å·¥æ‰£æ¬¾
--   actual_days = 0      â†’ å®žå‡º 0 å¤©ï¼ˆäººå·¥å¡«å†™ï¼‰ï¼ŒæŒ‰ 100% æ‰£æ—·å·¥
--   actual_days = N      â†’ æŒ‰ åº”出 - N è®¡ç®—旷工天数(超出请假单覆盖的部分)
-- ============================================================
ALTER TABLE hrm_salary_calculation
    MODIFY COLUMN actual_days INT NULL DEFAULT NULL
    COMMENT '实出天数(null=该月未生成考勤汇总,不扣旷工)';