docs: add vehicle recharge workflow design, plan, and migration SQL

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-09-26 20:48:17 +08:00
1 parent b430e75a4b
commit 94dd52832b
3 files changed
+1187

No files matched your search

@@ -0,0 +1,435 @@
-- 车辆 ETC/加油充值:可配置审批与财务发放登记
-- Spec: docs/superpowers/specs/2026-09-26-pl-vehicle-recharge-workflow-design.md
-- Plan Task 1: 结构 + 字典 + 菜单 + 流程种子 + 存量 pending 迁移
-- 可重复执行(列/菜单/字典/角色授权均做存在性判断)
SET NAMES utf8mb4;
-- =============================================================================
-- 1) bx_workflow_node.action_type
-- =============================================================================
SET @db := DATABASE();
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 'bx_workflow_node'
AND COLUMN_NAME = 'action_type'
);
SET @sql := IF(
@col_exists = 0,
'ALTER TABLE `bx_workflow_node`
ADD COLUMN `action_type` varchar(20) NOT NULL DEFAULT ''approve''
COMMENT ''approve-审批 disburse-发放登记'' AFTER `approver_name`',
'SELECT ''bx_workflow_node.action_type already exists'' AS info'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =============================================================================
-- 2) pl_vehicle_recharge_apply:wf_id / current_node / approval_round + status 注释
-- =============================================================================
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 'pl_vehicle_recharge_apply'
AND COLUMN_NAME = 'wf_id'
);
SET @sql := IF(
@col_exists = 0,
'ALTER TABLE `pl_vehicle_recharge_apply`
ADD COLUMN `wf_id` varchar(64) DEFAULT NULL COMMENT ''工作流定义ID'' AFTER `status`',
'SELECT ''pl_vehicle_recharge_apply.wf_id already exists'' AS info'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 'pl_vehicle_recharge_apply'
AND COLUMN_NAME = 'current_node'
);
SET @sql := IF(
@col_exists = 0,
'ALTER TABLE `pl_vehicle_recharge_apply`
ADD COLUMN `current_node` varchar(64) DEFAULT NULL COMMENT ''当前节点ID'' AFTER `wf_id`',
'SELECT ''pl_vehicle_recharge_apply.current_node already exists'' AS info'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 'pl_vehicle_recharge_apply'
AND COLUMN_NAME = 'approval_round'
);
SET @sql := IF(
@col_exists = 0,
'ALTER TABLE `pl_vehicle_recharge_apply`
ADD COLUMN `approval_round` int(11) NOT NULL DEFAULT 0 COMMENT ''当前审批轮次'' AFTER `current_node`',
'SELECT ''pl_vehicle_recharge_apply.approval_round already exists'' AS info'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
ALTER TABLE `pl_vehicle_recharge_apply`
MODIFY COLUMN `status` varchar(20) NOT NULL DEFAULT 'draft'
COMMENT 'draft-草稿 in_approval-审批中 rejected-已驳回 disbursed-已发放 cancelled-已作废';
-- =============================================================================
-- 3) 审批历史表
-- =============================================================================
CREATE TABLE IF NOT EXISTS `pl_vehicle_recharge_approval` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`apply_id` varchar(64) NOT NULL COMMENT '申请单ID',
`approval_round` int(11) NOT NULL DEFAULT 1 COMMENT '审批轮次',
`node_id` varchar(64) DEFAULT NULL COMMENT '节点ID快照',
`node_name` varchar(128) DEFAULT NULL COMMENT '节点名称快照',
`approver_id` varchar(64) NOT NULL COMMENT '审批人用户ID',
`approver_name` varchar(64) NOT NULL COMMENT '审批人姓名',
`approval_status` varchar(32) NOT NULL COMMENT 'approved/rejected/disbursed',
`approval_opinion` varchar(1024) DEFAULT NULL COMMENT '审批意见',
`approval_time` datetime NOT NULL COMMENT '审批时间',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_apply_id` (`apply_id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_approver` (`approver_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆充值申请审批历史';
-- =============================================================================
-- 4) 流程定义 + 节点种子
-- =============================================================================
INSERT INTO `bx_workflow_def` (
`id`, `biz_type`, `wf_name`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `del_flag`
)
VALUES (
'PL_WF_VEHICLE_RECHARGE', 'vehicle_recharge', 'ETC/加油充值审批流程', 1,
'shanxia2.0', 0, '充值申请默认审批流程', 'system', '', NOW(), 0
)
ON DUPLICATE KEY UPDATE
`wf_name` = VALUES(`wf_name`),
`biz_type` = VALUES(`biz_type`),
`status` = VALUES(`status`),
`del_flag` = 0,
`remark` = VALUES(`remark`);
INSERT INTO `bx_workflow_node` (
`id`, `wf_id`, `node_name`, `node_order`, `approver_id`, `approver_name`,
`action_type`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `del_flag`
)
VALUES
(
'PL_WR_NODE_GM', 'PL_WF_VEHICLE_RECHARGE', '总经理审批', 1,
'56D1C9DA5F6747DDAD25C248A156A524', '吴九华', 'approve',
'shanxia2.0', 0, NULL, 'system', '', NOW(), 0
),
(
'PL_WR_NODE_FIN', 'PL_WF_VEHICLE_RECHARGE', '财务发放', 2,
'CC2EED9A86F44D11AFFD0AD381893093', '汪璇', 'disburse',
'shanxia2.0', 0, NULL, 'system', '', NOW(), 0
)
ON DUPLICATE KEY UPDATE
`wf_id` = VALUES(`wf_id`),
`node_name` = VALUES(`node_name`),
`node_order` = VALUES(`node_order`),
`approver_id` = VALUES(`approver_id`),
`approver_name` = VALUES(`approver_name`),
`action_type` = VALUES(`action_type`),
`del_flag` = 0;
-- =============================================================================
-- 5) 字典 pl_recharge_apply_status
-- 软停用旧 pending;补齐 draft/in_approval/rejected;保留 disbursed/cancelled
-- =============================================================================
UPDATE `sys_dict_data`
SET `del_flag` = 1,
`remark` = '充值审批改造:pending(待发放)已废弃,存量已迁移为 in_approval',
`update_time` = NOW()
WHERE `id` = 'PL_RECHARGE_APPLY_PENDING'
AND `dict_type` = 'pl_recharge_apply_status'
AND `del_flag` = 0;
INSERT INTO `sys_dict_data` (
`id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`,
`order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `del_flag`
)
SELECT
'PL_RECHARGE_APPLY_DRAFT', '草稿', 'draft', 'info', 'pl_recharge_apply_status',
'shanxia2.0', 1, NULL, 'system', '', NOW(), 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `sys_dict_data` WHERE `id` = 'PL_RECHARGE_APPLY_DRAFT'
);
INSERT INTO `sys_dict_data` (
`id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`,
`order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `del_flag`
)
SELECT
'PL_RECHARGE_APPLY_IN_APPROVAL', '审批中', 'in_approval', 'warning', 'pl_recharge_apply_status',
'shanxia2.0', 2, NULL, 'system', '', NOW(), 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `sys_dict_data` WHERE `id` = 'PL_RECHARGE_APPLY_IN_APPROVAL'
);
INSERT INTO `sys_dict_data` (
`id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`,
`order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `del_flag`
)
SELECT
'PL_RECHARGE_APPLY_REJECTED', '已驳回', 'rejected', 'danger', 'pl_recharge_apply_status',
'shanxia2.0', 3, NULL, 'system', '', NOW(), 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `sys_dict_data` WHERE `id` = 'PL_RECHARGE_APPLY_REJECTED'
);
UPDATE `sys_dict_data`
SET `dict_label` = '已发放',
`tag_type` = 'success',
`order_num` = 4,
`del_flag` = 0,
`update_time` = NOW()
WHERE `id` = 'PL_RECHARGE_APPLY_DISBURSED'
AND `dict_type` = 'pl_recharge_apply_status';
UPDATE `sys_dict_data`
SET `dict_label` = '已作废',
`tag_type` = 'info',
`order_num` = 5,
`del_flag` = 0,
`update_time` = NOW()
WHERE `id` = 'PL_RECHARGE_APPLY_CANCELLED'
AND `dict_type` = 'pl_recharge_apply_status';
-- 幂等:若上述 INSERT 因已存在跳过,仍校正文案/排序/启用态
UPDATE `sys_dict_data`
SET `dict_label` = '草稿', `tag_type` = 'info', `order_num` = 1, `del_flag` = 0, `update_time` = NOW()
WHERE `id` = 'PL_RECHARGE_APPLY_DRAFT';
UPDATE `sys_dict_data`
SET `dict_label` = '审批中', `tag_type` = 'warning', `order_num` = 2, `del_flag` = 0, `update_time` = NOW()
WHERE `id` = 'PL_RECHARGE_APPLY_IN_APPROVAL';
UPDATE `sys_dict_data`
SET `dict_label` = '已驳回', `tag_type` = 'danger', `order_num` = 3, `del_flag` = 0, `update_time` = NOW()
WHERE `id` = 'PL_RECHARGE_APPLY_REJECTED';
-- =============================================================================
-- 6) 菜单:充值审批 / 充值审批流程(挂 PL_GROUP_VEHICLE)
-- 排序:申请(1) → 审批(2) → 发放登记(3) → 流程配置(4) → 其余顺延
-- 仅当发放登记仍为 order_num=2(首次)时整体后移,避免重复执行叠位
-- =============================================================================
SET @record_ord := (
SELECT `order_num` FROM `sys_menu`
WHERE `id` = 'PL_VEH_RECHARGE_RECORD' AND `del_flag` = 0
LIMIT 1
);
UPDATE `sys_menu`
SET `order_num` = `order_num` + 2,
`update_time` = NOW()
WHERE @record_ord = 2
AND `parent_id` = 'PL_GROUP_VEHICLE'
AND `order_num` >= 2
AND `del_flag` = 0
AND `id` NOT IN ('PL_VEH_RECHARGE_APPROVAL', 'PL_VEH_RECHARGE_WF');
UPDATE `sys_menu`
SET `order_num` = 3, `update_time` = NOW()
WHERE `id` = 'PL_VEH_RECHARGE_RECORD' AND `del_flag` = 0;
-- 充值审批(待办)
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
'PL_VEH_RECHARGE_APPROVAL', '充值审批', 'PL_GROUP_VEHICLE', 'C',
'vehicle-recharge-approval', 'pl/vehicle-recharge-approval/index',
'pl:vehicle-recharge-approval:list', 1, '1', '1', 'shanxia2.0', 2, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VEH_RECHARGE_APPROVAL' AND `del_flag` = 0
);
UPDATE `sys_menu`
SET `menu_name` = '充值审批',
`path` = 'vehicle-recharge-approval',
`component` = 'pl/vehicle-recharge-approval/index',
`perms` = 'pl:vehicle-recharge-approval:list',
`order_num` = 2,
`visible` = '1',
`status` = '1',
`update_time` = NOW()
WHERE `id` = 'PL_VEH_RECHARGE_APPROVAL' AND `del_flag` = 0;
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRAP_Q', '查询', 'PL_VEH_RECHARGE_APPROVAL', 'F', '', '',
'pl:vehicle-recharge-approval:query', 1, '1', '1', 'shanxia2.0', 1, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRAP_Q' AND `del_flag` = 0);
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRAP_A', '通过', 'PL_VEH_RECHARGE_APPROVAL', 'F', '', '',
'pl:vehicle-recharge-approval:approve', 1, '1', '1', 'shanxia2.0', 2, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRAP_A' AND `del_flag` = 0);
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRAP_J', '驳回', 'PL_VEH_RECHARGE_APPROVAL', 'F', '', '',
'pl:vehicle-recharge-approval:reject', 1, '1', '1', 'shanxia2.0', 3, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRAP_J' AND `del_flag` = 0);
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRAP_D', '发放', 'PL_VEH_RECHARGE_APPROVAL', 'F', '', '',
'pl:vehicle-recharge-approval:disburse', 1, '1', '1', 'shanxia2.0', 4, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRAP_D' AND `del_flag` = 0);
-- 充值审批流程(配置)
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
'PL_VEH_RECHARGE_WF', '充值审批流程', 'PL_GROUP_VEHICLE', 'C',
'vehicle-recharge-workflow', 'pl/vehicle-recharge-workflow/index',
'pl:vehicle-recharge-workflow:list', 1, '1', '1', 'shanxia2.0', 4, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VEH_RECHARGE_WF' AND `del_flag` = 0
);
UPDATE `sys_menu`
SET `menu_name` = '充值审批流程',
`path` = 'vehicle-recharge-workflow',
`component` = 'pl/vehicle-recharge-workflow/index',
`perms` = 'pl:vehicle-recharge-workflow:list',
`order_num` = 4,
`visible` = '1',
`status` = '1',
`update_time` = NOW()
WHERE `id` = 'PL_VEH_RECHARGE_WF' AND `del_flag` = 0;
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRWF_Q', '查询', 'PL_VEH_RECHARGE_WF', 'F', '', '',
'pl:vehicle-recharge-workflow:query', 1, '1', '1', 'shanxia2.0', 1, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRWF_Q' AND `del_flag` = 0);
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRWF_E', '编辑', 'PL_VEH_RECHARGE_WF', 'F', '', '',
'pl:vehicle-recharge-workflow:edit', 1, '1', '1', 'shanxia2.0', 2, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRWF_E' AND `del_flag` = 0);
INSERT INTO `sys_menu` (
`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
`is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT 'PL_VRWF_S', '保存', 'PL_VEH_RECHARGE_WF', 'F', '', '',
'pl:vehicle-recharge-workflow:save', 1, '1', '1', 'shanxia2.0', 3, NULL,
'system', '', NOW(), NULL, NOW(), 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'PL_VRWF_S' AND `del_flag` = 0);
-- 角色授权:已拥有充值申请(C 菜单或查询按钮)的角色同步获得新菜单
INSERT INTO `sys_role_menu` (
`id`, `role_id`, `menu_id`, `tenant_no`, `order_num`, `remark`,
`create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
MD5(CONCAT(rm.role_id, '|', m.menu_id, '|pl-veh-recharge-wf|v1')),
rm.role_id,
m.menu_id,
IFNULL(NULLIF(rm.tenant_no, ''), 'shanxia2.0'),
0,
'充值审批改造:同步授权',
'system',
'',
NOW(),
NULL,
NOW(),
0
FROM (
SELECT DISTINCT `role_id`, `tenant_no`
FROM `sys_role_menu`
WHERE `menu_id` IN ('PL_VEH_RECHARGE_APPLY', 'PL_VRA_Q')
AND `del_flag` = 0
) rm
JOIN (
SELECT 'PL_VEH_RECHARGE_APPROVAL' AS menu_id UNION ALL
SELECT 'PL_VRAP_Q' UNION ALL
SELECT 'PL_VRAP_A' UNION ALL
SELECT 'PL_VRAP_J' UNION ALL
SELECT 'PL_VRAP_D' UNION ALL
SELECT 'PL_VEH_RECHARGE_WF' UNION ALL
SELECT 'PL_VRWF_Q' UNION ALL
SELECT 'PL_VRWF_E' UNION ALL
SELECT 'PL_VRWF_S'
) m
WHERE NOT EXISTS (
SELECT 1 FROM `sys_role_menu` x
WHERE x.role_id = rm.role_id AND x.menu_id = m.menu_id AND x.del_flag = 0
);
-- =============================================================================
-- 7) 存量:pending 且无发放记录 → 审批中(落在财务发放节点)
-- =============================================================================
UPDATE `pl_vehicle_recharge_apply` a
LEFT JOIN `pl_vehicle_recharge_record` r
ON r.apply_id = a.id AND r.del_flag = 0
SET a.status = 'in_approval',
a.wf_id = 'PL_WF_VEHICLE_RECHARGE',
a.current_node = 'PL_WR_NODE_FIN',
a.approval_round = 1,
a.update_time = NOW()
WHERE a.del_flag = 0
AND a.status = 'pending'
AND r.id IS NULL;