commit
7fce099986
sql/mysql
yudao-dependencies
yudao-framework
yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo
yudao-spring-boot-starter-mybatis
yudao-spring-boot-starter-web
yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm
controller/admin
definition
task/vo/task
convert
definition
framework/flowable/core
service
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm
dal/mysql/receivable
service/contract
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo
payment
receipt
yudao-module-mall
yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/comment
yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product
controller/app/spu/vo
service/spu
yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion
dal/mysql/discount
service
coupon
discount
yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums
yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade
controller
admin/brokerage
app/aftersale
convert/brokerage
dal/dataobject/order
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member
controller/app/signin
service/point
yudao-module-system
yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums
yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system
dal/mysql/tenant
service/tenant
8
pom.xml
8
pom.xml
|
@ -27,7 +27,7 @@
|
|||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>2.3.0-jdk8-SNAPSHOT</revision>
|
||||
<revision>2.4.0-SNAPSHOT</revision>
|
||||
<!-- Maven 相关 -->
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
|
@ -36,9 +36,9 @@
|
|||
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
|
||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||
<!-- 看看咋放到 bom 里 -->
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
<spring.boot.version>2.7.18</spring.boot.version>
|
||||
<mapstruct.version>1.6.2</mapstruct.version>
|
||||
<lombok.version>1.18.36</lombok.version>
|
||||
<spring.boot.version>3.4.1</spring.boot.version>
|
||||
<mapstruct.version>1.6.3</mapstruct.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
Target Server Version : 80200 (8.2.0)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 23/11/2024 10:16:46
|
||||
Date: 31/12/2024 09:16:18
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
@ -91,7 +91,7 @@ CREATE TABLE `infra_api_error_log` (
|
|||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 21220 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 21226 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_api_error_log
|
||||
|
@ -250,7 +250,7 @@ CREATE TABLE `infra_file` (
|
|||
`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
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1561 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1577 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_file
|
||||
|
@ -1044,7 +1044,7 @@ CREATE TABLE `system_login_log` (
|
|||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3395 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3415 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_login_log
|
||||
|
@ -1175,7 +1175,7 @@ CREATE TABLE `system_menu` (
|
|||
`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
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2912 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2913 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_menu
|
||||
|
@ -1533,7 +1533,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
|||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2164, '配送管理', '', 1, 3, 2072, 'delivery', 'ep:shopping-cart', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:18:02', '1', '2023-09-28 10:58:09', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2165, '快递发货', '', 1, 0, 2164, 'express', 'ep:bicycle', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:22:06', '1', '2023-08-30 21:02:49', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2166, '门店自提', '', 1, 1, 2164, 'pick-up-store', 'ep:add-location', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:23:14', '1', '2023-08-30 21:03:21', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2167, '快递公司', '', 2, 0, 2165, 'express', 'ep:compass', 'mall/trade/delivery/express/index', 'Express', 0, b'1', b'1', b'1', '1', '2023-05-18 09:27:21', '1', '2023-08-30 21:02:59', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2167, '快递公司', '', 2, 0, 2165, 'express', 'ep:compass', 'mall/trade/delivery/express/index', 'Express', 0, b'1', b'1', b'1', '1', '2023-05-18 09:27:21', '1', '2024-11-29 11:20:54', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2168, '快递公司查询', 'trade:delivery:express:query', 3, 1, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2169, '快递公司创建', 'trade:delivery:express:create', 3, 2, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2170, '快递公司更新', 'trade:delivery:express:update', 3, 3, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
|
||||
|
@ -1617,8 +1617,8 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
|||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2348, '分销用户推广人查询', 'trade:brokerage-user:user-query', 3, 2, 2346, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2349, '分销用户推广订单查询', 'trade:brokerage-user:order-query', 3, 3, 2346, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2350, '分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, 2346, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2351, '分销用户修改推广员', 'trade:brokerage-user:update-bind-user', 3, 5, 2346, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2352, '分销用户清除推广员', 'trade:brokerage-user:clear-bind-user', 3, 6, 2346, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2351, '修改推广员', 'trade:brokerage-user:update-bind-user', 3, 5, 2346, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '1', '2024-12-01 14:33:07', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2352, '清除推广员', 'trade:brokerage-user:clear-bind-user', 3, 6, 2346, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '1', '2024-12-01 14:33:14', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2353, '佣金记录', '', 2, 1, 2345, 'brokerage-record', 'fa:money', 'mall/trade/brokerage/record/index', 'TradeBrokerageRecord', 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '1', '2024-02-26 20:33:30', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2354, '佣金记录查询', 'trade:brokerage-record:query', 3, 1, 2353, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2355, '佣金提现', '', 2, 2, 2345, 'brokerage-withdraw', 'fa:credit-card', 'mall/trade/brokerage/withdraw/index', 'TradeBrokerageWithdraw', 0, b'1', b'1', b'1', '', '2023-09-28 02:46:22', '1', '2024-02-26 20:33:35', b'0');
|
||||
|
@ -2044,6 +2044,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
|||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2909, 'IoT 产品物模型更新', 'iot:think-model-function:update', 3, 3, 2906, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-09-25 22:12:09', '', '2024-09-25 22:12:09', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2910, 'IoT 产品物模型删除', 'iot:think-model-function:delete', 3, 4, 2906, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-09-25 22:12:09', '', '2024-09-25 22:12:09', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2911, 'IoT 产品物模型导出', 'iot:think-model-function:export', 3, 5, 2906, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-09-25 22:12:09', '', '2024-09-25 22:12:09', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2912, '创建推广员', 'trade:brokerage-user:create', 3, 7, 2346, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-12-01 14:32:39', '1', '2024-12-01 14:32:39', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -2165,7 +2166,7 @@ CREATE TABLE `system_oauth2_access_token` (
|
|||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_access_token`(`access_token` ASC) USING BTREE,
|
||||
INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 11844 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 12055 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_access_token
|
||||
|
@ -2287,7 +2288,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
|
|||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1696 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1711 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_refresh_token
|
||||
|
@ -2313,7 +2314,7 @@ CREATE TABLE `system_operate_log` (
|
|||
`request_method` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '请求方法名',
|
||||
`request_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '请求地址',
|
||||
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户 IP',
|
||||
`user_agent` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '浏览器 UA',
|
||||
`user_agent` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '浏览器 UA',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
|
@ -3304,7 +3305,7 @@ CREATE TABLE `system_sms_code` (
|
|||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 644 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 645 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_code
|
||||
|
@ -3345,7 +3346,7 @@ CREATE TABLE `system_sms_log` (
|
|||
`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
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1238 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1241 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_log
|
||||
|
@ -3643,7 +3644,7 @@ CREATE TABLE `system_users` (
|
|||
-- Records of system_users
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1,2]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/bf2002b38950c904243be7c825d3f82e29f25a44526583c3fde2ebdff3a87f75.png', 0, '0:0:0:0:0:0:0:1', '2024-11-22 20:11:14', 'admin', '2021-01-05 17:03:47', NULL, '2024-11-22 20:11:14', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1,2]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/bf2002b38950c904243be7c825d3f82e29f25a44526583c3fde2ebdff3a87f75.png', 0, '0:0:0:0:0:0:0:1', '2024-12-28 20:29:58', 'admin', '2021-01-05 17:03:47', NULL, '2024-12-28 20:29:58', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$04$IgUse/ibRzAZ3rngCThmtemJeoh15Ux1TQ2hIMe4iwt/K3LcFHEda', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-11-02 14:00:46', '', '2021-01-07 09:07:17', NULL, '2024-11-02 14:00:46', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-08-11 17:48:12', '', '2021-01-13 23:50:35', NULL, '2024-08-11 17:48:12', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$jDFLttgfik0QqJKAbfhMa.2A9xXoZmAIxakdFJUzkX.MgBKT6ddo6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-09-17 15:05:43', '', '2021-01-21 02:13:53', NULL, '2024-09-17 15:05:43', b'0', 1);
|
||||
|
|
|
@ -14,26 +14,23 @@
|
|||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>2.3.0-jdk8-SNAPSHOT</revision>
|
||||
<revision>2.4.0-SNAPSHOT</revision>
|
||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.framework.version>5.3.39</spring.framework.version>
|
||||
<spring.security.version>5.8.14</spring.security.version>
|
||||
<spring.boot.version>2.7.18</spring.boot.version>
|
||||
<spring.cloud.version>2021.0.9</spring.cloud.version>
|
||||
<spring.cloud.alibaba.version>2021.0.6.1</spring.cloud.alibaba.version>
|
||||
<spring.boot.version>3.4.1</spring.boot.version>
|
||||
<spring.cloud.version>2024.0.0</spring.cloud.version>
|
||||
<spring.cloud.alibaba.version>2023.0.3.2</spring.cloud.alibaba.version>
|
||||
<!-- Web 相关 -->
|
||||
<servlet.versoin>2.5</servlet.versoin>
|
||||
<springdoc.version>1.7.0</springdoc.version>
|
||||
<knife4j.version>4.5.0</knife4j.version>
|
||||
<springdoc.version>2.7.0</springdoc.version>
|
||||
<knife4j.version>4.6.0</knife4j.version>
|
||||
<!-- DB 相关 -->
|
||||
<druid.version>1.2.23</druid.version>
|
||||
<mybatis.version>3.5.16</mybatis.version>
|
||||
<mybatis-plus.version>3.5.7</mybatis-plus.version>
|
||||
<druid.version>1.2.24</druid.version>
|
||||
<mybatis.version>3.5.17</mybatis.version>
|
||||
<mybatis-plus.version>3.5.9</mybatis-plus.version>
|
||||
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
|
||||
<mybatis-plus-join.version>1.4.13</mybatis-plus-join.version>
|
||||
<easy-trans.version>3.0.6</easy-trans.version>
|
||||
<redisson.version>3.36.0</redisson.version>
|
||||
<redisson.version>3.41.0</redisson.version>
|
||||
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
|
||||
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
|
||||
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
|
||||
|
@ -46,8 +43,8 @@
|
|||
<!-- 服务保障相关 -->
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<!-- 监控相关 -->
|
||||
<skywalking.version>8.12.0</skywalking.version>
|
||||
<spring-boot-admin.version>2.7.15</spring-boot-admin.version>
|
||||
<skywalking.version>9.0.0</skywalking.version>
|
||||
<spring-boot-admin.version>3.4.1</spring-boot-admin.version>
|
||||
<opentracing.version>0.33.0</opentracing.version>
|
||||
<!-- Test 测试相关 -->
|
||||
<podam.version>7.2.11.RELEASE</podam.version> <!-- Spring Boot 2.X 最多使用 7.2.11 版本 -->
|
||||
|
@ -58,13 +55,14 @@
|
|||
<!-- 工具类相关 -->
|
||||
<captcha-plus.version>1.0.8</captcha-plus.version>
|
||||
<jsoup.version>1.18.1</jsoup.version>
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
<mapstruct.version>1.6.2</mapstruct.version>
|
||||
<hutool.version>5.8.32</hutool.version>
|
||||
<lombok.version>1.18.36</lombok.version>
|
||||
<mapstruct.version>1.6.3</mapstruct.version>
|
||||
<hutool-5.version>5.8.35</hutool-5.version>
|
||||
<hutool-6.version>6.0.0-M19</hutool-6.version>
|
||||
<easyexcel.verion>4.0.3</easyexcel.verion>
|
||||
<velocity.version>2.4</velocity.version>
|
||||
<velocity.version>2.4.1</velocity.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<guava.version>33.2.1-jre</guava.version>
|
||||
<guava.version>33.4.0-jre</guava.version>
|
||||
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
||||
<commons-net.version>3.11.1</commons-net.version>
|
||||
<jsch.version>0.1.55</jsch.version>
|
||||
|
@ -72,7 +70,7 @@
|
|||
<ip2region.version>2.7.0</ip2region.version>
|
||||
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
||||
<reflections.version>0.10.2</reflections.version>
|
||||
<netty.version>4.1.113.Final</netty.version>
|
||||
<netty.version>4.1.116.Final</netty.version>
|
||||
<!-- 三方云服务相关 -->
|
||||
<commons-io.version>2.17.0</commons-io.version>
|
||||
<commons-compress.version>1.27.1</commons-compress.version>
|
||||
|
@ -192,9 +190,9 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId> <!-- 接口文档 UI:默认 -->
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
<groupId>com.github.xingfudeshi</groupId> <!-- TODO 芋艿:https://github.com/xiaoymin/knife4j/issues/874 -->
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 UI:knife4j -->
|
||||
|
@ -204,7 +202,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 UI:knife4j【网关专属】 -->
|
||||
<artifactId>knife4j-gateway-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
<version>4.5.0</version> <!-- TODO 芋艿:等 4.5.0 => 4.6.0 -->
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
|
@ -234,6 +232,11 @@
|
|||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package cn.iocoder.yudao.framework.common.pojo;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
@ -41,7 +42,7 @@ public class CommonResult<T> implements Serializable {
|
|||
* 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。
|
||||
*
|
||||
* @param result 传入的 result 对象
|
||||
* @param <T> 返回的泛型
|
||||
* @param <T> 返回的泛型
|
||||
* @return 新的 CommonResult 对象
|
||||
*/
|
||||
public static <T> CommonResult<T> error(CommonResult<?> result) {
|
||||
|
@ -49,13 +50,21 @@ public class CommonResult<T> implements Serializable {
|
|||
}
|
||||
|
||||
public static <T> CommonResult<T> error(Integer code, String message) {
|
||||
Assert.isTrue(!GlobalErrorCodeConstants.SUCCESS.getCode().equals(code), "code 必须是错误的!");
|
||||
Assert.notEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), code, "code 必须是错误的!");
|
||||
CommonResult<T> result = new CommonResult<>();
|
||||
result.code = code;
|
||||
result.msg = message;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> error(ErrorCode errorCode, Object... params) {
|
||||
Assert.notEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), errorCode.getCode(), "code 必须是错误的!");
|
||||
CommonResult<T> result = new CommonResult<>();
|
||||
result.code = errorCode.getCode();
|
||||
result.msg = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), params);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> error(ErrorCode errorCode) {
|
||||
return error(errorCode.getCode(), errorCode.getMsg());
|
||||
}
|
||||
|
|
|
@ -74,7 +74,17 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
|
||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||
<groupId>com.github.xingfudeshi</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId> <!-- 接口文档 -->
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.springframework.kafka.annotation.KafkaListener;
|
|||
@RequiredArgsConstructor
|
||||
public class KafkaWebSocketMessageConsumer {
|
||||
|
||||
private final KafkaWebSocketMessageSender rabbitMQWebSocketMessageSender;
|
||||
private final KafkaWebSocketMessageSender kafkaWebSocketMessageSender;
|
||||
|
||||
@RabbitHandler
|
||||
@KafkaListener(
|
||||
|
@ -20,7 +20,7 @@ public class KafkaWebSocketMessageConsumer {
|
|||
// 在 Group 上,使用 UUID 生成其后缀。这样,启动的 Consumer 的 Group 不同,以达到广播消费的目的
|
||||
groupId = "${yudao.websocket.sender-kafka.consumer-group}" + "-" + "#{T(java.util.UUID).randomUUID()}")
|
||||
public void onMessage(KafkaWebSocketMessage message) {
|
||||
rabbitMQWebSocketMessageSender.send(message.getSessionId(),
|
||||
kafkaWebSocketMessageSender.send(message.getSessionId(),
|
||||
message.getUserType(), message.getUserId(),
|
||||
message.getMessageType(), message.getMessageContent());
|
||||
}
|
||||
|
|
|
@ -99,7 +99,8 @@ public class BpmModelController {
|
|||
return null;
|
||||
}
|
||||
byte[] bpmnBytes = modelService.getModelBpmnXML(id);
|
||||
return success(BpmModelConvert.INSTANCE.buildModel(model, bpmnBytes));
|
||||
BpmSimpleModelNodeVO simpleModel = modelService.getSimpleModel(id);
|
||||
return success(BpmModelConvert.INSTANCE.buildModel(model, bpmnBytes, simpleModel));
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
|
@ -109,7 +110,6 @@ public class BpmModelController {
|
|||
return success(modelService.createModel(createRetVO));
|
||||
}
|
||||
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改模型")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
|
||||
|
@ -143,6 +143,7 @@ public class BpmModelController {
|
|||
return success(true);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@PutMapping("/update-bpmn")
|
||||
@Operation(summary = "修改模型的 BPMN")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
|
||||
|
@ -169,6 +170,7 @@ public class BpmModelController {
|
|||
return success(modelService.getSimpleModel(modelId));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@PostMapping("/simple/update")
|
||||
@Operation(summary = "保存仿钉钉流程设计模型")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
@ -35,12 +36,15 @@ public class BpmModelRespVO extends BpmModelMetaInfoVO {
|
|||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String bpmnXml;
|
||||
|
||||
@Schema(description = "可发起的用户数组")
|
||||
private List<UserSimpleBaseVO> startUsers;
|
||||
|
||||
@Schema(description = "BPMN XML")
|
||||
private String bpmnXml;
|
||||
|
||||
@Schema(description = "仿钉钉流程设计模型对象")
|
||||
private BpmSimpleModelNodeVO simpleModel;
|
||||
|
||||
/**
|
||||
* 最新部署的流程定义
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
@ -23,4 +26,11 @@ public class BpmModelSaveReqVO extends BpmModelMetaInfoVO {
|
|||
@Schema(description = "流程分类", example = "1")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "BPMN XML")
|
||||
private String bpmnXml;
|
||||
|
||||
@Schema(description = "仿钉钉流程设计模型对象")
|
||||
@Valid
|
||||
private BpmSimpleModelNodeVO simpleModel;
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ public class BpmTaskPageReqVO extends PageParam {
|
|||
@Schema(description = "流程任务名", example = "芋道")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "流程分类", example = "1")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
|
|
@ -8,6 +8,7 @@ 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.BpmModelRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelSaveReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
|
@ -58,12 +59,13 @@ public interface BpmModelConvert {
|
|||
return result;
|
||||
}
|
||||
|
||||
default BpmModelRespVO buildModel(Model model, byte[] bpmnBytes) {
|
||||
default BpmModelRespVO buildModel(Model model, byte[] bpmnBytes, BpmSimpleModelNodeVO simpleModel) {
|
||||
BpmModelMetaInfoVO metaInfo = parseMetaInfo(model);
|
||||
BpmModelRespVO modelVO = buildModel0(model, metaInfo, null, null, null, null, null);
|
||||
if (ArrayUtil.isNotEmpty(bpmnBytes)) {
|
||||
modelVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnBytes));
|
||||
}
|
||||
modelVO.setSimpleModel(simpleModel);
|
||||
return modelVO;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,12 +124,18 @@ public interface BpmTaskConvert {
|
|||
}
|
||||
|
||||
default BpmTaskRespVO buildTodoTask(Task todoTask, List<Task> childrenTasks,
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting) {
|
||||
return BeanUtils.toBean(todoTask, BpmTaskRespVO.class)
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting,
|
||||
BpmFormDO form) {
|
||||
BpmTaskRespVO bpmTaskRespVO = BeanUtils.toBean(todoTask, BpmTaskRespVO.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(todoTask)).setReason(FlowableUtils.getTaskReason(todoTask))
|
||||
.setButtonsSetting(buttonsSetting)
|
||||
.setChildren(convertList(childrenTasks, childTask -> BeanUtils.toBean(childTask, BpmTaskRespVO.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(childTask))));
|
||||
if (form != null) {
|
||||
bpmTaskRespVO.setFormId(form.getId()).setFormName(form.getName())
|
||||
.setFormConf(form.getConf()).setFormFields(form.getFields());
|
||||
}
|
||||
return bpmTaskRespVO;
|
||||
}
|
||||
|
||||
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
|
||||
|
|
|
@ -54,13 +54,13 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
|
|||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class);
|
||||
if (assigneeUserIds == null) {
|
||||
assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution);
|
||||
execution.setVariable(super.collectionVariable, assigneeUserIds);
|
||||
if (CollUtil.isEmpty(assigneeUserIds)) {
|
||||
// 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过!
|
||||
// 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务
|
||||
// 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时
|
||||
assigneeUserIds = SetUtils.asSet((Long) null);
|
||||
}
|
||||
execution.setVariableLocal(super.collectionVariable, assigneeUserIds);
|
||||
}
|
||||
return assigneeUserIds.size();
|
||||
}
|
||||
|
|
|
@ -43,17 +43,18 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
|
|||
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
|
||||
|
||||
// 第二步,获取任务的所有处理人
|
||||
// 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class);
|
||||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariableLocal(super.collectionVariable, Set.class);
|
||||
if (assigneeUserIds == null) {
|
||||
assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution);
|
||||
execution.setVariable(super.collectionVariable, assigneeUserIds);
|
||||
if (CollUtil.isEmpty(assigneeUserIds)) {
|
||||
// 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过!
|
||||
// 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务
|
||||
// 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时
|
||||
assigneeUserIds = SetUtils.asSet((Long) null);
|
||||
}
|
||||
execution.setVariableLocal(super.collectionVariable, assigneeUserIds);
|
||||
}
|
||||
return assigneeUserIds.size();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import java.util.Set;
|
|||
* @author jason
|
||||
*/
|
||||
@Component
|
||||
public class BpmTaskCandidateFormSDeptLeaderStrategy extends AbstractBpmTaskCandidateDeptLeaderStrategy {
|
||||
public class BpmTaskCandidateFormDeptLeaderStrategy extends AbstractBpmTaskCandidateDeptLeaderStrategy {
|
||||
|
||||
@Override
|
||||
public BpmTaskCandidateStrategyEnum getStrategy() {
|
|
@ -4,10 +4,14 @@ import cn.hutool.core.convert.Convert;
|
|||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -17,6 +21,7 @@ import java.util.Set;
|
|||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrategy {
|
||||
|
||||
@Override
|
||||
|
@ -38,8 +43,16 @@ public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrat
|
|||
@Override
|
||||
public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId, String param,
|
||||
Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
|
||||
Object result = FlowableUtils.getExpressionValue(processVariables, param);
|
||||
return Convert.toSet(Long.class, result);
|
||||
Map<String, Object> variables = processVariables == null ? new HashMap<>() : processVariables;
|
||||
try {
|
||||
Object result = FlowableUtils.getExpressionValue(variables, param);
|
||||
return Convert.toSet(Long.class, result);
|
||||
} catch (FlowableException ex) {
|
||||
// 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常,
|
||||
log.warn("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex);
|
||||
// 不能预测候选人,返回空列表, 避免流程无法进行
|
||||
return Sets.newHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -73,7 +73,6 @@ public class BpmnModelUtils {
|
|||
extensionElement.setName(name);
|
||||
attributes.forEach((key, value) -> {
|
||||
ExtensionAttribute extensionAttribute = new ExtensionAttribute(key, value);
|
||||
extensionAttribute.setNamespace(FLOWABLE_EXTENSIONS_NAMESPACE);
|
||||
extensionElement.addAttribute(extensionAttribute);
|
||||
});
|
||||
element.addExtensionElement(extensionElement);
|
||||
|
@ -278,8 +277,8 @@ public class BpmnModelUtils {
|
|||
}
|
||||
Map<String, String> fieldsPermission = MapUtil.newHashMap();
|
||||
extensionElements.forEach(element -> {
|
||||
String field = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, FORM_FIELD_PERMISSION_ELEMENT_FIELD_ATTRIBUTE);
|
||||
String permission = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, FORM_FIELD_PERMISSION_ELEMENT_PERMISSION_ATTRIBUTE);
|
||||
String field = element.getAttributeValue(null, FORM_FIELD_PERMISSION_ELEMENT_FIELD_ATTRIBUTE);
|
||||
String permission = element.getAttributeValue(null, FORM_FIELD_PERMISSION_ELEMENT_PERMISSION_ATTRIBUTE);
|
||||
if (StrUtil.isNotEmpty(field) && StrUtil.isNotEmpty(permission)) {
|
||||
fieldsPermission.put(field, permission);
|
||||
}
|
||||
|
@ -321,9 +320,9 @@ public class BpmnModelUtils {
|
|||
}
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonSettings = Maps.newHashMapWithExpectedSize(extensionElements.size());
|
||||
extensionElements.forEach(element -> {
|
||||
String id = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_ID_ATTRIBUTE);
|
||||
String displayName = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_DISPLAY_NAME_ATTRIBUTE);
|
||||
String enable = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_ENABLE_ATTRIBUTE);
|
||||
String id = element.getAttributeValue(null, BUTTON_SETTING_ELEMENT_ID_ATTRIBUTE);
|
||||
String displayName = element.getAttributeValue(null, BUTTON_SETTING_ELEMENT_DISPLAY_NAME_ATTRIBUTE);
|
||||
String enable = element.getAttributeValue(null, BUTTON_SETTING_ELEMENT_ENABLE_ATTRIBUTE);
|
||||
if (StrUtil.isNotEmpty(id)) {
|
||||
BpmTaskRespVO.OperationButtonSetting setting = new BpmTaskRespVO.OperationButtonSetting();
|
||||
buttonSettings.put(Integer.valueOf(id), setting.setDisplayName(displayName).setEnable(Boolean.parseBoolean(enable)));
|
||||
|
@ -720,7 +719,7 @@ public class BpmnModelUtils {
|
|||
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
||||
if (matchSequenceFlow == null) {
|
||||
matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()));
|
||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||
// 特殊:没有默认的情况下,并且只有 1 个条件,则认为它是默认的
|
||||
if (matchSequenceFlow == null && gateway.getOutgoingFlows().size() == 1) {
|
||||
matchSequenceFlow = gateway.getOutgoingFlows().get(0);
|
||||
|
@ -742,7 +741,7 @@ public class BpmnModelUtils {
|
|||
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
||||
if (CollUtil.isEmpty(matchSequenceFlows)) {
|
||||
matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
|
||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()));
|
||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||
// 特殊:没有默认的情况下,并且只有 1 个条件,则认为它是默认的
|
||||
if (CollUtil.isEmpty(matchSequenceFlows) && gateway.getOutgoingFlows().size() == 1) {
|
||||
matchSequenceFlows = gateway.getOutgoingFlows();
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Flowable 相关的工具方法
|
||||
|
@ -40,6 +41,17 @@ public class FlowableUtils {
|
|||
Authentication.setAuthenticatedUserId(null);
|
||||
}
|
||||
|
||||
public static <V> V executeAuthenticatedUserId(Long userId, Callable<V> callable) {
|
||||
setAuthenticatedUserId(userId);
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
clearAuthenticatedUserId();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTenantId() {
|
||||
Long tenantId = TenantContextHolder.getTenantId();
|
||||
return tenantId != null ? String.valueOf(tenantId) : ProcessEngineConfiguration.NO_TENANT_ID;
|
||||
|
|
|
@ -83,7 +83,7 @@ public class SimpleModelUtils {
|
|||
|
||||
private static BpmSimpleModelNodeVO buildStartNode() {
|
||||
return new BpmSimpleModelNodeVO().setId(START_EVENT_NODE_ID)
|
||||
.setName(BpmSimpleModelNodeType.START_USER_NODE.getName())
|
||||
.setName(BpmSimpleModelNodeType.START_NODE.getName())
|
||||
.setType(BpmSimpleModelNodeType.START_NODE.getType());
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.definition;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
|
@ -12,6 +13,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.B
|
|||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
|
@ -65,7 +67,7 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
public List<Model> getModelList(String name) {
|
||||
ModelQuery modelQuery = repositoryService.createModelQuery();
|
||||
if (StrUtil.isNotEmpty(name)) {
|
||||
modelQuery.modelNameLike(name);
|
||||
modelQuery.modelNameLike("%" + name + "%");
|
||||
}
|
||||
return modelQuery.list();
|
||||
}
|
||||
|
@ -82,26 +84,54 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
throw exception(MODEL_KEY_EXISTS, createReqVO.getKey());
|
||||
}
|
||||
|
||||
// 2.1 创建流程定义
|
||||
// 2. 创建 Model 对象
|
||||
createReqVO.setSort(System.currentTimeMillis()); // 使用当前时间,作为排序
|
||||
Model model = repositoryService.newModel();
|
||||
BpmModelConvert.INSTANCE.copyToModel(model, createReqVO);
|
||||
model.setTenantId(FlowableUtils.getTenantId());
|
||||
// 2.2 保存流程定义
|
||||
repositoryService.saveModel(model);
|
||||
|
||||
// 3. 保存模型
|
||||
saveModel(model, createReqVO);
|
||||
return model.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
|
||||
public void updateModel(Long userId, @Valid BpmModelSaveReqVO updateReqVO) {
|
||||
public void updateModel(Long userId, BpmModelSaveReqVO updateReqVO) {
|
||||
// 1. 校验流程模型存在
|
||||
Model model = validateModelManager(updateReqVO.getId(), userId);
|
||||
|
||||
// 修改流程定义
|
||||
// 2. 填充 Model 信息
|
||||
BpmModelConvert.INSTANCE.copyToModel(model, updateReqVO);
|
||||
// 更新模型
|
||||
|
||||
// 3. 保存模型
|
||||
saveModel(model, updateReqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存模型的基本信息、流程图
|
||||
*
|
||||
* @param model 模型
|
||||
* @param saveReqVO 保存信息
|
||||
*/
|
||||
private void saveModel(Model model, BpmModelSaveReqVO saveReqVO) {
|
||||
// 1. 保存模型的基础信息
|
||||
repositoryService.saveModel(model);
|
||||
|
||||
// 2. 保存流程图
|
||||
if (ObjUtil.equals(BpmModelTypeEnum.BPMN.getType(), saveReqVO.getType())
|
||||
&& StrUtil.isNotEmpty(saveReqVO.getBpmnXml())) {
|
||||
updateModelBpmnXml(model.getId(), saveReqVO.getBpmnXml());
|
||||
} else if (ObjUtil.equals(BpmModelTypeEnum.SIMPLE.getType(), saveReqVO.getType())
|
||||
&& saveReqVO.getSimpleModel() != null) {
|
||||
// JSON 转换成 bpmnModel
|
||||
BpmnModel bpmnModel = SimpleModelUtils.buildBpmnModel(model.getKey(), model.getName(),
|
||||
saveReqVO.getSimpleModel());
|
||||
// 保存 Bpmn XML
|
||||
updateModelBpmnXml(model.getId(), BpmnModelUtils.getBpmnXml(bpmnModel));
|
||||
// 保存 JSON 数据
|
||||
updateModelSimpleJson(model.getId(), saveReqVO.getSimpleModel());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -110,7 +140,7 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
// 1.1 校验流程模型存在
|
||||
List<Model> models = repositoryService.createModelQuery()
|
||||
.modelTenantId(FlowableUtils.getTenantId()).list();
|
||||
models.removeIf(model ->!ids.contains(model.getId()));
|
||||
models.removeIf(model -> !ids.contains(model.getId()));
|
||||
if (ids.size() != models.size()) {
|
||||
throw exception(MODEL_NOT_EXISTS);
|
||||
}
|
||||
|
@ -173,7 +203,8 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
String simpleJson = getModelSimpleJson(model.getId());
|
||||
|
||||
// 2.1 创建流程定义
|
||||
String definitionId = processDefinitionService.createProcessDefinition(model, metaInfo, bpmnBytes, simpleJson, form);
|
||||
String definitionId = processDefinitionService.createProcessDefinition(model, metaInfo, bpmnBytes, simpleJson,
|
||||
form);
|
||||
|
||||
// 2.2 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
|
||||
updateProcessDefinitionSuspended(model.getDeploymentId());
|
||||
|
@ -220,7 +251,8 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
// 1.1 校验流程模型存在
|
||||
Model model = validateModelManager(id, userId);
|
||||
// 1.2 校验流程定义存在
|
||||
ProcessDefinition definition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
|
||||
ProcessDefinition definition = processDefinitionService
|
||||
.getProcessDefinitionByDeploymentId(model.getDeploymentId());
|
||||
if (definition == null) {
|
||||
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
|
||||
}
|
||||
|
@ -276,7 +308,8 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
}
|
||||
return form;
|
||||
} else {
|
||||
if (StrUtil.isEmpty(metaInfo.getFormCustomCreatePath()) || StrUtil.isEmpty(metaInfo.getFormCustomViewPath())) {
|
||||
if (StrUtil.isEmpty(metaInfo.getFormCustomCreatePath())
|
||||
|| StrUtil.isEmpty(metaInfo.getFormCustomViewPath())) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
|
||||
}
|
||||
return null;
|
||||
|
@ -323,7 +356,8 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
if (oldDefinition == null) {
|
||||
return;
|
||||
}
|
||||
processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
|
||||
processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(),
|
||||
SuspensionState.SUSPENDED.getStateCode());
|
||||
}
|
||||
|
||||
private Model getModelByKey(String key) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
|||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
||||
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.enums.definition.*;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||
|
@ -20,6 +21,7 @@ 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;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
|
||||
|
@ -91,6 +93,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
private BpmModelService modelService;
|
||||
@Resource
|
||||
private BpmMessageService messageService;
|
||||
@Resource
|
||||
private BpmFormService formService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
@ -109,6 +113,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
||||
}
|
||||
if (StrUtil.isNotEmpty(pageVO.getCategory())) {
|
||||
taskQuery.taskCategory(pageVO.getCategory());
|
||||
}
|
||||
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
|
||||
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
|
||||
taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
|
||||
|
@ -153,7 +160,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(todoTask.getProcessDefinitionId());
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting = BpmnModelUtils.parseButtonsSetting(
|
||||
bpmnModel, todoTask.getTaskDefinitionKey());
|
||||
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting);
|
||||
|
||||
// 4. 任务表单
|
||||
BpmFormDO taskForm = null;
|
||||
if (StrUtil.isNotBlank(todoTask.getFormKey())){
|
||||
taskForm = formService.getForm(NumberUtils.parseLong(todoTask.getFormKey()));
|
||||
}
|
||||
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting, taskForm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -188,6 +201,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
||||
}
|
||||
if (StrUtil.isNotEmpty(pageVO.getCategory())) {
|
||||
taskQuery.taskCategory(pageVO.getCategory());
|
||||
}
|
||||
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
|
||||
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
|
||||
taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
|
||||
|
@ -441,7 +457,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
* 判断指定用户,是否是当前任务的加签人
|
||||
*
|
||||
* @param userId 用户 Id
|
||||
* @param task 任务
|
||||
* @param task 任务
|
||||
* @return 是否
|
||||
*/
|
||||
private boolean isAddSignUserTask(Long userId, Task task) {
|
||||
|
@ -669,7 +685,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
reqVO.getTargetTaskDefinitionKey(), task.getProcessDefinitionId());
|
||||
|
||||
// 2. 调用 Flowable 框架的退回逻辑
|
||||
returnTask(task, targetElement, reqVO);
|
||||
returnTask(userId, task, targetElement, reqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -701,11 +717,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
/**
|
||||
* 执行退回逻辑
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param currentTask 当前退回的任务
|
||||
* @param targetElement 需要退回到的目标任务
|
||||
* @param reqVO 前端参数封装
|
||||
*/
|
||||
public void returnTask(Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
|
||||
public void returnTask(Long userId, Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
|
||||
// 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveActivityIdsToSingleActivityId 回撤
|
||||
// 1.1 获取所有正常进行的任务节点 Key
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
|
||||
|
@ -721,22 +738,29 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
|
||||
return;
|
||||
}
|
||||
// 2.1 添加评论
|
||||
taskService.addComment(task.getId(), currentTask.getProcessInstanceId(), BpmCommentTypeEnum.RETURN.getType(),
|
||||
BpmCommentTypeEnum.RETURN.formatComment(reqVO.getReason()));
|
||||
// 2.2 更新 task 状态 + 原因
|
||||
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason());
|
||||
|
||||
// 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务
|
||||
if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记
|
||||
// 2.1.1 添加评论
|
||||
taskService.addComment(task.getId(), currentTask.getProcessInstanceId(), BpmCommentTypeEnum.RETURN.getType(),
|
||||
BpmCommentTypeEnum.RETURN.formatComment(reqVO.getReason()));
|
||||
// 2.1.2 更新 task 状态 + 原因
|
||||
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason());
|
||||
} else { // 情况二:别人的任务,进行 CANCEL 标记
|
||||
processTaskCanceled(task.getId());
|
||||
}
|
||||
});
|
||||
|
||||
// 3. 设置流程变量节点驳回标记:用于驳回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略。导致自动通过
|
||||
runtimeService.setVariable(currentTask.getProcessInstanceId(),
|
||||
String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE);
|
||||
|
||||
// 4. 执行驳回
|
||||
// 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId 原因:
|
||||
// 当多实例任务回退的时候有问题。相关 issue: https://github.com/flowable/flowable-engine/issues/3944
|
||||
List<String> runExecutionIds = convertList(taskList, Task::getExecutionId);
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(currentTask.getProcessInstanceId())
|
||||
.moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多)
|
||||
reqVO.getTargetTaskDefinitionKey()) // targetKey 跳转到的节点(1)
|
||||
.moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey())
|
||||
.changeState();
|
||||
}
|
||||
|
||||
|
@ -1021,14 +1045,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTaskElement);
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
|
||||
/**
|
||||
* 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
|
||||
* 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
|
||||
* 参见 <a href="https://gitee.com/zhijiantianya/yudao-cloud/issues/IB7V7Q">issue</a> 反馈
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(int transactionStatus) {
|
||||
// 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
|
||||
// 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
|
||||
if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) {
|
||||
// 回滚情况,直接返回
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_ROLLED_BACK)) {
|
||||
return;
|
||||
}
|
||||
// 特殊情况:第一个 task 【自动通过】时,第二个任务设置审批人时 transactionStatus 会为 STATUS_UNKNOWN,不知道啥原因
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_UNKNOWN)
|
||||
&& getTask(task.getId()) == null) {
|
||||
return;
|
||||
}
|
||||
// TODO 芋艿:可以后续优化成 getSelf();
|
||||
// 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝
|
||||
if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {
|
||||
// 如果有审批人、或者拥有人,则说明不满足情况一,不自动通过、不自动拒绝
|
||||
|
@ -1036,19 +1068,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
return;
|
||||
}
|
||||
if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
|
||||
getSelf().approveTask(null, new BpmTaskApproveReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));
|
||||
} else if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.REJECT.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
|
||||
getSelf().rejectTask(null, new BpmTaskRejectReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_REJECT.getReason()));
|
||||
}
|
||||
// 特殊情况二:【自动审核】审批类型为自动通过、不通过
|
||||
} else {
|
||||
if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
|
||||
getSelf().approveTask(null, new BpmTaskApproveReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_APPROVE.getReason()));
|
||||
} else if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
|
||||
getSelf().rejectTask(null, new BpmTaskRejectReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_REJECT.getReason()));
|
||||
}
|
||||
}
|
||||
|
@ -1087,8 +1119,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
// 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
|
||||
/**
|
||||
* 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
|
||||
* 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
|
||||
* 参见 <a href="https://gitee.com/zhijiantianya/yudao-cloud/issues/IB7V7Q">issue</a> 反馈
|
||||
*/
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
public void afterCompletion(int transactionStatus) {
|
||||
// 回滚情况,直接返回
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_ROLLED_BACK)) {
|
||||
return;
|
||||
}
|
||||
// 特殊情况:第一个 task 【自动通过】时,第二个任务设置审批人时 transactionStatus 会为 STATUS_UNKNOWN,不知道啥原因
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_UNKNOWN)
|
||||
&& getTask(task.getId()) == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isEmpty(task.getAssignee())) {
|
||||
log.error("[processTaskAssigned][taskId({}) 没有分配到负责人]", task.getId());
|
||||
return;
|
||||
|
|
|
@ -60,12 +60,13 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO
|
|||
// Backlog: 回款提醒类型
|
||||
LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
|
||||
if (CrmReceivablePlanPageReqVO.REMIND_TYPE_NEEDED.equals(pageReqVO.getRemindType())) { // 待回款
|
||||
// 查询条件:未回款 + 提醒时间 <= 当前时间(反过来即当前时间 >= 提醒时间,已经到达提醒的时间点)
|
||||
query.isNull(CrmReceivablePlanDO::getReceivableId) // 未回款
|
||||
.lt(CrmReceivablePlanDO::getReturnTime, beginOfToday) // 已逾期
|
||||
.lt(CrmReceivablePlanDO::getRemindTime, beginOfToday); // 今天开始提醒
|
||||
} else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_EXPIRED.equals(pageReqVO.getRemindType())) { // 已逾期
|
||||
.le(CrmReceivablePlanDO::getRemindTime, beginOfToday); // 今天开始提醒
|
||||
} else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_EXPIRED.equals(pageReqVO.getRemindType())) { // 已逾期
|
||||
// 查询条件:未回款 + 回款时间 < 当前时间(反过来即当前时间 > 回款时间,已经过了回款时间点)
|
||||
query.isNull(CrmReceivablePlanDO::getReceivableId) // 未回款
|
||||
.ge(CrmReceivablePlanDO::getReturnTime, beginOfToday); // 已逾期
|
||||
.lt(CrmReceivablePlanDO::getReturnTime, beginOfToday); // 已逾期
|
||||
} else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款
|
||||
query.isNotNull(CrmReceivablePlanDO::getReceivableId);
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
|
||||
@LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}}",
|
||||
success = CRM_CONTRACT_FOLLOW_UP_SUCCESS)
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
|
||||
public void updateContractFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
|
||||
|
|
|
@ -60,7 +60,8 @@ public class CrmPermissionUtils {
|
|||
}
|
||||
query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType)
|
||||
.eq(CrmPermissionDO::getBizId, bizId)
|
||||
.in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel()));
|
||||
.in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel())
|
||||
.eq(CrmPermissionDO::getUserId,userId));
|
||||
query.ne(ownerUserIdField, userId);
|
||||
}
|
||||
// 场景三:下属负责的数据(下属是负责人)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
@ -11,6 +12,7 @@ import java.util.List;
|
|||
|
||||
@Schema(description = "管理后台 - ERP 付款单 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ErpFinancePaymentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
@ -11,6 +12,7 @@ import java.util.List;
|
|||
|
||||
@Schema(description = "管理后台 - ERP 收款单 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ErpFinanceReceiptRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752")
|
||||
|
|
|
@ -15,8 +15,8 @@ import java.util.Arrays;
|
|||
@AllArgsConstructor
|
||||
public enum ProductCommentAuditStatusEnum implements IntArrayValuable {
|
||||
|
||||
NONE(1, "待审核"),
|
||||
APPROVE(2, "审批通过"),
|
||||
NONE(0, "待审核"),
|
||||
APPROVE(1, "审批通过"),
|
||||
REJECT(2, "审批不通过"),;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentAuditStatusEnum::getStatus).toArray();
|
||||
|
|
|
@ -48,4 +48,9 @@ public class AppProductSpuRespVO {
|
|||
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer salesCount;
|
||||
|
||||
// ========== 物流相关字段 =========
|
||||
|
||||
@Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private List<Integer> deliveryTypes;
|
||||
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
|||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateSpu(ProductSpuSaveReqVO updateReqVO) {
|
||||
// 校验 SPU 是否存在
|
||||
validateSpuExists(updateReqVO.getId());
|
||||
ProductSpuDO spu = validateSpuExists(updateReqVO.getId());
|
||||
// 校验分类、品牌
|
||||
validateCategory(updateReqVO.getCategoryId());
|
||||
brandService.validateProductBrand(updateReqVO.getBrandId());
|
||||
|
@ -87,7 +87,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
|||
productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());
|
||||
|
||||
// 更新 SPU
|
||||
ProductSpuDO updateObj = BeanUtils.toBean(updateReqVO, ProductSpuDO.class);
|
||||
ProductSpuDO updateObj = BeanUtils.toBean(updateReqVO, ProductSpuDO.class).setStatus(spu.getStatus());
|
||||
initSpuFromSkus(updateObj, skuSaveReqList);
|
||||
productSpuMapper.updateById(updateObj);
|
||||
// 批量更新 SKU
|
||||
|
@ -176,10 +176,12 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
|||
productSkuService.deleteSkuBySpuId(id);
|
||||
}
|
||||
|
||||
private void validateSpuExists(Long id) {
|
||||
if (productSpuMapper.selectById(id) == null) {
|
||||
private ProductSpuDO validateSpuExists(Long id) {
|
||||
ProductSpuDO spuDO = productSpuMapper.selectById(id);
|
||||
if (spuDO == null) {
|
||||
throw exception(SPU_NOT_EXISTS);
|
||||
}
|
||||
return spuDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,12 +26,6 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
|
|||
return selectList(DiscountProductDO::getActivityId, activityIds);
|
||||
}
|
||||
|
||||
default List<DiscountProductDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) {
|
||||
return selectList(new LambdaQueryWrapperX<DiscountProductDO>()
|
||||
.in(DiscountProductDO::getSpuId, spuIds)
|
||||
.eq(DiscountProductDO::getActivityStatus, status));
|
||||
}
|
||||
|
||||
default void updateByActivityId(DiscountProductDO discountProductDO) {
|
||||
update(discountProductDO, new LambdaUpdateWrapper<DiscountProductDO>()
|
||||
.eq(DiscountProductDO::getActivityId, discountProductDO.getActivityId()));
|
||||
|
|
|
@ -152,7 +152,7 @@ public class CouponServiceImpl implements CouponService {
|
|||
findAndThen(userCouponIdsMap, userId, couponIds::addAll);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[takeCouponsByAdmin][coupon({}) 优惠券发放失败]", entry, e);
|
||||
log.error("[takeCouponsByAdmin][coupon({}) 优惠券发放失败 userId({})]", entry, userId, e);
|
||||
}
|
||||
}
|
||||
return couponIds;
|
||||
|
@ -270,7 +270,7 @@ public class CouponServiceImpl implements CouponService {
|
|||
}
|
||||
// 校验剩余数量
|
||||
if (ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制
|
||||
&& couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
|
||||
&& couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
|
||||
throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
|
||||
}
|
||||
// 校验"固定日期"的有效期类型是否过期
|
||||
|
|
|
@ -220,11 +220,17 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
|
|||
|
||||
@Override
|
||||
public List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds) {
|
||||
if (CollUtil.isEmpty(activityIds)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return discountProductMapper.selectList(DiscountProductDO::getActivityId, activityIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiscountProductDO> getMatchDiscountProductListBySkuIds(Collection<Long> skuIds) {
|
||||
if (CollUtil.isEmpty(skuIds)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return discountProductMapper.selectListBySkuIdsAndStatusAndNow(skuIds, CommonStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1_011_007_006, "已绑定了推广人");
|
||||
ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1_011_007_007, "下级不能绑定自己的上级");
|
||||
ErrorCode BROKERAGE_USER_LEVEL_NOT_SUPPORT = new ErrorCode(1_011_007_008, "目前只支持 level 小于等于 2");
|
||||
ErrorCode BROKERAGE_CREATE_USER_EXISTS = new ErrorCode(1_011_007_009, "分销用户已存在");
|
||||
|
||||
// ========== 分销提现 模块 1-011-008-000 ==========
|
||||
ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1_011_008_000, "佣金提现记录不存在");
|
||||
|
|
|
@ -47,6 +47,13 @@ public class BrokerageUserController {
|
|||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建分销用户")
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-user:create')")
|
||||
public CommonResult<Long> createBrokerageUser(@Valid @RequestBody BrokerageUserCreateReqVO createReqVO) {
|
||||
return success(brokerageUserService.createBrokerageUser(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update-bind-user")
|
||||
@Operation(summary = "修改推广员")
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-bind-user')")
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 分销用户创建 Request VO")
|
||||
@Data
|
||||
public class BrokerageUserCreateReqVO {
|
||||
|
||||
@Schema(description = "分销用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "分销用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587")
|
||||
private Long bindUserId;
|
||||
|
||||
}
|
|
@ -20,7 +20,7 @@ import java.util.List;
|
|||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 售后日志")
|
||||
@Tag(name = "用户 App - 售后日志")
|
||||
@RestController
|
||||
@RequestMapping("/trade/after-sale-log")
|
||||
@Validated
|
||||
|
|
|
@ -59,6 +59,9 @@ public interface BrokerageUserConvert {
|
|||
}
|
||||
|
||||
default BrokerageUserRespVO copyTo(MemberUserRespDTO source, BrokerageUserRespVO target) {
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
Optional.ofNullable(source).ifPresent(
|
||||
user -> target.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
|
||||
return target;
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Map;
|
|||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("trade_order")
|
||||
@TableName(value = "trade_order", autoResultMap = true)
|
||||
@KeySequence("trade_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
|
|
|
@ -79,7 +79,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
|
|||
TradeConfigDO memberConfig = tradeConfigService.getTradeConfig();
|
||||
// 0 未启用分销功能
|
||||
if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) {
|
||||
log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,userId({})", userId);
|
||||
log.error("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,userId({}) bizType({}) list({})", userId, bizType, list);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package cn.iocoder.yudao.module.trade.service.brokerage;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 分销用户 Service 接口
|
||||
|
@ -108,6 +109,14 @@ public interface BrokerageUserService {
|
|||
*/
|
||||
boolean bindBrokerageUser(@NotNull Long userId, @NotNull Long bindUserId);
|
||||
|
||||
/**
|
||||
* 【管理员】创建分销用户
|
||||
*
|
||||
* @param createReqVO 请求
|
||||
* @return 编号
|
||||
*/
|
||||
Long createBrokerageUser(@Valid BrokerageUserCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 获取用户是否有分销资格
|
||||
*
|
||||
|
|
|
@ -8,9 +8,11 @@ import cn.hutool.core.util.ObjUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
|
||||
|
@ -27,6 +29,7 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
|
|||
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -110,7 +113,6 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
|
|||
if (brokerageUserDO == null) {
|
||||
throw exception(BROKERAGE_USER_NOT_EXISTS);
|
||||
}
|
||||
|
||||
return brokerageUserDO;
|
||||
}
|
||||
|
||||
|
@ -202,6 +204,24 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createBrokerageUser(BrokerageUserCreateReqVO createReqVO) {
|
||||
// 1.1 校验分销用户是否已存在
|
||||
BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(createReqVO.getUserId());
|
||||
if (brokerageUser != null) {
|
||||
throw exception(BROKERAGE_CREATE_USER_EXISTS);
|
||||
}
|
||||
// 1.2 校验是否能绑定用户
|
||||
brokerageUser = BeanUtils.toBean(createReqVO, BrokerageUserDO.class).setId(createReqVO.getUserId())
|
||||
.setBrokerageTime(LocalDateTime.now());
|
||||
validateCanBindUser(brokerageUser, createReqVO.getBindUserId());
|
||||
|
||||
// 2. 创建分销人
|
||||
brokerageUserMapper.insert(brokerageUser);
|
||||
return brokerageUser.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 补全绑定用户的字段
|
||||
*
|
||||
|
|
|
@ -55,7 +55,7 @@ public class CartServiceImpl implements CartService {
|
|||
cartMapper.updateById(new CartDO().setId(cart.getId()).setSelected(true)
|
||||
.setCount(cart.getCount() + count));
|
||||
return cart.getId();
|
||||
// 情况二:不存在,则进行插入
|
||||
// 情况二:不存在,则进行插入
|
||||
} else {
|
||||
cart = new CartDO().setUserId(userId).setSelected(true)
|
||||
.setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count);
|
||||
|
@ -121,7 +121,7 @@ public class CartServiceImpl implements CartService {
|
|||
}
|
||||
|
||||
// 批量标记删除
|
||||
cartMapper.deleteBatchIds(ids);
|
||||
cartMapper.deleteByIds(convertSet(carts, CartDO::getId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -329,7 +329,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
|||
/**
|
||||
* 校验支付订单的合法性
|
||||
*
|
||||
* @param order 交易订单
|
||||
* @param order 交易订单
|
||||
* @param payOrderId 支付订单编号
|
||||
* @return 支付订单
|
||||
*/
|
||||
|
@ -688,8 +688,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
|||
List<TradeOrderItemDO> updateItems = new ArrayList<>();
|
||||
for (int i = 0; i < orderOrderItems.size(); i++) {
|
||||
TradeOrderItemDO item = orderOrderItems.get(i);
|
||||
updateItems.add(new TradeOrderItemDO().setId(item.getId()).setAdjustPrice(item.getAdjustPrice() + dividePrices.get(i))
|
||||
.setPayPrice((item.getPayPrice() - item.getAdjustPrice()) + dividePrices.get(i)));
|
||||
updateItems.add(new TradeOrderItemDO().setId(item.getId())
|
||||
.setAdjustPrice(item.getAdjustPrice() + dividePrices.get(i))
|
||||
.setPayPrice(item.getPayPrice() + dividePrices.get(i)));
|
||||
}
|
||||
tradeOrderItemMapper.updateBatch(updateItems);
|
||||
|
||||
|
@ -747,7 +748,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
|||
}
|
||||
DeliveryPickUpStoreDO deliveryPickUpStore = pickUpStoreService.getDeliveryPickUpStore(order.getPickUpStoreId());
|
||||
if (deliveryPickUpStore == null
|
||||
|| !CollUtil.contains(deliveryPickUpStore.getVerifyUserIds(), userId)) {
|
||||
|| !CollUtil.contains(deliveryPickUpStore.getVerifyUserIds(), userId)) {
|
||||
throw exception(ORDER_PICK_UP_FAIL_NOT_VERIFY_USER);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
|||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
@ -19,6 +21,7 @@ import java.util.List;
|
|||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TradeCouponOrderHandler implements TradeOrderHandler {
|
||||
|
||||
@Resource
|
||||
|
@ -46,11 +49,15 @@ public class TradeCouponOrderHandler implements TradeOrderHandler {
|
|||
return;
|
||||
}
|
||||
// 赠送优惠券
|
||||
List<Long> couponIds = couponApi.takeCouponsByAdmin(order.getGiveCouponTemplateCounts(), order.getUserId()).getCheckedData();
|
||||
if (CollUtil.isEmpty(couponIds)) {
|
||||
return;
|
||||
try {
|
||||
List<Long> couponIds = couponApi.takeCouponsByAdmin(order.getGiveCouponTemplateCounts(), order.getUserId()).getCheckedData();
|
||||
if (CollUtil.isEmpty(couponIds)) {
|
||||
return;
|
||||
}
|
||||
orderUpdateService.updateOrderGiveCouponIds(order.getUserId(), order.getId(), couponIds);
|
||||
} catch (Exception e) {
|
||||
log.error("[afterPayOrder][order({}) 赠送优惠券({})失败,需要手工补偿]", order.getId(), order.getGiveCouponTemplateCounts(), e);
|
||||
}
|
||||
orderUpdateService.updateOrderGiveCouponIds(order.getUserId(), order.getId(), couponIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -122,9 +122,13 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
|
|||
*/
|
||||
private boolean isGlobalExpressFree(TradePriceCalculateRespBO result) {
|
||||
TradeConfigDO config = tradeConfigService.getTradeConfig();
|
||||
return config == null
|
||||
|| Boolean.TRUE.equals(config.getDeliveryExpressFreeEnabled()) // 开启包邮
|
||||
|| result.getPrice().getPayPrice() >= config.getDeliveryExpressFreePrice(); // 满足包邮的价格
|
||||
// 情况一:交易中心配置不存在默认不包邮
|
||||
if (config == null) {
|
||||
return false;
|
||||
}
|
||||
// 情况二:开启了全局包邮 && 满足包邮金额
|
||||
return Boolean.TRUE.equals(config.getDeliveryExpressFreeEnabled()) &&
|
||||
result.getPrice().getPayPrice() >= config.getDeliveryExpressFreePrice();
|
||||
}
|
||||
|
||||
private void calculateDeliveryPrice(List<OrderItem> selectedSkus,
|
||||
|
|
|
@ -21,7 +21,7 @@ import javax.annotation.Resource;
|
|||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - 签到记录")
|
||||
@Tag(name = "用户 App - 签到记录")
|
||||
@RestController
|
||||
@RequestMapping("/member/sign-in/record")
|
||||
@Validated
|
||||
|
|
|
@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.member.service.point;
|
|||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO;
|
||||
|
@ -11,6 +10,7 @@ import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
|||
import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointRecordMapper;
|
||||
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -75,7 +74,9 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService {
|
|||
Integer userPoint = ObjectUtil.defaultIfNull(user.getPoint(), 0);
|
||||
int totalPoint = userPoint + point; // 用户变动后的积分
|
||||
if (totalPoint < 0) {
|
||||
throw exception(USER_POINT_NOT_ENOUGH);
|
||||
log.error("[createPointRecord][userId({}) point({}) bizType({}) bizId({}) {}]", userId, point, bizType, bizId,
|
||||
USER_POINT_NOT_ENOUGH);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 更新用户积分
|
||||
|
|
|
@ -111,6 +111,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在");
|
||||
ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
|
||||
ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用");
|
||||
ErrorCode TENANT_PACKAGE_NAME_DUPLICATE = new ErrorCode(1_002_016_003, "已经存在该名字的租户套餐");
|
||||
|
||||
// ========== 社交用户 1-002-018-000 ==========
|
||||
ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}");
|
||||
|
|
|
@ -29,4 +29,8 @@ public interface TenantPackageMapper extends BaseMapperX<TenantPackageDO> {
|
|||
default List<TenantPackageDO> selectListByStatus(Integer status) {
|
||||
return selectList(TenantPackageDO::getStatus, status);
|
||||
}
|
||||
|
||||
default TenantPackageDO selectByName(String name) {
|
||||
return selectOne(TenantPackageDO::getName, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.system.service.tenant;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
@ -10,6 +11,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
|||
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
@ -19,6 +21,7 @@ import java.util.List;
|
|||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_PACKAGE_NAME_DUPLICATE;
|
||||
|
||||
/**
|
||||
* 租户套餐 Service 实现类
|
||||
|
@ -38,6 +41,8 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
|||
|
||||
@Override
|
||||
public Long createTenantPackage(TenantPackageSaveReqVO createReqVO) {
|
||||
// 校验套餐名是否重复
|
||||
validateTenantPackageNameUnique(null, createReqVO.getName());
|
||||
// 插入
|
||||
TenantPackageDO tenantPackage = BeanUtils.toBean(createReqVO, TenantPackageDO.class);
|
||||
tenantPackageMapper.insert(tenantPackage);
|
||||
|
@ -50,6 +55,8 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
|||
public void updateTenantPackage(TenantPackageSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
TenantPackageDO tenantPackage = validateTenantPackageExists(updateReqVO.getId());
|
||||
// 校验套餐名是否重复
|
||||
validateTenantPackageNameUnique(updateReqVO.getId(), updateReqVO.getName());
|
||||
// 更新
|
||||
TenantPackageDO updateObj = BeanUtils.toBean(updateReqVO, TenantPackageDO.class);
|
||||
tenantPackageMapper.updateById(updateObj);
|
||||
|
@ -111,4 +118,23 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
|||
return tenantPackageMapper.selectListByStatus(status);
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
void validateTenantPackageNameUnique(Long id, String name) {
|
||||
if (StrUtil.isBlank(name)) {
|
||||
return;
|
||||
}
|
||||
TenantPackageDO tenantPackage = tenantPackageMapper.selectByName(name);
|
||||
if (tenantPackage == null) {
|
||||
return;
|
||||
}
|
||||
// 如果 id 为空,说明不用比较是否为相同 id 的用户
|
||||
if (id == null) {
|
||||
throw exception(TENANT_PACKAGE_NAME_DUPLICATE);
|
||||
}
|
||||
if (!tenantPackage.getId().equals(id)) {
|
||||
throw exception(TENANT_PACKAGE_NAME_DUPLICATE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue