【同步】BOOT 和 CLOUD 的功能(im 为主)
parent
ed87b45dff
commit
eb7fa0d844
|
|
@ -1552,9 +1552,9 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
|
|||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, 'è‰ç¨¿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完æˆ', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已喿¶ˆ', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
COMMIT;
|
||||
SET IDENTITY_INSERT system_dict_data OFF;
|
||||
-- @formatter:on
|
||||
|
|
@ -5617,4 +5617,3 @@ INSERT INTO yudao_demo03_student (id, name, sex, birthday, description, creator,
|
|||
COMMIT;
|
||||
SET IDENTITY_INSERT yudao_demo03_student OFF;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
|
|||
|
|
@ -1653,9 +1653,9 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
|
|||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, 'è‰ç¨¿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完æˆ', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已喿¶ˆ', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
@ -5943,4 +5943,3 @@ COMMIT;
|
|||
DROP SEQUENCE IF EXISTS yudao_demo03_student_seq;
|
||||
CREATE SEQUENCE yudao_demo03_student_seq
|
||||
START 10;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1653,9 +1653,9 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
|
|||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, 'è‰ç¨¿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完æˆ', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已喿¶ˆ', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
@ -5943,4 +5943,3 @@ COMMIT;
|
|||
DROP SEQUENCE IF EXISTS yudao_demo03_student_seq;
|
||||
CREATE SEQUENCE yudao_demo03_student_seq
|
||||
START 10;
|
||||
|
||||
|
|
|
|||
|
|
@ -1605,9 +1605,9 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
|
|||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', to_date('2026-04-05 15:53:46', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-05 15:53:46', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', to_date('2026-04-05 15:53:46', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-05 15:53:46', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', to_date('2026-04-05 15:53:46', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-05 15:53:46', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, 'è‰ç¨¿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完æˆ', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已喿¶ˆ', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-04-16 09:47:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
@ -5801,4 +5801,3 @@ COMMIT;
|
|||
|
||||
CREATE SEQUENCE yudao_demo03_student_seq
|
||||
START WITH 10;
|
||||
|
||||
|
|
|
|||
|
|
@ -1653,9 +1653,9 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
|
|||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, 'è‰ç¨¿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完æˆ', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已喿¶ˆ', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
@ -5943,4 +5943,3 @@ COMMIT;
|
|||
DROP SEQUENCE IF EXISTS yudao_demo03_student_seq;
|
||||
CREATE SEQUENCE yudao_demo03_student_seq
|
||||
START 10;
|
||||
|
||||
|
|
|
|||
|
|
@ -3931,11 +3931,11 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
|
|||
GO
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3445, 3, N'已取消', N'5', N'mes_wm_product_produce_status', 0, N'danger', N'', N'已取消状态', N'1', N'2026-04-05 15:53:46', N'1', N'2026-04-05 15:53:46', N'0')
|
||||
GO
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, N'è‰ç¨¿', N'0', N'mes_pro_task_status', 0, N'', N'', NULL, N'1', N'2026-04-16 09:47:00', N'1', N'2026-04-16 09:47:00', N'0')
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3446, 0, N'草稿', N'0', N'mes_pro_task_status', 0, N'', N'', NULL, N'1', N'2026-04-16 09:47:00', N'1', N'2026-04-16 09:47:00', N'0')
|
||||
GO
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, N'已完æˆ', N'4', N'mes_pro_task_status', 0, N'', N'', NULL, N'1', N'2026-04-16 09:47:00', N'1', N'2026-04-16 09:47:00', N'0')
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3447, 1, N'已完成', N'4', N'mes_pro_task_status', 0, N'', N'', NULL, N'1', N'2026-04-16 09:47:00', N'1', N'2026-04-16 09:47:00', N'0')
|
||||
GO
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, N'已喿¶ˆ', N'5', N'mes_pro_task_status', 0, N'', N'', NULL, N'1', N'2026-04-16 09:47:00', N'1', N'2026-04-16 09:47:00', N'0')
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3448, 2, N'已取消', N'5', N'mes_pro_task_status', 0, N'', N'', NULL, N'1', N'2026-04-16 09:47:00', N'1', N'2026-04-16 09:47:00', N'0')
|
||||
GO
|
||||
SET IDENTITY_INSERT system_dict_data OFF
|
||||
GO
|
||||
|
|
@ -13915,4 +13915,3 @@ GO
|
|||
COMMIT
|
||||
GO
|
||||
-- @formatter:on
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package cn.iocoder.yudao.module.bpm.enums.task;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 附件类型枚举
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum BpmAttachmentTypeEnum {
|
||||
|
||||
TASK_ATTACHMENT("1", "用户任务附件");
|
||||
|
||||
/**
|
||||
* 操作类型
|
||||
* <p>
|
||||
* 由于 BPM attachment 类型为 String,所以这里就不使用 Integer
|
||||
*/
|
||||
private final String type;
|
||||
/**
|
||||
* 操作名字
|
||||
*/
|
||||
private final String name;
|
||||
}
|
||||
|
|
@ -107,6 +107,9 @@ public class BpmApprovalDetailRespVO {
|
|||
@Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
|
||||
private String signPicUrl;
|
||||
|
||||
@Schema(description = "附件", example = "[https://test.yudao.iocoder.cn/20260609/test.txt]")
|
||||
private List<String> attachments;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ public class BpmTaskApproveReqVO {
|
|||
@Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
|
||||
private String signPicUrl;
|
||||
|
||||
@Schema(description = "附件", example = "[https://test.yudao.iocoder.cn/20260609/test.txt]")
|
||||
private List<String> attachments;
|
||||
|
||||
@Schema(description = "变量实例(动态表单)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Map<String, Object> variables;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 不通过流程任务的 Request VO")
|
||||
@Data
|
||||
public class BpmTaskRejectReqVO {
|
||||
|
|
@ -15,4 +18,7 @@ public class BpmTaskRejectReqVO {
|
|||
@Schema(description = "审批意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "不错不错!")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "附件", example = "[https://test.yudao.iocoder.cn/20260609/test.txt]")
|
||||
private List<String> attachments;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
|||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
|
|
@ -21,7 +22,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
|
|||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
|
|
@ -34,6 +34,7 @@ import org.flowable.bpmn.model.BpmnModel;
|
|||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.engine.task.Attachment;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.mapstruct.Mapper;
|
||||
|
|
@ -82,7 +83,7 @@ public interface BpmProcessInstanceConvert {
|
|||
if (CollUtil.isNotEmpty(respVO.getTasks())) {
|
||||
respVO.getTasks().forEach(task -> {
|
||||
AdminUserRespDTO assigneeUser = userMap.get(task.getAssignee());
|
||||
if (assigneeUser!= null) {
|
||||
if (assigneeUser != null) {
|
||||
task.setAssigneeUser(BeanUtils.toBean(assigneeUser, UserSimpleBaseVO.class));
|
||||
MapUtils.findAndThen(deptMap, assigneeUser.getDeptId(), dept -> task.getAssigneeUser().setDeptName(dept.getName()));
|
||||
}
|
||||
|
|
@ -157,7 +158,7 @@ public interface BpmProcessInstanceConvert {
|
|||
// 基本信息
|
||||
respVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmProcessInstanceRespVO.class, o -> o
|
||||
.setStatus(FlowableUtils.getProcessInstanceStatus(processInstance)))
|
||||
.setStartUser(buildUser(processInstance.getStartUserId(), userMap, deptMap)));
|
||||
.setStartUser(buildUser(processInstance.getStartUserId(), userMap, deptMap)));
|
||||
respVO.setTasks(convertList(taskInstances, task -> BeanUtils.toBean(task, BpmTaskRespVO.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
|
||||
.setAssigneeUser(buildUser(task.getAssignee(), userMap, deptMap))
|
||||
|
|
@ -200,13 +201,14 @@ public interface BpmProcessInstanceConvert {
|
|||
return userVO;
|
||||
}
|
||||
|
||||
default BpmApprovalDetailRespVO.ActivityNodeTask buildApprovalTaskInfo(HistoricTaskInstance task) {
|
||||
default BpmApprovalDetailRespVO.ActivityNodeTask buildApprovalTaskInfo(HistoricTaskInstance task, List<Attachment> attachments) {
|
||||
if (task == null) {
|
||||
return null;
|
||||
}
|
||||
return BeanUtils.toBean(task, BpmApprovalDetailRespVO.ActivityNodeTask.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
|
||||
.setSignPicUrl(FlowableUtils.getTaskSignPicUrl(task));
|
||||
.setSignPicUrl(FlowableUtils.getTaskSignPicUrl(task))
|
||||
.setAttachments(convertList(attachments, Attachment::getUrl));
|
||||
}
|
||||
|
||||
default Set<Long> parseUserIds(HistoricProcessInstance processInstance,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import cn.iocoder.yudao.module.bpm.dal.redis.BpmProcessIdRedisDAO;
|
|||
import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmAttachmentTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
||||
|
|
@ -57,6 +58,7 @@ import org.flowable.engine.repository.ProcessDefinition;
|
|||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.engine.runtime.ProcessInstanceBuilder;
|
||||
import org.flowable.engine.task.Attachment;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
|
@ -404,8 +406,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
// 遍历 tasks 列表,只处理已结束的 UserTask
|
||||
// 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点
|
||||
List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null);
|
||||
// 获取已完成节点的附件
|
||||
Set<String> endTaskIds = convertSet(endTasks, HistoricTaskInstance::getId);
|
||||
List<Attachment> attachments = taskService.getAttachments(historicProcessInstance.getId(), endTaskIds, BpmAttachmentTypeEnum.TASK_ATTACHMENT);
|
||||
Map<String, List<Attachment>> taskAttachmentMap = convertMultiMap(attachments, Attachment::getTaskId);
|
||||
List<ActivityNode> approvalNodes = convertList(endTasks, task -> {
|
||||
FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||
List<Attachment> taskAttachments = taskAttachmentMap.get(task.getId());
|
||||
ActivityNode activityNode = new ActivityNode().setId(task.getTaskDefinitionKey()).setName(task.getName())
|
||||
.setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey())
|
||||
? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
|
||||
|
|
@ -414,7 +421,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
.setStatus(getEndActivityNodeStatus(task))
|
||||
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
|
||||
.setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
|
||||
.setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
|
||||
.setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task, taskAttachments)));
|
||||
// 如果是取消状态,则跳过
|
||||
if (BpmTaskStatusEnum.isCancelStatus(activityNode.getStatus())) {
|
||||
return null;
|
||||
|
|
@ -528,14 +535,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
if (task == null) {
|
||||
continue;
|
||||
}
|
||||
activityNode.getTasks().add(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task));
|
||||
activityNode.getTasks().add(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task, null));
|
||||
// 加签子任务,需要过滤掉已经完成的加签子任务
|
||||
List<HistoricTaskInstance> childrenTasks = filterList(
|
||||
taskService.getAllChildrenTaskListByParentTaskId(activity.getTaskId(), tasks),
|
||||
childTask -> childTask.getEndTime() == null);
|
||||
if (CollUtil.isNotEmpty(childrenTasks)) {
|
||||
activityNode.getTasks().addAll(
|
||||
convertList(childrenTasks, BpmProcessInstanceConvert.INSTANCE::buildApprovalTaskInfo));
|
||||
convertList(childrenTasks, item->BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(item, null)));
|
||||
}
|
||||
}
|
||||
// 处理每个任务的 candidateUsers 属性:如果是依次审批,需要预测它的后续审批人。因为 Task 是审批完一个,创建一个新的 Task
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmAttachmentTypeEnum;
|
||||
import jakarta.validation.Valid;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.task.Attachment;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskInfo;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
|
|
@ -14,6 +16,7 @@ import org.flowable.task.api.history.HistoricTaskInstance;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 流程任务实例 Service 接口
|
||||
|
|
@ -184,6 +187,17 @@ public interface BpmTaskService {
|
|||
*/
|
||||
List<HistoricTaskInstance> getFinishedTaskListByProcessInstanceIdWithoutCancel(String processInstanceId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据条件获取附件
|
||||
*
|
||||
* @param processInstanceId 流程 id
|
||||
* @param taskIds 任务 id 集合
|
||||
* @param attachmentType 附件类型
|
||||
* @return 附件集合
|
||||
*/
|
||||
List<Attachment> getAttachments(String processInstanceId, Set<String> taskIds, BpmAttachmentTypeEnum attachmentType);
|
||||
|
||||
// ========== Update 写入相关方法 ==========
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.task;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
|
|
@ -19,10 +20,7 @@ import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
|
|||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.*;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.*;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
|
||||
|
|
@ -49,6 +47,7 @@ import org.flowable.engine.history.HistoricActivityInstance;
|
|||
import org.flowable.engine.runtime.ActivityInstance;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.engine.task.Attachment;
|
||||
import org.flowable.task.api.DelegationState;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskInfo;
|
||||
|
|
@ -510,6 +509,18 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
.orderByHistoricTaskInstanceStartTime().asc().list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Attachment> getAttachments(String processInstanceId, Set<String> taskIds, BpmAttachmentTypeEnum attachmentType) {
|
||||
List<Attachment> result = taskService.getProcessInstanceAttachments(processInstanceId);
|
||||
if (CollUtil.isNotEmpty(taskIds)) {
|
||||
result = filterList(result, attachment -> taskIds.contains(attachment.getTaskId()));
|
||||
}
|
||||
if (attachmentType != null) {
|
||||
result = filterList(result, attachment -> attachmentType.getType().equals(attachment.getType()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定用户,是否是当前任务的审批人
|
||||
*
|
||||
|
|
@ -592,6 +603,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
// 2.2 添加评论
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
|
||||
BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason()));
|
||||
// 2.3 添加附件
|
||||
if (CollUtil.isNotEmpty(reqVO.getAttachments())) {
|
||||
reqVO.getAttachments().forEach(attachment -> taskService.createAttachment(BpmAttachmentTypeEnum.TASK_ATTACHMENT.getType(),
|
||||
task.getId(), task.getProcessInstanceId(), FileUtil.getName(URLUtil.getPath(attachment)), null, attachment));
|
||||
}
|
||||
|
||||
// 3. 设置流程变量。如果流程变量前端传空,需要从历史实例中获取,原因:前端表单如果在当前节点无可编辑的字段时 variables 一定会为空
|
||||
// 场景一:A 节点发起,B 节点表单无可编辑字段,审批通过时,C 节点需要流程变量获取下一个执行节点,但因为 B 节点无可编辑的字段,variables 为空,流程可能出现问题。
|
||||
|
|
@ -817,7 +833,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
// 2.2 添加流程评论
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
|
||||
BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
|
||||
// 2.3 如果当前任务时被加签的,则加它的根任务也标记成未通过
|
||||
// 2.3 添加附件
|
||||
if (CollUtil.isNotEmpty(reqVO.getAttachments())) {
|
||||
reqVO.getAttachments().forEach(attachment -> taskService.createAttachment(BpmAttachmentTypeEnum.TASK_ATTACHMENT.getType(),
|
||||
task.getId(), task.getProcessInstanceId(), FileUtil.getName(URLUtil.getPath(attachment)), null, attachment));
|
||||
}
|
||||
|
||||
// 2.4 如果当前任务时被加签的,则加它的根任务也标记成未通过
|
||||
// 疑问:为什么要标记未通过呢?
|
||||
// 回答:例如说 A 任务被向前加签除 B 任务时,B 任务被审批不通过,此时 A 会被取消。而 yudao-ui-admin-vue3 不展示“已取消”的任务,导致展示不出审批不通过的细节。
|
||||
if (task.getParentTaskId() != null) {
|
||||
|
|
@ -921,7 +943,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
* @param reqVO 前端参数封装
|
||||
*/
|
||||
public void returnTask(Long userId, BpmnModel bpmnModel, Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
|
||||
// 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveExecutionsToSingleActivityId 回撤
|
||||
// 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveActivityIdsToSingleActivityId 回撤
|
||||
// 1.1 获取所有正常进行的任务节点 Key
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
|
||||
List<String> runTaskKeyList = convertList(taskList, Task::getTaskDefinitionKey);
|
||||
|
|
@ -929,16 +951,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
// 为什么不直接使用 runTaskKeyList 呢?因为可能存在多个审批分支,例如说:A -> B -> C 和 D -> F,而只要 C 撤回到 A,需要排除掉 F
|
||||
List<UserTask> returnUserTaskList = BpmnModelUtils.iteratorFindChildUserTasks(targetElement, runTaskKeyList, null, null);
|
||||
List<String> returnTaskKeyList = convertList(returnUserTaskList, UserTask::getId);
|
||||
List<String> runExecutionIds = new ArrayList<>();
|
||||
// 2. 给当前要被退回的 task 数组,设置退回意见
|
||||
taskList.forEach(task -> {
|
||||
// 需要排除掉,不需要设置退回意见的任务
|
||||
if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
|
||||
return;
|
||||
}
|
||||
if (task.getExecutionId() != null) {
|
||||
runExecutionIds.add(task.getExecutionId());
|
||||
}
|
||||
// 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务
|
||||
if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记
|
||||
// 2.1.1 添加评论
|
||||
|
|
@ -955,21 +973,17 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
Set<String> needSimulateTaskDefinitionKeys = getNeedSimulateTaskDefinitionKeys(bpmnModel, currentTask, targetElement);
|
||||
|
||||
// 4. 执行驳回
|
||||
// 4.1 校验是否有可回撤的 execution,避免 moveExecutionsToSingleActivityId 传入空集合时 Flowable 内部报错
|
||||
if (CollUtil.isEmpty(runExecutionIds)) {
|
||||
throw exception(TASK_RETURN_FAIL_SOURCE_TARGET_ERROR);
|
||||
}
|
||||
// 4.2 执行驳回
|
||||
// ① 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId。原因:当多实例任务回退的时候有问题。
|
||||
// 相关 issue: https://github.com/flowable/flowable-engine/issues/3944
|
||||
// ② flowable 7.2.0 版本后,继续使用 moveActivityIdsToSingleActivityId 方法。原因:flowable 7.2.0 版本修复了该问题。
|
||||
// 相关 issue:https://github.com/YunaiV/ruoyi-vue-pro/issues/1018
|
||||
// ③ moveActivityIdsToSingleActivityId 使用遇到问题, 相关 issue https://gitee.com/zhijiantianya/yudao-cloud/issues/IJM8MS
|
||||
// 改成 moveExecutionsToSingleActivityId 好像并没有遇到 ② 提到的超时提醒失效的问题。暂时先改回 moveExecutionsToSingleActivityId
|
||||
// 目前还有的相关问题 https://t.zsxq.com/z4d9i。 估计需要升级 flowable 8 版本试试
|
||||
// ④ moveExecutionsToSingleActivityId 回退多实例的时候不会去删除多实例根, 应改成 moveActivityIdsToSingleActivityId
|
||||
// flowable 8.0.0 修复上面相关问题, 还修复了并行分支回退的问题 https://t.zsxq.com/z4d9i。
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(currentTask.getProcessInstanceId())
|
||||
.moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey())
|
||||
.moveActivityIdsToSingleActivityId(returnTaskKeyList, reqVO.getTargetTaskDefinitionKey())
|
||||
// 设置需要预测的任务 ids 的流程变量,用于辅助预测
|
||||
.processVariable(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskDefinitionKeys)
|
||||
// 设置流程变量节点退回标记, 用于退回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略,导致自动通过
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
|
@ -47,13 +48,13 @@ public class AppAfterSaleController {
|
|||
|
||||
@PostMapping(value = "/create")
|
||||
@Operation(summary = "申请售后")
|
||||
public CommonResult<Long> createAfterSale(@RequestBody AppAfterSaleCreateReqVO createReqVO) {
|
||||
public CommonResult<Long> createAfterSale(@Valid @RequestBody AppAfterSaleCreateReqVO createReqVO) {
|
||||
return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping(value = "/delivery")
|
||||
@Operation(summary = "退回货物")
|
||||
public CommonResult<Boolean> deliveryAfterSale(@RequestBody AppAfterSaleDeliveryReqVO deliveryReqVO) {
|
||||
public CommonResult<Boolean> deliveryAfterSale(@Valid @RequestBody AppAfterSaleDeliveryReqVO deliveryReqVO) {
|
||||
afterSaleService.deliveryAfterSale(getLoginUserId(), deliveryReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public final class MesBizTypeConstants {
|
|||
public static final int WM_STOCK = 106; // 库存:MesWmMaterialStockDO
|
||||
public static final int WM_BATCH = 107; // 批次:MesWmBatchDO
|
||||
public static final int WM_TRANSACTION = 108; // 库存事务流水:MesWmTransactionDO
|
||||
public static final int WM_SN = 109; // SN 码:MesWmSnDO
|
||||
public static final int WM_ITEM_RECEIPT_IN = 110; // 采购入库:MesWmItemReceiptDO
|
||||
public static final int WM_TRANSFER_OUT = 111; // 调拨出库:MesWmTransferDO
|
||||
public static final int WM_TRANSFER_IN = 112; // 调拨入库:MesWmTransferDO
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public enum BarcodeBizTypeEnum implements ArrayValuable<Integer> {
|
|||
PACKAGE(MesBizTypeConstants.WM_PACKAGE, "装箱单"),
|
||||
STOCK(MesBizTypeConstants.WM_STOCK, "库存"),
|
||||
BATCH(MesBizTypeConstants.WM_BATCH, "批次"),
|
||||
SN(MesBizTypeConstants.WM_SN, "SN 码"),
|
||||
PROCARD(MesBizTypeConstants.PRO_CARD, "流转卡"),
|
||||
WORKORDER(MesBizTypeConstants.PRO_WORKORDER, "工单"),
|
||||
TRANSORDER(MesBizTypeConstants.PRO_TRANS_ORDER, "流转单"),
|
||||
|
|
|
|||
|
|
@ -65,10 +65,21 @@ public class MesWmSnController {
|
|||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return success(PageResult.empty(pageResult.getTotal()));
|
||||
}
|
||||
buildGroupItemInfo(pageResult.getList());
|
||||
buildSnGroupItemVO(pageResult.getList());
|
||||
return success(pageResult);
|
||||
}
|
||||
|
||||
@GetMapping("/list-by-uuid")
|
||||
@Operation(summary = "获得批次 SN 码明细列表")
|
||||
@Parameter(name = "uuid", description = "批次 UUID", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('mes:wm-sn:query')")
|
||||
public CommonResult<List<MesWmSnRespVO>> getSnListByUuid(
|
||||
@RequestParam("uuid") @NotBlank(message = "批次 UUID 不能为空") String uuid) {
|
||||
List<MesWmSnRespVO> list = BeanUtils.toBean(snService.getSnListByUuid(uuid), MesWmSnRespVO.class);
|
||||
buildSnItemVO(list);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete-batch")
|
||||
@Operation(summary = "批量删除 SN 码(按批次 UUID)")
|
||||
@Parameter(name = "uuid", description = "批次 UUID", required = true)
|
||||
|
|
@ -85,7 +96,7 @@ public class MesWmSnController {
|
|||
public void exportSnGroupExcel(@Valid MesWmSnPageReqVO reqVO, HttpServletResponse response) throws IOException {
|
||||
reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<MesWmSnGroupRespVO> list = snService.getSnGroupPage(reqVO).getList();
|
||||
buildGroupItemInfo(list);
|
||||
buildSnGroupItemVO(list);
|
||||
ExcelUtils.write(response, "SN码分组.xls", "数据", MesWmSnGroupRespVO.class, list);
|
||||
}
|
||||
|
||||
|
|
@ -96,13 +107,13 @@ public class MesWmSnController {
|
|||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportSnExcel(@RequestParam("uuid") String uuid, HttpServletResponse response) throws IOException {
|
||||
List<MesWmSnRespVO> list = BeanUtils.toBean(snService.getSnListByUuid(uuid), MesWmSnRespVO.class);
|
||||
buildItemInfo(list);
|
||||
buildSnItemVO(list);
|
||||
ExcelUtils.write(response, "SN码明细.xls", "数据", MesWmSnRespVO.class, list);
|
||||
}
|
||||
|
||||
// ==================== 拼接 VO ====================
|
||||
|
||||
private void buildGroupItemInfo(List<MesWmSnGroupRespVO> list) {
|
||||
private void buildSnGroupItemVO(List<MesWmSnGroupRespVO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -115,7 +126,7 @@ public class MesWmSnController {
|
|||
}));
|
||||
}
|
||||
|
||||
private void buildItemInfo(List<MesWmSnRespVO> list) {
|
||||
private void buildSnItemVO(List<MesWmSnRespVO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodePa
|
|||
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* MES 条码清单 Mapper
|
||||
*
|
||||
|
|
@ -43,4 +45,10 @@ public interface MesWmBarcodeMapper extends BaseMapperX<MesWmBarcodeDO> {
|
|||
return selectCount(MesWmBarcodeDO::getConfigId, configId);
|
||||
}
|
||||
|
||||
default int deleteByBizTypeAndBizIds(Integer bizType, Collection<Long> bizIds) {
|
||||
return delete(new LambdaQueryWrapperX<MesWmBarcodeDO>()
|
||||
.eq(MesWmBarcodeDO::getBizType, bizType)
|
||||
.inIfPresent(MesWmBarcodeDO::getBizId, bizIds));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodeSa
|
|||
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* MES 条码清单 Service 接口
|
||||
*
|
||||
|
|
@ -35,6 +37,14 @@ public interface MesWmBarcodeService {
|
|||
*/
|
||||
void deleteBarcode(Long id);
|
||||
|
||||
/**
|
||||
* 基于业务类型和业务编号数组,删除条码
|
||||
*
|
||||
* @param bizType 业务类型
|
||||
* @param bizIds 业务编号数组
|
||||
*/
|
||||
void deleteBarcodeByBizTypeAndBizIds(Integer bizType, Collection<Long> bizIds);
|
||||
|
||||
/**
|
||||
* 获得条码
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.mes.service.wm.barcode;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
|
|
@ -14,6 +15,8 @@ import jakarta.annotation.Resource;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
||||
|
||||
|
|
@ -165,6 +168,14 @@ public class MesWmBarcodeServiceImpl implements MesWmBarcodeService {
|
|||
barcodeMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBarcodeByBizTypeAndBizIds(Integer bizType, Collection<Long> bizIds) {
|
||||
if (CollUtil.isEmpty(bizIds)) {
|
||||
return;
|
||||
}
|
||||
barcodeMapper.deleteByBizTypeAndBizIds(bizType, bizIds);
|
||||
}
|
||||
|
||||
private MesWmBarcodeDO validateBarcodeExists(Long id) {
|
||||
MesWmBarcodeDO barcode = barcodeMapper.selectById(id);
|
||||
if (barcode == null) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.mes.service.wm.sn;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGenerateReqVO;
|
||||
|
|
@ -8,9 +9,11 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnPageReqVO;
|
|||
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO;
|
||||
import cn.iocoder.yudao.module.mes.dal.mysql.wm.sn.MesWmSnMapper;
|
||||
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
|
||||
import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
|
||||
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
|
||||
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
|
||||
import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -20,6 +23,8 @@ import org.springframework.validation.annotation.Validated;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
/**
|
||||
* MES SN 码 Service 实现类
|
||||
*
|
||||
|
|
@ -39,6 +44,8 @@ public class MesWmSnServiceImpl implements MesWmSnService {
|
|||
private MesMdItemService itemService;
|
||||
@Resource
|
||||
private MesProWorkOrderService workOrderService;
|
||||
@Resource
|
||||
private MesWmBarcodeService barcodeService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
|
@ -62,6 +69,9 @@ public class MesWmSnServiceImpl implements MesWmSnService {
|
|||
}
|
||||
// 批量插入
|
||||
snMapper.insertBatch(sns);
|
||||
// 自动生成条码
|
||||
sns.forEach(sn -> barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.SN.getValue(),
|
||||
sn.getId(), sn.getCode(), sn.getCode()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -77,7 +87,16 @@ public class MesWmSnServiceImpl implements MesWmSnService {
|
|||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteSnByUuid(String uuid) {
|
||||
List<MesWmSnDO> sns = snMapper.selectListByUuid(uuid);
|
||||
if (CollUtil.isEmpty(sns)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 删除 SN 码关联的条码记录
|
||||
barcodeService.deleteBarcodeByBizTypeAndBizIds(BarcodeBizTypeEnum.SN.getValue(),
|
||||
convertList(sns, MesWmSnDO::getId));
|
||||
// 删除 SN 码
|
||||
snMapper.deleteByUuid(uuid);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
|
|||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
|
@ -99,8 +100,10 @@ public interface WmsInventoryMapper extends BaseMapperX<WmsInventoryDO> {
|
|||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Long> sortedIds = new ArrayList<>(ids);
|
||||
Collections.sort(sortedIds);
|
||||
return selectList(new LambdaQueryWrapperX<WmsInventoryDO>()
|
||||
.in(WmsInventoryDO::getId, ids)
|
||||
.in(WmsInventoryDO::getId, sortedIds)
|
||||
.orderByAsc(WmsInventoryDO::getId)
|
||||
.last("FOR UPDATE"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,6 +240,46 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest {
|
|||
assertEquals(0, new BigDecimal("-80.00").compareTo(histories.get(2).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_multipleExistingInventoryKeys() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 200L, "7.00"));
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "5.00"));
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "2.00");
|
||||
List<WmsInventoryChangeReqDTO.Item> items = new ArrayList<>(reqDTO.getItems());
|
||||
items.add(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(sku.getId())
|
||||
.setWarehouseId(200L)
|
||||
.setQuantity(new BigDecimal("3.00"))
|
||||
.setPrice(new BigDecimal("100.00"))
|
||||
.setTotalPrice(new BigDecimal("300.00"))
|
||||
.setRemark("测试入库 2"));
|
||||
reqDTO.setItems(items);
|
||||
|
||||
// 调用
|
||||
inventoryService.changeInventory(reqDTO);
|
||||
|
||||
// 断言:多条已存在库存余额分别更新
|
||||
WmsInventoryDO inventory1 = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory1);
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(inventory1.getQuantity()));
|
||||
WmsInventoryDO inventory2 = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 200L);
|
||||
assertNotNull(inventory2);
|
||||
assertEquals(0, new BigDecimal("10.00").compareTo(inventory2.getQuantity()));
|
||||
// 断言:库存流水保持入参明细顺序
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
histories.sort(Comparator.comparing(WmsInventoryHistoryDO::getId));
|
||||
assertEquals(2, histories.size());
|
||||
assertEquals(100L, histories.get(0).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(histories.get(0).getAfterQuantity()));
|
||||
assertEquals(200L, histories.get(1).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(histories.get(1).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("10.00").compareTo(histories.get(1).getAfterQuantity()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_concurrentCreateSameInventoryOnlyOneBalance() throws Exception {
|
||||
// mock 数据
|
||||
|
|
|
|||
Loading…
Reference in New Issue