xiaoyi
21 小时以前 f6003438d54d49abccedbdd5d1c311e637798995
fix(sql): 修正退单受理父菜单匹配,补齐新菜单授权与采购菜单 ERP 停用

## 问题
1. 退单管理菜单未生成:脚本按名称匹配父菜单「售后服务」,实际为「售后管理」,
WHERE 条件不成立导致 INSERT 未执行
2. 新增菜单未授权:system_role_menu 无记录,非超管角色看不到入口
3. 采购成本分析不可达:「采购管理」(2602) 父菜单 status=1 已停用,
导致 SRM 供应商管理整支(含招投标、统计分析)全部不可见

## 修复
- after_sale_cancellation_20261107.sql:父菜单改为按 path='/aftersales' 匹配,
并保留名称兜底;避免不同项目命名差异导致脚本空跑
- new_menu_role_grant_20261107.sql:新增菜单按「父菜单已授权的角色」继承授权,
避免遗漏
- srm_cost_analysis_menu_20261107.sql:采购成本分析菜单
- purchase_menu_erp_off_20261107.sql:启用「采购管理」父菜单,
同时停用其下 component 以 erp/ 开头的 ERP 专属子页面
(ERP 已从构建排除,保留会 404)

## 验证(本地 mom_local)
- 退单管理菜单 1075701 挂在 602587 下,6 个按钮权限齐全
- 采购成本分析菜单 1075699 挂在 602524 下
- 两个菜单均已授予 3 个角色(继承父菜单)
- 清 Redis 菜单缓存后,登录返回的菜单树含两者
- 菜单↔文件核对:239 个启用组件仅 1 个历史断链(bi/config/warehouse-coordinate)

## 注意
本次改动了菜单 status(采购管理启用、ERP 子菜单停用),
生产环境执行前需确认该分支是否符合上线预期。
已添加3个文件
已修改1个文件
73 ■■■■■ 文件已修改
sql/mysql/after_sale_cancellation_20261107.sql 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/new_menu_role_grant_20261107.sql 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/purchase_menu_erp_off_20261107.sql 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/srm_cost_analysis_menu_20261107.sql 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/after_sale_cancellation_20261107.sql
@@ -32,7 +32,12 @@
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='售后统一退单/变更受理';
-- èœå•:挂在售后服务下
SET @as_parent := (SELECT id FROM system_menu WHERE name='售后服务' AND parent_id=0 AND CAST(deleted AS UNSIGNED)=0 LIMIT 1);
-- çˆ¶èœå•按 path åŒ¹é…æ›´ç¨³å¦¥ï¼ˆä¸åŒé¡¹ç›®åç§°å¯èƒ½å«ã€Œå”®åŽç®¡ç†ã€æˆ–「售后服务」)
SET @as_parent := (SELECT id FROM system_menu
                   WHERE CAST(deleted AS UNSIGNED)=0 AND type=1 AND path='/aftersales' LIMIT 1);
SET @as_parent := IFNULL(@as_parent,
  (SELECT id FROM system_menu WHERE CAST(deleted AS UNSIGNED)=0 AND type=1
   AND (name='售后管理' OR name='售后服务') LIMIT 1));
INSERT INTO system_menu (name,permission,type,sort,parent_id,path,icon,component,component_name,status,visible,keep_alive,always_show,creator,updater)
SELECT '退单管理','',2,90,@as_parent,'cancellation','lucide:undo-2','aftersales/cancellation/index','AfterSaleCancellation',0,b'1',b'1',b'1','1','1'
WHERE @as_parent IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE component='aftersales/cancellation/index' AND CAST(deleted AS UNSIGNED)=0);
@@ -46,4 +51,4 @@
      UNION ALL SELECT '审批','aftersales:cancellation:approve',4
      UNION ALL SELECT '取消','aftersales:cancellation:cancel',5
      UNION ALL SELECT '删除','aftersales:cancellation:delete',6) p
WHERE @pg IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id=@pg AND m.permission=p.permission AND CAST(m.deleted AS UNSIGNED)=0);
WHERE @pg IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id=@pg AND m.permission=p.permission AND CAST(m.deleted AS UNSIGNED)=0);
sql/mysql/new_menu_role_grant_20261107.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
-- ä¸ºæ–°èœå•补齐角色授权:凡是已拥有父菜单的角色,一并授予新菜单及其按钮。
-- è¯´æ˜Žï¼šæ–°å¢žèœå•后若不授权,普通角色与管理员都看不到入口。
-- 1) é‡‡è´­æˆæœ¬åˆ†æžèœå•
INSERT INTO system_role_menu (role_id, menu_id, creator, create_time, updater, update_time, deleted)
SELECT rm.role_id, m.id, '1', NOW(), '1', NOW(), b'0'
FROM (SELECT DISTINCT role_id FROM system_role_menu
      WHERE menu_id = 602524 AND CAST(deleted AS UNSIGNED)=0) rm
CROSS JOIN (SELECT id FROM system_menu
            WHERE component='srm/statistics/cost-analysis' AND CAST(deleted AS UNSIGNED)=0) m
WHERE NOT EXISTS (SELECT 1 FROM system_role_menu x
                  WHERE x.role_id=rm.role_id AND x.menu_id=m.id AND CAST(x.deleted AS UNSIGNED)=0);
-- 2) é€€å•管理菜单及其按钮
INSERT INTO system_role_menu (role_id, menu_id, creator, create_time, updater, update_time, deleted)
SELECT rm.role_id, m.id, '1', NOW(), '1', NOW(), b'0'
FROM (SELECT DISTINCT role_id FROM system_role_menu
      WHERE menu_id = 602587 AND CAST(deleted AS UNSIGNED)=0) rm
CROSS JOIN (SELECT id FROM system_menu
            WHERE CAST(deleted AS UNSIGNED)=0
              AND (component='aftersales/cancellation/index'
                   OR permission LIKE 'aftersales:cancellation:%')) m
WHERE NOT EXISTS (SELECT 1 FROM system_role_menu x
                  WHERE x.role_id=rm.role_id AND x.menu_id=m.id AND CAST(x.deleted AS UNSIGNED)=0);
sql/mysql/purchase_menu_erp_off_20261107.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
-- é‡‡è´­ç®¡ç†èœå•分支调整:ERP å·²ä»Žæž„建中排除,但父菜单被停用导致 SRM ä¾›åº”商管理整支不可见
-- ï¼ˆå«æ‹›æŠ•æ ‡ / ç»Ÿè®¡åˆ†æž / é‡‡è´­æˆæœ¬åˆ†æžï¼‰ã€‚
-- å¤„理:启用「采购管理」父菜单,同时停用 ERP ä¸“属子页面,避免用户点到 404。
-- 1) å¯ç”¨é‡‡è´­ç®¡ç†çˆ¶èœå•
UPDATE system_menu SET status = 0
WHERE CAST(deleted AS UNSIGNED)=0 AND id = 2602;
-- 2) åœç”¨ ERP ä¸“属子菜单(component ä»¥ erp/ å¼€å¤´ï¼‰
UPDATE system_menu SET status = 1
WHERE CAST(deleted AS UNSIGNED)=0
  AND parent_id = 2602
  AND component LIKE 'erp/%';
-- 3) ç¡®è®¤ SRM åˆ†æ”¯ä¸ºå¯ç”¨çŠ¶æ€
UPDATE system_menu SET status = 0
WHERE CAST(deleted AS UNSIGNED)=0
  AND id = 602524;
UPDATE system_menu SET status = 0
WHERE CAST(deleted AS UNSIGNED)=0
  AND parent_id = 602524
  AND (component LIKE 'srm/%' OR component IS NULL);
sql/mysql/srm_cost_analysis_menu_20261107.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
-- é‡‡è´­æˆæœ¬åˆ†æžèœå•(基于 SRM æ‹›æ ‡éœ€æ±‚与供应商报价,不依赖 ERP)
SET @srm_parent := (SELECT id FROM system_menu WHERE CAST(deleted AS UNSIGNED)=0 AND type=1
                    AND (name='供应商管理' OR path LIKE '%srm%' OR path LIKE '%supplier%') LIMIT 1);
-- è‹¥æ‰¾ä¸åˆ° SRM çˆ¶èœå•,退化为挂在仓储物流下
SET @srm_parent := IFNULL(@srm_parent,
  (SELECT id FROM system_menu WHERE CAST(deleted AS UNSIGNED)=0 AND type=1 AND name='仓储物流' LIMIT 1));
INSERT INTO system_menu (name,permission,type,sort,parent_id,path,icon,component,component_name,status,visible,keep_alive,always_show,creator,updater)
SELECT '采购成本分析','',2,95,@srm_parent,'cost-analysis','lucide:line-chart','srm/statistics/cost-analysis','SrmCostAnalysis',0,b'1',b'1',b'1','1','1'
WHERE @srm_parent IS NOT NULL
  AND NOT EXISTS (SELECT 1 FROM system_menu WHERE component='srm/statistics/cost-analysis' AND CAST(deleted AS UNSIGNED)=0);
SET @pg := (SELECT id FROM system_menu WHERE component='srm/statistics/cost-analysis' AND CAST(deleted AS UNSIGNED)=0 LIMIT 1);
INSERT INTO system_menu (name,permission,type,sort,parent_id,path,icon,status,visible,keep_alive,always_show,creator,updater)
SELECT p.name,p.permission,3,p.sort_no,@pg,'','',0,b'1',b'1',b'1','1','1'
FROM (SELECT '查询' name,'srm:statistics:query' permission,1 sort_no) p
WHERE @pg IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id=@pg AND m.permission=p.permission AND CAST(m.deleted AS UNSIGNED)=0);