xiaoyi
2026-10-30 437fa3adb398545e111c832cdb7d0fafd37bece6
fix(hrm): 撤回误建的审批分类,清理无效请假数据,下线重复菜单

## 1. 撤回上一轮误建的 BPM 分类

上一轮我误判「请假审批缺少 BPM 分类」,新建了 4 个分类并把 qingjia 流程
复制了一份挂过去。实际请假审批本来就归在「考勤异常审批 hrm_attendance_approve」
分类下(原绑定 id=13/14 一直都在)。

撤回内容:
- 删除我复制的 2 条流程绑定(model_id 带 -leave 后缀)
- 删除 4 个误建分类:hrm_leave_approve / overtime_approve /
hrm_resignation_approve / hrm_transfer_approve
- 代码 HrmLeaveApplicationService.APPROVE_CATEGORY_CODE
改为 hrm_attendance_approve,与原绑定一致

验证:分类总数回到 14,hrm_attendance_approve 完好,
approve-process-definition-list 正常返回 qingjia v2。

## 2. 清理无效请假存量数据

两套互相重复、且都从未走过真实审批的数据:

A. bpm_oa_leave(10 条)
process_instance_id 是伪造字符串(OA-LEAVE-20260922001),
act_hi_procinst 里没有对应实例 → 审批中心点「进度」报
「流程实例不存在」→ 详情页崩溃。

B. hrm_leave_application(12 条)
process_instance_id 全为 NULL/空,状态是直接改库写死的。

经确认无任何外键或业务表引用,考勤记录也没有依赖它们的行,全部清除。

## 3. 下线重复的「审批中心→请假」菜单

菜单 1118「请假查询」挂在 visible=0 的「OA 示例」下,只授权给租户管理员,
普通员工访问 403,且数据已清空。与 HRM 的请假功能完全重复。

软删除 1118/1119/1120 及角色关联。代码保留,回滚:
UPDATE system_menu SET deleted=b''0'' WHERE id IN (1118,1119,1120);

## 备份
/data/backup/mysql/manual/pre_rollback_bpm_20261030164422.sql
/data/backup/mysql/manual/pre_cleanup_leave_20261030164516.sql
/data/backup/mysql/manual/pre_del_oa_menu_20261030164805.sql
已添加3个文件
已修改1个文件
155 ■■■■■ 文件已修改
sql/mysql/cleanup_stale_leave_20261030.sql 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/remove_oa_leave_menu_20261030.sql 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/rollback_hrm_bpm_category_20261030.sql 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/cleanup_stale_leave_20261030.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
-- ============================================================
-- æ¸…理无效的请假存量数据
-- ç”Ÿæˆæ—¶é—´ï¼š2026-10-30
--
-- èƒŒæ™¯ï¼šåº“里存在两套互相重复的请假数据,且都从未走过真实审批流程——
--
--   A. bpm_oa_leave(10 æ¡ï¼‰
--      process_instance_id å­˜çš„æ˜¯ä¼ªé€ å­—符串(OA-LEAVE-20260922001 è¿™ç§ï¼‰ï¼Œ
--      act_hi_procinst é‡Œæ ¹æœ¬æ²¡æœ‰å¯¹åº”实例。
--      åŽæžœï¼šå®¡æ‰¹ä¸­å¿ƒè¯·å‡é¡µé¢ç‚¹ã€Œè¿›åº¦ã€â†’ è°ƒ get-approval-detail
--            â†’ åŽç«¯ã€Œæµç¨‹å®žä¾‹ä¸å­˜åœ¨ã€â†’ é¡µé¢ 500。
--
--   B. hrm_leave_application(12 æ¡ï¼‰
--      process_instance_id å…¨ä¸º NULL æˆ–空串,状态(审批通过/驳回)
--      æ˜¯ç›´æŽ¥æ”¹åº“写死的,从未走过 BPM。
--      åªæœ‰ id=13(LA202610300002)是今天新提交的,状态审批通过,
--      åŒæ ·æ²¡æœ‰æµç¨‹å®žä¾‹ã€‚
--
-- ä¸¤å¥—数据内容一一对应(同样的 user_id / æ—¥æœŸ / ç±»åž‹ï¼‰ï¼Œæ˜Žæ˜¾æ˜¯åŒä¸€æ‰¹
-- æµ‹è¯•数据导了两次。经确认无任何外键或业务表引用(信息模式的依赖检查为空),
-- è€ƒå‹¤è®°å½•里也没有 leave_flag=1 çš„行依赖它们。
--
-- å¤„理:物理删除这两批数据,让请假功能从干净状态开始。
--      åˆ é™¤åŽå‘˜å·¥é‡æ–°æäº¤çš„请假会真正走 BPM,process_instance_id ä¸ºçœŸå®žå®žä¾‹ã€‚
--
-- å¤‡ä»½ï¼š/data/backup/mysql/manual/pre_cleanup_leave_*.sql
-- å¹‚等:可重复执行
-- ============================================================
-- ---------- 1. æ¸…理前快照 ----------
SELECT 'bpm_oa_leave' AS è¡¨å, COUNT(*) AS æ¡æ•° FROM bpm_oa_leave
UNION ALL
SELECT 'hrm_leave_application', COUNT(*) FROM hrm_leave_application WHERE deleted = b'0';
-- ---------- 2. åˆ é™¤ bpm_oa_leave å…¨éƒ¨ï¼ˆ10 æ¡ï¼Œå…¨æ˜¯ä¼ªé€ æµç¨‹å®žä¾‹ï¼‰----------
DELETE FROM bpm_oa_leave;
-- ---------- 3. åˆ é™¤ hrm_leave_application(12 æ¡ï¼Œå…¨éƒ¨æ— æµç¨‹å®žä¾‹ï¼‰----------
DELETE FROM hrm_leave_application WHERE process_instance_id IS NULL OR process_instance_id = '';
-- ---------- 4. æ¸…理可能残留的附件关联 ----------
-- é™„件表实际列名是 record_type / record_id / application
DELETE FROM system_storage_attachment
 WHERE record_type = 'hrm_leave_application'
   AND record_id NOT IN (SELECT id FROM hrm_leave_application);
-- ---------- 5. æ ¡éªŒ ----------
SELECT 'bpm_oa_leave' AS è¡¨å, COUNT(*) AS å‰©ä½™æ¡æ•° FROM bpm_oa_leave
UNION ALL
SELECT 'hrm_leave_application', COUNT(*) FROM hrm_leave_application WHERE deleted = b'0';
SELECT '无流程实例的请假单' AS æ£€æŸ¥é¡¹, COUNT(*) AS æ¡æ•°
  FROM hrm_leave_application
 WHERE deleted = b'0' AND (process_instance_id IS NULL OR process_instance_id = '');
sql/mysql/remove_oa_leave_menu_20261030.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
-- ============================================================
-- ä¸‹çº¿ã€Œå®¡æ‰¹ä¸­å¿ƒ â†’ è¯·å‡ã€é‡å¤èœå•页
-- ç”Ÿæˆæ—¶é—´ï¼š2026-10-30
--
-- èƒŒæ™¯ï¼šç³»ç»Ÿé‡Œå­˜åœ¨ä¸¤å¥—请假功能——
--
--   A. å®¡æ‰¹ä¸­å¿ƒ â†’ OA示例 â†’ è¯·å‡æŸ¥è¯¢ï¼ˆèœå• 1118)
--      æ•°æ®æº bpm_oa_leave,已清空(10 æ¡å…¨æ˜¯ä¼ªé€ æµç¨‹å®žä¾‹ï¼‰
--      æŒ‚在 visible=0 çš„「OA ç¤ºä¾‹ã€ä¸‹ï¼ŒåªæŽˆæƒç»™ç§Ÿæˆ·ç®¡ç†å‘˜
--      æ™®é€šå‘˜å·¥è®¿é—®è¿”回 403,点「进度」会因流程实例不存在而报错
--
--   B. äººäº‹å®¡æ‰¹ â†’ è¯·å‡ç”³è¯·ï¼ˆèœå• 6003)
--      æ•°æ®æº hrm_leave_application,与考勤/薪资打通
--      å·²é…ç½® BPM å®¡æ‰¹ï¼ˆqingjia v2,挂在 hrm_attendance_approve åˆ†ç±»ä¸‹ï¼‰
--      æ˜¯æ­£è§„在用的那一套
--
-- ç»“论:A æ˜¯æ—§æ¼”示页面,与 B å®Œå…¨é‡å¤ä¸”已无数据,直接下线。
--      ä»£ç ï¼ˆbpm/oa/leave)保留,日后需要时可恢复菜单。
--
-- åšæ³•:软删除菜单 1118 åŠå…¶ä¸¤ä¸ªæŒ‰é’®æƒé™ï¼ˆ1119 æŸ¥è¯¢ / 1120 åˆ›å»ºï¼‰
--      ä¸ç‰©ç†åˆ é™¤ï¼Œå¯å›žæ»š
-- å›žæ»šï¼šUPDATE system_menu SET deleted=b'0' WHERE id IN (1118,1119,1120);
-- ============================================================
-- ---------- 1. å¤„理前快照 ----------
SELECT id, name, parent_id, path, component, permission, type, visible+0 AS vis
  FROM system_menu WHERE id IN (1118, 1119, 1120) AND deleted = b'0';
-- ---------- 2. è½¯åˆ é™¤èœå•及其按钮权限 ----------
UPDATE system_menu
   SET deleted = b'1', updater = '1', update_time = NOW()
 WHERE id IN (1118, 1119, 1120)
   AND deleted = b'0';
-- ---------- 3. æ¸…理角色菜单关联,避免残留权限 ----------
DELETE FROM system_role_menu WHERE menu_id IN (1118, 1119, 1120);
-- ---------- 4. æ ¡éªŒ ----------
SELECT COUNT(*) AS å‰©ä½™æœ‰æ•ˆèœå•æ•° FROM system_menu
 WHERE id IN (1118, 1119, 1120) AND deleted = b'0';
SELECT COUNT(*) AS å‰©ä½™è§’色关联数 FROM system_role_menu
 WHERE menu_id IN (1118, 1119, 1120);
-- ---------- 5. ç¡®è®¤ HRM è¯·å‡èœå•完好 ----------
SELECT id, name, path, component, visible+0 AS vis
  FROM system_menu WHERE id = 6003 AND deleted = b'0';
sql/mysql/rollback_hrm_bpm_category_20261030.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
-- ============================================================
-- æ’¤å›žï¼šåˆ é™¤æˆ‘之前误建的 HRM å®¡æ‰¹åˆ†ç±»
-- ç”Ÿæˆæ—¶é—´ï¼š2026-10-30
--
-- èƒŒæ™¯ï¼šä¸Šä¸€è½®æˆ‘误判请假审批缺少 BPM åˆ†ç±»ï¼Œæ–°å»ºäº† 4 ä¸ªåˆ†ç±»ï¼Œ
--      å¹¶æŠŠ qingjia çš„æµç¨‹å®šä¹‰å¤åˆ¶äº†ä¸€ä»½æŒ‚到 hrm_leave_approve ä¸‹ã€‚
--
-- å®žé™…情况:请假审批本来就该归在「考勤异常审批 hrm_attendance_approve」
--          åˆ†ç±»ä¸‹ï¼ˆåŽŸç»‘å®š id=13/14 ä¸€ç›´éƒ½åœ¨ï¼‰ï¼Œä¸éœ€è¦å•独分类。
--
-- æœ¬æ¬¡å¤„理:
--   1. åˆ é™¤æˆ‘复制的 2 æ¡æµç¨‹ç»‘定(id=20/21,model_id å¸¦ -leave åŽç¼€ï¼‰
--   2. åˆ é™¤ 4 ä¸ªè¯¯å»ºåˆ†ç±»ï¼ˆå…¶ä¸­ hrm_leave_approve æœ‰ç»‘定,另 3 ä¸ªæ˜¯ç©ºå£³ï¼‰
--   3. ä»£ç ä¾§ HrmLeaveApplicationService.APPROVE_CATEGORY_CODE
--      å·²æ”¹ä¸º hrm_attendance_approve,保持与原绑定一致
--
-- ä¿ç•™ï¼šhrm_attendance_approve åˆ†ç±»åŠå…¶åŽŸæœ‰çš„ 2 æ¡ qingjia ç»‘定(id=13/14)
-- å¹‚等:可重复执行
-- ============================================================
-- ---------- 1. å¤„理前快照 ----------
SELECT '分类' AS é¡¹, id, name, code FROM bpm_category
 WHERE code IN ('hrm_leave_approve','overtime_approve','hrm_resignation_approve','hrm_transfer_approve')
   AND deleted = b'0'
UNION ALL
SELECT '绑定', id, model_id, category FROM bpm_process_definition_info
 WHERE category = 'hrm_leave_approve' AND deleted = b'0';
-- ---------- 2. åˆ é™¤æˆ‘复制的流程绑定(只删 model_id å¸¦ -leave åŽç¼€çš„)----------
DELETE FROM bpm_process_definition_info
 WHERE category = 'hrm_leave_approve'
   AND model_id LIKE '%-leave';
-- ---------- 3. åˆ é™¤ 4 ä¸ªè¯¯å»ºåˆ†ç±» ----------
DELETE FROM bpm_category
 WHERE code IN ('hrm_leave_approve','overtime_approve','hrm_resignation_approve','hrm_transfer_approve')
   AND deleted = b'0';
-- ---------- 4. æ ¡éªŒï¼šè¿™äº›åˆ†ç±»åº”已不存在 ----------
SELECT COUNT(*) AS æ®‹ç•™åˆ†ç±»æ•° FROM bpm_category
 WHERE code IN ('hrm_leave_approve','overtime_approve','hrm_resignation_approve','hrm_transfer_approve');
SELECT COUNT(*) AS æ®‹ç•™ç»‘定位数 FROM bpm_process_definition_info
 WHERE category = 'hrm_leave_approve';
-- ---------- 5. ç¡®è®¤åŽŸç»‘å®šå®Œå¥½ï¼ˆåº”ä¸º 2 æ¡ï¼šqingjia v1/v2)----------
SELECT id, process_definition_id, category FROM bpm_process_definition_info
 WHERE category = 'hrm_attendance_approve' AND deleted = b'0'
 ORDER BY id;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationService.java
@@ -24,8 +24,11 @@
    /**
     * BPM è¯·å‡å®¡æ‰¹åˆ†ç±»ç¼–码
     *
     * è¯·å‡æµç¨‹ç»Ÿä¸€å½’在「考勤异常审批」分类下,与考勤异常共用同一个审批分类,
     * ä¸å†å•独建 hrm_leave_approve åˆ†ç±»ã€‚
     */
    String APPROVE_CATEGORY_CODE = "hrm_leave_approve";
    String APPROVE_CATEGORY_CODE = "hrm_attendance_approve";
    /**
     * åˆ›å»ºè¯·å‡ç”³è¯·