sql/mysql/xgdl_review_audit_pending_changes.sql
@@ -3,9 +3,21 @@
-- 目标库:mom-xgdl
-- 说明:本脚本幂等,可重复执行;已存在的字段/菜单会自动跳过。
--       开发库(192.168.197.128)已全部执行过,本脚本用于向其它环境(如测试/生产)同步。
-- 内容结构:
--   第一部分  20 张单据表的审核人四字段
--   第二部分  上述单据的「审核」按钮权限(system_menu type=3)
--   第三部分  电力作业计划生成工单编码规则说明(无需执行)
--   第四部分  通用审批配置表 + 26 个业务类型 + 审批配置页菜单
--             + 采购计划/采购订单审核字段与按钮 + 角色授权
--
-- 执行前置要求:必须用支持 DELIMITER 与存储过程的客户端整体执行
--   (mysql CLI:mysql -h<host> -P<port> -u<user> -p mom-xgdl < 本文件)。
--   多数图形化/在线 SQL 控制台按分号拆分语句,会把 DELIMITER $$ 段落拆坏。
--
-- 对应代码提交:
--   refactor(crm/erp/hrm/mes): 单据审核改为审批配置状态机
--   fix(mes): 电力作业计划生成工单补充编码规则取号
--   e347fd6e refactor(approval): 采购计划/采购订单审批由 BPM 改为轻量级状态机
-- ============================================================================
SET NAMES utf8mb4;
@@ -154,115 +166,115 @@
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '销户申请审核' AS name, 'crm:cancellation:audit' AS perm, 'crm:cancellation:update' AS anchor) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'crm:cancellation:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:cancellation:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:cancellation:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '合同审核' AS name, 'crm:contract:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'crm:contract:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:contract:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:contract:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '发票审核' AS name, 'crm:invoice:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'crm:invoice:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:invoice:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:invoice:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '退费单审核' AS name, 'crm:refund:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'crm:refund:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:refund:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'crm:refund:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '付款单审核' AS name, 'erp:finance-payment:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'erp:finance-payment:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'erp:finance-payment:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'erp:finance-payment:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '采购申请审核' AS name, 'erp:purchase-request:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'erp:purchase-request:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'erp:purchase-request:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'erp:purchase-request:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '请假申请审核' AS name, 'hrm:leave:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'hrm:leave:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:leave:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:leave:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '转正申请审核' AS name, 'hrm:regularize:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'hrm:regularize:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:regularize:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:regularize:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '离职申请审核' AS name, 'hrm:resignation:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'hrm:resignation:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:resignation:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:resignation:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '调动申请审核' AS name, 'hrm:transfer:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'hrm:transfer:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:transfer:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:transfer:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '考勤异常审核' AS name, 'hrm:attendance-exception:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'hrm:attendance-exception:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:attendance-exception:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:attendance-exception:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '项目审核' AS name, 'mes:pd-project:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:pd-project:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:pd-project:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:pd-project:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '技术确认函审核' AS name, 'mes:pd-tech-confirm:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:pd-tech-confirm:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:pd-tech-confirm:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:pd-tech-confirm:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '采购入库单审核' AS name, 'mes:wm-item-receipt:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:wm-item-receipt:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-item-receipt:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-item-receipt:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '杂项出库单审核' AS name, 'mes:wm-misc-issue:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:wm-misc-issue:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-misc-issue:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-misc-issue:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '采购退货单审核' AS name, 'mes:wm-return-vendor:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:wm-return-vendor:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-return-vendor:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-return-vendor:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '盘点任务审核' AS name, 'mes:wm-stock-taking-task:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:wm-stock-taking-task:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-stock-taking-task:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm-stock-taking-task:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '设备入库单审核' AS name, 'mes:wm:equipment-receipt:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:wm:equipment-receipt:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm:equipment-receipt:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm:equipment-receipt:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '杂项入库单审核' AS name, 'mes:wm:misc-receipt:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:wm:misc-receipt:update') a ON 1 = 1
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm:misc-receipt:audit') m);
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:wm:misc-receipt:audit') m);
-- ============================================================================
-- 第三部分:电力作业计划生成工单 —— 工单编码取号规则(无变更,仅说明)
@@ -273,7 +285,228 @@
--   (注意:该脚本会 TRUNC 式重建规则表,仅适用于首次初始化,勿在已有数据的环境执行)。
-- ============================================================================
-- ============================================================================
-- 第四部分:通用审批配置(审批引擎的地基)
--
-- 前三部分只加了「审核人字段」和「审核按钮权限」,但没有建审批配置表本身。
-- 只跑前三部分的话,所有单据的「提交」都会在 validateApprovalEnabledAndGetApprovers
-- 处失败(审批配置不存在 / 未启用 / 未配置审批人)。本部分补齐:
--   4.1 审批配置主表 + 审批人子表
--   4.2 26 个业务类型种子(默认未启用)
--   4.3 审批配置页面菜单与查询/保存按钮
--   4.4 采购计划、采购订单的审核人四字段
--   4.5 采购计划、采购订单的审核按钮权限
--   4.6 角色授权(本框架无「超管绕过权限」逻辑,不授权则 admin 也看不到按钮)
--
-- 对应代码提交:e347fd6e refactor(approval): 采购计划/采购订单审批由 BPM 改为轻量级状态机
-- ============================================================================
-- 4.1 审批配置主表 / 审批人子表
CREATE TABLE IF NOT EXISTS system_approval_config (
  id bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  biz_type varchar(64) NOT NULL COMMENT '业务类型编码,与各模块审批分类编码一致',
  biz_name varchar(100) NOT NULL COMMENT '业务类型名称',
  approval_enabled bit(1) NOT NULL DEFAULT b'0' COMMENT '是否启用审批',
  remark varchar(500) NULL DEFAULT NULL COMMENT '备注',
  creator varchar(64) NULL DEFAULT '' COMMENT '创建者',
  create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  updater varchar(64) NULL DEFAULT '' COMMENT '更新者',
  update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  PRIMARY KEY (id) USING BTREE,
  KEY idx_biz_type (biz_type) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '通用审批配置表';
CREATE TABLE IF NOT EXISTS system_approval_config_user (
  id bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  config_id bigint NOT NULL COMMENT '审批配置ID(关联 system_approval_config.id)',
  user_id bigint NOT NULL COMMENT '审批人用户ID(系统用户)',
  sort int NOT NULL DEFAULT 0 COMMENT '显示顺序',
  creator varchar(64) NULL DEFAULT '' COMMENT '创建者',
  create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  updater varchar(64) NULL DEFAULT '' COMMENT '更新者',
  update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  PRIMARY KEY (id) USING BTREE,
  KEY idx_config_id (config_id) USING BTREE,
  KEY idx_user_id (user_id) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '通用审批配置-审批人表';
-- 4.2 业务类型种子:编码与各模块 *_APPROVE_* 常量一一对应,默认全部未启用
INSERT IGNORE INTO system_approval_config
  (biz_type, biz_name, approval_enabled, remark, creator, create_time, updater, update_time, deleted) VALUES
('purchase_plan_approve',        '采购计划审核',   b'0', 'ERP 采购计划', '1', NOW(), '1', NOW(), b'0'),
('purchase_request_approve',     '采购申请审核',   b'0', 'ERP 采购申请', '1', NOW(), '1', NOW(), b'0'),
('erp_purchase_order_approve',   '采购订单审核',   b'0', 'ERP 采购订单(原误用 purchase_request_approve,已改为独立编码)', '1', NOW(), '1', NOW(), b'0'),
('erp_purchase_invoice_approve', '采购来票审核',   b'0', 'ERP 采购来票', '1', NOW(), '1', NOW(), b'0'),
('erp_finance_payment_approve',  '付款单审核',     b'0', 'ERP 付款单', '1', NOW(), '1', NOW(), b'0'),
('contract_approve',             '合同审批',       b'0', 'CRM 合同', '1', NOW(), '1', NOW(), b'0'),
('refund_approve',               '退费审批',       b'0', 'CRM 退款', '1', NOW(), '1', NOW(), b'0'),
('cancellation_approve',         '销户审批',       b'0', 'CRM 销户', '1', NOW(), '1', NOW(), b'0'),
('crm_invoice_approve',          '开票审批',       b'0', 'CRM 发票', '1', NOW(), '1', NOW(), b'0'),
('sale_quotation_approve',       '销售报价审批',   b'0', 'CRM 销售报价', '1', NOW(), '1', NOW(), b'0'),
('hrm_leave_approve',            '请假审批',       b'0', 'HRM 请假申请', '1', NOW(), '1', NOW(), b'0'),
('hrm_regularize_approve',       '转正审批',       b'0', 'HRM 转正申请', '1', NOW(), '1', NOW(), b'0'),
('hrm_resignation_approve',      '离职审批',       b'0', 'HRM 离职申请', '1', NOW(), '1', NOW(), b'0'),
('hrm_transfer_approve',         '调动审批',       b'0', 'HRM 调动申请', '1', NOW(), '1', NOW(), b'0'),
('hrm_attendance_approve',       '考勤异常审批',   b'0', 'HRM 考勤异常', '1', NOW(), '1', NOW(), b'0'),
('performance_appraise_approve', '绩效考核审批',   b'0', 'HRM 绩效考核', '1', NOW(), '1', NOW(), b'0'),
('mes_pd_project_approve',       '产品项目审批',   b'0', 'MES 产品项目', '1', NOW(), '1', NOW(), b'0'),
('pd_tech_confirm_approve',      '技术确认函审批', b'0', 'MES 产品技术确认函', '1', NOW(), '1', NOW(), b'0'),
('item_receipt_approve',         '采购入库审批',   b'0', 'MES 采购入库单', '1', NOW(), '1', NOW(), b'0'),
('equipment_receipt_approve',    '设备入库审批',   b'0', 'MES 设备入库单', '1', NOW(), '1', NOW(), b'0'),
('misc_issue_approve',           '其他出库审批',   b'0', 'MES 其他出库单', '1', NOW(), '1', NOW(), b'0'),
('misc_receipt_approve',         '其他入库审批',   b'0', 'MES 其他入库单', '1', NOW(), '1', NOW(), b'0'),
('return_vendor_approve',        '退货审批',       b'0', 'MES 退货单', '1', NOW(), '1', NOW(), b'0'),
('stock_taking_result_approve',  '盘点结果审批',   b'0', 'MES 盘点单', '1', NOW(), '1', NOW(), b'0'),
('wms_approve',                  '仓库单据审核',   b'0', 'MES 仓储通用审批', '1', NOW(), '1', NOW(), b'0'),
('compensation_approve',         '赔付审批',       b'0', '售后赔偿单', '1', NOW(), '1', NOW(), b'0');
-- 4.3 审批配置页面菜单
--     父级锚定「系统管理」:取 system/user/index 的 parent_id,避免硬编码目录 ID
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT '审批配置', '', 2, 8, a.parent_id, 'approval-config', 'ep:stamp', 'system/approvalConfig/index', 'SystemApprovalConfig', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT MIN(m.parent_id) AS parent_id FROM system_menu m WHERE m.deleted = 0 AND m.component = 'system/user/index') a
WHERE a.parent_id IS NOT NULL
  AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND component = 'system/approvalConfig/index') x);
-- 4.3.1 审批配置查询按钮(父级 = 上面的页面菜单,按 component 反查)
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT '审批配置查询', 'system:approval-config:query', 3, 1, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT MIN(m.id) AS parent_id FROM system_menu m WHERE m.deleted = 0 AND m.component = 'system/approvalConfig/index') a
WHERE a.parent_id IS NOT NULL
  AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'system:approval-config:query') x);
-- 4.3.2 审批配置保存按钮
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT '审批配置保存', 'system:approval-config:update', 3, 2, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT MIN(m.id) AS parent_id FROM system_menu m WHERE m.deleted = 0 AND m.component = 'system/approvalConfig/index') a
WHERE a.parent_id IS NOT NULL
  AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'system:approval-config:update') x);
-- 4.4 采购计划 / 采购订单 审核人四字段
--     (第一部分只覆盖了另外 20 张表,这两张是采购计划/采购订单改造时补的)
DROP TABLE IF EXISTS _tmp_xgdl_po_review_cols;
CREATE TABLE _tmp_xgdl_po_review_cols (
    tbl    VARCHAR(64)  NOT NULL,
    col    VARCHAR(64)  NOT NULL,
    coldef VARCHAR(255) NOT NULL
);
INSERT INTO _tmp_xgdl_po_review_cols (tbl, col, coldef) VALUES
('erp_purchase_plan',  'reviewer_id',   'bigint COMMENT ''审核人编号(实际执行审核的用户)'''),
('erp_purchase_plan',  'reviewer_name', 'varchar(64) COMMENT ''审核人姓名(冗余记录,避免列表查询再查用户)'''),
('erp_purchase_plan',  'review_time',   'datetime COMMENT ''审核时间'''),
('erp_purchase_plan',  'review_remark', 'varchar(500) COMMENT ''审核意见(通过时的意见 / 不通过时的原因)'''),
('erp_purchase_order', 'reviewer_id',   'bigint COMMENT ''审核人编号(实际执行审核的用户)'''),
('erp_purchase_order', 'reviewer_name', 'varchar(64) COMMENT ''审核人姓名(冗余记录,避免列表查询再查用户)'''),
('erp_purchase_order', 'review_time',   'datetime COMMENT ''审核时间'''),
('erp_purchase_order', 'review_remark', 'varchar(500) COMMENT ''审核意见(通过时的意见 / 不通过时的原因)''');
DROP PROCEDURE IF EXISTS xgdl_add_po_review_cols;
DELIMITER $$
CREATE PROCEDURE xgdl_add_po_review_cols()
BEGIN
    DECLARE v_done INT DEFAULT 0;
    DECLARE v_tbl VARCHAR(64);
    DECLARE v_col VARCHAR(64);
    DECLARE v_def VARCHAR(255);
    DECLARE cur CURSOR FOR SELECT tbl, col, coldef FROM _tmp_xgdl_po_review_cols;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;
    OPEN cur;
    read_loop: LOOP
        FETCH cur INTO v_tbl, v_col, v_def;
        IF v_done = 1 THEN
            LEAVE read_loop;
        END IF;
        IF EXISTS (SELECT 1 FROM information_schema.tables
                   WHERE table_schema = DATABASE() AND table_name = v_tbl)
           AND NOT EXISTS (SELECT 1 FROM information_schema.columns
                   WHERE table_schema = DATABASE() AND table_name = v_tbl AND column_name = v_col)
        THEN
            SET @ddl = CONCAT('ALTER TABLE `', v_tbl, '` ADD COLUMN `', v_col, '` ', v_def);
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
    END LOOP;
    CLOSE cur;
END$$
DELIMITER ;
CALL xgdl_add_po_review_cols();
DROP PROCEDURE IF EXISTS xgdl_add_po_review_cols;
DROP TABLE IF EXISTS _tmp_xgdl_po_review_cols;
-- 4.5 采购计划 / 采购订单 审核按钮权限(锚点同第一部分:各自资源的 :update 按钮)
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '采购计划审核' AS name, 'erp:purchase-plan:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'erp:purchase-plan:update') a ON 1 = 1
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'erp:purchase-plan:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '采购订单审核' AS name, 'erp:purchase-order:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'erp:purchase-order:update') a ON 1 = 1
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'erp:purchase-order:audit') m);
-- 4.6 补漏:代码里已使用、但第二部分未创建的 3 个审核按钮权限
--     对账方式:grep -rhoE "'[a-z]+:[a-z0-9-]+:audit'" --include=*.java
--     缺失会导致对应页面的审核按钮对任何人都不显示(含 admin)。
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '故障赔付审核' AS name, 'aftersales:compensation:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'aftersales:compensation:update') a ON 1 = 1
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'aftersales:compensation:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '绩效考核审核' AS name, 'hrm:performance-appraise:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'hrm:performance-appraise:update') a ON 1 = 1
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'hrm:performance-appraise:audit') m);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
SELECT t.name, t.perm, 3, 99, a.parent_id, '', '', NULL, NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM (SELECT '产品项目审核' AS name, 'mes:pd-product:audit' AS perm) t
JOIN (SELECT MIN(x.parent_id) AS parent_id FROM system_menu x WHERE x.deleted = 0 AND x.permission = 'mes:pd-product:update') a ON 1 = 1
WHERE a.parent_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM system_menu WHERE deleted = 0 AND permission = 'mes:pd-product:audit') m);
-- 4.7 角色授权
--     重要:本框架 SecurityFrameworkServiceImpl 没有「超级管理员绕过权限校验」的短路逻辑,
--     权限一律走 system_role_menu。不授权的话连 admin 都看不到审批配置菜单和审核按钮。
--     开发库实测:全部 :audit 均已授予 super_admin(1) 与 common(2),
--     仅 mes:pd-product:audit 与 mes:pd-tech-confirm:audit 漏授 super_admin ——
--     下面这条语句会顺带把这两个缺口补齐。
--     其余角色请在「角色管理」页面按需勾选。
INSERT INTO system_role_menu (role_id, menu_id, creator, create_time, updater, update_time, deleted)
SELECT r.id, m.id, '1', NOW(), '1', NOW(), b'0'
FROM system_role r
CROSS JOIN system_menu m
WHERE r.code IN ('super_admin', 'common')
  AND r.deleted = 0
  AND m.deleted = 0
  AND ( m.component = 'system/approvalConfig/index'
        OR m.permission IN ('system:approval-config:query', 'system:approval-config:update')
        OR m.permission LIKE '%:audit' )
  AND NOT EXISTS (
      SELECT 1 FROM system_role_menu rm
      WHERE rm.role_id = r.id AND rm.menu_id = m.id AND rm.deleted = 0
  );
-- 完成。可执行以下语句校验:
-- SELECT table_name, column_name FROM information_schema.columns
--  WHERE table_schema = DATABASE() AND column_name = 'reviewer_id';
-- SELECT permission FROM system_menu WHERE deleted = 0 AND permission LIKE '%:audit';
-- SELECT COUNT(*) FROM system_approval_config WHERE deleted = 0;                     -- 期望 26
-- SELECT id, name, permission, parent_id FROM system_menu                            -- 必须回读三项,勿只看行数
--  WHERE deleted = 0 AND (component = 'system/approvalConfig/index'
--    OR permission LIKE 'system:approval-config:%'
--    OR permission IN ('erp:purchase-plan:audit','erp:purchase-order:audit'));
-- SELECT r.code, COUNT(*) FROM system_role_menu rm JOIN system_role r ON r.id = rm.role_id
--  JOIN system_menu m ON m.id = rm.menu_id
--  WHERE rm.deleted = 0 AND (m.component = 'system/approvalConfig/index'
--    OR m.permission LIKE 'system:approval-config:%'
--    OR m.permission IN ('erp:purchase-plan:audit','erp:purchase-order:audit'))
--  GROUP BY r.code;                                                                  -- 期望每角色 5 条