Commit 16f2a5b91ab2f9e909a85b238de37a588f0eec57

Authored by puhui999
2 parents 32cca12c fd072b7d

Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product

Showing 114 changed files with 4057 additions and 641 deletions

Too many changes.

To preserve performance only 100 of 114 files are displayed.

sql/mysql/menu.sql 0 → 100644
  1 +-- 菜单 SQL
  2 +INSERT INTO system_menu(
  3 + name, permission, type, sort, parent_id,
  4 + path, icon, component, status, component_name
  5 +)
  6 +VALUES (
  7 + '积分设置管理', '', 2, 0, 2162,
  8 + 'config', '', 'point/config/index', 0, 'PointConfig'
  9 +);
  10 +
  11 +-- 按钮父菜单ID
  12 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  13 +SELECT @parentId := LAST_INSERT_ID();
  14 +
  15 +-- 按钮 SQL
  16 +INSERT INTO system_menu(
  17 + name, permission, type, sort, parent_id,
  18 + path, icon, component, status
  19 +)
  20 +VALUES (
  21 + '积分设置查询', 'point:config:query', 3, 1, @parentId,
  22 + '', '', '', 0
  23 +);
  24 +INSERT INTO system_menu(
  25 + name, permission, type, sort, parent_id,
  26 + path, icon, component, status
  27 +)
  28 +VALUES (
  29 + '积分设置创建', 'point:config:create', 3, 2, @parentId,
  30 + '', '', '', 0
  31 +);
  32 +INSERT INTO system_menu(
  33 + name, permission, type, sort, parent_id,
  34 + path, icon, component, status
  35 +)
  36 +VALUES (
  37 + '积分设置更新', 'point:config:update', 3, 3, @parentId,
  38 + '', '', '', 0
  39 +);
  40 +INSERT INTO system_menu(
  41 + name, permission, type, sort, parent_id,
  42 + path, icon, component, status
  43 +)
  44 +VALUES (
  45 + '积分设置删除', 'point:config:delete', 3, 4, @parentId,
  46 + '', '', '', 0
  47 +);
  48 +INSERT INTO system_menu(
  49 + name, permission, type, sort, parent_id,
  50 + path, icon, component, status
  51 +)
  52 +VALUES (
  53 + '积分设置导出', 'point:config:export', 3, 5, @parentId,
  54 + '', '', '', 0
  55 +);
  56 +
  57 +
  58 +
  59 +-- 菜单 SQL
  60 +INSERT INTO system_menu(
  61 + name, permission, type, sort, parent_id,
  62 + path, icon, component, status, component_name
  63 +)
  64 +VALUES (
  65 + '积分签到规则管理', '', 2, 0, 2162,
  66 + 'sign-in-config', '', 'point/signInConfig/index', 0, 'SignInConfig'
  67 +);
  68 +
  69 +-- 按钮父菜单ID
  70 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  71 +SELECT @parentId := LAST_INSERT_ID();
  72 +
  73 +-- 按钮 SQL
  74 +INSERT INTO system_menu(
  75 + name, permission, type, sort, parent_id,
  76 + path, icon, component, status
  77 +)
  78 +VALUES (
  79 + '积分签到规则查询', 'point:sign-in-config:query', 3, 1, @parentId,
  80 + '', '', '', 0
  81 +);
  82 +INSERT INTO system_menu(
  83 + name, permission, type, sort, parent_id,
  84 + path, icon, component, status
  85 +)
  86 +VALUES (
  87 + '积分签到规则创建', 'point:sign-in-config:create', 3, 2, @parentId,
  88 + '', '', '', 0
  89 +);
  90 +INSERT INTO system_menu(
  91 + name, permission, type, sort, parent_id,
  92 + path, icon, component, status
  93 +)
  94 +VALUES (
  95 + '积分签到规则更新', 'point:sign-in-config:update', 3, 3, @parentId,
  96 + '', '', '', 0
  97 +);
  98 +INSERT INTO system_menu(
  99 + name, permission, type, sort, parent_id,
  100 + path, icon, component, status
  101 +)
  102 +VALUES (
  103 + '积分签到规则删除', 'point:sign-in-config:delete', 3, 4, @parentId,
  104 + '', '', '', 0
  105 +);
  106 +INSERT INTO system_menu(
  107 + name, permission, type, sort, parent_id,
  108 + path, icon, component, status
  109 +)
  110 +VALUES (
  111 + '积分签到规则导出', 'point:sign-in-config:export', 3, 5, @parentId,
  112 + '', '', '', 0
  113 +);
  114 +
  115 +
  116 +-- 菜单 SQL
  117 +INSERT INTO system_menu(
  118 + name, permission, type, sort, parent_id,
  119 + path, icon, component, status, component_name
  120 +)
  121 +VALUES (
  122 + '用户积分记录管理', '', 2, 0, 2162,
  123 + 'record', '', 'point/record/index', 0, 'PointRecord'
  124 +);
  125 +
  126 +-- 按钮父菜单ID
  127 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  128 +SELECT @parentId := LAST_INSERT_ID();
  129 +
  130 +-- 按钮 SQL
  131 +INSERT INTO system_menu(
  132 + name, permission, type, sort, parent_id,
  133 + path, icon, component, status
  134 +)
  135 +VALUES (
  136 + '用户积分记录查询', 'point:record:query', 3, 1, @parentId,
  137 + '', '', '', 0
  138 +);
  139 +INSERT INTO system_menu(
  140 + name, permission, type, sort, parent_id,
  141 + path, icon, component, status
  142 +)
  143 +VALUES (
  144 + '用户积分记录创建', 'point:record:create', 3, 2, @parentId,
  145 + '', '', '', 0
  146 +);
  147 +INSERT INTO system_menu(
  148 + name, permission, type, sort, parent_id,
  149 + path, icon, component, status
  150 +)
  151 +VALUES (
  152 + '用户积分记录更新', 'point:record:update', 3, 3, @parentId,
  153 + '', '', '', 0
  154 +);
  155 +INSERT INTO system_menu(
  156 + name, permission, type, sort, parent_id,
  157 + path, icon, component, status
  158 +)
  159 +VALUES (
  160 + '用户积分记录删除', 'point:record:delete', 3, 4, @parentId,
  161 + '', '', '', 0
  162 +);
  163 +INSERT INTO system_menu(
  164 + name, permission, type, sort, parent_id,
  165 + path, icon, component, status
  166 +)
  167 +VALUES (
  168 + '用户积分记录导出', 'point:record:export', 3, 5, @parentId,
  169 + '', '', '', 0
  170 +);
  171 +
  172 +
  173 +
  174 +-- 菜单 SQL
  175 +INSERT INTO system_menu(
  176 + name, permission, type, sort, parent_id,
  177 + path, icon, component, status, component_name
  178 +)
  179 +VALUES (
  180 + '用户签到积分管理', '', 2, 0, 2162,
  181 + 'sign-in-record', '', 'point/signInRecord/index', 0, 'SignInRecord'
  182 +);
  183 +
  184 +-- 按钮父菜单ID
  185 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  186 +SELECT @parentId := LAST_INSERT_ID();
  187 +
  188 +-- 按钮 SQL
  189 +INSERT INTO system_menu(
  190 + name, permission, type, sort, parent_id,
  191 + path, icon, component, status
  192 +)
  193 +VALUES (
  194 + '用户签到积分查询', 'point:sign-in-record:query', 3, 1, @parentId,
  195 + '', '', '', 0
  196 +);
  197 +INSERT INTO system_menu(
  198 + name, permission, type, sort, parent_id,
  199 + path, icon, component, status
  200 +)
  201 +VALUES (
  202 + '用户签到积分创建', 'point:sign-in-record:create', 3, 2, @parentId,
  203 + '', '', '', 0
  204 +);
  205 +INSERT INTO system_menu(
  206 + name, permission, type, sort, parent_id,
  207 + path, icon, component, status
  208 +)
  209 +VALUES (
  210 + '用户签到积分更新', 'point:sign-in-record:update', 3, 3, @parentId,
  211 + '', '', '', 0
  212 +);
  213 +INSERT INTO system_menu(
  214 + name, permission, type, sort, parent_id,
  215 + path, icon, component, status
  216 +)
  217 +VALUES (
  218 + '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, @parentId,
  219 + '', '', '', 0
  220 +);
  221 +INSERT INTO system_menu(
  222 + name, permission, type, sort, parent_id,
  223 + path, icon, component, status
  224 +)
  225 +VALUES (
  226 + '用户签到积分导出', 'point:sign-in-record:export', 3, 5, @parentId,
  227 + '', '', '', 0
  228 +);
  229 +
  230 +
sql/mysql/point.sql 0 → 100644
  1 +/*
  2 + Navicat Premium Data Transfer
  3 +
  4 + Source Server : docer-master-root(3308)
  5 + Source Server Type : MySQL
  6 + Source Server Version : 80030
  7 + Source Host : 10.211.55.5:3308
  8 + Source Schema : mall
  9 +
  10 + Target Server Type : MySQL
  11 + Target Server Version : 80030
  12 + File Encoding : 65001
  13 +
  14 + Date: 10/06/2023 20:13:57
  15 +*/
  16 +
  17 +SET NAMES utf8mb4;
  18 +SET FOREIGN_KEY_CHECKS = 0;
  19 +
  20 +-- ----------------------------
  21 +-- Table structure for member_point_config
  22 +-- ----------------------------
  23 +DROP TABLE IF EXISTS `member_point_config`;
  24 +CREATE TABLE `member_point_config` (
  25 + `id` int NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  26 + `trade_deduct_enable` int DEFAULT NULL COMMENT '1 开启积分抵扣\n0 关闭积分抵扣',
  27 + `trade_deduct_unit_price` decimal(10,2) DEFAULT NULL COMMENT '积分抵扣,抵扣最低为分 以0.01表示 1积分抵扣0.01元(单位:元)',
  28 + `trade_deduct_max_price` bigint DEFAULT NULL COMMENT '积分抵扣最大值',
  29 + `trade_give_point` bigint DEFAULT NULL COMMENT '1元赠送多少分',
  30 + `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  31 + `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
  32 + `tenant_id` varchar(255) DEFAULT NULL COMMENT '租户id',
  33 + `deleted` int DEFAULT '0' COMMENT '是否被删除 0 未删除 1已删除',
  34 + `creator` varchar(255) DEFAULT NULL COMMENT '创建人',
  35 + `updater` varchar(255) DEFAULT NULL COMMENT '更新人',
  36 + PRIMARY KEY (`id`)
  37 +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='积分设置';
  38 +
  39 +-- ----------------------------
  40 +-- Records of member_point_config
  41 +-- ----------------------------
  42 +BEGIN;
  43 +INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (1, 1, 0.01, 10000, 1, '2023-06-10 10:57:22', '2023-06-10 03:06:58', '1', 1, '1', '1');
  44 +INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (2, 1, 0.01, 10000, 10, '2023-06-10 11:07:12', '2023-06-10 11:07:12', '1', 0, '1', '1');
  45 +INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (3, 1, 12.00, 12, 12, '2023-06-10 16:09:26', '2023-06-10 08:10:53', '1', 1, '1', '1');
  46 +COMMIT;
  47 +
  48 +-- ----------------------------
  49 +-- Table structure for member_point_record
  50 +-- ----------------------------
  51 +DROP TABLE IF EXISTS `member_point_record`;
  52 +CREATE TABLE `member_point_record` (
  53 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  54 + `biz_id` varchar(255) DEFAULT NULL COMMENT '业务编码',
  55 + `biz_type` varchar(255) DEFAULT NULL COMMENT '业务类型',
  56 + `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '1增加 0扣减',
  57 + `title` varchar(255) DEFAULT NULL COMMENT '积分标题',
  58 + `description` varchar(5000) DEFAULT NULL COMMENT '积分描述',
  59 + `point` int DEFAULT NULL COMMENT '积分',
  60 + `total_point` int NOT NULL COMMENT '变动后的积分',
  61 + `status` int DEFAULT NULL COMMENT '状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款)\n',
  62 + `user_id` int DEFAULT NULL COMMENT '用户id',
  63 + `freezing_time` datetime DEFAULT NULL COMMENT '冻结时间',
  64 + `thawing_time` datetime DEFAULT NULL COMMENT '解冻时间',
  65 + `create_time` datetime DEFAULT NULL COMMENT '发生时间',
  66 + `tenant_id` varchar(255) DEFAULT NULL COMMENT '租户',
  67 + `deleted` int DEFAULT '0' COMMENT '是否删除',
  68 + `creator` varchar(255) DEFAULT NULL COMMENT '创建用户',
  69 + `updater` varchar(255) DEFAULT NULL COMMENT '更新用户',
  70 + `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  71 + PRIMARY KEY (`id`),
  72 + KEY `index_userId` (`user_id`),
  73 + KEY `index_title` (`title`) USING BTREE
  74 +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户积分记录';
  75 +
  76 +-- ----------------------------
  77 +-- Records of member_point_record
  78 +-- ----------------------------
  79 +BEGIN;
  80 +INSERT INTO `member_point_record` (`id`, `biz_id`, `biz_type`, `type`, `title`, `description`, `point`, `total_point`, `status`, `user_id`, `freezing_time`, `thawing_time`, `create_time`, `tenant_id`, `deleted`, `creator`, `updater`, `update_time`) VALUES (1, '1', '1', '1', '12', NULL, 212, 12, 1, 12, '2023-06-13 00:00:00', '2023-06-20 00:00:00', '2023-06-10 12:38:48', '1', 1, '1', '1', '2023-06-10 04:42:24');
  81 +INSERT INTO `member_point_record` (`id`, `biz_id`, `biz_type`, `type`, `title`, `description`, `point`, `total_point`, `status`, `user_id`, `freezing_time`, `thawing_time`, `create_time`, `tenant_id`, `deleted`, `creator`, `updater`, `update_time`) VALUES (2, '12', '1', '0', NULL, NULL, 1212, 12, 2, 12, '2023-06-28 00:00:00', NULL, '2023-06-10 12:42:48', '1', 0, '1', '1', '2023-06-10 12:43:04');
  82 +INSERT INTO `member_point_record` (`id`, `biz_id`, `biz_type`, `type`, `title`, `description`, `point`, `total_point`, `status`, `user_id`, `freezing_time`, `thawing_time`, `create_time`, `tenant_id`, `deleted`, `creator`, `updater`, `update_time`) VALUES (3, '12', '1', '1', '12', NULL, 12, 12, 1, 12, '2023-06-27 00:00:00', '2023-06-23 00:00:00', '2023-06-10 20:06:48', '1', 0, '1', '1', '2023-06-10 20:06:48');
  83 +COMMIT;
  84 +
  85 +-- ----------------------------
  86 +-- Table structure for member_sign_in_config
  87 +-- ----------------------------
  88 +DROP TABLE IF EXISTS `member_sign_in_config`;
  89 +CREATE TABLE `member_sign_in_config` (
  90 + `id` int NOT NULL AUTO_INCREMENT COMMENT '规则自增主键',
  91 + `day` int DEFAULT NULL COMMENT '签到第x天',
  92 + `point` int DEFAULT NULL COMMENT '签到天数对应分数',
  93 + `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  94 + `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
  95 + `tenant_id` varchar(255) DEFAULT NULL COMMENT '租户id',
  96 + `deleted` int DEFAULT '0' COMMENT '是否删除',
  97 + `creator` varchar(255) DEFAULT NULL COMMENT '创建人',
  98 + `updater` varchar(255) DEFAULT NULL COMMENT '变更人',
  99 + PRIMARY KEY (`id`)
  100 +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='积分签到规则';
  101 +
  102 +-- ----------------------------
  103 +-- Records of member_sign_in_config
  104 +-- ----------------------------
  105 +BEGIN;
  106 +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (1, 1, 10, '2023-06-10 11:34:43', '2023-06-10 11:34:43', '1', 0, '1', '1');
  107 +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (2, 2, 20, '2023-06-10 11:34:59', '2023-06-10 03:55:35', '1', 1, '1', '1');
  108 +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (3, 7, 1001, '2023-06-10 17:47:45', '2023-06-10 19:54:37', '1', 0, '1', '1');
  109 +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (4, 6, 12121, '2023-06-10 17:47:55', '2023-06-10 19:48:37', '1', 0, '1', '1');
  110 +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (5, 2, 12, '2023-06-10 19:54:52', '2023-06-10 19:54:52', '1', 0, '1', '1');
  111 +COMMIT;
  112 +
  113 +-- ----------------------------
  114 +-- Table structure for member_sign_in_record
  115 +-- ----------------------------
  116 +DROP TABLE IF EXISTS `member_sign_in_record`;
  117 +CREATE TABLE `member_sign_in_record` (
  118 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '签到自增id',
  119 + `user_id` int DEFAULT NULL COMMENT '签到用户',
  120 + `day` int DEFAULT NULL COMMENT '第几天签到',
  121 + `point` int DEFAULT NULL COMMENT '签到的分数',
  122 + `create_time` datetime DEFAULT NULL COMMENT '签到时间',
  123 + `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
  124 + `tenant_id` varchar(255) DEFAULT NULL COMMENT '租户id',
  125 + `deleted` int DEFAULT '0' COMMENT '是否删除',
  126 + `creator` varchar(255) DEFAULT NULL COMMENT '创建人',
  127 + `updater` varchar(255) DEFAULT NULL COMMENT '更新人',
  128 + PRIMARY KEY (`id`)
  129 +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户签到积分';
  130 +
  131 +-- ----------------------------
  132 +-- Records of member_sign_in_record
  133 +-- ----------------------------
  134 +BEGIN;
  135 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (1, 121, 1, 123, '2023-06-10 12:58:18', '2023-06-10 04:59:00', '1', 1, '1', '1');
  136 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (2, 12, 12, 12, '2023-06-10 19:56:39', '2023-06-10 11:56:45', '1', 1, '1', '1');
  137 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (3, 12, 12, 1212, '2023-06-10 20:01:17', '2023-06-10 12:01:23', '1', 1, '1', '1');
  138 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (4, 12, 12, 1212, '2023-06-10 20:01:27', '2023-06-10 20:01:27', '1', 0, '1', '1');
  139 +COMMIT;
  140 +
  141 +SET FOREIGN_KEY_CHECKS = 1;
  142 +
  143 +
  144 +INSERT INTO `mall`.`system_dict_type` ( `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES ( '积分业务类型', 'point_biz_type', 0, '', '1', '2023-06-10 12:15:00', '1', '2023-06-10 04:25:07', b'0', '1970-01-01 00:00:00');
  145 +INSERT INTO `mall`.`system_dict_type` ( `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES ( '积分订单状态', 'point_status', 0, '', '1', '2023-06-10 12:16:27', '1', '2023-06-10 12:16:27', b'0', '1970-01-01 00:00:00');
  146 +
  147 +INSERT INTO `mall`.`system_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 1, '购物', '1', 'point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:27', '1', '2023-06-10 04:25:15', b'0');
  148 +INSERT INTO `mall`.`system_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 2, '签到', '2', 'point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:48', '1', '2023-06-10 04:25:18', b'0');
  149 +INSERT INTO `mall`.`system_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 1, '订单创建', '1', 'point_status', 0, '', '', '', '1', '2023-06-10 12:16:42', '1', '2023-06-10 12:16:42', b'0');
  150 +INSERT INTO `mall`.`system_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 2, '冻结期', '2', 'point_status', 0, '', '', '', '1', '2023-06-10 12:16:58', '1', '2023-06-10 12:16:58', b'0');
  151 +INSERT INTO `mall`.`system_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 3, '完成', '3', 'point_status', 0, '', '', '', '1', '2023-06-10 12:17:07', '1', '2023-06-10 12:17:07', b'0');
  152 +INSERT INTO `mall`.`system_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 4, '失效(订单退款)', '4', 'point_status', 0, '', '', '', '1', '2023-06-10 12:17:21', '1', '2023-06-10 12:17:21', b'0');
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java
@@ -55,7 +55,6 @@ public class DateUtils { @@ -55,7 +55,6 @@ public class DateUtils {
55 return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); 55 return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
56 } 56 }
57 57
58 - @Deprecated  
59 public static Date addTime(Duration duration) { 58 public static Date addTime(Duration duration) {
60 return new Date(System.currentTimeMillis() + duration.toMillis()); 59 return new Date(System.currentTimeMillis() + duration.toMillis());
61 } 60 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/banner/vo/BannerRespVO.java
@@ -4,22 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema; @@ -4,22 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 import lombok.ToString; 5 import lombok.ToString;
6 6
7 -import javax.validation.constraints.NotNull;  
8 -import java.time.LocalDateTime;  
9 -  
10 -/**  
11 - * @author xia  
12 - */  
13 @Schema(description = "管理后台 - Banner Response VO") 7 @Schema(description = "管理后台 - Banner Response VO")
14 @Data 8 @Data
15 @ToString(callSuper = true) 9 @ToString(callSuper = true)
16 public class BannerRespVO extends BannerBaseVO { 10 public class BannerRespVO extends BannerBaseVO {
17 11
18 - @Schema(description = "banner编号", requiredMode = Schema.RequiredMode.REQUIRED)  
19 - @NotNull(message = "banner编号不能为空") 12 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
20 private Long id; 13 private Long id;
21 14
22 - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)  
23 - private LocalDateTime createTime;  
24 -  
25 } 15 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/banner/AppBannerController.java
1 package cn.iocoder.yudao.module.promotion.controller.app.banner; 1 package cn.iocoder.yudao.module.promotion.controller.app.banner;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 -import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO;  
5 -import cn.iocoder.yudao.module.promotion.convert.banner.BannerConvert;  
6 -import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;  
7 -import cn.iocoder.yudao.module.promotion.service.banner.BannerService; 4 +import cn.iocoder.yudao.module.promotion.controller.app.banner.vo.AppBannerRespVO;
8 import io.swagger.v3.oas.annotations.Operation; 5 import io.swagger.v3.oas.annotations.Operation;
9 import io.swagger.v3.oas.annotations.tags.Tag; 6 import io.swagger.v3.oas.annotations.tags.Tag;
10 -import org.springframework.security.access.prepost.PreAuthorize;  
11 import org.springframework.validation.annotation.Validated; 7 import org.springframework.validation.annotation.Validated;
12 import org.springframework.web.bind.annotation.GetMapping; 8 import org.springframework.web.bind.annotation.GetMapping;
13 import org.springframework.web.bind.annotation.RequestMapping; 9 import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.RequestParam;
14 import org.springframework.web.bind.annotation.RestController; 11 import org.springframework.web.bind.annotation.RestController;
15 12
16 -import javax.annotation.Resource; 13 +import java.util.ArrayList;
17 import java.util.List; 14 import java.util.List;
18 15
19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 16 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
20 17
21 -/**  
22 - * @author: XIA  
23 - */  
24 @RestController 18 @RestController
25 -@RequestMapping("/market/banner")  
26 -@Tag(name = "用户APP- 首页Banner") 19 +@RequestMapping("/promotion/banner")
  20 +@Tag(name = "用户 APP - 首页 Banner")
27 @Validated 21 @Validated
28 public class AppBannerController { 22 public class AppBannerController {
29 23
30 - @Resource  
31 - private BannerService bannerService;  
32 -  
33 - // TODO @xia:新建一个 AppBannerRespVO,只返回必要的字段。status 要过滤下。然后 sort 下结果  
34 @GetMapping("/list") 24 @GetMapping("/list")
35 - @Operation(summary = "获得banner列表")  
36 - @PreAuthorize("@ss.hasPermission('market:banner:query')")  
37 - public CommonResult<List<BannerRespVO>> getBannerList() {  
38 - List<BannerDO> list = bannerService.getBannerList();  
39 - return success(BannerConvert.INSTANCE.convertList(list)); 25 + @Operation(summary = "获得 banner 列表")
  26 + // todo @芋艿:swagger 注解,待补全
  27 + // TODO @芋艿:可以增加缓存,提升性能
  28 + // TODO @芋艿:position = 1 时,首页;position = 10 时,拼团活动页
  29 + public CommonResult<List<AppBannerRespVO>> getBannerList(@RequestParam("position") Integer position) {
  30 + List<AppBannerRespVO> bannerList = new ArrayList<>();
  31 + AppBannerRespVO banner1 = new AppBannerRespVO();
  32 + banner1.setUrl("https://www.example.com/link1");
  33 + banner1.setPicUrl("https://api.java.crmeb.net/crmebimage/public/content/2022/08/04/0f78716213f64bfa83f191d51a832cbf73f6axavoy.jpg");
  34 + bannerList.add(banner1);
  35 + AppBannerRespVO banner2 = new AppBannerRespVO();
  36 + banner2.setUrl("https://www.example.com/link2");
  37 + banner2.setPicUrl("https://api.java.crmeb.net/crmebimage/public/content/2023/01/11/be09e755268b43ee90b0db3a3e1b7132r7a6t2wvsm.jpg");
  38 + bannerList.add(banner2);
  39 + return success(bannerList);
40 } 40 }
41 41
42 } 42 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/banner/vo/AppBannerRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.app.banner.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +@Schema(description = "用户 App - Banner Response VO")
  9 +@Data
  10 +public class AppBannerRespVO {
  11 +
  12 + @Schema(description = "跳转链接", requiredMode = Schema.RequiredMode.REQUIRED)
  13 + @NotNull(message = "跳转链接不能为空")
  14 + private String url;
  15 +
  16 + @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED)
  17 + @NotNull(message = "图片地址不能为空")
  18 + private String picUrl;
  19 +
  20 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationController.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java
1 package cn.iocoder.yudao.module.promotion.controller.app.combination; 1 package cn.iocoder.yudao.module.promotion.controller.app.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO; 6 import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO;
5 import io.swagger.v3.oas.annotations.Operation; 8 import io.swagger.v3.oas.annotations.Operation;
6 import io.swagger.v3.oas.annotations.Parameter; 9 import io.swagger.v3.oas.annotations.Parameter;
7 import io.swagger.v3.oas.annotations.tags.Tag; 10 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -21,20 +24,79 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -21,20 +24,79 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 @RestController 24 @RestController
22 @RequestMapping("/promotion/combination-activity") 25 @RequestMapping("/promotion/combination-activity")
23 @Validated 26 @Validated
24 -public class AppCombinationController { 27 +public class AppCombinationActivityController {
  28 +
  29 + @GetMapping("/list")
  30 + @Operation(summary = "获得拼团活动列表", description = "用于小程序首页")
  31 + // TODO 芋艿:增加 Spring Cache
  32 + // TODO 芋艿:缺少 swagger 注解
  33 + public CommonResult<List<AppCombinationActivityRespVO>> getCombinationActivityList(
  34 + @RequestParam(name = "count", defaultValue = "6") Integer count) {
  35 + List<AppCombinationActivityRespVO> activityList = new ArrayList<>();
  36 + AppCombinationActivityRespVO activity1 = new AppCombinationActivityRespVO();
  37 + activity1.setId(1L);
  38 + activity1.setName("618 大拼团");
  39 + activity1.setUserSize(3);
  40 + activity1.setSpuId(2048L);
  41 + activity1.setPicUrl("商品图片地址");
  42 + activity1.setMarketPrice(50);
  43 + activity1.setCombinationPrice(100);
  44 + activityList.add(activity1);
  45 +
  46 + AppCombinationActivityRespVO activity2 = new AppCombinationActivityRespVO();
  47 + activity2.setId(2L);
  48 + activity2.setName("双十一拼团");
  49 + activity2.setUserSize(5);
  50 + activity2.setSpuId(4096L);
  51 + activity2.setPicUrl("商品图片地址");
  52 + activity2.setMarketPrice(100);
  53 + activity2.setCombinationPrice(200);
  54 + activityList.add(activity2);
  55 +
  56 + return success(activityList);
  57 + }
  58 +
  59 + @GetMapping("/page")
  60 + @Operation(summary = "获得拼团活动分页")
  61 + public CommonResult<PageResult<AppCombinationActivityRespVO>> getCombinationActivityPage(PageParam pageParam) {
  62 + List<AppCombinationActivityRespVO> activityList = new ArrayList<>();
  63 + AppCombinationActivityRespVO activity1 = new AppCombinationActivityRespVO();
  64 + activity1.setId(1L);
  65 + activity1.setName("618 大拼团");
  66 + activity1.setUserSize(3);
  67 + activity1.setSpuId(2048L);
  68 + activity1.setPicUrl("商品图片地址");
  69 + activity1.setMarketPrice(50);
  70 + activity1.setCombinationPrice(100);
  71 + activityList.add(activity1);
  72 +
  73 + AppCombinationActivityRespVO activity2 = new AppCombinationActivityRespVO();
  74 + activity2.setId(2L);
  75 + activity2.setName("双十一拼团");
  76 + activity2.setUserSize(5);
  77 + activity2.setSpuId(4096L);
  78 + activity2.setPicUrl("商品图片地址");
  79 + activity2.setMarketPrice(100);
  80 + activity2.setCombinationPrice(200);
  81 + activityList.add(activity2);
  82 +
  83 + return success(new PageResult<>(activityList, 2L));
  84 + }
25 85
26 @GetMapping("/get-detail") 86 @GetMapping("/get-detail")
27 @Operation(summary = "获得拼团活动明细") 87 @Operation(summary = "获得拼团活动明细")
28 @Parameter(name = "id", description = "活动编号", required = true, example = "1024") 88 @Parameter(name = "id", description = "活动编号", required = true, example = "1024")
29 - public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivity(@RequestParam("id") Long id) { 89 + public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivityDetail(@RequestParam("id") Long id) {
30 // TODO 芋艿:如果禁用的时候,需要抛出异常; 90 // TODO 芋艿:如果禁用的时候,需要抛出异常;
31 AppCombinationActivityDetailRespVO obj = new AppCombinationActivityDetailRespVO(); 91 AppCombinationActivityDetailRespVO obj = new AppCombinationActivityDetailRespVO();
32 // 设置其属性的值 92 // 设置其属性的值
33 obj.setId(id); 93 obj.setId(id);
34 obj.setName("晚九点限时秒杀"); 94 obj.setName("晚九点限时秒杀");
35 obj.setStatus(1); 95 obj.setStatus(1);
36 - obj.setStartTime(LocalDateTime.of(2023, 6, 11, 0, 0, 0));  
37 - obj.setEndTime(LocalDateTime.of(2023, 6, 11, 23, 59, 0)); 96 + obj.setStartTime(LocalDateTime.of(2023, 6, 15, 0, 0, 0));
  97 + obj.setEndTime(LocalDateTime.of(2023, 6, 15, 23, 59, 0));
  98 + obj.setUserSize(2);
  99 + obj.setSuccessCount(100);
38 obj.setSpuId(633L); 100 obj.setSpuId(633L);
39 // 创建一个Product对象的列表 101 // 创建一个Product对象的列表
40 List<AppCombinationActivityDetailRespVO.Product> productList = new ArrayList<>(); 102 List<AppCombinationActivityDetailRespVO.Product> productList = new ArrayList<>();
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.app.combination;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.util.date.DateUtils;
  5 +import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordRespVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO;
  8 +import io.swagger.v3.oas.annotations.Operation;
  9 +import io.swagger.v3.oas.annotations.Parameter;
  10 +import io.swagger.v3.oas.annotations.tags.Tag;
  11 +import org.springframework.validation.annotation.Validated;
  12 +import org.springframework.web.bind.annotation.GetMapping;
  13 +import org.springframework.web.bind.annotation.RequestMapping;
  14 +import org.springframework.web.bind.annotation.RequestParam;
  15 +import org.springframework.web.bind.annotation.RestController;
  16 +
  17 +import javax.validation.constraints.Max;
  18 +import java.time.Duration;
  19 +import java.util.ArrayList;
  20 +import java.util.Date;
  21 +import java.util.List;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +
  25 +@Tag(name = "用户 APP - 拼团活动")
  26 +@RestController
  27 +@RequestMapping("/promotion/combination-record")
  28 +@Validated
  29 +public class AppCombinationRecordController {
  30 +
  31 + @GetMapping("/get-summary")
  32 + @Operation(summary = "获得拼团活动的概要信息", description = "用于小程序首页")
  33 + // TODO 芋艿:增加 @Cache 缓存,1 分钟过期
  34 + public CommonResult<AppCombinationRecordSummaryRespVO> getCombinationSummary() {
  35 + AppCombinationRecordSummaryRespVO summary = new AppCombinationRecordSummaryRespVO();
  36 + summary.setUserCount(1024);
  37 + summary.setAvatars(new ArrayList<>());
  38 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLjFK35Wvia9lJKHoXfQuHhk0qZbvpPNxrAiaEKF7aL2k4I8kuqrdTWwliamdPHeyAA7DjAg725X2GIQ/132");
  39 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTK1pXgdj5DvBMwrbe8v3tFibSWeQATEsAibt3fllD8XwJ460P2r6KS3WCQvDefuv1bVpDhNCle6CTCA/132");
  40 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTL7KRGHBE62N0awFyBesmmxiaCicf1fJ7E7UCh6zA8GWlT1QC1zT01gG4OxI7BWDESkdPZ5o7tno4hA/132");
  41 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/ouwtwJycbic2JrCoZjETict0klxd1uRuicRneKk00ewMcCClxVcVHQT91Sh9MJGtwibf1fOicD1WpwSP4icJM6eQq1AA/132");
  42 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/RpUrhwens58qc99OcGs993xL4M5QPOe05ekqF9Eia440kRicAlicicIdQWicHBmy2bzLgHzHguWEzHHxnIgeictL7bLA/132");
  43 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/S4tfqmxc8GZGsKc1K4mnhpvtG16gtMrLnTQfDibhr7jJich9LRI5RQKZDoqEjZM3azMib5nic7F4ZXKMEgYyLO08KA/132");
  44 + summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
  45 + return success(summary);
  46 + }
  47 +
  48 + @GetMapping("/get-head-list")
  49 + @Operation(summary = "获得最近 n 条拼团记录(团长发起的)")
  50 + // TODO @芋艿:注解要补全
  51 + public CommonResult<List<AppCombinationRecordRespVO>> getHeadCombinationRecordList(
  52 + @RequestParam(value = "activityId", required = false) Long activityId,
  53 + @RequestParam("status") Integer status,
  54 + @RequestParam(value = "count", defaultValue = "20") @Max(20) Integer count) {
  55 + List<AppCombinationRecordRespVO> list = new ArrayList<>();
  56 + for (int i = 1; i <= count; i++) {
  57 + AppCombinationRecordRespVO record = new AppCombinationRecordRespVO();
  58 + record.setId((long) i);
  59 + record.setNickname("用户" + i);
  60 + record.setAvatar("头像" + i);
  61 + record.setExpireTime(new Date());
  62 + record.setUserSize(10);
  63 + record.setUserCount(i);
  64 + record.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
  65 + record.setActivityId(1L);
  66 + record.setSpuName("活动:" + i);
  67 + list.add(record);
  68 + }
  69 + return success(list);
  70 + }
  71 +
  72 + @GetMapping("/get-detail")
  73 + @Operation(summary = "获得拼团记录明细")
  74 + @Parameter(name = "id", description = "拼团记录编号", required = true, example = "1024")
  75 + public CommonResult<AppCombinationRecordDetailRespVO> getCombinationRecordDetail(@RequestParam("id") Long id) {
  76 + AppCombinationRecordDetailRespVO detail = new AppCombinationRecordDetailRespVO();
  77 + // 团长
  78 + AppCombinationRecordRespVO headRecord = new AppCombinationRecordRespVO();
  79 + headRecord.setId(1L);
  80 + headRecord.setNickname("用户" + 1);
  81 + headRecord.setAvatar("头像" + 1);
  82 + headRecord.setExpireTime(DateUtils.addTime(Duration.ofDays(1)));
  83 + headRecord.setUserSize(10);
  84 + headRecord.setUserCount(3);
  85 + headRecord.setStatus(1);
  86 + headRecord.setActivityId(10L);
  87 + headRecord.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
  88 + headRecord.setCombinationPrice(100);
  89 + detail.setHeadRecord(headRecord);
  90 + // 团员
  91 + List<AppCombinationRecordRespVO> list = new ArrayList<>();
  92 + for (int i = 1; i <= 2; i++) {
  93 + AppCombinationRecordRespVO record = new AppCombinationRecordRespVO();
  94 + record.setId((long) i);
  95 + record.setNickname("用户" + i);
  96 + record.setAvatar("头像" + i);
  97 + record.setExpireTime(new Date());
  98 + record.setUserSize(10);
  99 + record.setUserCount(i);
  100 + record.setStatus(1);
  101 + list.add(record);
  102 + }
  103 + detail.setMemberRecords(list);
  104 + // 订单编号
  105 + detail.setOrderId(100L);
  106 + return success(detail);
  107 + }
  108 +
  109 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityDetailRespVO.java
@@ -25,18 +25,18 @@ public class AppCombinationActivityDetailRespVO { @@ -25,18 +25,18 @@ public class AppCombinationActivityDetailRespVO {
25 @Schema(description = "活动结束时间", required = true) 25 @Schema(description = "活动结束时间", required = true)
26 private LocalDateTime endTime; 26 private LocalDateTime endTime;
27 27
  28 + @Schema(description = "拼团人数", required = true, example = "3")
  29 + private Integer userSize;
  30 +
  31 + @Schema(description = "成功的拼团数量", required = true, example = "100")
  32 + private Integer successCount;
  33 +
28 @Schema(description = "商品 SPU 编号", required = true, example = "2048") 34 @Schema(description = "商品 SPU 编号", required = true, example = "2048")
29 private Long spuId; 35 private Long spuId;
30 36
31 @Schema(description = "商品信息数组", required = true) 37 @Schema(description = "商品信息数组", required = true)
32 private List<Product> products; 38 private List<Product> products;
33 39
34 - @Schema(description = "成功的拼团记录", required = true)  
35 - private List<Record> successRecords;  
36 -  
37 - @Schema(description = "进行中的拼团记录", required = true)  
38 - private List<Record> runningRecords;  
39 -  
40 @Schema(description = "商品信息") 40 @Schema(description = "商品信息")
41 @Data 41 @Data
42 public static class Product { 42 public static class Product {
@@ -55,13 +55,4 @@ public class AppCombinationActivityDetailRespVO { @@ -55,13 +55,4 @@ public class AppCombinationActivityDetailRespVO {
55 55
56 } 56 }
57 57
58 - @Schema(description = "拼团记录")  
59 - @Data  
60 - public static class Record {  
61 -  
62 - @Schema(description = "拼团记录编号", required = true, example = "1024")  
63 - private Long id;  
64 -  
65 - }  
66 -  
67 } 58 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "用户 App - 拼团活动 Response VO")
  7 +@Data
  8 +public class AppCombinationActivityRespVO {
  9 +
  10 + @Schema(description = "拼团活动编号", required = true, example = "1024")
  11 + private Long id;
  12 +
  13 + @Schema(description = "拼团活动名称", required = true, example = "618 大拼团")
  14 + private String name;
  15 +
  16 + @Schema(description = "拼团人数", required = true, example = "3")
  17 + private Integer userSize;
  18 +
  19 + @Schema(description = "商品 SPU 编号", required = true, example = "2048")
  20 + private Long spuId;
  21 +
  22 + @Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
  23 + private String picUrl;
  24 +
  25 + @Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
  26 + private Integer marketPrice;
  27 +
  28 + @Schema(description = "拼团金额,单位:分", required = true, example = "100") // 从拼团商品里取最低价
  29 + private Integer combinationPrice;
  30 +
  31 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +@Schema(description = "用户 App - 拼团记录详细 Response VO")
  9 +@Data
  10 +public class AppCombinationRecordDetailRespVO {
  11 +
  12 + @Schema(description = "团长的拼团记录", required = true)
  13 + private AppCombinationRecordRespVO headRecord;
  14 +
  15 + @Schema(description = "成员的拼团记录", required = true)
  16 + private List<AppCombinationRecordRespVO> memberRecords;
  17 +
  18 + @Schema(description = "当前用户参团记录对应的订单编号", required = true, example = "1024") // 如果没参团,返回 null
  19 + private Long orderId;
  20 +
  21 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.Date;
  7 +
  8 +@Schema(description = "用户 App - 拼团记录 Response VO")
  9 +@Data
  10 +public class AppCombinationRecordRespVO {
  11 +
  12 + @Schema(description = "拼团记录编号", required = true, example = "1024")
  13 + private Long id;
  14 +
  15 + @Schema(description = "拼团活动编号", required = true, example = "1024")
  16 + private Long activityId;
  17 +
  18 + @Schema(description = "用户昵称", required = true, example = "1024")
  19 + private String nickname;
  20 +
  21 + @Schema(description = "用户头像", required = true, example = "1024")
  22 + private String avatar;
  23 +
  24 + @Schema(description = "过期时间", required = true)
  25 + private Date expireTime;
  26 +
  27 + @Schema(description = "可参团人数", required = true, example = "10")
  28 + private Integer userSize;
  29 +
  30 + @Schema(description = "已参团人数", required = true, example = "5")
  31 + private Integer userCount;
  32 +
  33 + @Schema(description = "拼团状态", required = true, example = "1")
  34 + private Integer status;
  35 +
  36 + @Schema(description = "商品名字", required = true, example = "我是大黄豆")
  37 + private String spuName;
  38 +
  39 + @Schema(description = "商品图片", required = true, example = "https://www.iocoder.cn/1.png")
  40 + private String picUrl;
  41 +
  42 + @Schema(description = "拼团金额,单位:分", required = true, example = "100")
  43 + private Integer combinationPrice;
  44 +
  45 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/record/AppCombinationRecordSummaryRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +@Schema(description = "用户 App - 拼团记录的简要概括 Response VO")
  9 +@Data
  10 +public class AppCombinationRecordSummaryRespVO {
  11 +
  12 + @Schema(description = "拼团用户数量", required = true, example = "1024")
  13 + private Integer userCount;
  14 +
  15 + @Schema(description = "拼团用户头像列表", required = true) // 只返回最近的 7 个
  16 + private List<String> avatars;
  17 +
  18 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/AppSeckillActivitiDetailRespVO.java
@@ -27,9 +27,6 @@ public class AppSeckillActivitiDetailRespVO { @@ -27,9 +27,6 @@ public class AppSeckillActivitiDetailRespVO {
27 @Schema(description = "活动结束时间", required = true) 27 @Schema(description = "活动结束时间", required = true)
28 private LocalDateTime endTime; 28 private LocalDateTime endTime;
29 29
30 -  
31 - private Long successGruopCount;  
32 -  
33 @Schema(description = "商品 SPU 编号", required = true, example = "2048") 30 @Schema(description = "商品 SPU 编号", required = true, example = "2048")
34 private Long spuId; 31 private Long spuId;
35 32
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
@@ -45,19 +45,26 @@ public interface ErrorCodeConstants { @@ -45,19 +45,26 @@ public interface ErrorCodeConstants {
45 // ========== Cart 模块 1011002000 ========== 45 // ========== Cart 模块 1011002000 ==========
46 ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); 46 ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");
47 47
48 - // ========== 物流配送模块 1011003000 ==========  
49 - ErrorCode DELIVERY_EXPRESS_NOT_EXISTS = new ErrorCode(1011003000, "快递公司不存在");  
50 - // TODO @jason:最好每个模块一段哈。express 一个;exmpresstemplate 一个;pickup 一个  
51 - ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011003001, "已经存在该编码的快递公司");  
52 - ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011003002, "运费模板不存在");  
53 - ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011003003, "已经存在该运费模板名");  
54 - ErrorCode DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY = new ErrorCode(1011003004, "计算快递运费时,收件人地址编号为空"); // TODO @jaosn:这个错误码,放到 Price 这块  
55 - ErrorCode PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND = new ErrorCode(1011003005, "找不到到商品对应的运费模板"); // TODO @jaosn:这个错误码,放到 Price 这块  
56 - ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011003006, "快递查询接口异常");  
57 - ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011003007, "快递查询返回失败, 原因:{}");  
58 - ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011003008, "自提门店不存在");  
59 -  
60 - // ========== Price 相关 1011004000 ============  
61 - ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011004000, "支付价格计算异常,原因:价格小于等于 0"); 48 + // ========== Price 相关 1011003000 ============
  49 + ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
  50 + ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY = new ErrorCode(1011003001, "计算快递运费异常,收件人地址编号为空");
  51 + ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
  52 +
  53 + // ========== 物流 Express 模块 1011004000 ==========
  54 + ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在");
  55 + ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011004001, "已经存在该编码的快递公司");
  56 + ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1011004002, "需要接入快递服务商,比如【快递100】");
  57 +
  58 + ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011004101, "快递查询接口异常");
  59 + ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011004102, "快递查询返回失败,原因:{}");
  60 +
  61 + // ========== 物流 Template 模块 1011005000 ==========
  62 + ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011005000, "已经存在该运费模板名");
  63 + ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");
  64 +
  65 + // ========== 物流 PICK_UP 模块 1011006000 ==========
  66 +
  67 + ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
  68 +
62 69
63 } 70 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
@@ -18,6 +18,7 @@ public class AppTradeOrderSettlementReqVO { @@ -18,6 +18,7 @@ public class AppTradeOrderSettlementReqVO {
18 18
19 @NotNull(message = "交易类型不能为空") 19 @NotNull(message = "交易类型不能为空")
20 @InEnum(value = TradeOrderTypeEnum.class, message = "交易类型必须是 {value}") 20 @InEnum(value = TradeOrderTypeEnum.class, message = "交易类型必须是 {value}")
  21 + @Deprecated // TODO 芋艿:后续干掉这个字段,对于前端不需要关注这个
21 private Integer type; 22 private Integer type;
22 23
23 @Schema(description = "商品项数组", required = true) 24 @Schema(description = "商品项数组", required = true)
@@ -30,6 +31,17 @@ public class AppTradeOrderSettlementReqVO { @@ -30,6 +31,17 @@ public class AppTradeOrderSettlementReqVO {
30 @Schema(description = "优惠劵编号", example = "1024") 31 @Schema(description = "优惠劵编号", example = "1024")
31 private Long couponId; 32 private Long couponId;
32 33
  34 + // ========== 秒杀活动相关字段 ==========
  35 + @Schema(description = "秒杀活动编号", example = "1024")
  36 + private Long seckillActivityId;
  37 +
  38 + // ========== 拼团活动相关字段 ==========
  39 + @Schema(description = "拼团活动编号", example = "1024")
  40 + private Long combinationActivityId;
  41 +
  42 + @Schema(description = "拼团团长编号", example = "2048")
  43 + private Long combinationHeadId;
  44 +
33 @Data 45 @Data
34 @Schema(description = "用户 App - 商品项") 46 @Schema(description = "用户 App - 商品项")
35 @Valid 47 @Valid
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java
@@ -6,12 +6,16 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat @@ -6,12 +6,16 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat
6 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; 6 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
7 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; 7 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; 8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
9 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;  
10 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO; 9 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
  10 +import com.google.common.collect.Maps;
11 import org.mapstruct.Mapper; 11 import org.mapstruct.Mapper;
12 import org.mapstruct.factory.Mappers; 12 import org.mapstruct.factory.Mappers;
13 13
14 import java.util.List; 14 import java.util.List;
  15 +import java.util.Map;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
  18 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
15 19
16 @Mapper 20 @Mapper
17 public interface DeliveryExpressTemplateConvert { 21 public interface DeliveryExpressTemplateConvert {
@@ -49,7 +53,7 @@ public interface DeliveryExpressTemplateConvert { @@ -49,7 +53,7 @@ public interface DeliveryExpressTemplateConvert {
49 53
50 DeliveryExpressTemplateChargeDO convertTemplateCharge(DeliveryExpressTemplateUpdateReqVO.ExpressTemplateChargeUpdateVO vo); 54 DeliveryExpressTemplateChargeDO convertTemplateCharge(DeliveryExpressTemplateUpdateReqVO.ExpressTemplateChargeUpdateVO vo);
51 55
52 - DeliveryExpressTemplateChargeBO convertTemplateCharge(DeliveryExpressTemplateChargeDO bean); 56 + DeliveryExpressTemplateRespBO.Charge convertTemplateCharge(DeliveryExpressTemplateChargeDO bean);
53 57
54 default List<DeliveryExpressTemplateChargeDO> convertTemplateChargeList(Long templateId, Integer chargeMode, List<ExpressTemplateChargeBaseVO> list) { 58 default List<DeliveryExpressTemplateChargeDO> convertTemplateChargeList(Long templateId, Integer chargeMode, List<ExpressTemplateChargeBaseVO> list) {
55 return CollectionUtils.convertList(list, vo -> convertTemplateCharge(templateId, chargeMode, vo)); 59 return CollectionUtils.convertList(list, vo -> convertTemplateCharge(templateId, chargeMode, vo));
@@ -61,7 +65,7 @@ public interface DeliveryExpressTemplateConvert { @@ -61,7 +65,7 @@ public interface DeliveryExpressTemplateConvert {
61 65
62 DeliveryExpressTemplateFreeDO convertTemplateFree(DeliveryExpressTemplateUpdateReqVO.ExpressTemplateFreeUpdateVO vo); 66 DeliveryExpressTemplateFreeDO convertTemplateFree(DeliveryExpressTemplateUpdateReqVO.ExpressTemplateFreeUpdateVO vo);
63 67
64 - DeliveryExpressTemplateFreeBO convertTemplateFree(DeliveryExpressTemplateFreeDO bean); 68 + DeliveryExpressTemplateRespBO.Free convertTemplateFree(DeliveryExpressTemplateFreeDO bean);
65 69
66 List<ExpressTemplateChargeBaseVO> convertTemplateChargeList(List<DeliveryExpressTemplateChargeDO> list); 70 List<ExpressTemplateChargeBaseVO> convertTemplateChargeList(List<DeliveryExpressTemplateChargeDO> list);
67 71
@@ -71,4 +75,22 @@ public interface DeliveryExpressTemplateConvert { @@ -71,4 +75,22 @@ public interface DeliveryExpressTemplateConvert {
71 return CollectionUtils.convertList(list, vo -> convertTemplateFree(templateId, vo)); 75 return CollectionUtils.convertList(list, vo -> convertTemplateFree(templateId, vo));
72 } 76 }
73 77
  78 + default Map<Long, DeliveryExpressTemplateRespBO> convertMap(Integer areaId, List<DeliveryExpressTemplateDO> templateList,
  79 + List<DeliveryExpressTemplateChargeDO> chargeList,
  80 + List<DeliveryExpressTemplateFreeDO> freeList) {
  81 + Map<Long, List<DeliveryExpressTemplateChargeDO>> templateIdChargeMap = convertMultiMap(chargeList,
  82 + DeliveryExpressTemplateChargeDO::getTemplateId);
  83 + Map<Long, List<DeliveryExpressTemplateFreeDO>> templateIdFreeMap = convertMultiMap(freeList,
  84 + DeliveryExpressTemplateFreeDO::getTemplateId);
  85 + // 组合运费模板配置 RespBO
  86 + Map<Long, DeliveryExpressTemplateRespBO> result = Maps.newHashMapWithExpectedSize(templateList.size());
  87 + templateList.forEach(template -> {
  88 + DeliveryExpressTemplateRespBO bo = new DeliveryExpressTemplateRespBO()
  89 + .setChargeMode(template.getChargeMode())
  90 + .setCharge(convertTemplateCharge(findFirst(templateIdChargeMap.get(template.getId()), charge -> charge.getAreaIds().contains(areaId))))
  91 + .setFree(convertTemplateFree(findFirst(templateIdFreeMap.get(template.getId()), free -> free.getAreaIds().contains(areaId))));
  92 + result.put(template.getId(), bo);
  93 + });
  94 + return result;
  95 + }
74 } 96 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateChargeMapper.java
@@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery; @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery;
2 2
3 3
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
6 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; 5 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
7 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 6 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
9 import org.apache.ibatis.annotations.Mapper; 7 import org.apache.ibatis.annotations.Mapper;
10 -import org.springframework.stereotype.Repository;  
11 8
  9 +import java.util.Collection;
12 import java.util.List; 10 import java.util.List;
13 11
14 @Mapper 12 @Mapper
@@ -23,6 +21,11 @@ public interface DeliveryExpressTemplateChargeMapper extends BaseMapperX&lt;Deliver @@ -23,6 +21,11 @@ public interface DeliveryExpressTemplateChargeMapper extends BaseMapperX&lt;Deliver
23 return delete(new LambdaQueryWrapper<DeliveryExpressTemplateChargeDO>() 21 return delete(new LambdaQueryWrapper<DeliveryExpressTemplateChargeDO>()
24 .eq(DeliveryExpressTemplateChargeDO::getTemplateId, templateId)); 22 .eq(DeliveryExpressTemplateChargeDO::getTemplateId, templateId));
25 } 23 }
  24 +
  25 + default List<DeliveryExpressTemplateChargeDO> selectByTemplateIds(Collection<Long> templateIds) {
  26 + return selectList(DeliveryExpressTemplateChargeDO::getTemplateId, templateIds);
  27 + }
  28 +
26 } 29 }
27 30
28 31
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateFreeMapper.java
1 package cn.iocoder.yudao.module.trade.dal.mysql.delivery; 1 package cn.iocoder.yudao.module.trade.dal.mysql.delivery;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
5 -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;  
6 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; 4 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
7 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
9 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
10 -import org.springframework.stereotype.Repository;  
11 7
  8 +import java.util.Collection;
12 import java.util.List; 9 import java.util.List;
13 10
14 @Mapper 11 @Mapper
@@ -23,6 +20,10 @@ public interface DeliveryExpressTemplateFreeMapper extends BaseMapperX&lt;DeliveryE @@ -23,6 +20,10 @@ public interface DeliveryExpressTemplateFreeMapper extends BaseMapperX&lt;DeliveryE
23 return delete(new LambdaQueryWrapper<DeliveryExpressTemplateFreeDO>() 20 return delete(new LambdaQueryWrapper<DeliveryExpressTemplateFreeDO>()
24 .eq(DeliveryExpressTemplateFreeDO::getTemplateId, templateId)); 21 .eq(DeliveryExpressTemplateFreeDO::getTemplateId, templateId));
25 } 22 }
  23 +
  24 + default List<DeliveryExpressTemplateFreeDO> selectListByTemplateIds(Collection<Long> templateIds) {
  25 + return selectList(DeliveryExpressTemplateFreeDO::getTemplateId, templateIds);
  26 + }
26 } 27 }
27 28
28 29
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/ExpressClientConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.framework.delivery.config;
  2 +
  3 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
  4 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.ExpressClientFactoryImpl;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.context.annotation.Configuration;
  8 +import org.springframework.web.client.RestTemplate;
  9 +
  10 +/**
  11 + * 快递客户端端配置类:
  12 + *
  13 + * 1. 快递客户端工厂 {@link ExpressClientFactory}
  14 + * 2. 默认的快递客户端实现 {@link ExpressClient}
  15 + *
  16 + * @author jason
  17 + */
  18 +@Configuration(proxyBeanMethods = false)
  19 +public class ExpressClientConfig {
  20 +
  21 + @Bean
  22 + public ExpressClientFactory expressClientFactory(TradeExpressProperties tradeExpressProperties,
  23 + RestTemplate restTemplate) {
  24 + return new ExpressClientFactoryImpl(tradeExpressProperties, restTemplate);
  25 + }
  26 +
  27 + @Bean
  28 + public ExpressClient defaultExpressClient(ExpressClientFactory expressClientFactory) {
  29 + return expressClientFactory.getDefaultExpressClient();
  30 + }
  31 +
  32 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressQueryProperties.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressProperties.java
1 package cn.iocoder.yudao.module.trade.framework.delivery.config; 1 package cn.iocoder.yudao.module.trade.framework.delivery.config;
2 2
3 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderEnum; 3 +import cn.iocoder.yudao.module.trade.framework.delivery.core.enums.ExpressClientEnum;
4 import lombok.Data; 4 import lombok.Data;
5 import org.springframework.boot.context.properties.ConfigurationProperties; 5 import org.springframework.boot.context.properties.ConfigurationProperties;
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
@@ -9,27 +9,25 @@ import org.springframework.validation.annotation.Validated; @@ -9,27 +9,25 @@ import org.springframework.validation.annotation.Validated;
9 import javax.validation.Valid; 9 import javax.validation.Valid;
10 import javax.validation.constraints.NotEmpty; 10 import javax.validation.constraints.NotEmpty;
11 11
12 -// TODO @jason:TradeExpressProperties;更通用哈  
13 // TODO @芋艿:未来要不要放数据库中?考虑 saas 多租户时,不同租户使用不同的配置? 12 // TODO @芋艿:未来要不要放数据库中?考虑 saas 多租户时,不同租户使用不同的配置?
14 /** 13 /**
15 - * 交易快递查询的配置项 14 + * 交易运费快递的配置项
16 * 15 *
17 * @author jason 16 * @author jason
18 */ 17 */
19 @Component 18 @Component
20 -@ConfigurationProperties(prefix = "yudao.trade.express.query") 19 +@ConfigurationProperties(prefix = "yudao.trade.express")
21 @Data 20 @Data
22 @Validated 21 @Validated
23 -public class TradeExpressQueryProperties { 22 +public class TradeExpressProperties {
24 23
25 /** 24 /**
26 - * 快递查询服务商 25 + * 快递客户端
27 * 26 *
28 - * 如果未配置,默认使用快递鸟 27 + * 默认不提供,需要提醒用户配置一个快递服务商。
29 */ 28 */
30 - // TODO @jason:可以把 expressQueryProvider 改成 client 变量,更简洁一点;  
31 - private ExpressQueryProviderEnum expressQueryProvider; // TODO @jaosn:默认值可以通过属性直接赋值哈;  
32 - // TODO @jason:需要考虑下,用户只配置了其中一个; 29 + private ExpressClientEnum client = ExpressClientEnum.NOT_PROVIDE;
  30 +
33 /** 31 /**
34 * 快递鸟配置 32 * 快递鸟配置
35 */ 33 */
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryClient.java deleted
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core;  
2 -  
3 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO;  
4 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRespDTO;  
5 -  
6 -import java.util.List;  
7 -  
8 -// TODO @jason:可以改成 ExpressClient,未来可能还对接别的接口噢  
9 -/**  
10 - * 快递查询客户端  
11 - *  
12 - * @author jason  
13 - */  
14 -public interface ExpressQueryClient {  
15 -  
16 - /**  
17 - * 快递实时查询  
18 - *  
19 - * @param reqDTO 查询请求参数  
20 - */  
21 - // TODO @jason:可以改成 getExpressTrackList。返回字段可以参考 https://doc.youzanyun.com/detail/API/0/5 响应的 data  
22 - List<ExpressQueryRespDTO> realTimeQuery(ExpressQueryReqDTO reqDTO);  
23 -  
24 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryProviderFactory.java deleted
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core;  
2 -  
3 -/**  
4 - * 快递服务商工厂,用于创建和缓存快递服务商服务  
5 - *  
6 - * @author jason  
7 - */  
8 -public interface ExpressQueryProviderFactory {  
9 -  
10 - /**  
11 - * 通过枚举获取快递查询服务商  
12 - *  
13 - * 如果不存在,就创建一个对应的快递查询服务商  
14 - *  
15 - * @param queryProviderEnum 快递服务商枚举  
16 - */  
17 - ExpressQueryProvider getOrCreateExpressQueryProvider(ExpressQueryProviderEnum queryProviderEnum);  
18 -  
19 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryProvider.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/ExpressClient.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client;
2 2
3 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO;  
4 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRespDTO; 3 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  4 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
5 5
6 import java.util.List; 6 import java.util.List;
7 7
8 /** 8 /**
9 - * 快递查询服务商 9 + * 快递客户端接口
10 * 10 *
11 * @author jason 11 * @author jason
12 */ 12 */
13 -public interface ExpressQueryProvider { 13 +public interface ExpressClient {
14 14
15 /** 15 /**
16 * 快递实时查询 16 * 快递实时查询
17 * 17 *
18 * @param reqDTO 查询请求参数 18 * @param reqDTO 查询请求参数
19 */ 19 */
20 - List<ExpressQueryRespDTO> realTimeQueryExpress(ExpressQueryReqDTO reqDTO); 20 + // TODO @jason:返回字段可以参考 https://doc.youzanyun.com/detail/API/0/5 响应的 data
  21 + List<ExpressTrackRespDTO> getExpressTrackList(ExpressTrackQueryReqDTO reqDTO);
21 22
22 } 23 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/ExpressClientFactory.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client;
  2 +
  3 +import cn.iocoder.yudao.module.trade.framework.delivery.core.enums.ExpressClientEnum;
  4 +
  5 +/**
  6 + * 快递客户端工厂接口:用于创建和缓存快递客户端
  7 + *
  8 + * @author jason
  9 + */
  10 +public interface ExpressClientFactory {
  11 +
  12 + /**
  13 + * 获取默认的快递客户端
  14 + */
  15 + ExpressClient getDefaultExpressClient();
  16 +
  17 + /**
  18 + * 通过枚举获取快递客户端,如果不存在,就创建一个对应快递客户端
  19 + *
  20 + * @param clientEnum 快递客户端枚举
  21 + */
  22 + ExpressClient getOrCreateExpressClient(ExpressClientEnum clientEnum);
  23 +
  24 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/convert/ExpressQueryConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.convert;
  2 +
  3 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  4 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100.Kd100ExpressQueryReqDTO;
  6 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100.Kd100ExpressQueryRespDTO;
  7 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao.KdNiaoExpressQueryReqDTO;
  8 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao.KdNiaoExpressQueryRespDTO;
  9 +import org.mapstruct.Mapper;
  10 +import org.mapstruct.factory.Mappers;
  11 +
  12 +import java.util.List;
  13 +
  14 +@Mapper
  15 +public interface ExpressQueryConvert {
  16 +
  17 + ExpressQueryConvert INSTANCE = Mappers.getMapper(ExpressQueryConvert.class);
  18 +
  19 + List<ExpressTrackRespDTO> convertList(List<KdNiaoExpressQueryRespDTO.ExpressTrack> expressTrackList);
  20 +
  21 + List<ExpressTrackRespDTO> convertList2(List<Kd100ExpressQueryRespDTO.ExpressTrack> expressTrackList);
  22 +
  23 + KdNiaoExpressQueryReqDTO convert(ExpressTrackQueryReqDTO dto);
  24 +
  25 + Kd100ExpressQueryReqDTO convert2(ExpressTrackQueryReqDTO dto);
  26 +
  27 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/ExpressQueryReqDTO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/ExpressTrackQueryReqDTO.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.dto; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto;
2 2
3 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; 3 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 /** 6 /**
7 - * 快递查询 Req DTO 7 + * 快递轨迹的查询 Req DTO
8 * 8 *
9 * @author jason 9 * @author jason
10 */ 10 */
11 @Data 11 @Data
12 -public class ExpressQueryReqDTO { 12 +public class ExpressTrackQueryReqDTO {
13 13
14 /** 14 /**
15 * 快递公司编码 15 * 快递公司编码
16 * 16 *
17 * 对应 {@link DeliveryExpressDO#getCode()} 17 * 对应 {@link DeliveryExpressDO#getCode()}
18 */ 18 */
19 - // TODO @jaosn:要不改成 expressCode;项目里使用这个哈  
20 - private String expressCompanyCode; 19 + private String expressCode;
21 20
22 /** 21 /**
23 * 发货快递单号 22 * 发货快递单号
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/ExpressQueryRespDTO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/ExpressTrackRespDTO.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.dto; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
@@ -8,7 +8,7 @@ import lombok.Data; @@ -8,7 +8,7 @@ import lombok.Data;
8 * @author jason 8 * @author jason
9 */ 9 */
10 @Data 10 @Data
11 -public class ExpressQueryRespDTO { 11 +public class ExpressTrackRespDTO {
12 12
13 // TODO @jason:LocalDateTime 13 // TODO @jason:LocalDateTime
14 /** 14 /**
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kd100/Kd100ExpressQueryReqDTO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryReqDTO.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kd100; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100;
2 2
3 import com.fasterxml.jackson.annotation.JsonInclude; 3 import com.fasterxml.jackson.annotation.JsonInclude;
4 import com.fasterxml.jackson.annotation.JsonProperty; 4 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -13,12 +13,11 @@ import lombok.Data; @@ -13,12 +13,11 @@ import lombok.Data;
13 @JsonInclude(JsonInclude.Include.NON_NULL) 13 @JsonInclude(JsonInclude.Include.NON_NULL)
14 public class Kd100ExpressQueryReqDTO { 14 public class Kd100ExpressQueryReqDTO {
15 15
16 - // TODO @jaosn:要不改成 expressCode;项目里使用这个哈  
17 /** 16 /**
18 * 快递公司编码 17 * 快递公司编码
19 */ 18 */
20 @JsonProperty("com") 19 @JsonProperty("com")
21 - private String expressCompanyCode; 20 + private String expressCode;
22 21
23 /** 22 /**
24 * 快递单号 23 * 快递单号
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kd100/Kd100ExpressQueryRespDTO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kd100; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100;
2 2
3 import com.fasterxml.jackson.annotation.JsonProperty; 3 import com.fasterxml.jackson.annotation.JsonProperty;
4 import lombok.Data; 4 import lombok.Data;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kdniao/KdNiaoExpressQueryReqDTO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kdniao/KdNiaoExpressQueryReqDTO.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kdniao; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao;
2 2
3 import com.fasterxml.jackson.annotation.JsonInclude; 3 import com.fasterxml.jackson.annotation.JsonInclude;
4 import com.fasterxml.jackson.annotation.JsonProperty; 4 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -13,12 +13,11 @@ import lombok.Data; @@ -13,12 +13,11 @@ import lombok.Data;
13 @JsonInclude(JsonInclude.Include.NON_NULL) 13 @JsonInclude(JsonInclude.Include.NON_NULL)
14 public class KdNiaoExpressQueryReqDTO { 14 public class KdNiaoExpressQueryReqDTO {
15 15
16 - // TODO @jaosn:要不改成 expressCode;项目里使用这个哈  
17 /** 16 /**
18 * 快递公司编码 17 * 快递公司编码
19 */ 18 */
20 @JsonProperty("ShipperCode") 19 @JsonProperty("ShipperCode")
21 - private String expressCompanyCode; 20 + private String expressCode;
22 /** 21 /**
23 * 快递单号 22 * 快递单号
24 */ 23 */
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/dto/provider/kdniao/KdNiaoExpressQueryRespDTO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kdniao/KdNiaoExpressQueryRespDTO.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kdniao; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao;
2 2
3 import com.fasterxml.jackson.annotation.JsonProperty; 3 import com.fasterxml.jackson.annotation.JsonProperty;
4 import lombok.Data; 4 import lombok.Data;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/ExpressClientFactoryImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
  2 +
  3 +import cn.hutool.core.lang.Assert;
  4 +import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
  6 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kd100.Kd100ExpressClient;
  7 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kdniao.KdNiaoExpressClient;
  8 +import cn.iocoder.yudao.module.trade.framework.delivery.core.enums.ExpressClientEnum;
  9 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory;
  10 +import lombok.AllArgsConstructor;
  11 +import org.springframework.web.client.RestTemplate;
  12 +
  13 +import java.util.Map;
  14 +import java.util.concurrent.ConcurrentHashMap;
  15 +
  16 +/**
  17 + * 快递客户端工厂实现类
  18 + *
  19 + * @author jason
  20 + */
  21 +@AllArgsConstructor
  22 +public class ExpressClientFactoryImpl implements ExpressClientFactory {
  23 +
  24 + private final Map<ExpressClientEnum, ExpressClient> clientMap = new ConcurrentHashMap<>(8);
  25 +
  26 + private final TradeExpressProperties tradeExpressProperties;
  27 + private final RestTemplate restTemplate;
  28 +
  29 + @Override
  30 + public ExpressClient getDefaultExpressClient() {
  31 + ExpressClient defaultClient = getOrCreateExpressClient(tradeExpressProperties.getClient());
  32 + Assert.notNull("默认的快递客户端不能为空");
  33 + return defaultClient;
  34 + }
  35 +
  36 + @Override
  37 + public ExpressClient getOrCreateExpressClient(ExpressClientEnum clientEnum) {
  38 + return clientMap.computeIfAbsent(clientEnum,
  39 + client -> createExpressClient(client, tradeExpressProperties));
  40 + }
  41 +
  42 + private ExpressClient createExpressClient(ExpressClientEnum queryProviderEnum,
  43 + TradeExpressProperties tradeExpressProperties) {
  44 + switch (queryProviderEnum) {
  45 + case NOT_PROVIDE:
  46 + return new NoProvideExpressClient();
  47 + case KD_NIAO:
  48 + return new KdNiaoExpressClient(restTemplate, tradeExpressProperties.getKdNiao());
  49 + case KD_100:
  50 + return new Kd100ExpressClient(restTemplate, tradeExpressProperties.getKd100());
  51 + }
  52 + return null;
  53 + }
  54 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/NoProvideExpressClient.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
  2 +
  3 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
  4 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
  6 +
  7 +import java.util.List;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  10 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_CLIENT_NOT_PROVIDE;
  11 +
  12 +/**
  13 + * 未实现的快递客户端,用来提醒用户需要接入快递服务商,
  14 + *
  15 + * @author jason
  16 + */
  17 +public class NoProvideExpressClient implements ExpressClient {
  18 +
  19 + @Override
  20 + public List<ExpressTrackRespDTO> getExpressTrackList(ExpressTrackQueryReqDTO reqDTO) {
  21 + throw exception(EXPRESS_CLIENT_NOT_PROVIDE);
  22 + }
  23 +
  24 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/Kd100ExpressQueryProvider.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/kd100/Kd100ExpressClient.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.impl; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kd100;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.HexUtil; 4 import cn.hutool.core.util.HexUtil;
5 import cn.hutool.crypto.digest.DigestUtil; 5 import cn.hutool.crypto.digest.DigestUtil;
6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 -import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressQueryProperties;  
8 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProvider;  
9 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO;  
10 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRespDTO;  
11 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kd100.Kd100ExpressQueryReqDTO;  
12 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kd100.Kd100ExpressQueryRespDTO; 7 +import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
  8 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
  9 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  10 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
  11 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100.Kd100ExpressQueryReqDTO;
  12 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100.Kd100ExpressQueryRespDTO;
  13 +import lombok.AllArgsConstructor;
13 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
14 import org.springframework.http.*; 15 import org.springframework.http.*;
15 import org.springframework.util.LinkedMultiValueMap; 16 import org.springframework.util.LinkedMultiValueMap;
@@ -23,48 +24,40 @@ import java.util.Objects; @@ -23,48 +24,40 @@ import java.util.Objects;
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_ERROR; 25 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_ERROR;
25 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_FAILED; 26 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_FAILED;
26 -import static cn.iocoder.yudao.module.trade.framework.delivery.core.convert.ExpressQueryConvert.INSTANCE; 27 +import static cn.iocoder.yudao.module.trade.framework.delivery.core.client.convert.ExpressQueryConvert.INSTANCE;
27 28
28 -// TODO @jason:可以参考 KdNiaoExpressQueryProvider 建议改改哈  
29 /** 29 /**
30 - * 快递 100 服务商 30 + * 快递 100 客户端
31 * 31 *
32 * @author jason 32 * @author jason
33 */ 33 */
34 @Slf4j 34 @Slf4j
35 -public class Kd100ExpressQueryProvider implements ExpressQueryProvider { 35 +@AllArgsConstructor
  36 +public class Kd100ExpressClient implements ExpressClient {
36 37
37 private static final String REAL_TIME_QUERY_URL = "https://poll.kuaidi100.com/poll/query.do"; 38 private static final String REAL_TIME_QUERY_URL = "https://poll.kuaidi100.com/poll/query.do";
38 39
39 private final RestTemplate restTemplate; 40 private final RestTemplate restTemplate;
40 - private final TradeExpressQueryProperties.Kd100Config config;  
41 -  
42 - public Kd100ExpressQueryProvider(RestTemplate restTemplate, TradeExpressQueryProperties.Kd100Config config) {  
43 - this.restTemplate = restTemplate;  
44 - this.config = config;  
45 - } 41 + private final TradeExpressProperties.Kd100Config config;
46 42
47 @Override 43 @Override
48 - public List<ExpressQueryRespDTO> realTimeQueryExpress(ExpressQueryReqDTO reqDTO) { 44 + public List<ExpressTrackRespDTO> getExpressTrackList(ExpressTrackQueryReqDTO reqDTO) {
49 // 发起查询 45 // 发起查询
50 Kd100ExpressQueryReqDTO kd100ReqParam = INSTANCE.convert2(reqDTO); 46 Kd100ExpressQueryReqDTO kd100ReqParam = INSTANCE.convert2(reqDTO);
51 - kd100ReqParam.setExpressCompanyCode(kd100ReqParam.getExpressCompanyCode().toLowerCase()); // 快递公司编码需要转成小写  
52 - Kd100ExpressQueryRespDTO respDTO = sendExpressQueryReq(REAL_TIME_QUERY_URL, kd100ReqParam, 47 + kd100ReqParam.setExpressCode(kd100ReqParam.getExpressCode().toLowerCase()); // 快递公司编码需要转成小写
  48 + Kd100ExpressQueryRespDTO respDTO = requestExpressQuery(REAL_TIME_QUERY_URL, kd100ReqParam,
53 Kd100ExpressQueryRespDTO.class); 49 Kd100ExpressQueryRespDTO.class);
54 - log.debug("[realTimeQueryExpress][快递 100 接口 查询接口返回 {}]", respDTO); 50 + log.debug("[getExpressTrackList][快递 100 接口 查询接口返回 {}]", respDTO);
  51 +
55 // 处理结果 52 // 处理结果
56 if (Objects.equals("false", respDTO.getResult())) { 53 if (Objects.equals("false", respDTO.getResult())) {
57 - log.error("[realTimeQueryExpress][快递 100 接口 返回失败 {}]", respDTO.getMessage()); 54 + log.error("[getExpressTrackList][快递 100 接口 返回失败 {}]", respDTO.getMessage());
58 throw exception(EXPRESS_API_QUERY_FAILED, respDTO.getMessage()); 55 throw exception(EXPRESS_API_QUERY_FAILED, respDTO.getMessage());
59 - // TODO @json:else 可以不用写哈;  
60 - } else {  
61 - // TODO @jason:convertList2 如果空,应该返回 list 了;  
62 - if (CollUtil.isNotEmpty(respDTO.getTracks())) {  
63 - return INSTANCE.convertList2(respDTO.getTracks());  
64 - } else {  
65 - return Collections.emptyList();  
66 - }  
67 } 56 }
  57 + if (CollUtil.isEmpty(respDTO.getTracks())) {
  58 + return Collections.emptyList();
  59 + }
  60 + return INSTANCE.convertList2(respDTO.getTracks());
68 } 61 }
69 62
70 /** 63 /**
@@ -76,8 +69,7 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider { @@ -76,8 +69,7 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider {
76 * @param <Req> 每个请求的请求结构 Req DTO 69 * @param <Req> 每个请求的请求结构 Req DTO
77 * @param <Resp> 每个请求的响应结构 Resp DTO 70 * @param <Resp> 每个请求的响应结构 Resp DTO
78 */ 71 */
79 - // TODO @jason:可以改成 request,发起请求哈;  
80 - private <Req, Resp> Resp sendExpressQueryReq(String url, Req req, Class<Resp> respClass) { 72 + private <Req, Resp> Resp requestExpressQuery(String url, Req req, Class<Resp> respClass) {
81 // 请求头 73 // 请求头
82 HttpHeaders headers = new HttpHeaders(); 74 HttpHeaders headers = new HttpHeaders();
83 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 75 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
@@ -92,23 +84,18 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider { @@ -92,23 +84,18 @@ public class Kd100ExpressQueryProvider implements ExpressQueryProvider {
92 log.debug("[sendExpressQueryReq][快递 100 接口的请求参数: {}]", requestBody); 84 log.debug("[sendExpressQueryReq][快递 100 接口的请求参数: {}]", requestBody);
93 // 发送请求 85 // 发送请求
94 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers); 86 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
95 - // TODO @jason:可以使用 restTemplate 的 post 方法哇?  
96 ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); 87 ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
97 log.debug("[sendExpressQueryReq][快递 100 接口响应结果 {}]", responseEntity); 88 log.debug("[sendExpressQueryReq][快递 100 接口响应结果 {}]", responseEntity);
98 89
99 // 处理响应 90 // 处理响应
100 - // TODO @jason:if return 原则;if (!responseEntity.getStatusCode().is2xxSuccessful()) 抛出异常;接着处理成功的  
101 - if (responseEntity.getStatusCode().is2xxSuccessful()) {  
102 - String response = responseEntity.getBody();  
103 - return JsonUtils.parseObject(response, respClass);  
104 - } else { 91 + if (!responseEntity.getStatusCode().is2xxSuccessful()) {
105 throw exception(EXPRESS_API_QUERY_ERROR); 92 throw exception(EXPRESS_API_QUERY_ERROR);
106 } 93 }
  94 + return JsonUtils.parseObject(responseEntity.getBody(), respClass);
107 } 95 }
108 96
109 private String generateReqSign(String param, String key, String customer) { 97 private String generateReqSign(String param, String key, String customer) {
110 String plainText = String.format("%s%s%s", param, key, customer); 98 String plainText = String.format("%s%s%s", param, key, customer);
111 - // TODO @jason:DigestUtil.md5Hex(plainText);  
112 return HexUtil.encodeHexStr(DigestUtil.md5(plainText), false); 99 return HexUtil.encodeHexStr(DigestUtil.md5(plainText), false);
113 } 100 }
114 101
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/KdNiaoExpressQueryProvider.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/kdniao/KdNiaoExpressClient.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.impl; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kdniao;
2 2
3 import cn.hutool.core.codec.Base64; 3 import cn.hutool.core.codec.Base64;
4 import cn.hutool.core.collection.CollUtil; 4 import cn.hutool.core.collection.CollUtil;
5 import cn.hutool.core.net.URLEncodeUtil; 5 import cn.hutool.core.net.URLEncodeUtil;
6 import cn.hutool.crypto.digest.DigestUtil; 6 import cn.hutool.crypto.digest.DigestUtil;
7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 -import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressQueryProperties;  
9 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProvider;  
10 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO;  
11 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRespDTO;  
12 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kdniao.KdNiaoExpressQueryReqDTO;  
13 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kdniao.KdNiaoExpressQueryRespDTO; 8 +import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
  9 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
  10 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  11 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
  12 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao.KdNiaoExpressQueryReqDTO;
  13 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kdniao.KdNiaoExpressQueryRespDTO;
  14 +import lombok.AllArgsConstructor;
14 import lombok.extern.slf4j.Slf4j; 15 import lombok.extern.slf4j.Slf4j;
15 import org.springframework.http.*; 16 import org.springframework.http.*;
16 import org.springframework.util.LinkedMultiValueMap; 17 import org.springframework.util.LinkedMultiValueMap;
@@ -23,15 +24,16 @@ import java.util.List; @@ -23,15 +24,16 @@ import java.util.List;
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_FAILED; 25 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_FAILED;
25 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_ERROR; 26 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_API_QUERY_ERROR;
26 -import static cn.iocoder.yudao.module.trade.framework.delivery.core.convert.ExpressQueryConvert.INSTANCE; 27 +import static cn.iocoder.yudao.module.trade.framework.delivery.core.client.convert.ExpressQueryConvert.INSTANCE;
27 28
28 /** 29 /**
29 - * 快递鸟服务商 30 + * 快递鸟客户端
30 * 31 *
31 * @author jason 32 * @author jason
32 */ 33 */
33 @Slf4j 34 @Slf4j
34 -public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { 35 +@AllArgsConstructor
  36 +public class KdNiaoExpressClient implements ExpressClient {
35 37
36 private static final String REAL_TIME_QUERY_URL = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx"; 38 private static final String REAL_TIME_QUERY_URL = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
37 39
@@ -39,15 +41,8 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { @@ -39,15 +41,8 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider {
39 * 快递鸟即时查询免费版 RequestType 41 * 快递鸟即时查询免费版 RequestType
40 */ 42 */
41 private static final String REAL_TIME_FREE_REQ_TYPE = "1002"; 43 private static final String REAL_TIME_FREE_REQ_TYPE = "1002";
42 -  
43 private final RestTemplate restTemplate; 44 private final RestTemplate restTemplate;
44 - private final TradeExpressQueryProperties.KdNiaoConfig config;  
45 -  
46 - // TODO @jason:可以改成 lombok 哈  
47 - public KdNiaoExpressQueryProvider(RestTemplate restTemplate, TradeExpressQueryProperties.KdNiaoConfig config) {  
48 - this.restTemplate = restTemplate;  
49 - this.config = config;  
50 - } 45 + private final TradeExpressProperties.KdNiaoConfig config;
51 46
52 /** 47 /**
53 * 快递鸟即时查询免费版本 48 * 快递鸟即时查询免费版本
@@ -56,26 +51,27 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { @@ -56,26 +51,27 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider {
56 * @param reqDTO 查询请求参数 51 * @param reqDTO 查询请求参数
57 */ 52 */
58 @Override 53 @Override
59 - public List<ExpressQueryRespDTO> realTimeQueryExpress(ExpressQueryReqDTO reqDTO) { 54 + public List<ExpressTrackRespDTO> getExpressTrackList(ExpressTrackQueryReqDTO reqDTO) {
60 KdNiaoExpressQueryReqDTO kdNiaoReqData = INSTANCE.convert(reqDTO); 55 KdNiaoExpressQueryReqDTO kdNiaoReqData = INSTANCE.convert(reqDTO);
61 // 快递公司编码需要转成大写 56 // 快递公司编码需要转成大写
62 - kdNiaoReqData.setExpressCompanyCode(reqDTO.getExpressCompanyCode().toUpperCase());  
63 - KdNiaoExpressQueryRespDTO respDTO = sendKdNiaoApiRequest(REAL_TIME_QUERY_URL, REAL_TIME_FREE_REQ_TYPE, 57 + kdNiaoReqData.setExpressCode(reqDTO.getExpressCode().toUpperCase());
  58 + KdNiaoExpressQueryRespDTO respDTO = requestKdNiaoApi(REAL_TIME_QUERY_URL, REAL_TIME_FREE_REQ_TYPE,
64 kdNiaoReqData, KdNiaoExpressQueryRespDTO.class); 59 kdNiaoReqData, KdNiaoExpressQueryRespDTO.class);
65 - log.debug("[realTimeQueryExpress][快递鸟即时查询接口返回 {}]", respDTO);  
66 - if(!respDTO.getSuccess()){  
67 - throw exception(EXPRESS_API_QUERY_FAILED, respDTO.getReason());  
68 - }else{  
69 - if (CollUtil.isNotEmpty(respDTO.getTracks())) {  
70 - return INSTANCE.convertList(respDTO.getTracks());  
71 - }else{  
72 - return Collections.emptyList();  
73 - } 60 + log.debug("[getExpressTrackList][快递鸟即时查询接口返回 {}]", respDTO);
  61 +
  62 + // 处理结果
  63 + if (respDTO == null || !respDTO.getSuccess()) {
  64 + throw exception(EXPRESS_API_QUERY_FAILED, respDTO == null ? "" : respDTO.getReason());
74 } 65 }
  66 + if (CollUtil.isNotEmpty(respDTO.getTracks())) {
  67 + return Collections.emptyList();
  68 + }
  69 + return INSTANCE.convertList(respDTO.getTracks());
75 } 70 }
76 71
77 /** 72 /**
78 - * 快递鸟 通用的 API 请求, 暂时没有其他应用场景, 暂时放这里 73 + * 快递鸟 通用的 API 请求,暂时没有其他应用场景, 暂时放这里
  74 + *
79 * @param url 请求 url 75 * @param url 请求 url
80 * @param requestType 对应的请求指令 (快递鸟的RequestType) 76 * @param requestType 对应的请求指令 (快递鸟的RequestType)
81 * @param req 对应请求的请求参数 77 * @param req 对应请求的请求参数
@@ -83,8 +79,8 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { @@ -83,8 +79,8 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider {
83 * @param <Req> 每个请求的请求结构 Req DTO 79 * @param <Req> 每个请求的请求结构 Req DTO
84 * @param <Resp> 每个请求的响应结构 Resp DTO 80 * @param <Resp> 每个请求的响应结构 Resp DTO
85 */ 81 */
86 - private <Req, Resp> Resp sendKdNiaoApiRequest(String url, String requestType, Req req,  
87 - Class<Resp> respClass){ 82 + private <Req, Resp> Resp requestKdNiaoApi(String url, String requestType, Req req,
  83 + Class<Resp> respClass){
88 // 请求头 84 // 请求头
89 HttpHeaders headers = new HttpHeaders(); 85 HttpHeaders headers = new HttpHeaders();
90 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 86 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
@@ -97,19 +93,16 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider { @@ -97,19 +93,16 @@ public class KdNiaoExpressQueryProvider implements ExpressQueryProvider {
97 requestBody.add("EBusinessID", config.getBusinessId()); 93 requestBody.add("EBusinessID", config.getBusinessId());
98 requestBody.add("DataSign", dataSign); 94 requestBody.add("DataSign", dataSign);
99 requestBody.add("RequestType", requestType); 95 requestBody.add("RequestType", requestType);
100 - log.debug("[sendKdNiaoApiRequest][快递鸟接口 RequestType : {}, 的请求参数 {}]", requestType, requestBody);  
101 - 96 + log.debug("[requestKdNiaoApi][快递鸟接口 RequestType : {}, 的请求参数 {}]", requestType, requestBody);
102 // 发送请求 97 // 发送请求
103 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers); 98 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
104 ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); 99 ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
105 log.debug("快递鸟接口 RequestType : {}, 的响应结果 {}", requestType, responseEntity); 100 log.debug("快递鸟接口 RequestType : {}, 的响应结果 {}", requestType, responseEntity);
106 // 处理响应 101 // 处理响应
107 - if (responseEntity.getStatusCode().is2xxSuccessful()) {  
108 - String response = responseEntity.getBody();  
109 - return JsonUtils.parseObject(response, respClass);  
110 - } else { 102 + if (!responseEntity.getStatusCode().is2xxSuccessful()) {
111 throw exception(EXPRESS_API_QUERY_ERROR); 103 throw exception(EXPRESS_API_QUERY_ERROR);
112 } 104 }
  105 + return JsonUtils.parseObject(responseEntity.getBody(), respClass);
113 } 106 }
114 107
115 /** 108 /**
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/convert/ExpressQueryConvert.java deleted
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.convert;  
2 -  
3 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO;  
4 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRespDTO;  
5 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kd100.Kd100ExpressQueryReqDTO;  
6 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kd100.Kd100ExpressQueryRespDTO;  
7 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kdniao.KdNiaoExpressQueryReqDTO;  
8 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.provider.kdniao.KdNiaoExpressQueryRespDTO;  
9 -import org.mapstruct.Mapper;  
10 -import org.mapstruct.factory.Mappers;  
11 -  
12 -import java.util.List;  
13 -  
14 -@Mapper  
15 -public interface ExpressQueryConvert {  
16 -  
17 - ExpressQueryConvert INSTANCE = Mappers.getMapper(ExpressQueryConvert.class);  
18 -  
19 - List<ExpressQueryRespDTO> convertList(List<KdNiaoExpressQueryRespDTO.ExpressTrack> expressTrackList);  
20 -  
21 - List<ExpressQueryRespDTO> convertList2(List<Kd100ExpressQueryRespDTO.ExpressTrack> expressTrackList);  
22 -  
23 - KdNiaoExpressQueryReqDTO convert(ExpressQueryReqDTO dto);  
24 -  
25 - Kd100ExpressQueryReqDTO convert2(ExpressQueryReqDTO dto);  
26 -  
27 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/ExpressQueryProviderEnum.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/enums/ExpressClientEnum.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.enums;
2 2
  3 +import lombok.AllArgsConstructor;
3 import lombok.Getter; 4 import lombok.Getter;
4 5
5 /** 6 /**
6 - * 快递查询服务商枚举 7 + * 快递客户端枚举
7 * 8 *
8 * @author jason 9 * @author jason
9 */ 10 */
10 @Getter 11 @Getter
  12 +@AllArgsConstructor
  13 +public enum ExpressClientEnum {
11 14
12 -public enum ExpressQueryProviderEnum {  
13 - 15 + NOT_PROVIDE("not-provide","未提供"),
14 KD_NIAO("kd-niao", "快递鸟"), 16 KD_NIAO("kd-niao", "快递鸟"),
15 KD_100("kd-100", "快递100"); 17 KD_100("kd-100", "快递100");
16 18
@@ -18,16 +20,9 @@ public enum ExpressQueryProviderEnum { @@ -18,16 +20,9 @@ public enum ExpressQueryProviderEnum {
18 * 快递服务商唯一编码 20 * 快递服务商唯一编码
19 */ 21 */
20 private final String code; 22 private final String code;
21 -  
22 /** 23 /**
23 * 快递服务商名称 24 * 快递服务商名称
24 */ 25 */
25 private final String name; 26 private final String name;
26 27
27 - // TODO @jaosn:@AllArgsConstructor 可以替代哈  
28 - ExpressQueryProviderEnum(String code, String name) {  
29 - this.code = code;  
30 - this.name = name;  
31 - }  
32 -  
33 } 28 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/ExpressQueryClientImpl.java deleted
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.impl;  
2 -  
3 -import cn.hutool.core.lang.Assert;  
4 -import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressQueryProperties;  
5 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryClient;  
6 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProvider;  
7 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderEnum;  
8 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderFactory;  
9 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO;  
10 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryRespDTO;  
11 -import lombok.extern.slf4j.Slf4j;  
12 -import org.springframework.stereotype.Component;  
13 -  
14 -import javax.annotation.PostConstruct;  
15 -import javax.annotation.Resource;  
16 -import java.util.List;  
17 -  
18 -import static cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderEnum.KD_NIAO;  
19 -  
20 -// TODO @jason:可以把整体包结构调整下;参考 sms client 的方式;  
21 -// + config  
22 -// + core  
23 -// client  
24 -// + dto  
25 -// + impl:里面可以放 kdniaoclient、kd100client  
26 -// ExpressClient  
27 -// ExpressClientFactory: 通过它直接获取默认和创建默认的 Client  
28 -// enums  
29 -/**  
30 - * 快递查询客户端实现  
31 - *  
32 - * @author jason  
33 - */  
34 -@Component  
35 -@Slf4j  
36 -public class ExpressQueryClientImpl implements ExpressQueryClient {  
37 -  
38 - @Resource  
39 - private ExpressQueryProviderFactory expressQueryProviderFactory;  
40 - @Resource  
41 - private TradeExpressQueryProperties tradeExpressQueryProperties;  
42 -  
43 - private ExpressQueryProvider expressQueryProvider;  
44 -  
45 - @PostConstruct  
46 - private void init() {  
47 - // 如果未设置,默认使用快递鸟  
48 - ExpressQueryProviderEnum queryProvider = tradeExpressQueryProperties.getExpressQueryProvider();  
49 - if (queryProvider == null) {  
50 - queryProvider = KD_NIAO;  
51 - }  
52 - // 创建客户端  
53 - expressQueryProvider = expressQueryProviderFactory.getOrCreateExpressQueryProvider(queryProvider);  
54 - if (expressQueryProvider == null) {  
55 - log.error("获取创建快递查询服务商{}失败,请检查相关配置", queryProvider);  
56 - }  
57 - Assert.notNull(expressQueryProvider, "快递查询服务商不能为空");  
58 - }  
59 -  
60 - @Override  
61 - public List<ExpressQueryRespDTO> realTimeQuery(ExpressQueryReqDTO reqDTO) {  
62 - return expressQueryProvider.realTimeQueryExpress(reqDTO);  
63 - }  
64 -  
65 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/ExpressQueryProviderFactoryImpl.java deleted
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.impl;  
2 -  
3 -import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressQueryProperties;  
4 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProvider;  
5 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderEnum;  
6 -import cn.iocoder.yudao.module.trade.framework.delivery.core.ExpressQueryProviderFactory;  
7 -import org.springframework.stereotype.Component;  
8 -import org.springframework.web.client.RestTemplate;  
9 -  
10 -import javax.annotation.Resource;  
11 -import java.util.Map;  
12 -import java.util.concurrent.ConcurrentHashMap;  
13 -  
14 -/**  
15 - * // TODO @jason:注释不全  
16 - * @author jason  
17 - */  
18 -@Component  
19 -public class ExpressQueryProviderFactoryImpl implements ExpressQueryProviderFactory {  
20 -  
21 - private final Map<ExpressQueryProviderEnum, ExpressQueryProvider> providerMap = new ConcurrentHashMap<>(8);  
22 -  
23 - @Resource  
24 - private TradeExpressQueryProperties tradeExpressQueryProperties;  
25 - @Resource  
26 - private RestTemplate restTemplate;  
27 -  
28 - @Override  
29 - public ExpressQueryProvider getOrCreateExpressQueryProvider(ExpressQueryProviderEnum queryProviderEnum) {  
30 - return providerMap.computeIfAbsent(queryProviderEnum,  
31 - provider -> createExpressQueryProvider(provider, tradeExpressQueryProperties));  
32 - }  
33 -  
34 - private ExpressQueryProvider createExpressQueryProvider(ExpressQueryProviderEnum queryProviderEnum,  
35 - TradeExpressQueryProperties tradeExpressQueryProperties) {  
36 - // TODO @jason:是不是直接 return 就好啦,更简洁一点  
37 - ExpressQueryProvider result = null;  
38 - switch (queryProviderEnum) {  
39 - case KD_NIAO:  
40 - result = new KdNiaoExpressQueryProvider(restTemplate, tradeExpressQueryProperties.getKdNiao());  
41 - break;  
42 - case KD_100:  
43 - result = new Kd100ExpressQueryProvider(restTemplate, tradeExpressQueryProperties.getKd100());  
44 - break;  
45 - }  
46 - return result;  
47 - }  
48 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java
@@ -75,7 +75,7 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService { @@ -75,7 +75,7 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService {
75 } 75 }
76 private void validateDeliveryExpressExists(Long id) { 76 private void validateDeliveryExpressExists(Long id) {
77 if (deliveryExpressMapper.selectById(id) == null) { 77 if (deliveryExpressMapper.selectById(id) == null) {
78 - throw exception(DELIVERY_EXPRESS_NOT_EXISTS); 78 + throw exception(EXPRESS_NOT_EXISTS);
79 } 79 }
80 } 80 }
81 81
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat
6 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; 6 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO;
7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO; 7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO;
8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; 8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
9 -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; 9 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
10 10
11 import javax.validation.Valid; 11 import javax.validation.Valid;
12 import java.util.Collection; 12 import java.util.Collection;
@@ -83,14 +83,13 @@ public interface DeliveryExpressTemplateService { @@ -83,14 +83,13 @@ public interface DeliveryExpressTemplateService {
83 */ 83 */
84 DeliveryExpressTemplateDO validateDeliveryExpressTemplate(Long templateId); 84 DeliveryExpressTemplateDO validateDeliveryExpressTemplate(Long templateId);
85 85
86 - // TODO @jason:可以把 spuIds 改成传递 ids 么?价格计算那,在 TradePriceCalculateRespBO 冗余好 templateId 字段。目的是,减少重复的查询  
87 /** 86 /**
88 - * 基于指定的 SPU 编号数组和收件人地址区域编号. 获取匹配运费模板 87 + * 基于运费模板编号数组和收件人地址区域编号,获取匹配运费模板
89 * 88 *
90 - * @param spuIds SPU 编号列表 89 + * @param ids 编号列表
91 * @param areaId 区域编号 90 * @param areaId 区域编号
92 - * @return Map (spuId -> 运费模板设置) 91 + * @return Map (templateId -> 运费模板设置)
93 */ 92 */
94 - Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateMapBySpuIdsAndArea(Collection<Long> spuIds, Integer areaId); 93 + Map<Long, DeliveryExpressTemplateRespBO> getExpressTemplateMapByIdsAndArea(Collection<Long> ids, Integer areaId);
95 94
96 } 95 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java
@@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.trade.service.delivery; @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.trade.service.delivery;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;  
7 -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;  
8 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateCreateReqVO; 6 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateCreateReqVO;
9 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateDetailRespVO; 7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateDetailRespVO;
10 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; 8 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO;
@@ -15,9 +13,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp @@ -15,9 +13,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp
15 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper; 13 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper;
16 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper; 14 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper;
17 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateMapper; 15 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateMapper;
18 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;  
19 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;  
20 -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; 16 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
21 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
22 import org.springframework.transaction.annotation.Transactional; 18 import org.springframework.transaction.annotation.Transactional;
23 import org.springframework.validation.annotation.Validated; 19 import org.springframework.validation.annotation.Validated;
@@ -46,8 +42,6 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla @@ -46,8 +42,6 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
46 private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper; 42 private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper;
47 @Resource 43 @Resource
48 private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper; 44 private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper;
49 - @Resource  
50 - private ProductSpuApi productSpuApi;  
51 45
52 @Override 46 @Override
53 @Transactional(rollbackFor = Exception.class) 47 @Transactional(rollbackFor = Exception.class)
@@ -228,41 +222,30 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla @@ -228,41 +222,30 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
228 } 222 }
229 223
230 @Override 224 @Override
231 - public Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateMapBySpuIdsAndArea(Collection<Long> spuIds, Integer areaId) { 225 + public Map<Long, DeliveryExpressTemplateRespBO> getExpressTemplateMapByIdsAndArea(Collection<Long> ids, Integer areaId) {
232 Assert.notNull(areaId, "区域编号 {} 不能为空", areaId); 226 Assert.notNull(areaId, "区域编号 {} 不能为空", areaId);
233 - List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);  
234 - if (CollUtil.isEmpty(spuList)) { 227 + // 查询 template 数组
  228 + if (CollUtil.isEmpty(ids)) {
235 return Collections.emptyMap(); 229 return Collections.emptyMap();
236 } 230 }
237 - Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getDeliveryTemplateId);  
238 - List<DeliveryExpressTemplateDO> templateList = expressTemplateMapper.selectBatchIds(spuMap.keySet());  
239 - Map<Long, SpuDeliveryExpressTemplateRespBO> result = new HashMap<>(templateList.size());  
240 - templateList.forEach(item -> {  
241 - ProductSpuRespDTO spu = spuMap.get(item.getId());  
242 - if (spu == null) {  
243 - return;  
244 - }  
245 - // TODO @jason:避免循环查询;最好类似 expressTemplateMapper.selectBatchIds(spuMap.keySet()); 批量查询,内存组合;  
246 - SpuDeliveryExpressTemplateRespBO bo = new SpuDeliveryExpressTemplateRespBO()  
247 - .setChargeMode(item.getChargeMode())  
248 - .setTemplateCharge(findMatchExpressTemplateCharge(item.getId(), areaId))  
249 - .setTemplateFree(findMatchExpressTemplateFree(item.getId(), areaId));  
250 - result.put(spu.getId(), bo);  
251 - });  
252 - return result; 231 + List<DeliveryExpressTemplateDO> templateList = expressTemplateMapper.selectBatchIds(ids);
  232 + // 查询 templateCharge 数组
  233 + List<DeliveryExpressTemplateChargeDO> chargeList = expressTemplateChargeMapper.selectByTemplateIds(ids);
  234 + // 查询 templateFree 数组
  235 + List<DeliveryExpressTemplateFreeDO> freeList = expressTemplateFreeMapper.selectListByTemplateIds(ids);
  236 +
  237 + // 组合运费模板配置 RespBO
  238 + return INSTANCE.convertMap(areaId, templateList, chargeList, freeList);
253 } 239 }
254 240
255 - private DeliveryExpressTemplateChargeBO findMatchExpressTemplateCharge(Long templateId, Integer areaId) {  
256 - return INSTANCE.convertTemplateCharge(findFirst(  
257 - expressTemplateChargeMapper.selectListByTemplateId(templateId), item -> item.getAreaIds().contains(areaId)  
258 - )  
259 - ); 241 + private DeliveryExpressTemplateRespBO.Charge findMatchExpressTemplateCharge(
  242 + List<DeliveryExpressTemplateChargeDO> templateChargeList, Integer areaId) {
  243 + return INSTANCE.convertTemplateCharge(findFirst(templateChargeList, item -> item.getAreaIds().contains(areaId)));
260 } 244 }
261 245
262 - private DeliveryExpressTemplateFreeBO findMatchExpressTemplateFree(Long templateId, Integer areaId) {  
263 - return INSTANCE.convertTemplateFree(findFirst(  
264 - expressTemplateFreeMapper.selectListByTemplateId(templateId), item -> item.getAreaIds().contains(areaId)  
265 - )); 246 + private DeliveryExpressTemplateRespBO.Free findMatchExpressTemplateFree(
  247 + List<DeliveryExpressTemplateFreeDO> templateFreeList, Integer areaId) {
  248 + return INSTANCE.convertTemplateFree(findFirst(templateFreeList, item -> item.getAreaIds().contains(areaId)));
266 } 249 }
267 250
268 } 251 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateFreeBO.java deleted
1 -package cn.iocoder.yudao.module.trade.service.delivery.bo;  
2 -  
3 -import lombok.Data;  
4 -  
5 -/**  
6 - * 快递运费模板包邮配置 BO  
7 - *  
8 - * @author jason  
9 - */  
10 -@Data  
11 -public class DeliveryExpressTemplateFreeBO {  
12 -  
13 - /**  
14 - * 包邮金额,单位:分  
15 - *  
16 - * 订单总金额 > 包邮金额时,才免运费  
17 - */  
18 - private Integer freePrice;  
19 -  
20 - /**  
21 - * 包邮件数  
22 - *  
23 - * 订单总件数 > 包邮件数时,才免运费  
24 - */  
25 - private Integer freeCount;  
26 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateChargeBO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateRespBO.java
1 package cn.iocoder.yudao.module.trade.service.delivery.bo; 1 package cn.iocoder.yudao.module.trade.service.delivery.bo;
2 2
  3 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
3 import lombok.Data; 4 import lombok.Data;
4 5
5 /** 6 /**
6 - * 快递运费模板费用配置 BO 7 + * 运费模板配置 Resp BO
7 * 8 *
8 * @author jason 9 * @author jason
9 */ 10 */
10 @Data 11 @Data
11 -public class DeliveryExpressTemplateChargeBO { 12 +public class DeliveryExpressTemplateRespBO {
12 13
13 /** 14 /**
14 - * 首件数量(件数,重量,或体积) 15 + * 配送计费方式
  16 + *
  17 + * 枚举 {@link DeliveryExpressChargeModeEnum}
15 */ 18 */
16 - private Double startCount; 19 + private Integer chargeMode;
  20 +
17 /** 21 /**
18 - * 起步价,单位:分 22 + * 运费模板快递运费设置
19 */ 23 */
20 - private Integer startPrice; 24 + private Charge charge;
  25 +
  26 + /**
  27 + * 运费模板包邮设置
  28 + */
  29 + private Free free;
  30 +
21 /** 31 /**
22 - * 续件数量(件, 重量,或体积) 32 + * 快递运费模板费用配置 BO
  33 + *
  34 + * @author jason
23 */ 35 */
24 - private Double extraCount; 36 + @Data
  37 + public static class Charge {
  38 +
  39 + /**
  40 + * 首件数量(件数,重量,或体积)
  41 + */
  42 + private Double startCount;
  43 + /**
  44 + * 起步价,单位:分
  45 + */
  46 + private Integer startPrice;
  47 + /**
  48 + * 续件数量(件, 重量,或体积)
  49 + */
  50 + private Double extraCount;
  51 + /**
  52 + * 额外价,单位:分
  53 + */
  54 + private Integer extraPrice;
  55 + }
  56 +
25 /** 57 /**
26 - * 额外价,单位:分 58 + * 快递运费模板包邮配置 BO
  59 + *
  60 + * @author jason
27 */ 61 */
28 - private Integer extraPrice; 62 + @Data
  63 + public static class Free {
  64 +
  65 + /**
  66 + * 包邮金额,单位:分
  67 + *
  68 + * 订单总金额 > 包邮金额时,才免运费
  69 + */
  70 + private Integer freePrice;
  71 +
  72 + /**
  73 + * 包邮件数
  74 + *
  75 + * 订单总件数 > 包邮件数时,才免运费
  76 + */
  77 + private Integer freeCount;
  78 + }
  79 +
29 } 80 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/SpuDeliveryExpressTemplateRespBO.java deleted
1 -package cn.iocoder.yudao.module.trade.service.delivery.bo;  
2 -  
3 -import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;  
4 -import lombok.Data;  
5 -  
6 -/**  
7 - * SPU 运费模板配置 Resp BO  
8 - *  
9 - * @author jason  
10 - */  
11 -@Data  
12 -public class SpuDeliveryExpressTemplateRespBO {  
13 -  
14 - /**  
15 - * 配送计费方式  
16 - *  
17 - * 枚举 {@link DeliveryExpressChargeModeEnum}  
18 - */  
19 - private Integer chargeMode;  
20 -  
21 - // TODO @jaosn:可以把 DeliveryExpressTemplateChargeBO 和 DeliveryExpressTemplateFreeBO 搞成内嵌的类。这样简洁一点  
22 -  
23 - /**  
24 - * 运费模板快递运费设置  
25 - */  
26 - private DeliveryExpressTemplateChargeBO templateCharge;  
27 -  
28 - /**  
29 - * 运费模板包邮设置  
30 - */  
31 - private DeliveryExpressTemplateFreeBO templateFree;  
32 -  
33 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
@@ -342,7 +342,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -342,7 +342,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
342 // TODO 芋艿:logisticsId 校验存在 发货物流公司 fix 342 // TODO 芋艿:logisticsId 校验存在 发货物流公司 fix
343 DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); 343 DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
344 if (deliveryExpress == null) { 344 if (deliveryExpress == null) {
345 - throw exception(DELIVERY_EXPRESS_NOT_EXISTS); 345 + throw exception(EXPRESS_NOT_EXISTS);
346 } 346 }
347 347
348 // 更新 TradeOrderDO 状态为已发货,等待收货 348 // 更新 TradeOrderDO 状态为已发货,等待收货
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
@@ -180,6 +180,11 @@ public class TradePriceCalculateRespBO { @@ -180,6 +180,11 @@ public class TradePriceCalculateRespBO {
180 */ 180 */
181 private Long categoryId; 181 private Long categoryId;
182 182
  183 + /**
  184 + * 运费模板 Id
  185 + */
  186 + private Long deliveryTemplateId;
  187 +
183 // ========== 商品 SKU 信息 ========== 188 // ========== 商品 SKU 信息 ==========
184 /** 189 /**
185 * 商品重量,单位:kg 千克 190 * 商品重量,单位:kg 千克
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
@@ -7,9 +7,7 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; @@ -7,9 +7,7 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
7 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; 7 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
8 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; 8 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
9 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; 9 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
10 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;  
11 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;  
12 -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; 10 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
13 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; 11 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
14 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; 12 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
15 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem; 13 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem;
@@ -24,8 +22,8 @@ import java.util.Set; @@ -24,8 +22,8 @@ import java.util.Set;
24 22
25 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 24 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
27 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY;  
28 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND; 25 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY;
  26 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND;
29 27
30 /** 28 /**
31 * 运费的 {@link TradePriceCalculator} 实现类 29 * 运费的 {@link TradePriceCalculator} 实现类
@@ -49,7 +47,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -49,7 +47,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
49 return; 47 return;
50 } 48 }
51 if (param.getAddressId() == null) { 49 if (param.getAddressId() == null) {
52 - throw exception(DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY); 50 + throw exception(PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY);
53 } 51 }
54 // 1.2 得到收件地址区域 52 // 1.2 得到收件地址区域
55 AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId()); 53 AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
@@ -57,29 +55,29 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -57,29 +55,29 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
57 55
58 // 2. 过滤出已选中的商品SKU 56 // 2. 过滤出已选中的商品SKU
59 List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected); 57 List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
60 - Set<Long> spuIds = convertSet(selectedItem, OrderItem::getSpuId);  
61 - Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap =  
62 - deliveryExpressTemplateService.getExpressTemplateMapBySpuIdsAndArea(spuIds, address.getAreaId()); 58 + Set<Long> deliveryTemplateIds = convertSet(selectedItem, OrderItem::getDeliveryTemplateId);
  59 + Map<Long, DeliveryExpressTemplateRespBO> expressTemplateMap =
  60 + deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(deliveryTemplateIds, address.getAreaId());
63 // 3. 计算配送费用 61 // 3. 计算配送费用
64 - if (CollUtil.isEmpty(spuExpressTemplateMap)) {  
65 - log.error("[calculate][找不到商品 spuId{} areaId{} 对应的运费模板]", spuIds, address.getAreaId());  
66 - throw exception(PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND); 62 + if (CollUtil.isEmpty(expressTemplateMap)) {
  63 + log.error("[calculate][找不到商品 templateIds {} areaId{} 对应的运费模板]", deliveryTemplateIds, address.getAreaId());
  64 + throw exception(PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND);
67 } 65 }
68 - calculateDeliveryPrice(selectedItem, spuExpressTemplateMap, result); 66 + calculateDeliveryPrice(selectedItem, expressTemplateMap, result);
69 } 67 }
70 68
71 private void calculateDeliveryPrice(List<OrderItem> selectedSkus, 69 private void calculateDeliveryPrice(List<OrderItem> selectedSkus,
72 - Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap, 70 + Map<Long, DeliveryExpressTemplateRespBO> expressTemplateMap,
73 TradePriceCalculateRespBO result) { 71 TradePriceCalculateRespBO result) {
74 - // 按 SPU 来计算商品的运费:一个 spuId 可能对应多条订单商品 SKU  
75 - Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedSkus, OrderItem::getSpuId);  
76 - // 依次计算每个 SPU 的快递运费  
77 - for (Map.Entry<Long, List<OrderItem>> entry : spuIdItemMap.entrySet()) {  
78 - Long spuId = entry.getKey(); 72 + // 按商品运费模板来计算商品的运费:相同的运费模板可能对应多条订单商品 SKU
  73 + Map<Long, List<OrderItem>> tplIdItemMap = convertMultiMap(selectedSkus, OrderItem::getDeliveryTemplateId);
  74 + // 依次计算快递运费
  75 + for (Map.Entry<Long, List<OrderItem>> entry : tplIdItemMap.entrySet()) {
  76 + Long templateId = entry.getKey();
79 List<OrderItem> orderItems = entry.getValue(); 77 List<OrderItem> orderItems = entry.getValue();
80 - SpuDeliveryExpressTemplateRespBO templateBO = spuExpressTemplateMap.get(spuId); 78 + DeliveryExpressTemplateRespBO templateBO = expressTemplateMap.get(templateId);
81 if (templateBO == null) { 79 if (templateBO == null) {
82 - log.error("不能计算快递运费。不能找到 spuId : {}. 对应的运费模板配置 Resp BO", spuId); 80 + log.error("[calculateDeliveryPrice][不能计算快递运费,找不到 templateId({}) 对应的运费模板配置]", templateId);
83 continue; 81 continue;
84 } 82 }
85 // 总件数, 总金额, 总重量, 总体积 83 // 总件数, 总金额, 总重量, 总体积
@@ -95,12 +93,12 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -95,12 +93,12 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
95 } 93 }
96 // 优先判断是否包邮. 如果包邮不计算快递运费 94 // 优先判断是否包邮. 如果包邮不计算快递运费
97 if (isExpressFree(templateBO.getChargeMode(), totalCount, totalWeight, 95 if (isExpressFree(templateBO.getChargeMode(), totalCount, totalWeight,
98 - totalVolume, totalPrice, templateBO.getTemplateFree())) { 96 + totalVolume, totalPrice, templateBO.getFree())) {
99 continue; 97 continue;
100 } 98 }
101 // 计算快递运费 99 // 计算快递运费
102 calculateExpressFeeByChargeMode(totalCount, totalWeight, totalVolume, 100 calculateExpressFeeByChargeMode(totalCount, totalWeight, totalVolume,
103 - templateBO.getChargeMode(), templateBO.getTemplateCharge(), orderItems); 101 + templateBO.getChargeMode(), templateBO.getCharge(), orderItems);
104 102
105 } 103 }
106 TradePriceCalculatorHelper.recountAllPrice(result); 104 TradePriceCalculatorHelper.recountAllPrice(result);
@@ -117,10 +115,10 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -117,10 +115,10 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
117 * @param orderItems SKU 商品项目 115 * @param orderItems SKU 商品项目
118 */ 116 */
119 private void calculateExpressFeeByChargeMode(double totalCount, double totalWeight, double totalVolume, 117 private void calculateExpressFeeByChargeMode(double totalCount, double totalWeight, double totalVolume,
120 - int chargeMode, DeliveryExpressTemplateChargeBO templateCharge, 118 + int chargeMode, DeliveryExpressTemplateRespBO.Charge templateCharge,
121 List<OrderItem> orderItems) { 119 List<OrderItem> orderItems) {
122 if (templateCharge == null) { 120 if (templateCharge == null) {
123 - log.error("计算快递运费时,不能找到对应的快递运费模板费用配置。无法计算以下商品 SKU 项目运费: {}", orderItems); 121 + log.error("[calculateExpressFeeByChargeMode][计算快递运费时,找不到 SKU({}) 对应的运费模版]", orderItems);
124 return; 122 return;
125 } 123 }
126 DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode); 124 DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode);
@@ -147,7 +145,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -147,7 +145,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
147 * @param templateCharge 快递运费配置 145 * @param templateCharge 快递运费配置
148 * @param orderItems SKU 商品项目 146 * @param orderItems SKU 商品项目
149 */ 147 */
150 - private void calculateExpressFee(double total, DeliveryExpressTemplateChargeBO templateCharge, List<OrderItem> orderItems) { 148 + private void calculateExpressFee(double total, DeliveryExpressTemplateRespBO.Charge templateCharge, List<OrderItem> orderItems) {
151 int deliveryPrice; 149 int deliveryPrice;
152 if (total <= templateCharge.getStartCount()) { 150 if (total <= templateCharge.getStartCount()) {
153 deliveryPrice = templateCharge.getStartPrice(); 151 deliveryPrice = templateCharge.getStartPrice();
@@ -176,7 +174,6 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -176,7 +174,6 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
176 for (OrderItem item : orderItems) { 174 for (OrderItem item : orderItems) {
177 // 更新快递运费 175 // 更新快递运费
178 item.setDeliveryPrice(dividePrice); 176 item.setDeliveryPrice(dividePrice);
179 -  
180 TradePriceCalculatorHelper.recountPayPrice(item); 177 TradePriceCalculatorHelper.recountPayPrice(item);
181 } 178 }
182 } 179 }
@@ -192,7 +189,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -192,7 +189,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
192 * @param templateFree 包邮配置 189 * @param templateFree 包邮配置
193 */ 190 */
194 private boolean isExpressFree(Integer chargeMode, int totalCount, double totalWeight, 191 private boolean isExpressFree(Integer chargeMode, int totalCount, double totalWeight,
195 - double totalVolume, int totalPrice, DeliveryExpressTemplateFreeBO templateFree) { 192 + double totalVolume, int totalPrice, DeliveryExpressTemplateRespBO.Free templateFree) {
196 if (templateFree == null) { 193 if (templateFree == null) {
197 return false; 194 return false;
198 } 195 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
@@ -56,7 +56,8 @@ public class TradePriceCalculatorHelper { @@ -56,7 +56,8 @@ public class TradePriceCalculatorHelper {
56 orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties()) 56 orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties())
57 .setWeight(sku.getWeight()).setVolume(sku.getVolume()); 57 .setWeight(sku.getWeight()).setVolume(sku.getVolume());
58 // spu 信息 58 // spu 信息
59 - orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId()); 59 + orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId())
  60 + .setDeliveryTemplateId(spu.getDeliveryTemplateId());
60 if (orderItem.getPicUrl() == null) { 61 if (orderItem.getPicUrl() == null) {
61 orderItem.setPicUrl(spu.getPicUrl()); 62 orderItem.setPicUrl(spu.getPicUrl());
62 } 63 }
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/Kd100ExpressQueryProviderTest.java renamed to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/Kd100ExpressClientTest.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.impl; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
4 -import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressQueryProperties;  
5 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO; 4 +import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  6 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kd100.Kd100ExpressClient;
6 import org.junit.jupiter.api.BeforeEach; 7 import org.junit.jupiter.api.BeforeEach;
7 import org.junit.jupiter.api.Disabled; 8 import org.junit.jupiter.api.Disabled;
8 import org.junit.jupiter.api.Test; 9 import org.junit.jupiter.api.Test;
@@ -18,39 +19,41 @@ import javax.annotation.Resource; @@ -18,39 +19,41 @@ import javax.annotation.Resource;
18 import static org.junit.jupiter.api.Assertions.assertEquals; 19 import static org.junit.jupiter.api.Assertions.assertEquals;
19 import static org.junit.jupiter.api.Assertions.assertThrows; 20 import static org.junit.jupiter.api.Assertions.assertThrows;
20 21
  22 +// TODO @jason:可以参考 AliyunSmsClientTest 写,纯 mockito,无需启动 spring 容器
21 /** 23 /**
22 * @author jason 24 * @author jason
23 */ 25 */
24 -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = Kd100ExpressQueryProviderTest.Application.class)  
25 -@ActiveProfiles("trade-delivery-query") // 设置使用 trade-delivery-query 配置文件  
26 -public class Kd100ExpressQueryProviderTest { 26 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = Kd100ExpressClientTest.Application.class)
  27 +@ActiveProfiles("unit-test") // 设置使用 trade-delivery-query 配置文件
  28 +public class Kd100ExpressClientTest {
  29 +
27 @Resource 30 @Resource
28 private RestTemplateBuilder builder; 31 private RestTemplateBuilder builder;
29 @Resource 32 @Resource
30 - private TradeExpressQueryProperties expressQueryProperties; 33 + private TradeExpressProperties expressQueryProperties;
31 34
32 - private Kd100ExpressQueryProvider kd100ExpressQueryProvider; 35 + private Kd100ExpressClient kd100ExpressClient;
33 36
34 @BeforeEach 37 @BeforeEach
35 public void init(){ 38 public void init(){
36 - kd100ExpressQueryProvider = new Kd100ExpressQueryProvider(builder.build(),expressQueryProperties.getKd100()); 39 + kd100ExpressClient = new Kd100ExpressClient(builder.build(),expressQueryProperties.getKd100());
37 } 40 }
38 @Test 41 @Test
39 @Disabled("需要 授权 key. 暂时忽略") 42 @Disabled("需要 授权 key. 暂时忽略")
40 void testRealTimeQueryExpressFailed() { 43 void testRealTimeQueryExpressFailed() {
41 ServiceException t = assertThrows(ServiceException.class, () -> { 44 ServiceException t = assertThrows(ServiceException.class, () -> {
42 - ExpressQueryReqDTO reqDTO = new ExpressQueryReqDTO();  
43 - reqDTO.setExpressCompanyCode("yto"); 45 + ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
  46 + reqDTO.setExpressCode("yto");
44 reqDTO.setLogisticsNo("YT9383342193097"); 47 reqDTO.setLogisticsNo("YT9383342193097");
45 - kd100ExpressQueryProvider.realTimeQueryExpress(reqDTO); 48 + kd100ExpressClient.getExpressTrackList(reqDTO);
46 }); 49 });
47 - assertEquals(1011003007, t.getCode()); 50 + assertEquals(1011003005, t.getCode());
48 } 51 }
49 52
50 @Import({ 53 @Import({
51 RestTemplateAutoConfiguration.class 54 RestTemplateAutoConfiguration.class
52 }) 55 })
53 - @EnableConfigurationProperties(TradeExpressQueryProperties.class) 56 + @EnableConfigurationProperties(TradeExpressProperties.class)
54 public static class Application { 57 public static class Application {
55 } 58 }
56 -}  
57 \ No newline at end of file 59 \ No newline at end of file
  60 +}
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/framework/delivery/core/impl/KdNiaoExpressQueryProviderTest.java renamed to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/KdNiaoExpressClientTest.java
1 -package cn.iocoder.yudao.module.trade.framework.delivery.core.impl; 1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
4 -import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressQueryProperties;  
5 -import cn.iocoder.yudao.module.trade.framework.delivery.core.dto.ExpressQueryReqDTO; 4 +import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
  6 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kdniao.KdNiaoExpressClient;
6 import org.junit.jupiter.api.BeforeEach; 7 import org.junit.jupiter.api.BeforeEach;
7 import org.junit.jupiter.api.Disabled; 8 import org.junit.jupiter.api.Disabled;
8 import org.junit.jupiter.api.Test; 9 import org.junit.jupiter.api.Test;
@@ -17,39 +18,42 @@ import javax.annotation.Resource; @@ -17,39 +18,42 @@ import javax.annotation.Resource;
17 18
18 import static org.junit.jupiter.api.Assertions.assertThrows; 19 import static org.junit.jupiter.api.Assertions.assertThrows;
19 20
20 -// TODO @芋艿:单测最后 review 21 +// TODO @jason:可以参考 AliyunSmsClientTest 写,纯 mockito,无需启动 spring 容器
21 /** 22 /**
  23 + * {@link KdNiaoExpressClient} 的单元测试
  24 + *
22 * @author jason 25 * @author jason
23 */ 26 */
24 -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = KdNiaoExpressQueryProviderTest.Application.class)  
25 -@ActiveProfiles("trade-delivery-query") // 设置使用 trade-delivery-query 配置文件 TODO @jason:可以直接写到 application-unit-test.yaml 配置文件里  
26 -public class KdNiaoExpressQueryProviderTest { 27 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = KdNiaoExpressClientTest.Application.class)
  28 +@ActiveProfiles("unit-test")
  29 +public class KdNiaoExpressClientTest {
  30 +
27 @Resource 31 @Resource
28 private RestTemplateBuilder builder; 32 private RestTemplateBuilder builder;
29 @Resource 33 @Resource
30 - private TradeExpressQueryProperties expressQueryProperties; 34 + private TradeExpressProperties expressQueryProperties;
31 35
32 - private KdNiaoExpressQueryProvider kdNiaoExpressQueryProvider; 36 + private KdNiaoExpressClient kdNiaoExpressClient;
33 37
34 @BeforeEach 38 @BeforeEach
35 public void init(){ 39 public void init(){
36 - kdNiaoExpressQueryProvider = new KdNiaoExpressQueryProvider(builder.build(),expressQueryProperties.getKdNiao()); 40 + kdNiaoExpressClient = new KdNiaoExpressClient(builder.build(),expressQueryProperties.getKdNiao());
37 } 41 }
38 @Test 42 @Test
39 @Disabled("需要 授权 key. 暂时忽略") 43 @Disabled("需要 授权 key. 暂时忽略")
40 void testRealTimeQueryExpressFailed() { 44 void testRealTimeQueryExpressFailed() {
41 assertThrows(ServiceException.class,() ->{ 45 assertThrows(ServiceException.class,() ->{
42 - ExpressQueryReqDTO reqDTO = new ExpressQueryReqDTO();  
43 - reqDTO.setExpressCompanyCode("yy"); 46 + ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
  47 + reqDTO.setExpressCode("yy");
44 reqDTO.setLogisticsNo("YT9383342193097"); 48 reqDTO.setLogisticsNo("YT9383342193097");
45 - kdNiaoExpressQueryProvider.realTimeQueryExpress(reqDTO); 49 + kdNiaoExpressClient.getExpressTrackList(reqDTO);
46 }); 50 });
47 } 51 }
48 52
49 @Import({ 53 @Import({
50 RestTemplateAutoConfiguration.class 54 RestTemplateAutoConfiguration.class
51 }) 55 })
52 - @EnableConfigurationProperties(TradeExpressQueryProperties.class) 56 + @EnableConfigurationProperties(TradeExpressProperties.class)
53 public static class Application { 57 public static class Application {
54 } 58 }
55 } 59 }
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/NoProvideExpressClientTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.common.exception.ServiceException;
  4 +import cn.iocoder.yudao.module.trade.framework.delivery.config.ExpressClientConfig;
  5 +import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
  6 +import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClient;
  7 +import org.junit.jupiter.api.Test;
  8 +import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
  9 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  10 +import org.springframework.boot.test.context.SpringBootTest;
  11 +import org.springframework.boot.web.client.RestTemplateBuilder;
  12 +import org.springframework.context.annotation.Bean;
  13 +import org.springframework.context.annotation.Import;
  14 +import org.springframework.test.context.ActiveProfiles;
  15 +import org.springframework.web.client.RestTemplate;
  16 +
  17 +import javax.annotation.Resource;
  18 +
  19 +import static org.junit.jupiter.api.Assertions.assertEquals;
  20 +import static org.junit.jupiter.api.Assertions.assertThrows;
  21 +
  22 +// TODO @jason:可以参考 AliyunSmsClientTest 写,纯 mockito,无需启动 spring 容器
  23 +/**
  24 + * @author jason
  25 + */
  26 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = NoProvideExpressClientTest.Application.class)
  27 +@ActiveProfiles("unit-test") // 设置使用 trade-delivery-query 配置文件
  28 +@Import({ExpressClientConfig.class})
  29 +public class NoProvideExpressClientTest {
  30 +
  31 + @Resource
  32 + private ExpressClient expressClient;
  33 +
  34 + @Test
  35 + void getExpressTrackList() {
  36 + ServiceException t = assertThrows(ServiceException.class, () -> {
  37 + expressClient.getExpressTrackList(null);
  38 + });
  39 + assertEquals(1011003006, t.getCode());
  40 + }
  41 +
  42 + @Import({
  43 + RestTemplateAutoConfiguration.class,
  44 + })
  45 + @EnableConfigurationProperties(TradeExpressProperties.class)
  46 + public static class Application {
  47 +
  48 + @Bean
  49 + private RestTemplate restTemplate(RestTemplateBuilder builder) {
  50 + return builder.build();
  51 + }
  52 + }
  53 +}
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculatorTest.java
1 package cn.iocoder.yudao.module.trade.service.price.calculator; 1 package cn.iocoder.yudao.module.trade.service.price.calculator;
2 2
  3 +import cn.hutool.core.map.MapUtil;
3 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4 import cn.iocoder.yudao.module.member.api.address.AddressApi; 5 import cn.iocoder.yudao.module.member.api.address.AddressApi;
5 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 6 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
  7 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
  8 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
6 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; 9 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
7 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;  
8 -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;  
9 -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; 10 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
10 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; 11 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
11 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; 12 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
12 import org.junit.jupiter.api.BeforeEach; 13 import org.junit.jupiter.api.BeforeEach;
@@ -16,20 +17,17 @@ import org.mockito.InjectMocks; @@ -16,20 +17,17 @@ import org.mockito.InjectMocks;
16 import org.mockito.Mock; 17 import org.mockito.Mock;
17 18
18 import java.util.ArrayList; 19 import java.util.ArrayList;
19 -import java.util.HashMap;  
20 -import java.util.Map;  
21 20
22 import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; 21 import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
23 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 22 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
24 -import static cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum.PIECE;  
25 -import static cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum.EXPRESS;  
26 import static java.util.Arrays.asList; 23 import static java.util.Arrays.asList;
  24 +import static org.assertj.core.api.Assertions.assertThat;
27 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.ArgumentMatchers.eq;
28 import static org.mockito.Mockito.when; 26 import static org.mockito.Mockito.when;
29 27
30 -import static org.assertj.core.api.Assertions.assertThat;  
31 -  
32 /** 28 /**
  29 + * {@link TradeDeliveryPriceCalculator} 的单元测试
  30 + *
33 * @author jason 31 * @author jason
34 */ 32 */
35 public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { 33 public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
@@ -43,49 +41,52 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { @@ -43,49 +41,52 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
43 41
44 private TradePriceCalculateReqBO reqBO; 42 private TradePriceCalculateReqBO reqBO;
45 private TradePriceCalculateRespBO resultBO; 43 private TradePriceCalculateRespBO resultBO;
46 - private AddressRespDTO addressResp;  
47 - private DeliveryExpressTemplateChargeBO chargeBO;  
48 - private DeliveryExpressTemplateFreeBO freeBO;  
49 - private SpuDeliveryExpressTemplateRespBO spuTemplateRespBO; 44 +
  45 + private DeliveryExpressTemplateRespBO templateRespBO;
  46 + private DeliveryExpressTemplateRespBO.Charge chargeBO;
  47 + private DeliveryExpressTemplateRespBO.Free freeBO;
50 48
51 @BeforeEach 49 @BeforeEach
52 public void init(){ 50 public void init(){
53 // 准备参数 51 // 准备参数
54 reqBO = new TradePriceCalculateReqBO() 52 reqBO = new TradePriceCalculateReqBO()
55 - .setDeliveryType(EXPRESS.getMode()) 53 + .setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode())
56 .setAddressId(10L) 54 .setAddressId(10L)
57 .setUserId(1L) 55 .setUserId(1L)
58 .setItems(asList( 56 .setItems(asList(
59 new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), 57 new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true),
60 new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(10).setSelected(true), 58 new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(10).setSelected(true),
61 - new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(false) 59 + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(false) // 未选中
62 )); 60 ));
63 resultBO = new TradePriceCalculateRespBO() 61 resultBO = new TradePriceCalculateRespBO()
64 .setPrice(new TradePriceCalculateRespBO.Price()) 62 .setPrice(new TradePriceCalculateRespBO.Price())
65 .setPromotions(new ArrayList<>()) 63 .setPromotions(new ArrayList<>())
66 .setItems(asList( 64 .setItems(asList(
67 - new TradePriceCalculateRespBO.OrderItem().setSpuId(1L).setSkuId(10L).setCount(2).setSelected(true) 65 + new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(10L).setCount(2).setSelected(true)
68 .setWeight(10d).setVolume(10d).setPrice(100), 66 .setWeight(10d).setVolume(10d).setPrice(100),
69 - new TradePriceCalculateRespBO.OrderItem().setSpuId(1L).setSkuId(20L).setCount(10).setSelected(true) 67 + new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(20L).setCount(10).setSelected(true)
70 .setWeight(10d).setVolume(10d).setPrice(200), 68 .setWeight(10d).setVolume(10d).setPrice(200),
71 - new TradePriceCalculateRespBO.OrderItem().setSpuId(1L).setSkuId(30L).setCount(1).setSelected(false) 69 + new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(30L).setCount(1).setSelected(false)
72 .setWeight(10d).setVolume(10d).setPrice(300) 70 .setWeight(10d).setVolume(10d).setPrice(300)
73 )); 71 ));
74 // 保证价格被初始化上 72 // 保证价格被初始化上
75 TradePriceCalculatorHelper.recountPayPrice(resultBO.getItems()); 73 TradePriceCalculatorHelper.recountPayPrice(resultBO.getItems());
76 TradePriceCalculatorHelper.recountAllPrice(resultBO); 74 TradePriceCalculatorHelper.recountAllPrice(resultBO);
  75 +
77 // 准备收件地址数据 76 // 准备收件地址数据
78 - addressResp = randomPojo(AddressRespDTO.class, item -> item.setAreaId(10)); 77 + AddressRespDTO addressResp = randomPojo(AddressRespDTO.class, item -> item.setAreaId(10));
  78 + when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);
  79 +
79 // 准备运费模板费用配置数据 80 // 准备运费模板费用配置数据
80 - chargeBO = randomPojo(DeliveryExpressTemplateChargeBO.class, 81 + chargeBO = randomPojo(DeliveryExpressTemplateRespBO.Charge.class,
81 item -> item.setStartCount(10D).setStartPrice(1000).setExtraCount(10D).setExtraPrice(2000)); 82 item -> item.setStartCount(10D).setStartPrice(1000).setExtraCount(10D).setExtraPrice(2000));
82 - // 准备运费模板包邮配置数据 订单总件数 < 包邮件数时 12 < 20  
83 - freeBO = randomPojo(DeliveryExpressTemplateFreeBO.class, 83 + // 准备运费模板包邮配置数据:订单总件数 < 包邮件数时 12 < 20
  84 + freeBO = randomPojo(DeliveryExpressTemplateRespBO.Free.class,
84 item -> item.setFreeCount(20).setFreePrice(100)); 85 item -> item.setFreeCount(20).setFreePrice(100));
85 - // 准备 SP 运费模板 数据  
86 - spuTemplateRespBO = randomPojo(SpuDeliveryExpressTemplateRespBO.class,  
87 - item -> item.setChargeMode(PIECE.getType())  
88 - .setTemplateCharge(chargeBO).setTemplateFree(freeBO)); 86 + // 准备 SP 运费模板数据
  87 + templateRespBO = randomPojo(DeliveryExpressTemplateRespBO.class,
  88 + item -> item.setChargeMode(DeliveryExpressChargeModeEnum.PIECE.getType())
  89 + .setCharge(chargeBO).setFree(freeBO));
89 } 90 }
90 91
91 @Test 92 @Test
@@ -94,32 +95,27 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { @@ -94,32 +95,27 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
94 // SKU 1 : 100 * 2 = 200 95 // SKU 1 : 100 * 2 = 200
95 // SKU 2 :200 * 10 = 2000 96 // SKU 2 :200 * 10 = 2000
96 // 运费 首件 1000 + 续件 2000 = 3000 97 // 运费 首件 1000 + 续件 2000 = 3000
97 - Map<Long, SpuDeliveryExpressTemplateRespBO> respMap = new HashMap<>();  
98 - respMap.put(1L, spuTemplateRespBO);  
99 -  
100 // mock 方法 98 // mock 方法
101 - when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);  
102 - when(deliveryExpressTemplateService.getExpressTemplateMapBySpuIdsAndArea(eq(asSet(1L)), eq(10)))  
103 - .thenReturn(respMap); 99 + when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10)))
  100 + .thenReturn(MapUtil.of(1L, templateRespBO));
104 101
  102 + // 调用
105 calculator.calculate(reqBO, resultBO); 103 calculator.calculate(reqBO, resultBO);
106 - 104 + // 断言
107 TradePriceCalculateRespBO.Price price = resultBO.getPrice(); 105 TradePriceCalculateRespBO.Price price = resultBO.getPrice();
108 -  
109 assertThat(price) 106 assertThat(price)
110 .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice") 107 .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice")
111 .containsExactly(2200, 0, 0, 0, 3000, 5200); 108 .containsExactly(2200, 0, 0, 0, 3000, 5200);
112 - // 断言:SKU  
113 assertThat(resultBO.getItems()).hasSize(3); 109 assertThat(resultBO.getItems()).hasSize(3);
114 - // SKU1 110 + // 断言:SKU1
115 assertThat(resultBO.getItems().get(0)) 111 assertThat(resultBO.getItems().get(0))
116 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") 112 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
117 .containsExactly(100, 2, 0, 0, 0, 1500, 1700); 113 .containsExactly(100, 2, 0, 0, 0, 1500, 1700);
118 - // SKU2 114 + // 断言:SKU2
119 assertThat(resultBO.getItems().get(1)) 115 assertThat(resultBO.getItems().get(1))
120 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") 116 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
121 .containsExactly(200, 10, 0, 0, 0, 1500, 3500); 117 .containsExactly(200, 10, 0, 0, 0, 1500, 3500);
122 - // SKU3 未选中 118 + // 断言:SKU3 未选中
123 assertThat(resultBO.getItems().get(2)) 119 assertThat(resultBO.getItems().get(2))
124 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") 120 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
125 .containsExactly(300, 1, 0, 0, 0, 0, 300); 121 .containsExactly(300, 1, 0, 0, 0, 0, 300);
@@ -131,38 +127,33 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { @@ -131,38 +127,33 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
131 // SKU 1 : 100 * 2 = 200 127 // SKU 1 : 100 * 2 = 200
132 // SKU 2 :200 * 10 = 2000 128 // SKU 2 :200 * 10 = 2000
133 // 运费 0 129 // 运费 0
134 - Map<Long, SpuDeliveryExpressTemplateRespBO> respMap = new HashMap<>();  
135 - respMap.put(1L, spuTemplateRespBO);  
136 - // 准备运费模板包邮配置数据 包邮 订单总件数 > 包邮件数时 12 > 10  
137 - freeBO = randomPojo(DeliveryExpressTemplateFreeBO.class,  
138 - item -> item.setFreeCount(10).setFreePrice(1000));  
139 - spuTemplateRespBO.setTemplateFree(freeBO);  
140 // mock 方法 130 // mock 方法
141 - when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);  
142 - when(deliveryExpressTemplateService.getExpressTemplateMapBySpuIdsAndArea(eq(asSet(1L)), eq(10)))  
143 - .thenReturn(respMap); 131 + // 准备运费模板包邮配置数据 包邮 订单总件数 > 包邮件数时 12 > 10
  132 + templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class,
  133 + item -> item.setFreeCount(10).setFreePrice(1000)));
  134 + when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10)))
  135 + .thenReturn(MapUtil.of(1L, templateRespBO));
144 136
  137 + // 调用
145 calculator.calculate(reqBO, resultBO); 138 calculator.calculate(reqBO, resultBO);
146 - 139 + // 断言
147 TradePriceCalculateRespBO.Price price = resultBO.getPrice(); 140 TradePriceCalculateRespBO.Price price = resultBO.getPrice();
148 -  
149 - // 断言price  
150 assertThat(price) 141 assertThat(price)
151 .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice") 142 .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice")
152 .containsExactly(2200, 0, 0, 0, 0, 2200); 143 .containsExactly(2200, 0, 0, 0, 0, 2200);
153 - // 断言:SKU  
154 assertThat(resultBO.getItems()).hasSize(3); 144 assertThat(resultBO.getItems()).hasSize(3);
155 - // SKU1 145 + // 断言:SKU1
156 assertThat(resultBO.getItems().get(0)) 146 assertThat(resultBO.getItems().get(0))
157 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") 147 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
158 .containsExactly(100, 2, 0, 0, 0, 0, 200); 148 .containsExactly(100, 2, 0, 0, 0, 0, 200);
159 - // SKU2 149 + // 断言:SKU2
160 assertThat(resultBO.getItems().get(1)) 150 assertThat(resultBO.getItems().get(1))
161 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") 151 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
162 .containsExactly(200, 10, 0, 0, 0, 0, 2000); 152 .containsExactly(200, 10, 0, 0, 0, 0, 2000);
163 - // SKU3 未选中 153 + // 断言:SKU3 未选中
164 assertThat(resultBO.getItems().get(2)) 154 assertThat(resultBO.getItems().get(2))
165 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") 155 .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
166 .containsExactly(300, 1, 0, 0, 0, 0, 300); 156 .containsExactly(300, 1, 0, 0, 0, 0, 300);
167 } 157 }
168 -}  
169 \ No newline at end of file 158 \ No newline at end of file
  159 +
  160 +}
yudao-module-mall/yudao-module-trade-biz/src/test/resources/application-trade-delivery-query.yaml deleted
1 -spring:  
2 - main:  
3 - lazy-initialization: true # 开启懒加载,加快速度  
4 - banner-mode: off # 单元测试,禁用 Banner  
5 -  
6 ---- #################### 交易快递查询相关配置 ####################  
7 -  
8 -yudao:  
9 - trade:  
10 - express:  
11 - query:  
12 - express-query-provider: kd_niao  
13 - kd-niao:  
14 - api-key: xxx  
15 - business-id: xxxxxxxx  
16 - kd100:  
17 - customer: xxxx  
18 - key: xxxxx  
yudao-module-mall/yudao-module-trade-biz/src/test/resources/application-unit-test.yaml
@@ -51,3 +51,11 @@ yudao: @@ -51,3 +51,11 @@ yudao:
51 order: 51 order:
52 app-id: 1 52 app-id: 1
53 merchant-order-id: 1 53 merchant-order-id: 1
  54 + express:
  55 + kd-niao:
  56 + api-key: xxxx
  57 + business-id: xxxxx
  58 + kd100:
  59 + customer: xxxxx
  60 + key: xxxxx
  61 + client: not_provide
54 \ No newline at end of file 62 \ No newline at end of file
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointConfigController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.point;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigRespVO;
  5 +import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigSaveReqVO;
  6 +import cn.iocoder.yudao.module.member.convert.point.MemberPointConfigConvert;
  7 +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
  8 +import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +import io.swagger.v3.oas.annotations.tags.Tag;
  11 +import org.springframework.security.access.prepost.PreAuthorize;
  12 +import org.springframework.validation.annotation.Validated;
  13 +import org.springframework.web.bind.annotation.*;
  14 +
  15 +import javax.annotation.Resource;
  16 +import javax.validation.Valid;
  17 +
  18 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  19 +
  20 +@Tag(name = "管理后台 - 会员积分设置")
  21 +@RestController
  22 +@RequestMapping("/point/config")
  23 +@Validated
  24 +public class MemberPointConfigController {
  25 +
  26 + @Resource
  27 + private MemberPointConfigService memberPointConfigService;
  28 +
  29 + @PutMapping("/update")
  30 + @Operation(summary = "保存会员积分配置")
  31 + @PreAuthorize("@ss.hasPermission('member:point-config:save')")
  32 + public CommonResult<Boolean> updateConfig(@Valid @RequestBody MemberPointConfigSaveReqVO saveReqVO) {
  33 + memberPointConfigService.saveConfig(saveReqVO);
  34 + return success(true);
  35 + }
  36 +
  37 + @GetMapping("/get")
  38 + @Operation(summary = "获得会员积分配置")
  39 + @PreAuthorize("@ss.hasPermission('member:point-config:query')")
  40 + public CommonResult<MemberPointConfigRespVO> getConfig() {
  41 + MemberPointConfigDO config = memberPointConfigService.getConfig();
  42 + return success(MemberPointConfigConvert.INSTANCE.convert(config));
  43 + }
  44 +
  45 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.point.vo.config;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.math.BigDecimal;
  7 +
  8 +/**
  9 + * 会员积分配置 Base VO,提供给添加、修改、详细的子 VO 使用
  10 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  11 + */
  12 +@Data
  13 +public class MemberPointConfigBaseVO {
  14 +
  15 + @Schema(description = "积分抵扣开关", required = true, example = "true")
  16 + private Boolean tradeDeductEnable;
  17 +
  18 + @Schema(description = "积分抵扣,单位:分", example = "13506")
  19 + private BigDecimal tradeDeductUnitPrice;
  20 +
  21 + @Schema(description = "积分抵扣最大值", example = "32428")
  22 + private Long tradeDeductMaxPrice;
  23 +
  24 + @Schema(description = "1 元赠送多少分")
  25 + private Long tradeGivePoint;
  26 +
  27 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.point.vo.config;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@Schema(description = "管理后台 - 会员积分配置 Response VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class MemberPointConfigRespVO extends MemberPointConfigBaseVO {
  13 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.point.vo.config;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@Schema(description = "管理后台 - 会员积分配置保存 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class MemberPointConfigSaveReqVO extends MemberPointConfigBaseVO {
  13 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/recrod/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod;
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointConfigConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.convert.point;
  2 +
  3 +import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigRespVO;
  4 +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
  5 +import org.mapstruct.Mapper;
  6 +import org.mapstruct.factory.Mappers;
  7 +
  8 +/**
  9 + * 会员积分配置 Convert
  10 + *
  11 + * @author QingX
  12 + */
  13 +@Mapper
  14 +public interface MemberPointConfigConvert {
  15 +
  16 + MemberPointConfigConvert INSTANCE = Mappers.getMapper(MemberPointConfigConvert.class);
  17 +
  18 + MemberPointConfigRespVO convert(MemberPointConfigDO bean);
  19 +
  20 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.dal.dataobject.point;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.math.BigDecimal;
  10 +
  11 +/**
  12 + * 会员积分配置 DO
  13 + *
  14 + * @author QingX
  15 + */
  16 +@TableName("member_point_config")
  17 +@KeySequence("member_point_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class MemberPointConfigDO extends BaseDO {
  25 +
  26 + /**
  27 + * 自增主键
  28 + */
  29 + @TableId
  30 + private Integer id;
  31 + /**
  32 + * 积分抵扣开关
  33 + */
  34 + private Boolean tradeDeductEnable;
  35 + /**
  36 + * 积分抵扣,单位:分
  37 + *
  38 + * 1 积分抵扣多少分
  39 + */
  40 + private BigDecimal tradeDeductUnitPrice;
  41 + /**
  42 + * 积分抵扣最大值
  43 + */
  44 + private Integer tradeDeductMaxPrice;
  45 + /**
  46 + * 1 元赠送多少分
  47 + */
  48 + private Integer tradeGivePoint;
  49 +
  50 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointConfigMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.dal.mysql.point;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * 积分设置 Mapper
  9 + *
  10 + * @author QingX
  11 + */
  12 +@Mapper
  13 +public interface MemberPointConfigMapper extends BaseMapperX<MemberPointConfigDO> {
  14 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointConfigService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.service.point;
  2 +
  3 +import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigSaveReqVO;
  4 +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
  5 +
  6 +import javax.validation.Valid;
  7 +
  8 +/**
  9 + * 会员积分配置 Service 接口
  10 + *
  11 + * @author QingX
  12 + */
  13 +public interface MemberPointConfigService {
  14 +
  15 + /**
  16 + * 保存会员积分配置
  17 + *
  18 + * @param saveReqVO 更新信息
  19 + */
  20 + void saveConfig(@Valid MemberPointConfigSaveReqVO saveReqVO);
  21 +
  22 + /**
  23 + * 获得会员积分配置
  24 + *
  25 + * @return 积分配置
  26 + */
  27 + MemberPointConfigDO getConfig();
  28 +
  29 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointConfigServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.service.point;
  2 +
  3 +import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigSaveReqVO;
  4 +import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
  5 +import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointConfigMapper;
  6 +import org.springframework.stereotype.Service;
  7 +import org.springframework.validation.annotation.Validated;
  8 +
  9 +import javax.annotation.Resource;
  10 +
  11 +/**
  12 + * 会员积分配置 Service 实现类
  13 + *
  14 + * @author QingX
  15 + */
  16 +@Service
  17 +@Validated
  18 +public class MemberPointConfigServiceImpl implements MemberPointConfigService {
  19 +
  20 + @Resource
  21 + private MemberPointConfigMapper memberPointConfigMapper;
  22 +
  23 + @Override
  24 + public void saveConfig(MemberPointConfigSaveReqVO saveReqVO) {
  25 + // TODO qingx:配置存在,则 update;不存在则 insert
  26 + }
  27 +
  28 + @Override
  29 + public MemberPointConfigDO getConfig() {
  30 + // TODO qingx:直接查询到一条;
  31 + return null;
  32 + }
  33 +}
yudao-module-point/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>cn.iocoder.boot</groupId>
  8 + <artifactId>yudao</artifactId>
  9 + <version>${revision}</version>
  10 + </parent>
  11 +
  12 + <artifactId>yudao-module-point</artifactId>
  13 + <packaging>pom</packaging>
  14 + <modules>
  15 + <module>yudao-module-point-api</module>
  16 + </modules>
  17 +
  18 +
  19 +</project>
0 \ No newline at end of file 20 \ No newline at end of file
yudao-module-point/yudao-module-point-api/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>cn.iocoder.boot</groupId>
  8 + <artifactId>yudao-module-point</artifactId>
  9 + <version>${revision}</version>
  10 + </parent>
  11 +
  12 + <artifactId>yudao-module-point-api</artifactId>
  13 + <packaging>jar</packaging>
  14 +
  15 + <dependencies>
  16 + <dependency>
  17 + <groupId>cn.iocoder.boot</groupId>
  18 + <artifactId>yudao-common</artifactId>
  19 + </dependency>
  20 +
  21 + <!-- 参数校验 -->
  22 + <dependency>
  23 + <groupId>org.springframework.boot</groupId>
  24 + <artifactId>spring-boot-starter-validation</artifactId>
  25 + <optional>true</optional>
  26 + </dependency>
  27 + </dependencies>
  28 +</project>
0 \ No newline at end of file 29 \ No newline at end of file
yudao-module-point/yudao-module-point-api/src/main/java/cn/iocoder/yudao/module/point/enums/ErrorCodeConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.enums;
  2 +
  3 +
  4 +import cn.iocoder.yudao.framework.common.exception.ErrorCode;
  5 +
  6 +/**
  7 + * Pay 错误码 Core 枚举类
  8 + *
  9 + * pay 系统,使用 1-007-000-000 段
  10 + */
  11 +public interface ErrorCodeConstants {
  12 +
  13 + ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(499, "积分设置不存在");
  14 +
  15 + ErrorCode CONFIG_EXISTS = new ErrorCode(499, "积分设置已存在,只允配置一条记录");
  16 +
  17 +
  18 + ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(499, "签到天数规则不存在");
  19 + ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(499, "签到天数规则已存在");
  20 +
  21 + ErrorCode RECORD_NOT_EXISTS = new ErrorCode( 499, "用户积分记录不存在");
  22 +
  23 + ErrorCode SIGN_IN_RECORD_NOT_EXISTS = new ErrorCode(499, "用户签到积分不存在");
  24 +
  25 +
  26 +
  27 +}
yudao-module-point/yudao-module-point-biz/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>cn.iocoder.boot</groupId>
  8 + <artifactId>yudao-module-point</artifactId>
  9 + <version>${revision}</version>
  10 + </parent>
  11 +
  12 + <artifactId>yudao-module-point-biz</artifactId>
  13 + <packaging>jar</packaging>
  14 +
  15 + <dependencies>
  16 + <dependency>
  17 + <groupId>cn.iocoder.boot</groupId>
  18 + <artifactId>yudao-module-point-api</artifactId>
  19 + <version>${revision}</version>
  20 + </dependency>
  21 +
  22 + <!-- 业务组件 -->
  23 + <dependency>
  24 + <groupId>cn.iocoder.boot</groupId>
  25 + <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
  26 + </dependency>
  27 +
  28 + <!-- Web 相关 -->
  29 + <dependency>
  30 + <groupId>cn.iocoder.boot</groupId>
  31 + <artifactId>yudao-spring-boot-starter-web</artifactId>
  32 + </dependency>
  33 +
  34 + <dependency>
  35 + <groupId>cn.iocoder.boot</groupId>
  36 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  37 + </dependency>
  38 +
  39 + <!-- DB 相关 -->
  40 + <dependency>
  41 + <groupId>cn.iocoder.boot</groupId>
  42 + <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
  43 + </dependency>
  44 +
  45 + <!-- Test 测试相关 -->
  46 + <dependency>
  47 + <groupId>cn.iocoder.boot</groupId>
  48 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  49 + </dependency>
  50 +
  51 + <!-- 工具类相关 -->
  52 + <dependency>
  53 + <groupId>cn.iocoder.boot</groupId>
  54 + <artifactId>yudao-spring-boot-starter-excel</artifactId>
  55 + </dependency>
  56 + </dependencies>
  57 +</project>
0 \ No newline at end of file 58 \ No newline at end of file
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/PointRecordController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord;
  2 +
  3 +import org.springframework.web.bind.annotation.*;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import io.swagger.v3.oas.annotations.Parameter;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  18 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  22 +
  23 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  24 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  25 +
  26 +import cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo.*;
  27 +import cn.iocoder.yudao.module.point.dal.dataobject.pointrecord.PointRecordDO;
  28 +import cn.iocoder.yudao.module.point.convert.pointrecord.PointRecordConvert;
  29 +import cn.iocoder.yudao.module.point.service.pointrecord.PointRecordService;
  30 +
  31 +@Tag(name = "管理后台 - 用户积分记录")
  32 +@RestController
  33 +@RequestMapping("/point/record")
  34 +@Validated
  35 +public class PointRecordController {
  36 +
  37 + @Resource
  38 + private PointRecordService recordService;
  39 +
  40 + @PostMapping("/create")
  41 + @Operation(summary = "创建用户积分记录")
  42 + @PreAuthorize("@ss.hasPermission('point:record:create')")
  43 + public CommonResult<Long> createRecord(@Valid @RequestBody PointRecordCreateReqVO createReqVO) {
  44 + return success(recordService.createRecord(createReqVO));
  45 + }
  46 +
  47 + @PutMapping("/update")
  48 + @Operation(summary = "更新用户积分记录")
  49 + @PreAuthorize("@ss.hasPermission('point:record:update')")
  50 + public CommonResult<Boolean> updateRecord(@Valid @RequestBody PointRecordUpdateReqVO updateReqVO) {
  51 + recordService.updateRecord(updateReqVO);
  52 + return success(true);
  53 + }
  54 +
  55 + @DeleteMapping("/delete")
  56 + @Operation(summary = "删除用户积分记录")
  57 + @Parameter(name = "id", description = "编号", required = true)
  58 + @PreAuthorize("@ss.hasPermission('point:record:delete')")
  59 + public CommonResult<Boolean> deleteRecord(@RequestParam("id") Long id) {
  60 + recordService.deleteRecord(id);
  61 + return success(true);
  62 + }
  63 +
  64 + @GetMapping("/get")
  65 + @Operation(summary = "获得用户积分记录")
  66 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  67 + @PreAuthorize("@ss.hasPermission('point:record:query')")
  68 + public CommonResult<PointRecordRespVO> getRecord(@RequestParam("id") Long id) {
  69 + PointRecordDO record = recordService.getRecord(id);
  70 + return success(PointRecordConvert.INSTANCE.convert(record));
  71 + }
  72 +
  73 + @GetMapping("/list")
  74 + @Operation(summary = "获得用户积分记录列表")
  75 + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
  76 + @PreAuthorize("@ss.hasPermission('point:record:query')")
  77 + public CommonResult<List<PointRecordRespVO>> getRecordList(@RequestParam("ids") Collection<Long> ids) {
  78 + List<PointRecordDO> list = recordService.getRecordList(ids);
  79 + return success(PointRecordConvert.INSTANCE.convertList(list));
  80 + }
  81 +
  82 + @GetMapping("/page")
  83 + @Operation(summary = "获得用户积分记录分页")
  84 + @PreAuthorize("@ss.hasPermission('point:record:query')")
  85 + public CommonResult<PageResult<PointRecordRespVO>> getRecordPage(@Valid PointRecordPageReqVO pageVO) {
  86 + PageResult<PointRecordDO> pageResult = recordService.getRecordPage(pageVO);
  87 + return success(PointRecordConvert.INSTANCE.convertPage(pageResult));
  88 + }
  89 +
  90 + @GetMapping("/export-excel")
  91 + @Operation(summary = "导出用户积分记录 Excel")
  92 + @PreAuthorize("@ss.hasPermission('point:record:export')")
  93 + @OperateLog(type = EXPORT)
  94 + public void exportRecordExcel(@Valid PointRecordExportReqVO exportReqVO,
  95 + HttpServletResponse response) throws IOException {
  96 + List<PointRecordDO> list = recordService.getRecordList(exportReqVO);
  97 + // 导出 Excel
  98 + List<PointRecordExcelVO> datas = PointRecordConvert.INSTANCE.convertList02(list);
  99 + ExcelUtils.write(response, "用户积分记录.xls", "数据", PointRecordExcelVO.class, datas);
  100 + }
  101 +
  102 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +import java.time.LocalDateTime;
  9 +import java.time.LocalDateTime;
  10 +import javax.validation.constraints.*;
  11 +import org.springframework.format.annotation.DateTimeFormat;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +/**
  16 + * 用户积分记录 Base VO,提供给添加、修改、详细的子 VO 使用
  17 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  18 + */
  19 +@Data
  20 +public class PointRecordBaseVO {
  21 +
  22 + @Schema(description = "业务编码", example = "22706")
  23 + @NotNull(message = "业务编码不能为空")
  24 + private String bizId;
  25 +
  26 + @Schema(description = "业务类型", example = "1")
  27 + @NotNull(message = "业务类型不能为空")
  28 + private String bizType;
  29 +
  30 + @Schema(description = "1增加 0扣减", example = "1")
  31 + @NotNull(message = "操作类型不能为空")
  32 + private String type;
  33 +
  34 + @Schema(description = "积分标题")
  35 + @NotNull(message = "积分标题不能为空")
  36 + private String title;
  37 +
  38 + @Schema(description = "积分描述", example = "你猜")
  39 + private String description;
  40 +
  41 + @Schema(description = "积分")
  42 + @NotNull(message = "操作积分不能为空")
  43 + private Integer point;
  44 +
  45 + @Schema(description = "变动后的积分", requiredMode = Schema.RequiredMode.REQUIRED)
  46 +// @NotNull(message = "变动后的积分不能为空")
  47 + private Integer totalPoint;
  48 +
  49 + @Schema(description = "状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款) ", example = "1")
  50 + @NotNull(message = "积分状态不能为空")
  51 + private Integer status;
  52 +
  53 + @Schema(description = "用户id", example = "31169")
  54 + @NotNull(message = "用户ID不能为空")
  55 + private Integer userId;
  56 +
  57 + @Schema(description = "冻结时间")
  58 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  59 + @NotNull(message = "冻结时间不能为空")
  60 + private LocalDateTime freezingTime;
  61 +
  62 + @Schema(description = "解冻时间")
  63 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  64 + @NotNull(message = "解冻时间不能为空")
  65 + private LocalDateTime thawingTime;
  66 +
  67 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@Schema(description = "管理后台 - 用户积分记录创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class PointRecordCreateReqVO extends PointRecordBaseVO {
  13 +
  14 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +import java.time.LocalDateTime;
  9 +import java.time.LocalDateTime;
  10 +
  11 +import com.alibaba.excel.annotation.ExcelProperty;
  12 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  13 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  14 +
  15 +
  16 +/**
  17 + * 用户积分记录 Excel VO
  18 + *
  19 + * @author QingX
  20 + */
  21 +@Data
  22 +public class PointRecordExcelVO {
  23 +
  24 + @ExcelProperty("自增主键")
  25 + private Long id;
  26 +
  27 + @ExcelProperty("业务编码")
  28 + private String bizId;
  29 +
  30 + @ExcelProperty(value = "业务类型", converter = DictConvert.class)
  31 + @DictFormat("biz_type") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
  32 + private String bizType;
  33 +
  34 + @ExcelProperty("1增加 0扣减")
  35 + private String type;
  36 +
  37 + @ExcelProperty("积分标题")
  38 + private String title;
  39 +
  40 + @ExcelProperty("积分描述")
  41 + private String description;
  42 +
  43 + @ExcelProperty("积分")
  44 + private Integer point;
  45 +
  46 + @ExcelProperty("变动后的积分")
  47 + private Integer totalPoint;
  48 +
  49 + @ExcelProperty(value = "状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款) ", converter = DictConvert.class)
  50 + @DictFormat("point_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
  51 + private Integer status;
  52 +
  53 + @ExcelProperty("用户id")
  54 + private Integer userId;
  55 +
  56 + @ExcelProperty("冻结时间")
  57 + private LocalDateTime freezingTime;
  58 +
  59 + @ExcelProperty("解冻时间")
  60 + private LocalDateTime thawingTime;
  61 +
  62 + @ExcelProperty("发生时间")
  63 + private LocalDateTime createTime;
  64 +
  65 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +
  8 +@Schema(description = "管理后台 - 用户积分记录 Excel 导出 Request VO,参数和 PointRecordPageReqVO 是一致的")
  9 +@Data
  10 +public class PointRecordExportReqVO {
  11 +
  12 + @Schema(description = "业务编码", example = "22706")
  13 + private String bizId;
  14 +
  15 + @Schema(description = "业务类型", example = "1")
  16 + private String bizType;
  17 +
  18 + @Schema(description = "1增加 0扣减", example = "1")
  19 + private String type;
  20 +
  21 + @Schema(description = "积分标题")
  22 + private String title;
  23 +
  24 + @Schema(description = "状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款) ", example = "1")
  25 + private Integer status;
  26 +
  27 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +
  8 +@Schema(description = "管理后台 - 用户积分记录分页 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class PointRecordPageReqVO extends PageParam {
  13 +
  14 + @Schema(description = "业务编码", example = "22706")
  15 + private String bizId;
  16 +
  17 + @Schema(description = "业务类型", example = "1")
  18 + private String bizType;
  19 +
  20 + @Schema(description = "1增加 0扣减", example = "1")
  21 + private String type;
  22 +
  23 + @Schema(description = "积分标题")
  24 + private String title;
  25 +
  26 + @Schema(description = "状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款) ", example = "1")
  27 + private Integer status;
  28 +
  29 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.time.LocalDateTime;
  6 +
  7 +@Schema(description = "管理后台 - 用户积分记录 Response VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class PointRecordRespVO extends PointRecordBaseVO {
  12 +
  13 + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "31457")
  14 + private Long id;
  15 +
  16 + @Schema(description = "发生时间")
  17 + private LocalDateTime createTime;
  18 +
  19 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/pointrecord/vo/PointRecordUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@Schema(description = "管理后台 - 用户积分记录更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class PointRecordUpdateReqVO extends PointRecordBaseVO {
  13 +
  14 + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "31457")
  15 + @NotNull(message = "自增主键不能为空")
  16 + private Long id;
  17 +
  18 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/SignInConfigController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig;
  2 +
  3 +import org.springframework.web.bind.annotation.*;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import io.swagger.v3.oas.annotations.Parameter;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  18 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  22 +
  23 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  24 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  25 +
  26 +import cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo.*;
  27 +import cn.iocoder.yudao.module.point.dal.dataobject.signinconfig.SignInConfigDO;
  28 +import cn.iocoder.yudao.module.point.convert.signinconfig.SignInConfigConvert;
  29 +import cn.iocoder.yudao.module.point.service.signinconfig.SignInConfigService;
  30 +
  31 +@Tag(name = "管理后台 - 积分签到规则")
  32 +@RestController
  33 +@RequestMapping("/point/sign-in-config")
  34 +@Validated
  35 +public class SignInConfigController {
  36 +
  37 + @Resource
  38 + private SignInConfigService signInConfigService;
  39 +
  40 + @PostMapping("/create")
  41 + @Operation(summary = "创建积分签到规则")
  42 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:create')")
  43 + public CommonResult<Integer> createSignInConfig(@Valid @RequestBody SignInConfigCreateReqVO createReqVO) {
  44 + return success(signInConfigService.createSignInConfig(createReqVO));
  45 + }
  46 +
  47 + @PutMapping("/update")
  48 + @Operation(summary = "更新积分签到规则")
  49 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:update')")
  50 + public CommonResult<Boolean> updateSignInConfig(@Valid @RequestBody SignInConfigUpdateReqVO updateReqVO) {
  51 + signInConfigService.updateSignInConfig(updateReqVO);
  52 + return success(true);
  53 + }
  54 +
  55 + @DeleteMapping("/delete")
  56 + @Operation(summary = "删除积分签到规则")
  57 + @Parameter(name = "id", description = "编号", required = true)
  58 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:delete')")
  59 + public CommonResult<Boolean> deleteSignInConfig(@RequestParam("id") Integer id) {
  60 + signInConfigService.deleteSignInConfig(id);
  61 + return success(true);
  62 + }
  63 +
  64 + @GetMapping("/get")
  65 + @Operation(summary = "获得积分签到规则")
  66 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  67 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:query')")
  68 + public CommonResult<SignInConfigRespVO> getSignInConfig(@RequestParam("id") Integer id) {
  69 + SignInConfigDO signInConfig = signInConfigService.getSignInConfig(id);
  70 + return success(SignInConfigConvert.INSTANCE.convert(signInConfig));
  71 + }
  72 +
  73 + @GetMapping("/list")
  74 + @Operation(summary = "获得积分签到规则列表")
  75 + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
  76 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:query')")
  77 + public CommonResult<List<SignInConfigRespVO>> getSignInConfigList(@RequestParam("ids") Collection<Integer> ids) {
  78 + List<SignInConfigDO> list = signInConfigService.getSignInConfigList(ids);
  79 + return success(SignInConfigConvert.INSTANCE.convertList(list));
  80 + }
  81 +
  82 + @GetMapping("/page")
  83 + @Operation(summary = "获得积分签到规则分页")
  84 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:query')")
  85 + public CommonResult<PageResult<SignInConfigRespVO>> getSignInConfigPage(@Valid SignInConfigPageReqVO pageVO) {
  86 + PageResult<SignInConfigDO> pageResult = signInConfigService.getSignInConfigPage(pageVO);
  87 + return success(SignInConfigConvert.INSTANCE.convertPage(pageResult));
  88 + }
  89 +
  90 + @GetMapping("/export-excel")
  91 + @Operation(summary = "导出积分签到规则 Excel")
  92 + @PreAuthorize("@ss.hasPermission('point:sign-in-config:export')")
  93 + @OperateLog(type = EXPORT)
  94 + public void exportSignInConfigExcel(@Valid SignInConfigExportReqVO exportReqVO,
  95 + HttpServletResponse response) throws IOException {
  96 + List<SignInConfigDO> list = signInConfigService.getSignInConfigList(exportReqVO);
  97 + // 导出 Excel
  98 + List<SignInConfigExcelVO> datas = SignInConfigConvert.INSTANCE.convertList02(list);
  99 + ExcelUtils.write(response, "积分签到规则.xls", "数据", SignInConfigExcelVO.class, datas);
  100 + }
  101 +
  102 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +import javax.validation.constraints.*;
  9 +
  10 +/**
  11 + * 积分签到规则 Base VO,提供给添加、修改、详细的子 VO 使用
  12 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  13 + */
  14 +@Data
  15 +public class SignInConfigBaseVO {
  16 +
  17 + @Schema(description = "签到第x天", example = "7")
  18 + private Integer day;
  19 +
  20 + @Schema(description = "签到天数对应分数", example = "10")
  21 + private Integer point;
  22 +
  23 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@Schema(description = "管理后台 - 积分签到规则创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SignInConfigCreateReqVO extends SignInConfigBaseVO {
  13 +
  14 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +
  9 +import com.alibaba.excel.annotation.ExcelProperty;
  10 +
  11 +/**
  12 + * 积分签到规则 Excel VO
  13 + *
  14 + * @author QingX
  15 + */
  16 +@Data
  17 +public class SignInConfigExcelVO {
  18 +
  19 + @ExcelProperty("签到第x天")
  20 + private Integer day;
  21 +
  22 + @ExcelProperty("签到天数对应分数")
  23 + private Integer point;
  24 +
  25 + @ExcelProperty("创建时间")
  26 + private LocalDateTime createTime;
  27 +
  28 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +
  8 +@Schema(description = "管理后台 - 积分签到规则 Excel 导出 Request VO,参数和 SignInConfigPageReqVO 是一致的")
  9 +@Data
  10 +public class SignInConfigExportReqVO {
  11 +
  12 + @Schema(description = "签到第x天", example = "7")
  13 + private Integer day;
  14 +
  15 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +
  8 +@Schema(description = "管理后台 - 积分签到规则分页 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SignInConfigPageReqVO extends PageParam {
  13 +
  14 + @Schema(description = "签到第x天", example = "7")
  15 + private Integer day;
  16 +
  17 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.time.LocalDateTime;
  6 +
  7 +@Schema(description = "管理后台 - 积分签到规则 Response VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class SignInConfigRespVO extends SignInConfigBaseVO {
  12 +
  13 + @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "20937")
  14 + private Integer id;
  15 +
  16 + @Schema(description = "创建时间")
  17 + private LocalDateTime createTime;
  18 +
  19 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinconfig/vo/SignInConfigUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@Schema(description = "管理后台 - 积分签到规则更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SignInConfigUpdateReqVO extends SignInConfigBaseVO {
  13 +
  14 + @Schema(description = "规则自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "13653")
  15 + @NotNull(message = "规则自增主键不能为空")
  16 + private Integer id;
  17 +
  18 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/SignInRecordController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord;
  2 +
  3 +import org.springframework.web.bind.annotation.*;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import io.swagger.v3.oas.annotations.Parameter;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  18 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  22 +
  23 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  24 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  25 +
  26 +import cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo.*;
  27 +import cn.iocoder.yudao.module.point.dal.dataobject.signinrecord.SignInRecordDO;
  28 +import cn.iocoder.yudao.module.point.convert.signinrecord.SignInRecordConvert;
  29 +import cn.iocoder.yudao.module.point.service.signinrecord.SignInRecordService;
  30 +
  31 +@Tag(name = "管理后台 - 用户签到积分")
  32 +@RestController
  33 +@RequestMapping("/point/sign-in-record")
  34 +@Validated
  35 +public class SignInRecordController {
  36 +
  37 + @Resource
  38 + private SignInRecordService signInRecordService;
  39 +
  40 + @PostMapping("/create")
  41 + @Operation(summary = "创建用户签到积分")
  42 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:create')")
  43 + public CommonResult<Long> createSignInRecord(@Valid @RequestBody SignInRecordCreateReqVO createReqVO) {
  44 + return success(signInRecordService.createSignInRecord(createReqVO));
  45 + }
  46 +
  47 + @PutMapping("/update")
  48 + @Operation(summary = "更新用户签到积分")
  49 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:update')")
  50 + public CommonResult<Boolean> updateSignInRecord(@Valid @RequestBody SignInRecordUpdateReqVO updateReqVO) {
  51 + signInRecordService.updateSignInRecord(updateReqVO);
  52 + return success(true);
  53 + }
  54 +
  55 + @DeleteMapping("/delete")
  56 + @Operation(summary = "删除用户签到积分")
  57 + @Parameter(name = "id", description = "编号", required = true)
  58 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:delete')")
  59 + public CommonResult<Boolean> deleteSignInRecord(@RequestParam("id") Long id) {
  60 + signInRecordService.deleteSignInRecord(id);
  61 + return success(true);
  62 + }
  63 +
  64 + @GetMapping("/get")
  65 + @Operation(summary = "获得用户签到积分")
  66 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  67 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:query')")
  68 + public CommonResult<SignInRecordRespVO> getSignInRecord(@RequestParam("id") Long id) {
  69 + SignInRecordDO signInRecord = signInRecordService.getSignInRecord(id);
  70 + return success(SignInRecordConvert.INSTANCE.convert(signInRecord));
  71 + }
  72 +
  73 + @GetMapping("/list")
  74 + @Operation(summary = "获得用户签到积分列表")
  75 + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
  76 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:query')")
  77 + public CommonResult<List<SignInRecordRespVO>> getSignInRecordList(@RequestParam("ids") Collection<Long> ids) {
  78 + List<SignInRecordDO> list = signInRecordService.getSignInRecordList(ids);
  79 + return success(SignInRecordConvert.INSTANCE.convertList(list));
  80 + }
  81 +
  82 + @GetMapping("/page")
  83 + @Operation(summary = "获得用户签到积分分页")
  84 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:query')")
  85 + public CommonResult<PageResult<SignInRecordRespVO>> getSignInRecordPage(@Valid SignInRecordPageReqVO pageVO) {
  86 + PageResult<SignInRecordDO> pageResult = signInRecordService.getSignInRecordPage(pageVO);
  87 + return success(SignInRecordConvert.INSTANCE.convertPage(pageResult));
  88 + }
  89 +
  90 + @GetMapping("/export-excel")
  91 + @Operation(summary = "导出用户签到积分 Excel")
  92 + @PreAuthorize("@ss.hasPermission('point:sign-in-record:export')")
  93 + @OperateLog(type = EXPORT)
  94 + public void exportSignInRecordExcel(@Valid SignInRecordExportReqVO exportReqVO,
  95 + HttpServletResponse response) throws IOException {
  96 + List<SignInRecordDO> list = signInRecordService.getSignInRecordList(exportReqVO);
  97 + // 导出 Excel
  98 + List<SignInRecordExcelVO> datas = SignInRecordConvert.INSTANCE.convertList02(list);
  99 + ExcelUtils.write(response, "用户签到积分.xls", "数据", SignInRecordExcelVO.class, datas);
  100 + }
  101 +
  102 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +import javax.validation.constraints.*;
  9 +
  10 +/**
  11 + * 用户签到积分 Base VO,提供给添加、修改、详细的子 VO 使用
  12 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  13 + */
  14 +@Data
  15 +public class SignInRecordBaseVO {
  16 +
  17 + @Schema(description = "签到用户", example = "6507")
  18 + private Integer userId;
  19 +
  20 + @Schema(description = "第几天签到")
  21 + private Integer day;
  22 +
  23 + @Schema(description = "签到的分数")
  24 + private Integer point;
  25 +
  26 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@Schema(description = "管理后台 - 用户签到积分创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SignInRecordCreateReqVO extends SignInRecordBaseVO {
  13 +
  14 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +
  9 +import com.alibaba.excel.annotation.ExcelProperty;
  10 +
  11 +/**
  12 + * 用户签到积分 Excel VO
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Data
  17 +public class SignInRecordExcelVO {
  18 +
  19 + @ExcelProperty("签到自增id")
  20 + private Long id;
  21 +
  22 + @ExcelProperty("签到用户")
  23 + private Integer userId;
  24 +
  25 + @ExcelProperty("第几天签到")
  26 + private Integer day;
  27 +
  28 + @ExcelProperty("签到的分数")
  29 + private Integer point;
  30 +
  31 + @ExcelProperty("签到时间")
  32 + private LocalDateTime createTime;
  33 +
  34 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import java.time.LocalDateTime;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@Schema(description = "管理后台 - 用户签到积分 Excel 导出 Request VO,参数和 SignInRecordPageReqVO 是一致的")
  13 +@Data
  14 +public class SignInRecordExportReqVO {
  15 +
  16 + @Schema(description = "签到用户", example = "6507")
  17 + private Integer userId;
  18 +
  19 + @Schema(description = "第几天签到")
  20 + private Integer day;
  21 +
  22 + @Schema(description = "签到时间")
  23 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  24 + private LocalDateTime[] createTime;
  25 +
  26 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@Schema(description = "管理后台 - 用户签到积分分页 Request VO")
  13 +@Data
  14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class SignInRecordPageReqVO extends PageParam {
  17 +
  18 + @Schema(description = "签到用户", example = "6507")
  19 + private Integer userId;
  20 +
  21 + @Schema(description = "第几天签到")
  22 + private Integer day;
  23 +
  24 + @Schema(description = "签到时间")
  25 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  26 + private LocalDateTime[] createTime;
  27 +
  28 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.time.LocalDateTime;
  6 +
  7 +@Schema(description = "管理后台 - 用户签到积分 Response VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class SignInRecordRespVO extends SignInRecordBaseVO {
  12 +
  13 + @Schema(description = "签到自增id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11903")
  14 + private Long id;
  15 +
  16 + @Schema(description = "签到时间")
  17 + private LocalDateTime createTime;
  18 +
  19 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/controller/admin/signinrecord/vo/SignInRecordUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@Schema(description = "管理后台 - 用户签到积分更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SignInRecordUpdateReqVO extends SignInRecordBaseVO {
  13 +
  14 + @Schema(description = "签到自增id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11903")
  15 + @NotNull(message = "签到自增id不能为空")
  16 + private Long id;
  17 +
  18 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/convert/pointrecord/PointRecordConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.convert.pointrecord;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +import cn.iocoder.yudao.module.point.controller.admin.pointrecord.vo.*;
  10 +import cn.iocoder.yudao.module.point.dal.dataobject.pointrecord.PointRecordDO;
  11 +
  12 +/**
  13 + * 用户积分记录 Convert
  14 + *
  15 + * @author QingX
  16 + */
  17 +@Mapper
  18 +public interface PointRecordConvert {
  19 +
  20 + PointRecordConvert INSTANCE = Mappers.getMapper(PointRecordConvert.class);
  21 +
  22 + PointRecordDO convert(PointRecordCreateReqVO bean);
  23 +
  24 + PointRecordDO convert(PointRecordUpdateReqVO bean);
  25 +
  26 + PointRecordRespVO convert(PointRecordDO bean);
  27 +
  28 + List<PointRecordRespVO> convertList(List<PointRecordDO> list);
  29 +
  30 + PageResult<PointRecordRespVO> convertPage(PageResult<PointRecordDO> page);
  31 +
  32 + List<PointRecordExcelVO> convertList02(List<PointRecordDO> list);
  33 +
  34 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/convert/signinconfig/SignInConfigConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.convert.signinconfig;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +import cn.iocoder.yudao.module.point.controller.admin.signinconfig.vo.*;
  10 +import cn.iocoder.yudao.module.point.dal.dataobject.signinconfig.SignInConfigDO;
  11 +
  12 +/**
  13 + * 积分签到规则 Convert
  14 + *
  15 + * @author QingX
  16 + */
  17 +@Mapper
  18 +public interface SignInConfigConvert {
  19 +
  20 + SignInConfigConvert INSTANCE = Mappers.getMapper(SignInConfigConvert.class);
  21 +
  22 + SignInConfigDO convert(SignInConfigCreateReqVO bean);
  23 +
  24 + SignInConfigDO convert(SignInConfigUpdateReqVO bean);
  25 +
  26 + SignInConfigRespVO convert(SignInConfigDO bean);
  27 +
  28 + List<SignInConfigRespVO> convertList(List<SignInConfigDO> list);
  29 +
  30 + PageResult<SignInConfigRespVO> convertPage(PageResult<SignInConfigDO> page);
  31 +
  32 + List<SignInConfigExcelVO> convertList02(List<SignInConfigDO> list);
  33 +
  34 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/convert/signinrecord/SignInRecordConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.convert.signinrecord;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +import cn.iocoder.yudao.module.point.controller.admin.signinrecord.vo.*;
  10 +import cn.iocoder.yudao.module.point.dal.dataobject.signinrecord.SignInRecordDO;
  11 +
  12 +/**
  13 + * 用户签到积分 Convert
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface SignInRecordConvert {
  19 +
  20 + SignInRecordConvert INSTANCE = Mappers.getMapper(SignInRecordConvert.class);
  21 +
  22 + SignInRecordDO convert(SignInRecordCreateReqVO bean);
  23 +
  24 + SignInRecordDO convert(SignInRecordUpdateReqVO bean);
  25 +
  26 + SignInRecordRespVO convert(SignInRecordDO bean);
  27 +
  28 + List<SignInRecordRespVO> convertList(List<SignInRecordDO> list);
  29 +
  30 + PageResult<SignInRecordRespVO> convertPage(PageResult<SignInRecordDO> page);
  31 +
  32 + List<SignInRecordExcelVO> convertList02(List<SignInRecordDO> list);
  33 +
  34 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/dal/dataobject/pointrecord/PointRecordDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.dal.dataobject.pointrecord;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import java.time.LocalDateTime;
  8 +import java.time.LocalDateTime;
  9 +import com.baomidou.mybatisplus.annotation.*;
  10 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  11 +
  12 +/**
  13 + * 用户积分记录 DO
  14 + *
  15 + * @author QingX
  16 + */
  17 +@TableName("member_point_record")
  18 +@KeySequence("member_point_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class PointRecordDO extends BaseDO {
  26 +
  27 + /**
  28 + * 自增主键
  29 + */
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 业务编码
  34 + */
  35 + private String bizId;
  36 + /**
  37 + * 业务类型
  38 + *
  39 + * 枚举 {@link TODO biz_type 对应的类}
  40 + */
  41 + private String bizType;
  42 + /**
  43 + * 1增加 0扣减
  44 + */
  45 + private String type;
  46 + /**
  47 + * 积分标题
  48 + */
  49 + private String title;
  50 + /**
  51 + * 积分描述
  52 + */
  53 + private String description;
  54 + /**
  55 + * 积分
  56 + */
  57 + private Integer point;
  58 + /**
  59 + * 变动后的积分
  60 + */
  61 + private Integer totalPoint;
  62 + /**
  63 + * 状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款)
  64 +
  65 + *
  66 + * 枚举 {@link TODO point_status 对应的类}
  67 + */
  68 + private Integer status;
  69 + /**
  70 + * 用户id
  71 + */
  72 + private Integer userId;
  73 + /**
  74 + * 冻结时间
  75 + */
  76 + private LocalDateTime freezingTime;
  77 + /**
  78 + * 解冻时间
  79 + */
  80 + private LocalDateTime thawingTime;
  81 +
  82 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/dal/dataobject/signinconfig/SignInConfigDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.dal.dataobject.signinconfig;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 积分签到规则 DO
  12 + *
  13 + * @author QingX
  14 + */
  15 +@TableName("member_sign_in_config")
  16 +@KeySequence("member_sign_in_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class SignInConfigDO extends BaseDO {
  24 +
  25 + /**
  26 + * 规则自增主键
  27 + */
  28 + @TableId
  29 + private Integer id;
  30 + /**
  31 + * 签到第x天
  32 + */
  33 + private Integer day;
  34 + /**
  35 + * 签到天数对应分数
  36 + */
  37 + private Integer point;
  38 +
  39 +}
yudao-module-point/yudao-module-point-biz/src/main/java/cn/iocoder/yudao/module/point/dal/dataobject/signinrecord/SignInRecordDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.point.dal.dataobject.signinrecord;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 用户签到积分 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("member_sign_in_record")
  16 +@KeySequence("member_sign_in_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class SignInRecordDO extends BaseDO {
  24 +
  25 + /**
  26 + * 签到自增id
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 签到用户
  32 + */
  33 + private Integer userId;
  34 + /**
  35 + * 第几天签到
  36 + */
  37 + private Integer day;
  38 + /**
  39 + * 签到的分数
  40 + */
  41 + private Integer point;
  42 +
  43 +}