Commit 057952bdeb6262abc46fd698e4b449dea77ed19f
Merge branch 'feature/mall_product' of https://gitee.com/CrazyWorld/ruoyi-vue-pr…
…o into feature/mall_product # Conflicts: # yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
Showing
85 changed files
with
1578 additions
and
497 deletions
sql/mysql/member.sql
0 → 100644
| 1 | +-- 查询上级菜单、排序 | ||
| 2 | +SELECT parent_id, sort | ||
| 3 | +INTO @parentId, @sort | ||
| 4 | +FROM system_menu | ||
| 5 | +WHERE name = '用户等级修改' | ||
| 6 | +LIMIT 1; | ||
| 7 | +-- 新增 按钮权限 | ||
| 8 | +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 9 | +VALUES ('用户积分修改', 'member:user:update-point', 3, @sort + 1, @parentId, '', '', '', 0); | ||
| 10 | +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 11 | +VALUES ('用户余额修改', 'member:user:update-balance', 3, @sort + 2, @parentId, '', '', '', 0); |
sql/mysql/ruoyi-vue-pro.sql
| @@ -805,7 +805,7 @@ CREATE TABLE `member_level_record` ( | @@ -805,7 +805,7 @@ CREATE TABLE `member_level_record` ( | ||
| 805 | `user_id` bigint NOT NULL DEFAULT 0 COMMENT '用户编号', | 805 | `user_id` bigint NOT NULL DEFAULT 0 COMMENT '用户编号', |
| 806 | `level_id` bigint NOT NULL DEFAULT 0 COMMENT '等级编号', | 806 | `level_id` bigint NOT NULL DEFAULT 0 COMMENT '等级编号', |
| 807 | `level` int NOT NULL DEFAULT 0 COMMENT '会员等级', | 807 | `level` int NOT NULL DEFAULT 0 COMMENT '会员等级', |
| 808 | - `discount_percent` tinyint NOT NULL DEFAULT 100 COMMENT '享受折扣', | 808 | + `discount_percent` int NOT NULL DEFAULT 100 COMMENT '享受折扣', |
| 809 | `experience` int NOT NULL DEFAULT 0 COMMENT '升级经验', | 809 | `experience` int NOT NULL DEFAULT 0 COMMENT '升级经验', |
| 810 | `user_experience` int NOT NULL DEFAULT 0 COMMENT '会员此时的经验', | 810 | `user_experience` int NOT NULL DEFAULT 0 COMMENT '会员此时的经验', |
| 811 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '备注', | 811 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '备注', |
| @@ -827,15 +827,15 @@ BEGIN; | @@ -827,15 +827,15 @@ BEGIN; | ||
| 827 | COMMIT; | 827 | COMMIT; |
| 828 | 828 | ||
| 829 | -- ---------------------------- | 829 | -- ---------------------------- |
| 830 | --- Table structure for member_point_config | 830 | +-- Table structure for member_config |
| 831 | -- ---------------------------- | 831 | -- ---------------------------- |
| 832 | -DROP TABLE IF EXISTS `member_point_config`; | ||
| 833 | -CREATE TABLE `member_point_config` ( | 832 | +DROP TABLE IF EXISTS `member_config`; |
| 833 | +CREATE TABLE `member_config` ( | ||
| 834 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', | 834 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', |
| 835 | - `trade_deduct_enable` bit(1) NOT NULL COMMENT '是否开启积分抵扣', | ||
| 836 | - `trade_deduct_unit_price` int NOT NULL COMMENT '积分抵扣(单位:分)', | ||
| 837 | - `trade_deduct_max_price` int NULL DEFAULT NULL COMMENT '积分抵扣最大值', | ||
| 838 | - `trade_give_point` bigint NULL DEFAULT NULL COMMENT '1 元赠送多少分', | 835 | + `point_trade_deduct_enable` bit(1) NOT NULL COMMENT '是否开启积分抵扣', |
| 836 | + `point_trade_deduct_unit_price` int NOT NULL COMMENT '积分抵扣(单位:分)', | ||
| 837 | + `point_trade_deduct_max_price` int NULL DEFAULT NULL COMMENT '积分抵扣最大值', | ||
| 838 | + `point_trade_give_point` bigint NULL DEFAULT NULL COMMENT '1 元赠送多少分', | ||
| 839 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | 839 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 840 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | 840 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 841 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | 841 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', |
| @@ -843,13 +843,13 @@ CREATE TABLE `member_point_config` ( | @@ -843,13 +843,13 @@ CREATE TABLE `member_point_config` ( | ||
| 843 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 843 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 844 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 844 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 845 | PRIMARY KEY (`id`) USING BTREE | 845 | PRIMARY KEY (`id`) USING BTREE |
| 846 | -) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员积分配置表'; | 846 | +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员配置表'; |
| 847 | 847 | ||
| 848 | -- ---------------------------- | 848 | -- ---------------------------- |
| 849 | --- Records of member_point_config | 849 | +-- Records of member_config |
| 850 | -- ---------------------------- | 850 | -- ---------------------------- |
| 851 | BEGIN; | 851 | BEGIN; |
| 852 | -INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, b'1', 100, 2, 3, '1', '2023-08-20 09:54:42', '1', '2023-08-20 09:54:42', b'0', 1); | 852 | +INSERT INTO `member_config` (`id`, `point_trade_deduct_enable`, `point_trade_deduct_unit_price`, `point_trade_deduct_max_price`, `point_trade_give_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, b'1', 100, 2, 3, '1', '2023-08-20 09:54:42', '1', '2023-08-20 09:54:42', b'0', 1); |
| 853 | COMMIT; | 853 | COMMIT; |
| 854 | 854 | ||
| 855 | -- ---------------------------- | 855 | -- ---------------------------- |
| @@ -915,7 +915,8 @@ DROP TABLE IF EXISTS `member_sign_in_config`; | @@ -915,7 +915,8 @@ DROP TABLE IF EXISTS `member_sign_in_config`; | ||
| 915 | CREATE TABLE `member_sign_in_config` ( | 915 | CREATE TABLE `member_sign_in_config` ( |
| 916 | `id` int NOT NULL AUTO_INCREMENT COMMENT '编号', | 916 | `id` int NOT NULL AUTO_INCREMENT COMMENT '编号', |
| 917 | `day` int NOT NULL COMMENT '第几天', | 917 | `day` int NOT NULL COMMENT '第几天', |
| 918 | - `point` int NOT NULL COMMENT '奖励积分', | 918 | + `point` int NOT NULL DEFAULT 0 COMMENT '奖励积分', |
| 919 | + `experience` int NOT NULL DEFAULT 0 COMMENT '奖励经验', | ||
| 919 | `status` tinyint NOT NULL COMMENT '状态', | 920 | `status` tinyint NOT NULL COMMENT '状态', |
| 920 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者', | 921 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者', |
| 921 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | 922 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| @@ -930,18 +931,18 @@ CREATE TABLE `member_sign_in_config` ( | @@ -930,18 +931,18 @@ CREATE TABLE `member_sign_in_config` ( | ||
| 930 | -- Records of member_sign_in_config | 931 | -- Records of member_sign_in_config |
| 931 | -- ---------------------------- | 932 | -- ---------------------------- |
| 932 | BEGIN; | 933 | BEGIN; |
| 933 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 10, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 934 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, 20, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 935 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 7, 1001, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 936 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 6, 12121, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 937 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 2, 12, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 938 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 1, 10, 0, '1', '2023-08-20 19:20:42', '1', '2023-08-20 19:20:56', b'0', 1); | ||
| 939 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 7, 22, 0, '1', '2023-08-20 19:20:48', '1', '2023-08-20 19:20:48', b'0', 1); | ||
| 940 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 2, 3, 0, '1', '2023-08-21 20:22:44', '1', '2023-08-21 20:22:44', b'0', 1); | ||
| 941 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 3, 4, 0, '1', '2023-08-21 20:22:48', '1', '2023-08-21 20:22:48', b'0', 1); | ||
| 942 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 4, 5, 0, '1', '2023-08-21 20:22:51', '1', '2023-08-21 20:22:51', b'0', 1); | ||
| 943 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 5, 6, 0, '1', '2023-08-21 20:22:56', '1', '2023-08-21 20:22:56', b'0', 1); | ||
| 944 | -INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 6, 7, 0, '1', '2023-08-21 20:22:59', '1', '2023-08-21 20:22:59', b'0', 1); | 934 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 10, 10, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); |
| 935 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, 20, 20, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 936 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 7, 1001, 1001, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 937 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 6, 12121, 12121, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 938 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 3, 12, 12, 0, '', '2023-08-20 01:38:56', '', '2023-08-20 01:38:56', b'0', 0); | ||
| 939 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 1, 10, 10, 0, '1', '2023-08-20 19:20:42', '1', '2023-08-20 19:20:56', b'0', 1); | ||
| 940 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 7, 22, 22, 0, '1', '2023-08-20 19:20:48', '1', '2023-08-20 19:20:48', b'0', 1); | ||
| 941 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 2, 3, 3, 0, '1', '2023-08-21 20:22:44', '1', '2023-08-21 20:22:44', b'0', 1); | ||
| 942 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 3, 4, 4, 0, '1', '2023-08-21 20:22:48', '1', '2023-08-21 20:22:48', b'0', 1); | ||
| 943 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 4, 5, 5, 0, '1', '2023-08-21 20:22:51', '1', '2023-08-21 20:22:51', b'0', 1); | ||
| 944 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 5, 6, 6, 0, '1', '2023-08-21 20:22:56', '1', '2023-08-21 20:22:56', b'0', 1); | ||
| 945 | +INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `experience`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 6, 7, 7, 0, '1', '2023-08-21 20:22:59', '1', '2023-08-21 20:22:59', b'0', 1); | ||
| 945 | COMMIT; | 946 | COMMIT; |
| 946 | 947 | ||
| 947 | -- ---------------------------- | 948 | -- ---------------------------- |
| @@ -952,7 +953,8 @@ CREATE TABLE `member_sign_in_record` ( | @@ -952,7 +953,8 @@ CREATE TABLE `member_sign_in_record` ( | ||
| 952 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '签到自增id', | 953 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '签到自增id', |
| 953 | `user_id` int NULL DEFAULT NULL COMMENT '签到用户', | 954 | `user_id` int NULL DEFAULT NULL COMMENT '签到用户', |
| 954 | `day` int NULL DEFAULT NULL COMMENT '第几天签到', | 955 | `day` int NULL DEFAULT NULL COMMENT '第几天签到', |
| 955 | - `point` int NULL DEFAULT NULL COMMENT '签到的分数', | 956 | + `point` int NOT NULL DEFAULT 0 COMMENT '签到的积分', |
| 957 | + `experience` int NOT NULL DEFAULT 0 COMMENT '签到的经验', | ||
| 956 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | 958 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 957 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | 959 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 958 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | 960 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', |
| @@ -962,6 +964,8 @@ CREATE TABLE `member_sign_in_record` ( | @@ -962,6 +964,8 @@ CREATE TABLE `member_sign_in_record` ( | ||
| 962 | PRIMARY KEY (`id`) USING BTREE | 964 | PRIMARY KEY (`id`) USING BTREE |
| 963 | ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '签到记录'; | 965 | ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '签到记录'; |
| 964 | 966 | ||
| 967 | +CREATE INDEX user_id_index ON member_sign_in_record (user_id); | ||
| 968 | + | ||
| 965 | -- ---------------------------- | 969 | -- ---------------------------- |
| 966 | -- Records of member_sign_in_record | 970 | -- Records of member_sign_in_record |
| 967 | -- ---------------------------- | 971 | -- ---------------------------- |
| @@ -2013,20 +2017,19 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i | @@ -2013,20 +2017,19 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i | ||
| 2013 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2184, '自提门店导出', 'trade:delivery:pick-up-store:export', 3, 5, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0'); | 2017 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2184, '自提门店导出', 'trade:delivery:pick-up-store:export', 3, 5, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0'); |
| 2014 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2209, '秒杀活动', '', 2, 3, 2030, 'seckill', 'ep:place', '', '', 0, b'1', b'1', b'1', '1', '2023-06-24 17:39:13', '1', '2023-06-24 18:55:15', b'0'); | 2018 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2209, '秒杀活动', '', 2, 3, 2030, 'seckill', 'ep:place', '', '', 0, b'1', b'1', b'1', '1', '2023-06-24 17:39:13', '1', '2023-06-24 18:55:15', b'0'); |
| 2015 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2262, '会员中心', '', 1, 55, 0, '/member', 'ep:bicycle', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-06-10 00:42:03', '1', '2023-08-20 09:23:56', b'0'); | 2019 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2262, '会员中心', '', 1, 55, 0, '/member', 'ep:bicycle', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-06-10 00:42:03', '1', '2023-08-20 09:23:56', b'0'); |
| 2016 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2275, '积分配置', '', 2, 0, 2299, 'config', 'fa:archive', 'member/point/config/index', 'PointConfig', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-08-20 12:01:20', b'0'); | ||
| 2017 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2276, '积分设置查询', 'point:config:query', 3, 1, 2275, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '', '2023-06-10 02:07:44', b'0'); | ||
| 2018 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2277, '积分设置创建', 'point:config:save', 3, 2, 2275, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 20:32:31', b'0'); | 2020 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2275, '会员配置', '', 2, 0, 2262, 'config', 'fa:archive', 'member/config/index', 'MemberConfig', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-08-20 12:01:20', b'0'); |
| 2021 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2276, '会员配置查询', 'member:config:query', 3, 1, 2275, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '', '2023-06-10 02:07:44', b'0'); | ||
| 2022 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2277, '会员配置创建', 'member:config:save', 3, 2, 2275, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 20:32:31', b'0'); | ||
| 2019 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2281, '签到配置', '', 2, 2, 2300, 'config', 'ep:calendar', 'member/signin/config/index', 'SignInConfig', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-08-20 19:25:51', b'0'); | 2023 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2281, '签到配置', '', 2, 2, 2300, 'config', 'ep:calendar', 'member/signin/config/index', 'SignInConfig', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-08-20 19:25:51', b'0'); |
| 2020 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2282, '积分签到规则查询', 'point:sign-in-config:query', 3, 1, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); | 2024 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2282, '积分签到规则查询', 'point:sign-in-config:query', 3, 1, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); |
| 2021 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2283, '积分签到规则创建', 'point:sign-in-config:create', 3, 2, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); | 2025 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2283, '积分签到规则创建', 'point:sign-in-config:create', 3, 2, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); |
| 2022 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2284, '积分签到规则更新', 'point:sign-in-config:update', 3, 3, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); | 2026 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2284, '积分签到规则更新', 'point:sign-in-config:update', 3, 3, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); |
| 2023 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2285, '积分签到规则删除', 'point:sign-in-config:delete', 3, 4, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); | 2027 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2285, '积分签到规则删除', 'point:sign-in-config:delete', 3, 4, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0'); |
| 2024 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2287, '积分记录', '', 2, 1, 2299, 'record', 'fa:asterisk', 'member/point/record/index', 'PointRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '1', '2023-08-20 12:01:42', b'0'); | ||
| 2025 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2288, '用户积分记录查询', 'point:record:query', 3, 1, 2287, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '', '2023-06-10 04:18:50', b'0'); | 2028 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2287, '会员积分', '', 2, 1, 2262, 'point', 'ep:pointer', 'member/point/record/index', 'PointRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '1', '2023-08-20 12:01:42', b'0'); |
| 2029 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2288, '会员积分记录查询', 'point:record:query', 3, 1, 2287, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '', '2023-06-10 04:18:50', b'0'); | ||
| 2026 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2293, '签到记录', '', 2, 3, 2300, 'record', 'ep:chicken', 'member/signin/record/index', 'SignInRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '1', '2023-08-20 19:26:02', b'0'); | 2030 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2293, '签到记录', '', 2, 3, 2300, 'record', 'ep:chicken', 'member/signin/record/index', 'SignInRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '1', '2023-08-20 19:26:02', b'0'); |
| 2027 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2294, '用户签到积分查询', 'point:sign-in-record:query', 3, 1, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0'); | 2031 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2294, '用户签到积分查询', 'point:sign-in-record:query', 3, 1, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0'); |
| 2028 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2297, '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0'); | 2032 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2297, '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0'); |
| 2029 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2299, '会员积分', '', 1, 10, 2262, 'point', 'ep:pointer', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:48:51', '1', '2023-08-20 09:23:35', b'0'); | ||
| 2030 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2300, '会员签到', '', 1, 11, 2262, 'signin', 'ep:alarm-clock', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-08-20 09:23:48', b'0'); | 2033 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2300, '会员签到', '', 1, 11, 2262, 'signin', 'ep:alarm-clock', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-08-20 09:23:48', b'0'); |
| 2031 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2301, '回调通知', '', 2, 4, 1117, 'notify', 'example', 'pay/notify/index', 'PayNotify', 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '1', '2023-07-20 13:45:08', b'0'); | 2034 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2301, '回调通知', '', 2, 4, 1117, 'notify', 'example', 'pay/notify/index', 'PayNotify', 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '1', '2023-07-20 13:45:08', b'0'); |
| 2032 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0'); | 2035 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0'); |
sql/mysql/trade_order.sql
0 → 100644
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
| @@ -6,6 +6,7 @@ import java.time.Duration; | @@ -6,6 +6,7 @@ import java.time.Duration; | ||
| 6 | import java.time.LocalDate; | 6 | import java.time.LocalDate; |
| 7 | import java.time.LocalDateTime; | 7 | import java.time.LocalDateTime; |
| 8 | import java.time.LocalTime; | 8 | import java.time.LocalTime; |
| 9 | +import java.time.temporal.TemporalAdjusters; | ||
| 9 | 10 | ||
| 10 | /** | 11 | /** |
| 11 | * 时间工具类,用于 {@link java.time.LocalDateTime} | 12 | * 时间工具类,用于 {@link java.time.LocalDateTime} |
| @@ -137,4 +138,29 @@ public class LocalDateTimeUtils { | @@ -137,4 +138,29 @@ public class LocalDateTimeUtils { | ||
| 137 | 138 | ||
| 138 | } | 139 | } |
| 139 | 140 | ||
| 141 | + /** | ||
| 142 | + * 获取指定日期所在的月份的开始时间 | ||
| 143 | + * 例如:2023-09-30 00:00:00,000 | ||
| 144 | + * | ||
| 145 | + * @param date 日期 | ||
| 146 | + * @return 月份的开始时间 | ||
| 147 | + */ | ||
| 148 | + public static LocalDateTime beginOfMonth(LocalDateTime date) { | ||
| 149 | + return date | ||
| 150 | + .with(TemporalAdjusters.firstDayOfMonth()) | ||
| 151 | + .with(LocalTime.MIN); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + /** | ||
| 155 | + * 获取指定日期所在的月份的最后时间 | ||
| 156 | + * 例如:2023-09-30 23:59:59,999 | ||
| 157 | + * | ||
| 158 | + * @param date 日期 | ||
| 159 | + * @return 月份的结束时间 | ||
| 160 | + */ | ||
| 161 | + public static LocalDateTime endOfMonth(LocalDateTime date) { | ||
| 162 | + return date | ||
| 163 | + .with(TemporalAdjusters.lastDayOfMonth()) | ||
| 164 | + .with(LocalTime.MAX); | ||
| 165 | + } | ||
| 140 | } | 166 | } |
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.api.category; | ||
| 2 | + | ||
| 3 | +import java.util.Collection; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 商品分类 API 接口 | ||
| 7 | + * | ||
| 8 | + * @author owen | ||
| 9 | + */ | ||
| 10 | +public interface ProductCategoryApi { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 校验商品分类是否有效。如下情况,视为无效: | ||
| 14 | + * 1. 商品分类编号不存在 | ||
| 15 | + * 2. 商品分类被禁用 | ||
| 16 | + * | ||
| 17 | + * @param ids 商品分类编号数组 | ||
| 18 | + */ | ||
| 19 | + void validateCategoryList(Collection<Long> ids); | ||
| 20 | +} |
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
| @@ -22,10 +22,26 @@ public interface ProductSpuApi { | @@ -22,10 +22,26 @@ public interface ProductSpuApi { | ||
| 22 | List<ProductSpuRespDTO> getSpuList(Collection<Long> ids); | 22 | List<ProductSpuRespDTO> getSpuList(Collection<Long> ids); |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | + * 批量查询 SPU 数组,并且校验是否 SPU 是否有效 | ||
| 26 | + * | ||
| 27 | + * @param ids SPU 编号列表 | ||
| 28 | + * @return SPU 数组 | ||
| 29 | + */ | ||
| 30 | + List<ProductSpuRespDTO> getSpuListAndValidate(Collection<Long> ids); | ||
| 31 | + | ||
| 32 | + /** | ||
| 25 | * 获得 SPU | 33 | * 获得 SPU |
| 26 | * | 34 | * |
| 27 | * @return SPU | 35 | * @return SPU |
| 28 | */ | 36 | */ |
| 29 | ProductSpuRespDTO getSpu(Long id); | 37 | ProductSpuRespDTO getSpu(Long id); |
| 30 | 38 | ||
| 39 | + /** | ||
| 40 | + * 校验商品是否有效。如下情况,视为无效: | ||
| 41 | + * 1. 商品编号不存在 | ||
| 42 | + * 2. 商品被禁用 | ||
| 43 | + * | ||
| 44 | + * @param ids 商品编号数组 | ||
| 45 | + */ | ||
| 46 | + void validateSpuList(Collection<Long> ids); | ||
| 31 | } | 47 | } |
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
| @@ -34,7 +34,7 @@ public interface ErrorCodeConstants { | @@ -34,7 +34,7 @@ public interface ErrorCodeConstants { | ||
| 34 | // ========== 商品 SPU 1-008-005-000 ========== | 34 | // ========== 商品 SPU 1-008-005-000 ========== |
| 35 | ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在"); | 35 | ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在"); |
| 36 | ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下"); | 36 | ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下"); |
| 37 | - ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU 不处于上架状态"); | 37 | + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU【[]】不处于上架状态"); |
| 38 | ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_003, "商品 SPU 不处于回收站状态"); | 38 | ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_003, "商品 SPU 不处于回收站状态"); |
| 39 | 39 | ||
| 40 | // ========== 商品 SKU 1-008-006-000 ========== | 40 | // ========== 商品 SKU 1-008-006-000 ========== |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/category/ProductCategoryApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.api.category; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; | ||
| 4 | +import org.springframework.stereotype.Service; | ||
| 5 | +import org.springframework.validation.annotation.Validated; | ||
| 6 | + | ||
| 7 | +import javax.annotation.Resource; | ||
| 8 | +import java.util.Collection; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 商品分类 API 接口实现类 | ||
| 12 | + * | ||
| 13 | + * @author owen | ||
| 14 | + */ | ||
| 15 | +@Service | ||
| 16 | +@Validated | ||
| 17 | +public class ProductCategoryApiImpl implements ProductCategoryApi { | ||
| 18 | + | ||
| 19 | + @Resource | ||
| 20 | + private ProductCategoryService productCategoryService; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public void validateCategoryList(Collection<Long> ids) { | ||
| 24 | + productCategoryService.validateCategoryList(ids); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
| @@ -3,9 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu; | @@ -3,9 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu; | ||
| 3 | import cn.hutool.core.collection.CollectionUtil; | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | 4 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 5 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | 5 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; |
| 6 | -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | ||
| 7 | -import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | ||
| 8 | -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; | ||
| 9 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | 6 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; |
| 10 | import org.springframework.stereotype.Service; | 7 | import org.springframework.stereotype.Service; |
| 11 | import org.springframework.validation.annotation.Validated; | 8 | import org.springframework.validation.annotation.Validated; |
| @@ -37,8 +34,18 @@ public class ProductSpuApiImpl implements ProductSpuApi { | @@ -37,8 +34,18 @@ public class ProductSpuApiImpl implements ProductSpuApi { | ||
| 37 | } | 34 | } |
| 38 | 35 | ||
| 39 | @Override | 36 | @Override |
| 37 | + public List<ProductSpuRespDTO> getSpuListAndValidate(Collection<Long> ids) { | ||
| 38 | + return ProductSpuConvert.INSTANCE.convertList2(spuService.validateSpuList(ids)); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 40 | public ProductSpuRespDTO getSpu(Long id) { | 42 | public ProductSpuRespDTO getSpu(Long id) { |
| 41 | return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id)); | 43 | return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id)); |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 46 | + @Override | ||
| 47 | + public void validateSpuList(Collection<Long> ids) { | ||
| 48 | + spuService.validateSpuList(ids); | ||
| 49 | + } | ||
| 50 | + | ||
| 44 | } | 51 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
| @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg | @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg | ||
| 6 | import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; | 6 | import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; |
| 7 | 7 | ||
| 8 | import javax.validation.Valid; | 8 | import javax.validation.Valid; |
| 9 | +import java.util.Collection; | ||
| 9 | import java.util.List; | 10 | import java.util.List; |
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| @@ -75,4 +76,12 @@ public interface ProductCategoryService { | @@ -75,4 +76,12 @@ public interface ProductCategoryService { | ||
| 75 | */ | 76 | */ |
| 76 | List<ProductCategoryDO> getEnableCategoryList(); | 77 | List<ProductCategoryDO> getEnableCategoryList(); |
| 77 | 78 | ||
| 79 | + /** | ||
| 80 | + * 校验商品分类是否有效。如下情况,视为无效: | ||
| 81 | + * 1. 商品分类编号不存在 | ||
| 82 | + * 2. 商品分类被禁用 | ||
| 83 | + * | ||
| 84 | + * @param ids 商品分类编号数组 | ||
| 85 | + */ | ||
| 86 | + void validateCategoryList(Collection<Long> ids); | ||
| 78 | } | 87 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
| 1 | package cn.iocoder.yudao.module.product.service.category; | 1 | package cn.iocoder.yudao.module.product.service.category; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 4 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO; | 6 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; |
| 6 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO; |
| @@ -13,7 +15,9 @@ import org.springframework.stereotype.Service; | @@ -13,7 +15,9 @@ import org.springframework.stereotype.Service; | ||
| 13 | import org.springframework.validation.annotation.Validated; | 15 | import org.springframework.validation.annotation.Validated; |
| 14 | 16 | ||
| 15 | import javax.annotation.Resource; | 17 | import javax.annotation.Resource; |
| 18 | +import java.util.Collection; | ||
| 16 | import java.util.List; | 19 | import java.util.List; |
| 20 | +import java.util.Map; | ||
| 17 | import java.util.Objects; | 21 | import java.util.Objects; |
| 18 | 22 | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -100,6 +104,26 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { | @@ -100,6 +104,26 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { | ||
| 100 | } | 104 | } |
| 101 | 105 | ||
| 102 | @Override | 106 | @Override |
| 107 | + public void validateCategoryList(Collection<Long> ids) { | ||
| 108 | + if (CollUtil.isEmpty(ids)) { | ||
| 109 | + return; | ||
| 110 | + } | ||
| 111 | + // 获得商品分类信息 | ||
| 112 | + List<ProductCategoryDO> categoryList = productCategoryMapper.selectBatchIds(ids); | ||
| 113 | + Map<Long, ProductCategoryDO> categoryMap = CollectionUtils.convertMap(categoryList, ProductCategoryDO::getId); | ||
| 114 | + // 校验 | ||
| 115 | + ids.forEach(id -> { | ||
| 116 | + ProductCategoryDO category = categoryMap.get(id); | ||
| 117 | + if (category == null) { | ||
| 118 | + throw exception(CATEGORY_NOT_EXISTS); | ||
| 119 | + } | ||
| 120 | + if (!CommonStatusEnum.ENABLE.getStatus().equals(category.getStatus())) { | ||
| 121 | + throw exception(CATEGORY_DISABLED, category.getName()); | ||
| 122 | + } | ||
| 123 | + }); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + @Override | ||
| 103 | public ProductCategoryDO getCategory(Long id) { | 127 | public ProductCategoryDO getCategory(Long id) { |
| 104 | return productCategoryMapper.selectById(id); | 128 | return productCategoryMapper.selectById(id); |
| 105 | } | 129 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
| @@ -136,4 +136,14 @@ public interface ProductSpuService { | @@ -136,4 +136,14 @@ public interface ProductSpuService { | ||
| 136 | */ | 136 | */ |
| 137 | Long getSpuCountByCategoryId(Long categoryId); | 137 | Long getSpuCountByCategoryId(Long categoryId); |
| 138 | 138 | ||
| 139 | + | ||
| 140 | + /** | ||
| 141 | + * 校验商品是否有效。如下情况,视为无效: | ||
| 142 | + * 1. 商品编号不存在 | ||
| 143 | + * 2. 商品被禁用 | ||
| 144 | + * | ||
| 145 | + * @param ids 商品编号数组 | ||
| 146 | + * @return 商品 SPU 列表 | ||
| 147 | + */ | ||
| 148 | + List<ProductSpuDO> validateSpuList(Collection<Long> ids); | ||
| 139 | } | 149 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| 1 | package cn.iocoder.yudao.module.product.service.spu; | 1 | package cn.iocoder.yudao.module.product.service.spu; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| @@ -140,6 +141,28 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -140,6 +141,28 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 140 | } | 141 | } |
| 141 | 142 | ||
| 142 | @Override | 143 | @Override |
| 144 | + public List<ProductSpuDO> validateSpuList(Collection<Long> ids) { | ||
| 145 | + if (CollUtil.isEmpty(ids)) { | ||
| 146 | + return Collections.emptyList(); | ||
| 147 | + } | ||
| 148 | + // 获得商品信息 | ||
| 149 | + List<ProductSpuDO> spuList = productSpuMapper.selectBatchIds(ids); | ||
| 150 | + Map<Long, ProductSpuDO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuDO::getId); | ||
| 151 | + // 校验 | ||
| 152 | + ids.forEach(id -> { | ||
| 153 | + ProductSpuDO spu = spuMap.get(id); | ||
| 154 | + if (spu == null) { | ||
| 155 | + throw exception(SPU_NOT_EXISTS); | ||
| 156 | + } | ||
| 157 | + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { | ||
| 158 | + throw exception(SPU_NOT_ENABLE, spu.getName()); | ||
| 159 | + } | ||
| 160 | + }); | ||
| 161 | + | ||
| 162 | + return spuList; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + @Override | ||
| 143 | @Transactional(rollbackFor = Exception.class) | 166 | @Transactional(rollbackFor = Exception.class) |
| 144 | public void deleteSpu(Long id) { | 167 | public void deleteSpu(Long id) { |
| 145 | // 校验存在 | 168 | // 校验存在 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.util.ObjUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| @@ -25,11 +24,9 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -25,11 +24,9 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
| 25 | import org.springframework.web.bind.annotation.RestController; | 24 | import org.springframework.web.bind.annotation.RestController; |
| 26 | 25 | ||
| 27 | import javax.annotation.Resource; | 26 | import javax.annotation.Resource; |
| 28 | -import java.time.LocalDateTime; | ||
| 29 | import java.util.*; | 27 | import java.util.*; |
| 30 | 28 | ||
| 31 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 29 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 32 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 33 | import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; | 30 | import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; |
| 34 | 31 | ||
| 35 | @Tag(name = "用户 App - 优惠劵模板") | 32 | @Tag(name = "用户 App - 优惠劵模板") |
| @@ -46,7 +43,6 @@ public class AppCouponTemplateController { | @@ -46,7 +43,6 @@ public class AppCouponTemplateController { | ||
| 46 | @Resource | 43 | @Resource |
| 47 | private ProductSpuApi productSpuApi; | 44 | private ProductSpuApi productSpuApi; |
| 48 | 45 | ||
| 49 | - // TODO 疯狂:这里应该还有个 list 接口哈;获得优惠劵模版列表,用于首页、商品页的优惠劵 | ||
| 50 | @GetMapping("/list") | 46 | @GetMapping("/list") |
| 51 | @Operation(summary = "获得优惠劵模版列表") | 47 | @Operation(summary = "获得优惠劵模版列表") |
| 52 | @Parameters({ | 48 | @Parameters({ |
| @@ -56,46 +52,28 @@ public class AppCouponTemplateController { | @@ -56,46 +52,28 @@ public class AppCouponTemplateController { | ||
| 56 | }) | 52 | }) |
| 57 | public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList( | 53 | public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList( |
| 58 | @RequestParam(value = "spuId", required = false) Long spuId, | 54 | @RequestParam(value = "spuId", required = false) Long spuId, |
| 59 | - @RequestParam(value = "useType", required = false) Integer useType, | 55 | + @RequestParam(value = "productScope", required = false) Integer productScope, |
| 60 | @RequestParam(value = "count", required = false, defaultValue = "10") Integer count) { | 56 | @RequestParam(value = "count", required = false, defaultValue = "10") Integer count) { |
| 61 | - List<AppCouponTemplateRespVO> list = new ArrayList<>(); | ||
| 62 | - Random random = new Random(); | ||
| 63 | - for (int i = 0; i < 10; i++) { | ||
| 64 | - AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO(); | ||
| 65 | - vo.setId(i + 1L); | ||
| 66 | - vo.setName("优惠劵" + (i + 1)); | ||
| 67 | - vo.setTakeLimitCount(random.nextInt(10) + 1); | ||
| 68 | - vo.setUsePrice(random.nextInt(100) * 100); | ||
| 69 | - vo.setValidityType(random.nextInt(2) + 1); | ||
| 70 | - if (vo.getValidityType() == 1) { | ||
| 71 | - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10))); | ||
| 72 | - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10)); | ||
| 73 | - } else { | ||
| 74 | - vo.setFixedStartTerm(random.nextInt(10)); | ||
| 75 | - vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1); | ||
| 76 | - } | ||
| 77 | - vo.setDiscountType(random.nextInt(2) + 1); | ||
| 78 | - if (vo.getDiscountType() == 1) { | ||
| 79 | - vo.setDiscountPercent(null); | ||
| 80 | - vo.setDiscountPrice(random.nextInt(50) * 100); | ||
| 81 | - vo.setDiscountLimitPrice(null); | ||
| 82 | - } else { | ||
| 83 | - vo.setDiscountPercent(random.nextInt(90) + 10); | ||
| 84 | - vo.setDiscountPrice(null); | ||
| 85 | - vo.setDiscountLimitPrice(random.nextInt(200) * 100); | ||
| 86 | - } | ||
| 87 | - // TODO @疯狂:是否已领取,要不在 TemplateService 搞个 static 方法,让它基于 countMap 这种去计算,这样好点? | ||
| 88 | - vo.setTakeStatus(random.nextBoolean()); | ||
| 89 | - list.add(vo); | ||
| 90 | - } | ||
| 91 | - return success(list); | 57 | + // 1.1 处理查询条件:商品范围编号 |
| 58 | + Long productScopeValue = getProductScopeValue(productScope, spuId); | ||
| 59 | + // 1.2 处理查询条件:领取方式 = 直接领取 | ||
| 60 | + List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue()); | ||
| 61 | + | ||
| 62 | + // 2. 查询 | ||
| 63 | + List<CouponTemplateDO> list = couponTemplateService.getCouponTemplateList(canTakeTypes, productScope, | ||
| 64 | + productScopeValue, count); | ||
| 65 | + | ||
| 66 | + // 3.1 领取数量 | ||
| 67 | + Map<Long, Boolean> canCanTakeMap = couponService.getUserCanCanTakeMap(getLoginUserId(), list); | ||
| 68 | + // 3.2 拼接返回 | ||
| 69 | + return success(CouponTemplateConvert.INSTANCE.convertAppList(list, canCanTakeMap)); | ||
| 92 | } | 70 | } |
| 93 | 71 | ||
| 94 | @GetMapping("/page") | 72 | @GetMapping("/page") |
| 95 | @Operation(summary = "获得优惠劵模版分页") | 73 | @Operation(summary = "获得优惠劵模版分页") |
| 96 | public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) { | 74 | public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) { |
| 97 | // 1.1 处理查询条件:商品范围编号 | 75 | // 1.1 处理查询条件:商品范围编号 |
| 98 | - Long productScopeValue = getProductScopeValue(pageReqVO); | 76 | + Long productScopeValue = getProductScopeValue(pageReqVO.getProductScope(), pageReqVO.getSpuId()); |
| 99 | // 1.2 处理查询条件:领取方式 = 直接领取 | 77 | // 1.2 处理查询条件:领取方式 = 直接领取 |
| 100 | List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue()); | 78 | List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue()); |
| 101 | 79 | ||
| @@ -104,35 +82,30 @@ public class AppCouponTemplateController { | @@ -104,35 +82,30 @@ public class AppCouponTemplateController { | ||
| 104 | CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue)); | 82 | CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue)); |
| 105 | 83 | ||
| 106 | // 3.1 领取数量 | 84 | // 3.1 领取数量 |
| 107 | - Map<Long, Integer> couponTakeCountMap = new HashMap<>(0); | ||
| 108 | - Long userId = getLoginUserId(); | ||
| 109 | - if (userId != null) { | ||
| 110 | - List<Long> templateIds = convertList(pageResult.getList(), CouponTemplateDO::getId, | ||
| 111 | - t -> ObjUtil.notEqual(t.getTakeLimitCount(), -1)); // 只查有设置“每人限领个数”的 | ||
| 112 | - couponTakeCountMap = couponService.getTakeCountMapByTemplateIds(templateIds, userId); | ||
| 113 | - } | 85 | + Map<Long, Boolean> canCanTakeMap = couponService.getUserCanCanTakeMap(getLoginUserId(), pageResult.getList()); |
| 114 | // 3.2 拼接返回 | 86 | // 3.2 拼接返回 |
| 115 | - return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap)); | 87 | + return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, canCanTakeMap)); |
| 116 | } | 88 | } |
| 117 | 89 | ||
| 118 | /** | 90 | /** |
| 119 | - * 获得分页查询的商品范围 | 91 | + * 获得商品的使用范围编号 |
| 120 | * | 92 | * |
| 121 | - * @param pageReqVO 分页查询 | ||
| 122 | - * @return 商品范围 | 93 | + * @param productScope 商品范围 |
| 94 | + * @param spuId 商品 SPU 编号 | ||
| 95 | + * @return 商品范围编号 | ||
| 123 | */ | 96 | */ |
| 124 | - private Long getProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) { | ||
| 125 | - // 通用券:清除商品范围 | ||
| 126 | - if (pageReqVO.getProductScope() == null || ObjectUtils.equalsAny(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope(), null)) { | 97 | + private Long getProductScopeValue(Integer productScope, Long spuId) { |
| 98 | + // 通用券:没有商品范围 | ||
| 99 | + if (productScope == null || ObjectUtils.equalsAny(productScope, PromotionProductScopeEnum.ALL.getScope(), null)) { | ||
| 127 | return null; | 100 | return null; |
| 128 | } | 101 | } |
| 129 | - // 品类券:查询商品的品类 | ||
| 130 | - if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) { | ||
| 131 | - return Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId())) | 102 | + // 品类券:查询商品的品类编号 |
| 103 | + if (Objects.equals(productScope, PromotionProductScopeEnum.CATEGORY.getScope()) && spuId != null) { | ||
| 104 | + return Optional.ofNullable(productSpuApi.getSpu(spuId)) | ||
| 132 | .map(ProductSpuRespDTO::getCategoryId).orElse(null); | 105 | .map(ProductSpuRespDTO::getCategoryId).orElse(null); |
| 133 | } | 106 | } |
| 134 | // 商品卷:直接返回 | 107 | // 商品卷:直接返回 |
| 135 | - return pageReqVO.getSpuId(); | 108 | + return spuId; |
| 136 | } | 109 | } |
| 137 | 110 | ||
| 138 | } | 111 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java
| @@ -55,7 +55,7 @@ public class AppCouponTemplateRespVO { | @@ -55,7 +55,7 @@ public class AppCouponTemplateRespVO { | ||
| 55 | 55 | ||
| 56 | // ========== 用户相关字段 ========== | 56 | // ========== 用户相关字段 ========== |
| 57 | 57 | ||
| 58 | - @Schema(description = "是否已领取", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 59 | - private Boolean takeStatus; | 58 | + @Schema(description = "是否可以领取", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") |
| 59 | + private Boolean canTake; | ||
| 60 | 60 | ||
| 61 | } | 61 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java
| @@ -37,21 +37,25 @@ public interface CouponTemplateConvert { | @@ -37,21 +37,25 @@ public interface CouponTemplateConvert { | ||
| 37 | 37 | ||
| 38 | PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult); | 38 | PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult); |
| 39 | 39 | ||
| 40 | - default PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult, Map<Long, Integer> couponTakeCountMap) { | 40 | + List<AppCouponTemplateRespVO> convertAppList(List<CouponTemplateDO> list); |
| 41 | + | ||
| 42 | + default PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult, Map<Long, Boolean> userCanTakeMap) { | ||
| 41 | PageResult<AppCouponTemplateRespVO> result = convertAppPage(pageResult); | 43 | PageResult<AppCouponTemplateRespVO> result = convertAppPage(pageResult); |
| 42 | - if (MapUtil.isEmpty(couponTakeCountMap)) { | ||
| 43 | - return result; | ||
| 44 | - } | ||
| 45 | - for (AppCouponTemplateRespVO template : result.getList()) { | ||
| 46 | - // 每人领取数量无限制 | ||
| 47 | - if (template.getTakeLimitCount() == -1) { | ||
| 48 | - template.setTakeStatus(false); | ||
| 49 | - continue; | ||
| 50 | - } | 44 | + copyTo(result.getList(), userCanTakeMap); |
| 45 | + return result; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + default List<AppCouponTemplateRespVO> convertAppList(List<CouponTemplateDO> list, Map<Long, Boolean> userCanTakeMap) { | ||
| 49 | + List<AppCouponTemplateRespVO> result = convertAppList(list); | ||
| 50 | + copyTo(result, userCanTakeMap); | ||
| 51 | + return result; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + default void copyTo(List<AppCouponTemplateRespVO> list, Map<Long, Boolean> userCanTakeMap) { | ||
| 55 | + for (AppCouponTemplateRespVO template : list) { | ||
| 51 | // 检查已领取数量是否超过限领数量 | 56 | // 检查已领取数量是否超过限领数量 |
| 52 | - template.setTakeStatus(MapUtil.getInt(couponTakeCountMap, template.getId(), 0) >= template.getTakeLimitCount()); | 57 | + template.setCanTake(MapUtil.getBool(userCanTakeMap, template.getId(), false)); |
| 53 | } | 58 | } |
| 54 | - return result; | ||
| 55 | } | 59 | } |
| 56 | 60 | ||
| 57 | } | 61 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | 3 | +import cn.hutool.core.map.MapUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 8 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 10 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | 10 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; |
| 11 | -import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO; | ||
| 12 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 11 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 13 | import com.github.yulichang.toolkit.MPJWrappers; | 12 | import com.github.yulichang.toolkit.MPJWrappers; |
| 14 | import org.apache.ibatis.annotations.Mapper; | 13 | import org.apache.ibatis.annotations.Mapper; |
| @@ -16,9 +15,12 @@ import org.apache.ibatis.annotations.Mapper; | @@ -16,9 +15,12 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 16 | import java.time.LocalDateTime; | 15 | import java.time.LocalDateTime; |
| 17 | import java.util.Collection; | 16 | import java.util.Collection; |
| 18 | import java.util.List; | 17 | import java.util.List; |
| 18 | +import java.util.Map; | ||
| 19 | import java.util.function.Function; | 19 | import java.util.function.Function; |
| 20 | import java.util.stream.Collectors; | 20 | import java.util.stream.Collectors; |
| 21 | 21 | ||
| 22 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 23 | + | ||
| 22 | /** | 24 | /** |
| 23 | * 优惠劵 Mapper | 25 | * 优惠劵 Mapper |
| 24 | * | 26 | * |
| @@ -70,14 +72,16 @@ public interface CouponMapper extends BaseMapperX<CouponDO> { | @@ -70,14 +72,16 @@ public interface CouponMapper extends BaseMapperX<CouponDO> { | ||
| 70 | ); | 72 | ); |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 73 | - // TODO @疯狂:这个是不是搞个 Map 就可以呀? | ||
| 74 | - default List<CouponTakeCountBO> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) { | ||
| 75 | - return BeanUtil.copyToList(selectMaps(MPJWrappers.lambdaJoin(CouponDO.class) | ||
| 76 | - .select(CouponDO::getTemplateId) | ||
| 77 | - .selectCount(CouponDO::getId, CouponTakeCountBO::getCount) | 75 | + default Map<Long, Integer> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) { |
| 76 | + String templateIdAlias = "templateId"; | ||
| 77 | + String countAlias = "count"; | ||
| 78 | + List<Map<String, Object>> list = selectMaps(MPJWrappers.lambdaJoin(CouponDO.class) | ||
| 79 | + .selectAs(CouponDO::getTemplateId, templateIdAlias) | ||
| 80 | + .selectCount(CouponDO::getId, countAlias) | ||
| 78 | .eq(CouponDO::getUserId, userId) | 81 | .eq(CouponDO::getUserId, userId) |
| 79 | .in(CouponDO::getTemplateId, templateIds) | 82 | .in(CouponDO::getTemplateId, templateIds) |
| 80 | - .groupBy(CouponDO::getTemplateId)), CouponTakeCountBO.class); | 83 | + .groupBy(CouponDO::getTemplateId)); |
| 84 | + return convertMap(list, map -> MapUtil.getLong(map, templateIdAlias), map -> MapUtil.getInt(map, countAlias)); | ||
| 81 | } | 85 | } |
| 82 | 86 | ||
| 83 | default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope( | 87 | default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope( |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
| @@ -12,6 +12,7 @@ import org.apache.ibatis.annotations.Mapper; | @@ -12,6 +12,7 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 12 | import org.apache.ibatis.annotations.Param; | 12 | import org.apache.ibatis.annotations.Param; |
| 13 | 13 | ||
| 14 | import java.time.LocalDateTime; | 14 | import java.time.LocalDateTime; |
| 15 | +import java.util.List; | ||
| 15 | import java.util.function.Consumer; | 16 | import java.util.function.Consumer; |
| 16 | 17 | ||
| 17 | /** | 18 | /** |
| @@ -23,16 +24,8 @@ import java.util.function.Consumer; | @@ -23,16 +24,8 @@ import java.util.function.Consumer; | ||
| 23 | public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { | 24 | public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { |
| 24 | 25 | ||
| 25 | default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) { | 26 | default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) { |
| 26 | - // 构建可领取的查询条件, 好啰嗦 ( ╯-_-)╯┴—┴ | ||
| 27 | - Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = null; | ||
| 28 | - if (CollUtil.isNotEmpty(reqVO.getCanTakeTypes())) { | ||
| 29 | - canTakeConsumer = w -> | ||
| 30 | - w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的 | ||
| 31 | - .in(CouponTemplateDO::getTakeType, reqVO.getCanTakeTypes()) // 2. 领取方式一致 | ||
| 32 | - .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime) // 3. 未过期 | ||
| 33 | - .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now())) | ||
| 34 | - .apply(" take_count < total_count "); // 4. 剩余数量大于 0 | ||
| 35 | - } | 27 | + // 构建可领取的查询条件 |
| 28 | + Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = buildCanTakeQueryConsumer(reqVO.getCanTakeTypes()); | ||
| 36 | // 执行分页查询 | 29 | // 执行分页查询 |
| 37 | return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>() | 30 | return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>() |
| 38 | .likeIfPresent(CouponTemplateDO::getName, reqVO.getName()) | 31 | .likeIfPresent(CouponTemplateDO::getName, reqVO.getName()) |
| @@ -48,4 +41,33 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { | @@ -48,4 +41,33 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { | ||
| 48 | 41 | ||
| 49 | void updateTakeCount(@Param("id") Long id, @Param("incrCount") Integer incrCount); | 42 | void updateTakeCount(@Param("id") Long id, @Param("incrCount") Integer incrCount); |
| 50 | 43 | ||
| 44 | + default List<CouponTemplateDO> selectListByTakeType(Integer takeType) { | ||
| 45 | + return selectList(CouponTemplateDO::getTakeType, takeType); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + default List<CouponTemplateDO> selectList(List<Integer> canTakeTypes, Integer productScope, Long productScopeValue, Integer count) { | ||
| 49 | + // 构建可领取的查询条件 | ||
| 50 | + Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = buildCanTakeQueryConsumer(canTakeTypes); | ||
| 51 | + return selectList(new LambdaQueryWrapperX<CouponTemplateDO>() | ||
| 52 | + .eqIfPresent(CouponTemplateDO::getProductScope, productScope) | ||
| 53 | + .and(productScopeValue != null, w -> w.apply("FIND_IN_SET({0}, product_scope_values)", | ||
| 54 | + productScopeValue)) | ||
| 55 | + .and(canTakeConsumer != null, canTakeConsumer) | ||
| 56 | + .last(" LIMIT " + count) | ||
| 57 | + .orderByDesc(CouponTemplateDO::getId)); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + static Consumer<LambdaQueryWrapper<CouponTemplateDO>> buildCanTakeQueryConsumer(List<Integer> canTakeTypes) { | ||
| 61 | + Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = null; | ||
| 62 | + if (CollUtil.isNotEmpty(canTakeTypes)) { | ||
| 63 | + canTakeConsumer = w -> | ||
| 64 | + w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的 | ||
| 65 | + .in(CouponTemplateDO::getTakeType, canTakeTypes) // 2. 领取方式一致 | ||
| 66 | + .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime) // 3. 未过期 | ||
| 67 | + .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now())) | ||
| 68 | + .apply(" take_count < total_count "); // 4. 剩余数量大于 0 | ||
| 69 | + } | ||
| 70 | + return canTakeConsumer; | ||
| 71 | + } | ||
| 72 | + | ||
| 51 | } | 73 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/RegisterCouponSendConsumer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.mq.consumer.coupon; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; | ||
| 4 | +import cn.iocoder.yudao.module.member.mq.message.user.RegisterCouponSendMessage; | ||
| 5 | +import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; | ||
| 6 | +import lombok.extern.slf4j.Slf4j; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 针对 {@link RegisterCouponSendMessage} 的消费者 | ||
| 13 | + * | ||
| 14 | + * @author owen | ||
| 15 | + */ | ||
| 16 | +@Component | ||
| 17 | +@Slf4j | ||
| 18 | +public class RegisterCouponSendConsumer extends AbstractStreamMessageListener<RegisterCouponSendMessage> { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private CouponService couponService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void onMessage(RegisterCouponSendMessage message) { | ||
| 25 | + log.info("[onMessage][消息内容({})]", message); | ||
| 26 | + couponService.takeCouponByRegister(message.getUserId()); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
| 1 | package cn.iocoder.yudao.module.promotion.service.coupon; | 1 | package cn.iocoder.yudao.module.promotion.service.coupon; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.map.MapUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 9 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | ||
| 8 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | 10 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; |
| 9 | -import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO; | ||
| 10 | 11 | ||
| 11 | import java.util.*; | 12 | import java.util.*; |
| 12 | 13 | ||
| 13 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 14 | - | ||
| 15 | /** | 14 | /** |
| 16 | * 优惠劵 Service 接口 | 15 | * 优惠劵 Service 接口 |
| 17 | * | 16 | * |
| @@ -119,12 +118,9 @@ public interface CouponService { | @@ -119,12 +118,9 @@ public interface CouponService { | ||
| 119 | /** | 118 | /** |
| 120 | * 【系统】给用户发送新人券 | 119 | * 【系统】给用户发送新人券 |
| 121 | * | 120 | * |
| 122 | - * @param templateId 优惠券模板编号 | ||
| 123 | - * @param userId 用户编号列表 | 121 | + * @param userId 用户编号 |
| 124 | */ | 122 | */ |
| 125 | - default void takeCouponByRegister(Long templateId, Long userId) { | ||
| 126 | - takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER); | ||
| 127 | - } | 123 | + void takeCouponByRegister(Long userId); |
| 128 | 124 | ||
| 129 | /** | 125 | /** |
| 130 | * 获取会员领取指定优惠券的数量 | 126 | * 获取会员领取指定优惠券的数量 |
| @@ -134,11 +130,8 @@ public interface CouponService { | @@ -134,11 +130,8 @@ public interface CouponService { | ||
| 134 | * @return 领取优惠券的数量 | 130 | * @return 领取优惠券的数量 |
| 135 | */ | 131 | */ |
| 136 | default Integer getTakeCount(Long templateId, Long userId) { | 132 | default Integer getTakeCount(Long templateId, Long userId) { |
| 137 | - return CollUtil.emptyIfNull(getTakeCountListByTemplateIds(Collections.singleton(templateId), userId)) | ||
| 138 | - .stream() | ||
| 139 | - .findFirst() | ||
| 140 | - .map(CouponTakeCountBO::getCount) | ||
| 141 | - .orElse(0); | 133 | + Map<Long, Integer> map = getTakeCountMapByTemplateIds(Collections.singleton(templateId), userId); |
| 134 | + return MapUtil.getInt(map, templateId, 0); | ||
| 142 | } | 135 | } |
| 143 | 136 | ||
| 144 | /** | 137 | /** |
| @@ -148,19 +141,7 @@ public interface CouponService { | @@ -148,19 +141,7 @@ public interface CouponService { | ||
| 148 | * @param userId 用户编号 | 141 | * @param userId 用户编号 |
| 149 | * @return 领取优惠券的数量 | 142 | * @return 领取优惠券的数量 |
| 150 | */ | 143 | */ |
| 151 | - default Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) { | ||
| 152 | - return convertMap(getTakeCountListByTemplateIds(templateIds, userId), | ||
| 153 | - CouponTakeCountBO::getTemplateId, CouponTakeCountBO::getCount); | ||
| 154 | - } | ||
| 155 | - | ||
| 156 | - /** | ||
| 157 | - * 统计会员领取优惠券的数量 | ||
| 158 | - * | ||
| 159 | - * @param templateIds 优惠券模板编号列表 | ||
| 160 | - * @param userId 用户编号 | ||
| 161 | - * @return 领取优惠券的数量 | ||
| 162 | - */ | ||
| 163 | - List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId); | 144 | + Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId); |
| 164 | 145 | ||
| 165 | /** | 146 | /** |
| 166 | * 获取用户匹配的优惠券列表 | 147 | * 获取用户匹配的优惠券列表 |
| @@ -178,4 +159,13 @@ public interface CouponService { | @@ -178,4 +159,13 @@ public interface CouponService { | ||
| 178 | */ | 159 | */ |
| 179 | int expireCoupon(); | 160 | int expireCoupon(); |
| 180 | 161 | ||
| 162 | + /** | ||
| 163 | + * 获取用户是否可以领取优惠券 | ||
| 164 | + * | ||
| 165 | + * @param userId 用户编号 | ||
| 166 | + * @param templates 优惠券列表 | ||
| 167 | + * @return 是否可以领取 | ||
| 168 | + */ | ||
| 169 | + Map<Long, Boolean> getUserCanCanTakeMap(Long userId, List<CouponTemplateDO> templates); | ||
| 170 | + | ||
| 181 | } | 171 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.service.coupon; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.service.coupon; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollStreamUtil; | 3 | import cn.hutool.core.collection.CollStreamUtil; |
| 4 | import cn.hutool.core.collection.CollUtil; | 4 | import cn.hutool.core.collection.CollUtil; |
| 5 | -import cn.hutool.core.collection.ListUtil; | ||
| 6 | import cn.hutool.core.map.MapUtil; | 5 | import cn.hutool.core.map.MapUtil; |
| 7 | import cn.hutool.core.util.ObjectUtil; | 6 | import cn.hutool.core.util.ObjectUtil; |
| 8 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| @@ -21,7 +20,6 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper; | @@ -21,7 +20,6 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper; | ||
| 21 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | 20 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; |
| 22 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | 21 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; |
| 23 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum; | 22 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum; |
| 24 | -import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO; | ||
| 25 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
| 26 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 27 | import org.springframework.transaction.annotation.Transactional; | 25 | import org.springframework.transaction.annotation.Transactional; |
| @@ -29,18 +27,14 @@ import org.springframework.validation.annotation.Validated; | @@ -29,18 +27,14 @@ import org.springframework.validation.annotation.Validated; | ||
| 29 | 27 | ||
| 30 | import javax.annotation.Resource; | 28 | import javax.annotation.Resource; |
| 31 | import java.time.LocalDateTime; | 29 | import java.time.LocalDateTime; |
| 32 | -import java.util.Collection; | ||
| 33 | -import java.util.List; | ||
| 34 | -import java.util.Map; | ||
| 35 | -import java.util.Set; | 30 | +import java.util.*; |
| 36 | import java.util.stream.Collectors; | 31 | import java.util.stream.Collectors; |
| 37 | 32 | ||
| 38 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 33 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 39 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 40 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 35 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 41 | import static java.util.Arrays.asList; | 36 | import static java.util.Arrays.asList; |
| 42 | 37 | ||
| 43 | -// TODO @疯狂:注册时,赠送用户优惠劵;为了解耦,可以考虑注册时发个 MQ 消息;然后营销这里监听后消费; | ||
| 44 | /** | 38 | /** |
| 45 | * 优惠劵 Service 实现类 | 39 | * 优惠劵 Service 实现类 |
| 46 | * | 40 | * |
| @@ -184,9 +178,17 @@ public class CouponServiceImpl implements CouponService { | @@ -184,9 +178,17 @@ public class CouponServiceImpl implements CouponService { | ||
| 184 | } | 178 | } |
| 185 | 179 | ||
| 186 | @Override | 180 | @Override |
| 187 | - public List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId) { | 181 | + public void takeCouponByRegister(Long userId) { |
| 182 | + List<CouponTemplateDO> templates = couponTemplateService.getCouponTemplateByTakeType(CouponTakeTypeEnum.REGISTER); | ||
| 183 | + for (CouponTemplateDO template : templates) { | ||
| 184 | + takeCoupon(template.getId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER); | ||
| 185 | + } | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + @Override | ||
| 189 | + public Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) { | ||
| 188 | if (CollUtil.isEmpty(templateIds)) { | 190 | if (CollUtil.isEmpty(templateIds)) { |
| 189 | - return ListUtil.empty(); | 191 | + return Collections.emptyMap(); |
| 190 | } | 192 | } |
| 191 | return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds); | 193 | return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds); |
| 192 | } | 194 | } |
| @@ -222,6 +224,29 @@ public class CouponServiceImpl implements CouponService { | @@ -222,6 +224,29 @@ public class CouponServiceImpl implements CouponService { | ||
| 222 | return count; | 224 | return count; |
| 223 | } | 225 | } |
| 224 | 226 | ||
| 227 | + @Override | ||
| 228 | + public Map<Long, Boolean> getUserCanCanTakeMap(Long userId, List<CouponTemplateDO> templates) { | ||
| 229 | + Map<Long, Boolean> userCanTakeMap = convertMap(templates, CouponTemplateDO::getId, templateId -> true); | ||
| 230 | + // 未登录时,都显示可以领取 | ||
| 231 | + if (userId == null) { | ||
| 232 | + return userCanTakeMap; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + // 过滤领取数量无限制的 | ||
| 236 | + Set<Long> templateIds = convertSet(templates, CouponTemplateDO::getId, template -> template.getTakeLimitCount() != -1); | ||
| 237 | + | ||
| 238 | + // 检查用户领取的数量是否超过限制 | ||
| 239 | + if (CollUtil.isNotEmpty(templateIds)) { | ||
| 240 | + Map<Long, Integer> couponTakeCountMap = this.getTakeCountMapByTemplateIds(templateIds, userId); | ||
| 241 | + for (CouponTemplateDO template : templates) { | ||
| 242 | + Integer takeCount = couponTakeCountMap.get(template.getId()); | ||
| 243 | + userCanTakeMap.put(template.getId(), takeCount == null || takeCount < template.getTakeLimitCount()); | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + return userCanTakeMap; | ||
| 248 | + } | ||
| 249 | + | ||
| 225 | /** | 250 | /** |
| 226 | * 过期单个优惠劵 | 251 | * 过期单个优惠劵 |
| 227 | * | 252 | * |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
| @@ -5,8 +5,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou | @@ -5,8 +5,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou | ||
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 8 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | ||
| 8 | 9 | ||
| 9 | import javax.validation.Valid; | 10 | import javax.validation.Valid; |
| 11 | +import java.util.List; | ||
| 10 | 12 | ||
| 11 | /** | 13 | /** |
| 12 | * 优惠劵模板 Service 接口 | 14 | * 优惠劵模板 Service 接口 |
| @@ -69,4 +71,24 @@ public interface CouponTemplateService { | @@ -69,4 +71,24 @@ public interface CouponTemplateService { | ||
| 69 | */ | 71 | */ |
| 70 | void updateCouponTemplateTakeCount(Long id, int incrCount); | 72 | void updateCouponTemplateTakeCount(Long id, int incrCount); |
| 71 | 73 | ||
| 74 | + /** | ||
| 75 | + * 获得指定领取方式的优惠券模板 | ||
| 76 | + * | ||
| 77 | + * @param takeType 领取方式 | ||
| 78 | + * @return 优惠券模板列表 | ||
| 79 | + */ | ||
| 80 | + List<CouponTemplateDO> getCouponTemplateByTakeType(CouponTakeTypeEnum takeType); | ||
| 81 | + | ||
| 82 | + /** | ||
| 83 | + * 获得优惠券模板列表 | ||
| 84 | + * | ||
| 85 | + * @param canTakeTypes 可领取的类型列表 | ||
| 86 | + * @param productScope 商品使用范围类型 | ||
| 87 | + * @param productScopeValue 商品使用范围编号 | ||
| 88 | + * @param count 查询数量 | ||
| 89 | + * @return 优惠券模板列表 | ||
| 90 | + */ | ||
| 91 | + List<CouponTemplateDO> getCouponTemplateList(List<Integer> canTakeTypes, Integer productScope, | ||
| 92 | + Long productScopeValue, Integer count); | ||
| 93 | + | ||
| 72 | } | 94 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
| @@ -2,16 +2,22 @@ package cn.iocoder.yudao.module.promotion.service.coupon; | @@ -2,16 +2,22 @@ package cn.iocoder.yudao.module.promotion.service.coupon; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | +import cn.iocoder.yudao.module.product.api.category.ProductCategoryApi; | ||
| 6 | +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateCreateReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateCreateReqVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; | 9 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; |
| 8 | import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; | 10 | import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 10 | import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; | 12 | import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; |
| 13 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | ||
| 14 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | ||
| 11 | import org.springframework.stereotype.Service; | 15 | import org.springframework.stereotype.Service; |
| 12 | import org.springframework.validation.annotation.Validated; | 16 | import org.springframework.validation.annotation.Validated; |
| 13 | 17 | ||
| 14 | import javax.annotation.Resource; | 18 | import javax.annotation.Resource; |
| 19 | +import java.util.List; | ||
| 20 | +import java.util.Objects; | ||
| 15 | 21 | ||
| 16 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 22 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 17 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS; | 23 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS; |
| @@ -29,9 +35,15 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | @@ -29,9 +35,15 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | ||
| 29 | @Resource | 35 | @Resource |
| 30 | private CouponTemplateMapper couponTemplateMapper; | 36 | private CouponTemplateMapper couponTemplateMapper; |
| 31 | 37 | ||
| 32 | - // TODO @疯狂:新增/修改时,需要校验对应的商品、分类是否存在 | 38 | + @Resource |
| 39 | + private ProductCategoryApi productCategoryApi; | ||
| 40 | + @Resource | ||
| 41 | + private ProductSpuApi productSpuApi; | ||
| 42 | + | ||
| 33 | @Override | 43 | @Override |
| 34 | public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) { | 44 | public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) { |
| 45 | + // 校验商品范围 | ||
| 46 | + validateProductScope(createReqVO.getProductScope(), createReqVO.getProductScopeValues()); | ||
| 35 | // 插入 | 47 | // 插入 |
| 36 | CouponTemplateDO couponTemplate = CouponTemplateConvert.INSTANCE.convert(createReqVO) | 48 | CouponTemplateDO couponTemplate = CouponTemplateConvert.INSTANCE.convert(createReqVO) |
| 37 | .setStatus(CommonStatusEnum.ENABLE.getStatus()); | 49 | .setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| @@ -48,6 +60,8 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | @@ -48,6 +60,8 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | ||
| 48 | if (updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) { | 60 | if (updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) { |
| 49 | throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount()); | 61 | throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount()); |
| 50 | } | 62 | } |
| 63 | + // 校验商品范围 | ||
| 64 | + validateProductScope(updateReqVO.getProductScope(), updateReqVO.getProductScopeValues()); | ||
| 51 | 65 | ||
| 52 | // 更新 | 66 | // 更新 |
| 53 | CouponTemplateDO updateObj = CouponTemplateConvert.INSTANCE.convert(updateReqVO); | 67 | CouponTemplateDO updateObj = CouponTemplateConvert.INSTANCE.convert(updateReqVO); |
| @@ -78,6 +92,14 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | @@ -78,6 +92,14 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | ||
| 78 | return couponTemplate; | 92 | return couponTemplate; |
| 79 | } | 93 | } |
| 80 | 94 | ||
| 95 | + private void validateProductScope(Integer productScope, List<Long> productScopeValues) { | ||
| 96 | + if (Objects.equals(PromotionProductScopeEnum.SPU.getScope(), productScope)) { | ||
| 97 | + productSpuApi.validateSpuList(productScopeValues); | ||
| 98 | + } else if (Objects.equals(PromotionProductScopeEnum.CATEGORY.getScope(), productScope)) { | ||
| 99 | + productCategoryApi.validateCategoryList(productScopeValues); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 81 | @Override | 103 | @Override |
| 82 | public CouponTemplateDO getCouponTemplate(Long id) { | 104 | public CouponTemplateDO getCouponTemplate(Long id) { |
| 83 | return couponTemplateMapper.selectById(id); | 105 | return couponTemplateMapper.selectById(id); |
| @@ -93,4 +115,15 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | @@ -93,4 +115,15 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { | ||
| 93 | couponTemplateMapper.updateTakeCount(id, incrCount); | 115 | couponTemplateMapper.updateTakeCount(id, incrCount); |
| 94 | } | 116 | } |
| 95 | 117 | ||
| 118 | + @Override | ||
| 119 | + public List<CouponTemplateDO> getCouponTemplateByTakeType(CouponTakeTypeEnum takeType) { | ||
| 120 | + return couponTemplateMapper.selectListByTakeType(takeType.getValue()); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + @Override | ||
| 124 | + public List<CouponTemplateDO> getCouponTemplateList(List<Integer> canTakeTypes, Integer productScope, | ||
| 125 | + Long productScopeValue, Integer count) { | ||
| 126 | + return couponTemplateMapper.selectList(canTakeTypes, productScope, productScopeValue, count); | ||
| 127 | + } | ||
| 128 | + | ||
| 96 | } | 129 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/bo/CouponTakeCountBO.java deleted
| 1 | -package cn.iocoder.yudao.module.promotion.service.coupon.bo; | ||
| 2 | - | ||
| 3 | -import lombok.Data; | ||
| 4 | - | ||
| 5 | -/** | ||
| 6 | - * 优惠券领取数量 BO | ||
| 7 | - * | ||
| 8 | - * @author owen | ||
| 9 | - */ | ||
| 10 | -@Data | ||
| 11 | -public class CouponTakeCountBO { | ||
| 12 | - | ||
| 13 | - /** | ||
| 14 | - * 优惠劵模板编号 | ||
| 15 | - */ | ||
| 16 | - private Long templateId; | ||
| 17 | - /** | ||
| 18 | - * 领取数量 | ||
| 19 | - */ | ||
| 20 | - private Integer count; | ||
| 21 | - | ||
| 22 | -} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java
| @@ -32,7 +32,6 @@ public class TradeStatisticsController { | @@ -32,7 +32,6 @@ public class TradeStatisticsController { | ||
| 32 | @Resource | 32 | @Resource |
| 33 | private TradeStatisticsService tradeStatisticsService; | 33 | private TradeStatisticsService tradeStatisticsService; |
| 34 | 34 | ||
| 35 | - // TODO @疯狂:要不这个就是 /trend/summary 的特例,前端自己查询两次? | ||
| 36 | @GetMapping("/summary") | 35 | @GetMapping("/summary") |
| 37 | @Operation(summary = "获得交易统计") | 36 | @Operation(summary = "获得交易统计") |
| 38 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") | 37 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") |
| @@ -40,7 +39,6 @@ public class TradeStatisticsController { | @@ -40,7 +39,6 @@ public class TradeStatisticsController { | ||
| 40 | return success(tradeStatisticsService.getTradeSummaryComparison()); | 39 | return success(tradeStatisticsService.getTradeSummaryComparison()); |
| 41 | } | 40 | } |
| 42 | 41 | ||
| 43 | - // TODO @疯狂:直接 comparison?主要 trend 和 comparison 二选一,一个是数据趋势,一个是数据对比哈; | ||
| 44 | @GetMapping("/trend/summary") | 42 | @GetMapping("/trend/summary") |
| 45 | @Operation(summary = "获得交易状况统计") | 43 | @Operation(summary = "获得交易状况统计") |
| 46 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") | 44 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java
| 1 | package cn.iocoder.yudao.module.statistics.service.trade; | 1 | package cn.iocoder.yudao.module.statistics.service.trade; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.date.LocalDateTimeUtil; | 3 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | ||
| 4 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; | 5 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; |
| 5 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; | 6 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; |
| 6 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; | 7 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; |
| @@ -13,8 +14,6 @@ import org.springframework.validation.annotation.Validated; | @@ -13,8 +14,6 @@ import org.springframework.validation.annotation.Validated; | ||
| 13 | import javax.annotation.Resource; | 14 | import javax.annotation.Resource; |
| 14 | import java.time.Duration; | 15 | import java.time.Duration; |
| 15 | import java.time.LocalDateTime; | 16 | import java.time.LocalDateTime; |
| 16 | -import java.time.LocalTime; | ||
| 17 | -import java.time.temporal.TemporalAdjusters; | ||
| 18 | import java.util.List; | 17 | import java.util.List; |
| 19 | 18 | ||
| 20 | /** | 19 | /** |
| @@ -79,18 +78,9 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { | @@ -79,18 +78,9 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { | ||
| 79 | * @return 交易数据 | 78 | * @return 交易数据 |
| 80 | */ | 79 | */ |
| 81 | private TradeSummaryRespBO getTradeSummaryByMonths(int months) { | 80 | private TradeSummaryRespBO getTradeSummaryByMonths(int months) { |
| 82 | - // TODO @疯狂:可以在 LocalDateUtils 封装方法;获得月份的开始;以及结束两个方法;然后这里就可以直接调用了 | ||
| 83 | - // 月份开始时间 | ||
| 84 | - LocalDateTime beginOfMonth = LocalDateTime.now() | ||
| 85 | - .plusMonths(months) | ||
| 86 | - .with(TemporalAdjusters.firstDayOfMonth()) | ||
| 87 | - .with(LocalTime.MIN); | ||
| 88 | - // 月份截止时间 | ||
| 89 | - LocalDateTime endOfToday = LocalDateTime.now() | ||
| 90 | - .plusMonths(months) | ||
| 91 | - .with(TemporalAdjusters.lastDayOfMonth()) | ||
| 92 | - .with(LocalTime.MAX); | ||
| 93 | - return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(beginOfMonth, endOfToday); | 81 | + LocalDateTime monthDate = LocalDateTime.now().plusMonths(months); |
| 82 | + return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween( | ||
| 83 | + LocalDateTimeUtils.beginOfMonth(monthDate), LocalDateTimeUtils.endOfMonth(monthDate)); | ||
| 94 | } | 84 | } |
| 95 | 85 | ||
| 96 | } | 86 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java
| @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert; | @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert; | ||
| 11 | import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert; | 11 | import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert; |
| 12 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; | 12 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; |
| 13 | import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; | 13 | import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; |
| 14 | +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; | ||
| 14 | import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; | 15 | import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; |
| 15 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; | 16 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; |
| 16 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; | 17 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; |
| @@ -84,7 +85,7 @@ public class AppBrokerageUserController { | @@ -84,7 +85,7 @@ public class AppBrokerageUserController { | ||
| 84 | LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday); | 85 | LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday); |
| 85 | LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday); | 86 | LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday); |
| 86 | Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(brokerageUser.getId(), | 87 | Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(brokerageUser.getId(), |
| 87 | - BrokerageRecordBizTypeEnum.ORDER.getType(), beginTime, endTime); | 88 | + BrokerageRecordBizTypeEnum.ORDER, BrokerageRecordStatusEnum.SETTLEMENT, beginTime, endTime); |
| 88 | // 统计用户提现的佣金 | 89 | // 统计用户提现的佣金 |
| 89 | Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(brokerageUser.getId()), | 90 | Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(brokerageUser.getId()), |
| 90 | BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream() | 91 | BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream() |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageUserConvert.java
| @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokera | @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokera | ||
| 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; | 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; |
| 12 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO; |
| 13 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO; | 13 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO; |
| 14 | -import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 15 | import org.mapstruct.Mapper; | 14 | import org.mapstruct.Mapper; |
| 16 | import org.mapstruct.MappingTarget; | 15 | import org.mapstruct.MappingTarget; |
| 17 | import org.mapstruct.factory.Mappers; | 16 | import org.mapstruct.factory.Mappers; |
| @@ -88,8 +87,8 @@ public interface BrokerageUserConvert { | @@ -88,8 +87,8 @@ public interface BrokerageUserConvert { | ||
| 88 | return respVO; | 87 | return respVO; |
| 89 | } | 88 | } |
| 90 | 89 | ||
| 91 | - default void copyTo(IPage<AppBrokerageUserChildSummaryRespVO> pageResult, Map<Long, MemberUserRespDTO> userMap) { | ||
| 92 | - for (AppBrokerageUserChildSummaryRespVO vo : pageResult.getRecords()) { | 90 | + default void copyTo(List<AppBrokerageUserChildSummaryRespVO> list, Map<Long, MemberUserRespDTO> userMap) { |
| 91 | + for (AppBrokerageUserChildSummaryRespVO vo : list) { | ||
| 93 | Optional.ofNullable(userMap.get(vo.getId())).ifPresent(user -> | 92 | Optional.ofNullable(userMap.get(vo.getId())).ifPresent(user -> |
| 94 | vo.setNickname(user.getNickname()).setAvatar(user.getAvatar())); | 93 | vo.setNickname(user.getNickname()).setAvatar(user.getAvatar())); |
| 95 | } | 94 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java
| @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order; | @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 6 | +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; | ||
| 5 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; |
| 7 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | 9 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| @@ -105,7 +107,12 @@ public class TradeOrderDO extends BaseDO { | @@ -105,7 +107,12 @@ public class TradeOrderDO extends BaseDO { | ||
| 105 | */ | 107 | */ |
| 106 | private Boolean commentStatus; | 108 | private Boolean commentStatus; |
| 107 | 109 | ||
| 108 | - // TODO @疯狂:加一个推广人编号; | 110 | + /** |
| 111 | + * 推广人编号 | ||
| 112 | + * {@link BrokerageUserDO#getId()} | ||
| 113 | + * {@link MemberUserRespDTO#getId()} | ||
| 114 | + */ | ||
| 115 | + private Long brokerageUserId; | ||
| 109 | 116 | ||
| 110 | // ========== 价格 + 支付基本信息 ========== | 117 | // ========== 价格 + 支付基本信息 ========== |
| 111 | 118 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageRecordMapper.java
| @@ -80,10 +80,11 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { | @@ -80,10 +80,11 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { | ||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | @Select("SELECT SUM(price) FROM trade_brokerage_record " + | 82 | @Select("SELECT SUM(price) FROM trade_brokerage_record " + |
| 83 | - "WHERE user_id = #{userId} AND biz_type = #{bizType} " + | ||
| 84 | - "AND create_time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE") | 83 | + "WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status} " + |
| 84 | + "AND unfreeze_time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE") | ||
| 85 | Integer selectSummaryPriceByUserIdAndBizTypeAndCreateTimeBetween(@Param("userId") Long userId, | 85 | Integer selectSummaryPriceByUserIdAndBizTypeAndCreateTimeBetween(@Param("userId") Long userId, |
| 86 | @Param("bizType") Integer bizType, | 86 | @Param("bizType") Integer bizType, |
| 87 | + @Param("status") Integer status, | ||
| 87 | @Param("beginTime") LocalDateTime beginTime, | 88 | @Param("beginTime") LocalDateTime beginTime, |
| 88 | @Param("endTime") LocalDateTime endTime); | 89 | @Param("endTime") LocalDateTime endTime); |
| 89 | 90 | ||
| @@ -98,4 +99,13 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { | @@ -98,4 +99,13 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { | ||
| 98 | @Param("beginTime") LocalDateTime beginTime, | 99 | @Param("beginTime") LocalDateTime beginTime, |
| 99 | @Param("endTime") LocalDateTime endTime); | 100 | @Param("endTime") LocalDateTime endTime); |
| 100 | 101 | ||
| 102 | + @Select("SELECT COUNT(1) FROM trade_brokerage_record " + | ||
| 103 | + "WHERE biz_type = #{bizType} AND status = #{status} AND deleted = FALSE " + | ||
| 104 | + "AND unfreeze_time BETWEEN #{beginTime} AND #{endTime} " + | ||
| 105 | + "GROUP BY user_id HAVING SUM(price) > #{brokeragePrice}") | ||
| 106 | + Integer selectCountByPriceGt(@Param("brokeragePrice") Integer brokeragePrice, | ||
| 107 | + @Param("bizType") Integer bizType, | ||
| 108 | + @Param("status") Integer status, | ||
| 109 | + @Param("beginTime") LocalDateTime beginTime, | ||
| 110 | + @Param("endTime") LocalDateTime endTime); | ||
| 101 | } | 111 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageUserMapper.java
| @@ -138,13 +138,35 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> { | @@ -138,13 +138,35 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> { | ||
| 138 | @Param("beginTime") LocalDateTime beginTime, | 138 | @Param("beginTime") LocalDateTime beginTime, |
| 139 | @Param("endTime") LocalDateTime endTime); | 139 | @Param("endTime") LocalDateTime endTime); |
| 140 | 140 | ||
| 141 | + /** | ||
| 142 | + * 下级分销统计(分页) | ||
| 143 | + * | ||
| 144 | + * @param bizType 业务类型 | ||
| 145 | + * @param status 状态 | ||
| 146 | + * @param bindUserIds 绑定用户编号列表 | ||
| 147 | + * @param sortingField 排序字段 | ||
| 148 | + * @return 下级分销统计分页列表 | ||
| 149 | + */ | ||
| 141 | IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page, | 150 | IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page, |
| 142 | - @Param("ids") List<Long> ids, // BrokerageUser 的 ids 数组 | ||
| 143 | @Param("bizType") Integer bizType, | 151 | @Param("bizType") Integer bizType, |
| 144 | @Param("status") Integer status, | 152 | @Param("status") Integer status, |
| 145 | @Param("bindUserIds") List<Long> bindUserIds, | 153 | @Param("bindUserIds") List<Long> bindUserIds, |
| 146 | @Param("sortingField") SortingField sortingField); | 154 | @Param("sortingField") SortingField sortingField); |
| 147 | 155 | ||
| 156 | + /** | ||
| 157 | + * 下级分销统计(不分页) | ||
| 158 | + * | ||
| 159 | + * @param bizType 业务类型 | ||
| 160 | + * @param status 状态 | ||
| 161 | + * @param bindUserIds 绑定用户编号列表 | ||
| 162 | + * @param sortingField 排序字段 | ||
| 163 | + * @return 下级分销统计列表 | ||
| 164 | + */ | ||
| 165 | + List<AppBrokerageUserChildSummaryRespVO> selectSummaryListByUserId(@Param("bizType") Integer bizType, | ||
| 166 | + @Param("status") Integer status, | ||
| 167 | + @Param("bindUserIds") List<Long> bindUserIds, | ||
| 168 | + @Param("sortingField") SortingField sortingField); | ||
| 169 | + | ||
| 148 | default List<BrokerageUserDO> selectListByBindUserId(Long bindUserId) { | 170 | default List<BrokerageUserDO> selectListByBindUserId(Long bindUserId) { |
| 149 | return selectList(BrokerageUserDO::getBindUserId, bindUserId); | 171 | return selectList(BrokerageUserDO::getBindUserId, bindUserId); |
| 150 | } | 172 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java
| @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokera | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokera | ||
| 7 | import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; | 7 | import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; |
| 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO; |
| 9 | import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; | 9 | import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; |
| 10 | +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; | ||
| 10 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; | 11 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; |
| 11 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO; |
| 12 | 13 | ||
| @@ -120,11 +121,13 @@ public interface BrokerageRecordService { | @@ -120,11 +121,13 @@ public interface BrokerageRecordService { | ||
| 120 | * | 121 | * |
| 121 | * @param userId 用户编号 | 122 | * @param userId 用户编号 |
| 122 | * @param bizType 业务类型 | 123 | * @param bizType 业务类型 |
| 124 | + * @param status 状态 | ||
| 123 | * @param beginTime 开始时间 | 125 | * @param beginTime 开始时间 |
| 124 | * @param endTime 截止时间 | 126 | * @param endTime 截止时间 |
| 125 | * @return 用户佣金合计 | 127 | * @return 用户佣金合计 |
| 126 | */ | 128 | */ |
| 127 | - Integer getSummaryPriceByUserId(Long userId, Integer bizType, LocalDateTime beginTime, LocalDateTime endTime); | 129 | + Integer getSummaryPriceByUserId(Long userId, BrokerageRecordBizTypeEnum bizType, BrokerageRecordStatusEnum status, |
| 130 | + LocalDateTime beginTime, LocalDateTime endTime); | ||
| 128 | 131 | ||
| 129 | /** | 132 | /** |
| 130 | * 获得用户佣金排行分页列表(基于佣金总数) | 133 | * 获得用户佣金排行分页列表(基于佣金总数) |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java
| @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage; | @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.collection.ListUtil; | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | -import cn.hutool.core.util.ArrayUtil; | ||
| 6 | -import cn.hutool.core.util.BooleanUtil; | ||
| 7 | -import cn.hutool.core.util.ObjectUtil; | ||
| 8 | -import cn.hutool.core.util.StrUtil; | 5 | +import cn.hutool.core.util.*; |
| 9 | import cn.hutool.extra.spring.SpringUtil; | 6 | import cn.hutool.extra.spring.SpringUtil; |
| 10 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 11 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; | 8 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; |
| @@ -265,9 +262,10 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { | @@ -265,9 +262,10 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { | ||
| 265 | } | 262 | } |
| 266 | 263 | ||
| 267 | @Override | 264 | @Override |
| 268 | - public Integer getSummaryPriceByUserId(Long userId, Integer bizType, LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 269 | - return brokerageRecordMapper.selectSummaryPriceByUserIdAndBizTypeAndCreateTimeBetween(userId, bizType, | ||
| 270 | - beginTime, endTime); | 265 | + public Integer getSummaryPriceByUserId(Long userId, BrokerageRecordBizTypeEnum bizType, BrokerageRecordStatusEnum status, |
| 266 | + LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 267 | + return brokerageRecordMapper.selectSummaryPriceByUserIdAndBizTypeAndCreateTimeBetween(userId, | ||
| 268 | + bizType.getType(), status.getStatus(), beginTime, endTime); | ||
| 271 | } | 269 | } |
| 272 | 270 | ||
| 273 | @Override | 271 | @Override |
| @@ -279,17 +277,18 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { | @@ -279,17 +277,18 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { | ||
| 279 | return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); | 277 | return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); |
| 280 | } | 278 | } |
| 281 | 279 | ||
| 282 | - // TODO @疯狂:这个要不我们先做精准的?先查询自己的推广金额,然后查询比该金额多的有多少人? | ||
| 283 | @Override | 280 | @Override |
| 284 | public Integer getUserRankByPrice(Long userId, LocalDateTime[] times) { | 281 | public Integer getUserRankByPrice(Long userId, LocalDateTime[] times) { |
| 285 | - AppBrokerageUserRankPageReqVO pageParam = new AppBrokerageUserRankPageReqVO().setTimes(times); | ||
| 286 | - // 取前 100 名 | ||
| 287 | - pageParam.setPageSize(100); | ||
| 288 | - PageResult<AppBrokerageUserRankByPriceRespVO> pageResult = getBrokerageUserChildSummaryPageByPrice(pageParam); | ||
| 289 | - // 获得索引 | ||
| 290 | - int index = CollUtil.indexOf(pageResult.getList(), user -> Objects.equals(userId, user.getId())); | 282 | + // 用户的推广金额 |
| 283 | + Integer price = brokerageRecordMapper.selectSummaryPriceByUserIdAndBizTypeAndCreateTimeBetween(userId, | ||
| 284 | + BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), | ||
| 285 | + ArrayUtil.get(times, 0), ArrayUtil.get(times, 1)); | ||
| 286 | + // 排在用户前面的人数 | ||
| 287 | + Integer greaterCount = brokerageRecordMapper.selectCountByPriceGt(price, | ||
| 288 | + BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), | ||
| 289 | + ArrayUtil.get(times, 0), ArrayUtil.get(times, 1)); | ||
| 291 | // 获得排名 | 290 | // 获得排名 |
| 292 | - return index + 1; | 291 | + return ObjUtil.defaultIfNull(greaterCount, 0) + 1; |
| 293 | } | 292 | } |
| 294 | 293 | ||
| 295 | @Override | 294 | @Override |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java
| @@ -31,6 +31,7 @@ import org.springframework.validation.annotation.Validated; | @@ -31,6 +31,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 31 | import javax.annotation.Resource; | 31 | import javax.annotation.Resource; |
| 32 | import java.time.LocalDateTime; | 32 | import java.time.LocalDateTime; |
| 33 | import java.util.*; | 33 | import java.util.*; |
| 34 | +import java.util.stream.Collectors; | ||
| 34 | 35 | ||
| 35 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 36 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 36 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 37 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| @@ -225,25 +226,66 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { | @@ -225,25 +226,66 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { | ||
| 225 | 226 | ||
| 226 | @Override | 227 | @Override |
| 227 | public PageResult<AppBrokerageUserChildSummaryRespVO> getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId) { | 228 | public PageResult<AppBrokerageUserChildSummaryRespVO> getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId) { |
| 228 | - // 1.1 根据昵称过滤用户 | ||
| 229 | - List<Long> ids = StrUtil.isBlank(pageReqVO.getNickname()) | ||
| 230 | - ? Collections.emptyList() | ||
| 231 | - : convertList(memberUserApi.getUserListByNickname(pageReqVO.getNickname()), MemberUserRespDTO::getId); | ||
| 232 | - // 1.2 生成推广员编号列表 | ||
| 233 | - // TODO @疯狂:是不是可以先 1.2 查询出来,然后查询对应的昵称,进行过滤?避免昵称过滤返回的 id 过多; | 229 | + // 生成推广员编号列表 |
| 234 | List<Long> bindUserIds = buildBindUserIdsByLevel(userId, pageReqVO.getLevel()); | 230 | List<Long> bindUserIds = buildBindUserIdsByLevel(userId, pageReqVO.getLevel()); |
| 235 | 231 | ||
| 236 | - // 2. 分页查询 | ||
| 237 | - IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId( | ||
| 238 | - MyBatisUtils.buildPage(pageReqVO), ids, BrokerageRecordBizTypeEnum.ORDER.getType(), | ||
| 239 | - BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), bindUserIds, pageReqVO.getSortingField() | 232 | + // 情况一:没有昵称过滤条件时,直接使用数据库的分页查询 |
| 233 | + if (StrUtil.isBlank(pageReqVO.getNickname())) { | ||
| 234 | + // 1.1 分页查询 | ||
| 235 | + IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId( | ||
| 236 | + MyBatisUtils.buildPage(pageReqVO), BrokerageRecordBizTypeEnum.ORDER.getType(), | ||
| 237 | + BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), bindUserIds, pageReqVO.getSortingField() | ||
| 238 | + ); | ||
| 239 | + | ||
| 240 | + // 1.2 拼接数据并返回 | ||
| 241 | + List<Long> userIds = convertList(pageResult.getRecords(), AppBrokerageUserChildSummaryRespVO::getId); | ||
| 242 | + Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds); | ||
| 243 | + BrokerageUserConvert.INSTANCE.copyTo(pageResult.getRecords(), userMap); | ||
| 244 | + return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + // 情况二:有昵称过滤条件时,需要跨模块(Member)过滤 | ||
| 248 | + // 2.1 查询所有匹配的分销用户 | ||
| 249 | + List<AppBrokerageUserChildSummaryRespVO> list = brokerageUserMapper.selectSummaryListByUserId( | ||
| 250 | + BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), | ||
| 251 | + bindUserIds, pageReqVO.getSortingField() | ||
| 240 | ); | 252 | ); |
| 253 | + if (CollUtil.isEmpty(list)) { | ||
| 254 | + return PageResult.empty(); | ||
| 255 | + } | ||
| 241 | 256 | ||
| 242 | - // 3. 拼接数据并返回 | ||
| 243 | - List<Long> userIds = convertList(pageResult.getRecords(), AppBrokerageUserChildSummaryRespVO::getId); | ||
| 244 | - Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds); | ||
| 245 | - BrokerageUserConvert.INSTANCE.copyTo(pageResult, userMap); | ||
| 246 | - return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); | 257 | + // 2.2 查出对应的用户信息 |
| 258 | + List<MemberUserRespDTO> users = memberUserApi.getUserList(convertList(list, AppBrokerageUserChildSummaryRespVO::getId)); | ||
| 259 | + if (CollUtil.isEmpty(users)) { | ||
| 260 | + return PageResult.empty(); | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + // 2.3 根据昵称过滤出用户编号 | ||
| 264 | + Map<Long, MemberUserRespDTO> userMap = users.stream() | ||
| 265 | + .filter(user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname())) | ||
| 266 | + .collect(Collectors.toMap(MemberUserRespDTO::getId, dto -> dto)); | ||
| 267 | + if (CollUtil.isEmpty(userMap)) { | ||
| 268 | + return PageResult.empty(); | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + // 2.4 根据用户编号过滤结果 | ||
| 272 | + list.removeIf(vo -> !userMap.containsKey(vo.getId())); | ||
| 273 | + if (CollUtil.isEmpty(list)) { | ||
| 274 | + return PageResult.empty(); | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + // 2.5 处理分页 | ||
| 278 | + List<AppBrokerageUserChildSummaryRespVO> result = list.stream() | ||
| 279 | + .skip((long) (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize()) | ||
| 280 | + .limit(pageReqVO.getPageSize()) | ||
| 281 | + .collect(Collectors.toList()); | ||
| 282 | + if (CollUtil.isEmpty(result)) { | ||
| 283 | + return PageResult.empty(); | ||
| 284 | + } | ||
| 285 | + | ||
| 286 | + // 2.6 拼接数据并返回 | ||
| 287 | + BrokerageUserConvert.INSTANCE.copyTo(result, userMap); | ||
| 288 | + return new PageResult<>(result, (long) list.size()); | ||
| 247 | } | 289 | } |
| 248 | 290 | ||
| 249 | private boolean isUserCanBind(BrokerageUserDO user) { | 291 | private boolean isUserCanBind(BrokerageUserDO user) { |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -40,6 +40,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle | @@ -40,6 +40,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle | ||
| 40 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; | 40 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; |
| 41 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; | 41 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; |
| 42 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | 42 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; |
| 43 | +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; | ||
| 43 | import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; | 44 | import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; |
| 44 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; | 45 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 45 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 46 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| @@ -54,6 +55,7 @@ import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties | @@ -54,6 +55,7 @@ import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties | ||
| 54 | import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; | 55 | import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; |
| 55 | import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; | 56 | import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; |
| 56 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; | 57 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; |
| 58 | +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; | ||
| 57 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; | 59 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; |
| 58 | import cn.iocoder.yudao.module.trade.service.cart.CartService; | 60 | import cn.iocoder.yudao.module.trade.service.cart.CartService; |
| 59 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; | 61 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; |
| @@ -108,6 +110,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -108,6 +110,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 108 | private DeliveryExpressService deliveryExpressService; | 110 | private DeliveryExpressService deliveryExpressService; |
| 109 | @Resource | 111 | @Resource |
| 110 | private TradeMessageService tradeMessageService; | 112 | private TradeMessageService tradeMessageService; |
| 113 | + @Resource | ||
| 114 | + private BrokerageUserService brokerageUserService; | ||
| 115 | + @Resource | ||
| 116 | + private BrokerageRecordService brokerageRecordService; | ||
| 111 | 117 | ||
| 112 | @Resource | 118 | @Resource |
| 113 | private ProductSpuApi productSpuApi; | 119 | private ProductSpuApi productSpuApi; |
| @@ -130,8 +136,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -130,8 +136,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 130 | @Resource | 136 | @Resource |
| 131 | private MemberPointApi memberPointApi; | 137 | private MemberPointApi memberPointApi; |
| 132 | @Resource | 138 | @Resource |
| 133 | - private BrokerageRecordService brokerageRecordService; | ||
| 134 | - @Resource | ||
| 135 | private ProductCommentApi productCommentApi; | 139 | private ProductCommentApi productCommentApi; |
| 136 | 140 | ||
| 137 | @Resource | 141 | @Resource |
| @@ -301,6 +305,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -301,6 +305,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 301 | // 6. 插入订单日志 | 305 | // 6. 插入订单日志 |
| 302 | TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); | 306 | TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); |
| 303 | 307 | ||
| 308 | + // 7. 设置订单推广人 | ||
| 309 | + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId()); | ||
| 310 | + if (brokerageUser != null && brokerageUser.getBindUserId() != null) { | ||
| 311 | + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setBrokerageUserId(brokerageUser.getBindUserId())); | ||
| 312 | + } | ||
| 313 | + | ||
| 304 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! | 314 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! |
| 305 | } | 315 | } |
| 306 | 316 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java
| @@ -4,7 +4,6 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | @@ -4,7 +4,6 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 4 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | 4 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 5 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | 5 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; |
| 6 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | 6 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 7 | -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | ||
| 8 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 7 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 8 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 10 | import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; | 9 | import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; |
| @@ -20,7 +19,8 @@ import java.util.Map; | @@ -20,7 +19,8 @@ import java.util.Map; | ||
| 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 20 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 22 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 23 | -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; | 22 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; |
| 23 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; | ||
| 24 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; | 24 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; |
| 25 | 25 | ||
| 26 | /** | 26 | /** |
| @@ -82,18 +82,7 @@ public class TradePriceServiceImpl implements TradePriceService { | @@ -82,18 +82,7 @@ public class TradePriceServiceImpl implements TradePriceService { | ||
| 82 | 82 | ||
| 83 | private List<ProductSpuRespDTO> checkSpuList(List<ProductSkuRespDTO> skuList) { | 83 | private List<ProductSpuRespDTO> checkSpuList(List<ProductSkuRespDTO> skuList) { |
| 84 | // 获得商品 SPU 数组 | 84 | // 获得商品 SPU 数组 |
| 85 | - List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(convertSet(skuList, ProductSkuRespDTO::getSpuId)); | ||
| 86 | - | ||
| 87 | - // 校验商品 SPU | ||
| 88 | - spus.forEach(spu -> { | ||
| 89 | - if (spu == null) { | ||
| 90 | - throw exception(SPU_NOT_EXISTS); | ||
| 91 | - } | ||
| 92 | - if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { | ||
| 93 | - throw exception(SPU_NOT_ENABLE); | ||
| 94 | - } | ||
| 95 | - }); | ||
| 96 | - return spus; | 85 | + return productSpuApi.getSpuListAndValidate(convertSet(skuList, ProductSkuRespDTO::getSpuId)); |
| 97 | } | 86 | } |
| 98 | 87 | ||
| 99 | } | 88 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointGiveCalculator.java
| @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.BooleanUtil; | 3 | import cn.hutool.core.util.BooleanUtil; |
| 4 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; | 4 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; |
| 5 | -import cn.iocoder.yudao.module.member.api.point.MemberPointApi; | ||
| 6 | -import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO; | 5 | +import cn.iocoder.yudao.module.member.api.config.MemberConfigApi; |
| 6 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 7 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 7 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 8 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 8 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 9 | import lombok.extern.slf4j.Slf4j; | 9 | import lombok.extern.slf4j.Slf4j; |
| @@ -16,7 +16,6 @@ import java.util.Optional; | @@ -16,7 +16,6 @@ import java.util.Optional; | ||
| 16 | 16 | ||
| 17 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | 17 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| 18 | 18 | ||
| 19 | -// TODO @疯狂:这个可以搞个单测; | ||
| 20 | /** | 19 | /** |
| 21 | * 赠送积分的 {@link TradePriceCalculator} 实现类 | 20 | * 赠送积分的 {@link TradePriceCalculator} 实现类 |
| 22 | * | 21 | * |
| @@ -28,14 +27,14 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -28,14 +27,14 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 28 | public class TradePointGiveCalculator implements TradePriceCalculator { | 27 | public class TradePointGiveCalculator implements TradePriceCalculator { |
| 29 | 28 | ||
| 30 | @Resource | 29 | @Resource |
| 31 | - private MemberPointApi memberPointApi; | 30 | + private MemberConfigApi memberConfigApi; |
| 32 | 31 | ||
| 33 | @Override | 32 | @Override |
| 34 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 33 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 35 | // 1.1 校验积分功能是否开启 | 34 | // 1.1 校验积分功能是否开启 |
| 36 | - int givePointPerYuan = Optional.ofNullable(memberPointApi.getConfig()) | ||
| 37 | - .filter(config -> BooleanUtil.isTrue(config.getTradeDeductEnable())) | ||
| 38 | - .map(MemberPointConfigRespDTO::getTradeGivePoint) | 35 | + int givePointPerYuan = Optional.ofNullable(memberConfigApi.getConfig()) |
| 36 | + .filter(config -> BooleanUtil.isTrue(config.getPointTradeDeductEnable())) | ||
| 37 | + .map(MemberConfigRespDTO::getPointTradeGivePoint) | ||
| 39 | .orElse(0); | 38 | .orElse(0); |
| 40 | if (givePointPerYuan <= 0) { | 39 | if (givePointPerYuan <= 0) { |
| 41 | return; | 40 | return; |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointUsePriceCalculator.java
| @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.BooleanUtil; | 3 | import cn.hutool.core.util.BooleanUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | -import cn.iocoder.yudao.module.member.api.point.MemberPointApi; | ||
| 6 | -import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO; | 5 | +import cn.iocoder.yudao.module.member.api.config.MemberConfigApi; |
| 6 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 7 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | 7 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; |
| 8 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 8 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| @@ -20,7 +20,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | @@ -20,7 +20,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | ||
| 20 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | 20 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| 21 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; | 21 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; |
| 22 | 22 | ||
| 23 | -// TODO @疯狂:搞个单测,嘿嘿; | ||
| 24 | /** | 23 | /** |
| 25 | * 使用积分的 {@link TradePriceCalculator} 实现类 | 24 | * 使用积分的 {@link TradePriceCalculator} 实现类 |
| 26 | * | 25 | * |
| @@ -32,19 +31,21 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCU | @@ -32,19 +31,21 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCU | ||
| 32 | public class TradePointUsePriceCalculator implements TradePriceCalculator { | 31 | public class TradePointUsePriceCalculator implements TradePriceCalculator { |
| 33 | 32 | ||
| 34 | @Resource | 33 | @Resource |
| 35 | - private MemberPointApi memberPointApi; | 34 | + private MemberConfigApi memberConfigApi; |
| 36 | @Resource | 35 | @Resource |
| 37 | private MemberUserApi memberUserApi; | 36 | private MemberUserApi memberUserApi; |
| 38 | 37 | ||
| 39 | @Override | 38 | @Override |
| 40 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 39 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 40 | + // 默认使用积分为 0 | ||
| 41 | + result.setUsePoint(0); | ||
| 41 | // 1.1 校验是否使用积分 | 42 | // 1.1 校验是否使用积分 |
| 42 | if (!BooleanUtil.isTrue(param.getPointStatus())) { | 43 | if (!BooleanUtil.isTrue(param.getPointStatus())) { |
| 43 | result.setUsePoint(0); | 44 | result.setUsePoint(0); |
| 44 | return; | 45 | return; |
| 45 | } | 46 | } |
| 46 | // 1.2 校验积分抵扣是否开启 | 47 | // 1.2 校验积分抵扣是否开启 |
| 47 | - MemberPointConfigRespDTO config = memberPointApi.getConfig(); | 48 | + MemberConfigRespDTO config = memberConfigApi.getConfig(); |
| 48 | if (!isDeductPointEnable(config)) { | 49 | if (!isDeductPointEnable(config)) { |
| 49 | return; | 50 | return; |
| 50 | } | 51 | } |
| @@ -76,20 +77,20 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { | @@ -76,20 +77,20 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { | ||
| 76 | TradePriceCalculatorHelper.recountAllPrice(result); | 77 | TradePriceCalculatorHelper.recountAllPrice(result); |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | - private boolean isDeductPointEnable(MemberPointConfigRespDTO config) { | 80 | + private boolean isDeductPointEnable(MemberConfigRespDTO config) { |
| 80 | return config != null && | 81 | return config != null && |
| 81 | - !BooleanUtil.isTrue(config.getTradeDeductEnable()) && // 积分功能是否启用 | ||
| 82 | - config.getTradeDeductUnitPrice() != null && config.getTradeDeductUnitPrice() > 0; // 有没有配置:1 积分抵扣多少分 | 82 | + BooleanUtil.isTrue(config.getPointTradeDeductEnable()) && // 积分功能是否启用 |
| 83 | + config.getPointTradeDeductUnitPrice() != null && config.getPointTradeDeductUnitPrice() > 0; // 有没有配置:1 积分抵扣多少分 | ||
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | - private Integer calculatePointPrice(MemberPointConfigRespDTO config, Integer usePoint, TradePriceCalculateRespBO result) { | 86 | + private Integer calculatePointPrice(MemberConfigRespDTO config, Integer usePoint, TradePriceCalculateRespBO result) { |
| 86 | // 每个订单最多可以使用的积分数量 | 87 | // 每个订单最多可以使用的积分数量 |
| 87 | - if (config.getTradeDeductMaxPrice() != null && config.getTradeDeductMaxPrice() > 0) { | ||
| 88 | - usePoint = Math.min(usePoint, config.getTradeDeductMaxPrice()); | 88 | + if (config.getPointTradeDeductMaxPrice() != null && config.getPointTradeDeductMaxPrice() > 0) { |
| 89 | + usePoint = Math.min(usePoint, config.getPointTradeDeductMaxPrice()); | ||
| 89 | } | 90 | } |
| 90 | // TODO @疯狂:这里应该是,抵扣到只剩下 0.01; | 91 | // TODO @疯狂:这里应该是,抵扣到只剩下 0.01; |
| 91 | // 积分优惠金额(分) | 92 | // 积分优惠金额(分) |
| 92 | - int pointPrice = usePoint * config.getTradeDeductUnitPrice(); | 93 | + int pointPrice = usePoint * config.getPointTradeDeductUnitPrice(); |
| 93 | if (result.getPrice().getPayPrice() <= pointPrice) { | 94 | if (result.getPrice().getPayPrice() <= pointPrice) { |
| 94 | // 禁止 0 元购 | 95 | // 禁止 0 元购 |
| 95 | throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); | 96 | throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); |
| @@ -99,7 +100,7 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { | @@ -99,7 +100,7 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { | ||
| 99 | // pointPrice = result.getPrice().getPayPrice(); | 100 | // pointPrice = result.getPrice().getPayPrice(); |
| 100 | // // 反推需要扣除的积分 | 101 | // // 反推需要扣除的积分 |
| 101 | // usePoint = NumberUtil.toBigDecimal(pointPrice) | 102 | // usePoint = NumberUtil.toBigDecimal(pointPrice) |
| 102 | -// .divide(NumberUtil.toBigDecimal(config.getTradeDeductUnitPrice()), 0, RoundingMode.HALF_UP) | 103 | +// .divide(NumberUtil.toBigDecimal(config.getPointTradeDeductUnitPrice()), 0, RoundingMode.HALF_UP) |
| 103 | // .intValue(); | 104 | // .intValue(); |
| 104 | // } | 105 | // } |
| 105 | // 记录使用的积分 | 106 | // 记录使用的积分 |
yudao-module-mall/yudao-module-trade-biz/src/main/resources/mapper/brokerage/BrokerageUserMapper.xml
| @@ -2,8 +2,7 @@ | @@ -2,8 +2,7 @@ | ||
| 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| 3 | <mapper namespace="cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper"> | 3 | <mapper namespace="cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper"> |
| 4 | 4 | ||
| 5 | - <select id="selectSummaryPageByUserId" | ||
| 6 | - resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> | 5 | + <sql id="selectSummaryListByUserId"> |
| 7 | SELECT bu.id, bu.bind_user_time AS brokerageTime, | 6 | SELECT bu.id, bu.bind_user_time AS brokerageTime, |
| 8 | (SELECT SUM(price) FROM trade_brokerage_record r | 7 | (SELECT SUM(price) FROM trade_brokerage_record r |
| 9 | WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice, | 8 | WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice, |
| @@ -14,12 +13,6 @@ | @@ -14,12 +13,6 @@ | ||
| 14 | FROM trade_brokerage_user AS bu | 13 | FROM trade_brokerage_user AS bu |
| 15 | <where> | 14 | <where> |
| 16 | bu.deleted = false | 15 | bu.deleted = false |
| 17 | - <if test="ids != null and ids.size() > 0"> | ||
| 18 | - and bu.id in | ||
| 19 | - <foreach collection="ids" open="(" item="id" separator="," close=")"> | ||
| 20 | - #{id} | ||
| 21 | - </foreach> | ||
| 22 | - </if> | ||
| 23 | <if test="bindUserIds != null and bindUserIds.size() > 0"> | 16 | <if test="bindUserIds != null and bindUserIds.size() > 0"> |
| 24 | and bu.bind_user_id in | 17 | and bu.bind_user_id in |
| 25 | <foreach collection="bindUserIds" open="(" item="bindUserId" separator="," close=")"> | 18 | <foreach collection="bindUserIds" open="(" item="bindUserId" separator="," close=")"> |
| @@ -41,6 +34,15 @@ | @@ -41,6 +34,15 @@ | ||
| 41 | ORDER BY bu.bind_user_time DESC | 34 | ORDER BY bu.bind_user_time DESC |
| 42 | </otherwise> | 35 | </otherwise> |
| 43 | </choose> | 36 | </choose> |
| 37 | + </sql> | ||
| 38 | + | ||
| 39 | + <select id="selectSummaryPageByUserId" | ||
| 40 | + resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> | ||
| 41 | + <include refid="selectSummaryListByUserId" /> | ||
| 42 | + </select> | ||
| 43 | + <select id="selectSummaryListByUserId" | ||
| 44 | + resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> | ||
| 45 | + <include refid="selectSummaryListByUserId" /> | ||
| 44 | </select> | 46 | </select> |
| 45 | 47 | ||
| 46 | </mapper> | 48 | </mapper> |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointGiveCalculatorTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 4 | +import cn.iocoder.yudao.module.member.api.config.MemberConfigApi; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 6 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 7 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | ||
| 8 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 9 | +import org.junit.jupiter.api.Test; | ||
| 10 | +import org.mockito.InjectMocks; | ||
| 11 | +import org.mockito.Mock; | ||
| 12 | + | ||
| 13 | +import java.util.ArrayList; | ||
| 14 | + | ||
| 15 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 16 | +import static java.util.Arrays.asList; | ||
| 17 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 18 | +import static org.mockito.Mockito.when; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * {@link TradePointGiveCalculator} 的单元测试类 | ||
| 22 | + * | ||
| 23 | + * @author owen | ||
| 24 | + */ | ||
| 25 | +public class TradePointGiveCalculatorTest extends BaseMockitoUnitTest { | ||
| 26 | + | ||
| 27 | + @InjectMocks | ||
| 28 | + private TradePointGiveCalculator tradePointGiveCalculator; | ||
| 29 | + | ||
| 30 | + @Mock | ||
| 31 | + private MemberConfigApi memberConfigApi; | ||
| 32 | + | ||
| 33 | + @Test | ||
| 34 | + public void testCalculate() { | ||
| 35 | + | ||
| 36 | + // 准备参数 | ||
| 37 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 38 | + .setUserId(233L) | ||
| 39 | + .setItems(asList( | ||
| 40 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 全局积分 | ||
| 41 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 全局积分 + SKU 积分 | ||
| 42 | + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(false), // 全局积分,但是未选中 | ||
| 43 | + new TradePriceCalculateReqBO.Item().setSkuId(40L).setCount(5).setSelected(false) // 全局积分 + SKU 积分,但是未选中 | ||
| 44 | + )); | ||
| 45 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 46 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 47 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 48 | + .setPromotions(new ArrayList<>()) | ||
| 49 | + .setItems(asList( | ||
| 50 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 51 | + .setPrice(100).setSpuId(1L).setGivePoint(0), | ||
| 52 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 53 | + .setPrice(50).setSpuId(2L).setGivePoint(100), | ||
| 54 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(4).setSelected(false) | ||
| 55 | + .setPrice(30).setSpuId(3L).setGivePoint(0), | ||
| 56 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(40L).setCount(5).setSelected(false) | ||
| 57 | + .setPrice(60).setSpuId(1L).setGivePoint(100) | ||
| 58 | + )); | ||
| 59 | + // 保证价格被初始化上 | ||
| 60 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 61 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 62 | + | ||
| 63 | + // mock 方法(积分配置 信息) | ||
| 64 | + MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class, | ||
| 65 | + o -> o.setPointTradeDeductEnable(true) // 启用积分折扣 | ||
| 66 | + .setPointTradeGivePoint(100)); // 1 元赠送多少分 | ||
| 67 | + when(memberConfigApi.getConfig()).thenReturn(memberConfig); | ||
| 68 | + | ||
| 69 | + // 调用 | ||
| 70 | + tradePointGiveCalculator.calculate(param, result); | ||
| 71 | + // 断言:Price 部分 | ||
| 72 | + assertEquals(result.getGivePoint(), 2 * 100 + 3 * 50 + 100); | ||
| 73 | + // 断言:SKU 1 | ||
| 74 | + TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 75 | + assertEquals(orderItem01.getSkuId(), 10L); | ||
| 76 | + assertEquals(orderItem01.getCount(), 2); | ||
| 77 | + assertEquals(orderItem01.getPrice(), 100); | ||
| 78 | + assertEquals(orderItem01.getGivePoint(), 2 * 100); // 全局积分 | ||
| 79 | + // 断言:SKU 2 | ||
| 80 | + TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 81 | + assertEquals(orderItem02.getSkuId(), 20L); | ||
| 82 | + assertEquals(orderItem02.getCount(), 3); | ||
| 83 | + assertEquals(orderItem02.getPrice(), 50); | ||
| 84 | + assertEquals(orderItem02.getGivePoint(), 3 * 50 + 100); // 全局积分 + SKU 积分 | ||
| 85 | + // 断言:SKU 3 | ||
| 86 | + TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2); | ||
| 87 | + assertEquals(orderItem03.getSkuId(), 30L); | ||
| 88 | + assertEquals(orderItem03.getCount(), 4); | ||
| 89 | + assertEquals(orderItem03.getPrice(), 30); | ||
| 90 | + assertEquals(orderItem03.getGivePoint(), 0); // 全局积分,但是未选中 | ||
| 91 | + // 断言:SKU 4 | ||
| 92 | + TradePriceCalculateRespBO.OrderItem orderItem04 = result.getItems().get(3); | ||
| 93 | + assertEquals(orderItem04.getSkuId(), 40L); | ||
| 94 | + assertEquals(orderItem04.getCount(), 5); | ||
| 95 | + assertEquals(orderItem04.getPrice(), 60); | ||
| 96 | + assertEquals(orderItem04.getGivePoint(), 100); // 全局积分 + SKU 积分,但是未选中 | ||
| 97 | + } | ||
| 98 | +} | ||
| 0 | \ No newline at end of file | 99 | \ No newline at end of file |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointUsePriceCalculatorTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 4 | +import cn.iocoder.yudao.module.member.api.config.MemberConfigApi; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 6 | +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 7 | +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 8 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 10 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | ||
| 11 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 12 | +import org.junit.jupiter.api.Test; | ||
| 13 | +import org.mockito.InjectMocks; | ||
| 14 | +import org.mockito.Mock; | ||
| 15 | + | ||
| 16 | +import java.util.ArrayList; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 19 | +import static java.util.Arrays.asList; | ||
| 20 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 21 | +import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| 22 | +import static org.mockito.Mockito.when; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * {@link TradePointUsePriceCalculator } 的单元测试类 | ||
| 26 | + * | ||
| 27 | + * @author owen | ||
| 28 | + */ | ||
| 29 | +public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 30 | + | ||
| 31 | + @InjectMocks | ||
| 32 | + private TradePointUsePriceCalculator tradePointUsePriceCalculator; | ||
| 33 | + | ||
| 34 | + @Mock | ||
| 35 | + private MemberConfigApi memberConfigApi; | ||
| 36 | + @Mock | ||
| 37 | + private MemberUserApi memberUserApi; | ||
| 38 | + | ||
| 39 | + @Test | ||
| 40 | + public void testCalculate_success() { | ||
| 41 | + // 准备参数 | ||
| 42 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 43 | + .setUserId(233L).setPointStatus(true) // 是否使用积分 | ||
| 44 | + .setItems(asList( | ||
| 45 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分 | ||
| 46 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分 | ||
| 47 | + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分 | ||
| 48 | + )); | ||
| 49 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 50 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 51 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 52 | + .setPromotions(new ArrayList<>()) | ||
| 53 | + .setItems(asList( | ||
| 54 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 55 | + .setPrice(100).setSpuId(1L), | ||
| 56 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 57 | + .setPrice(50).setSpuId(2L), | ||
| 58 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false) | ||
| 59 | + .setPrice(30).setSpuId(3L) | ||
| 60 | + )); | ||
| 61 | + // 保证价格被初始化上 | ||
| 62 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 63 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 64 | + | ||
| 65 | + // mock 方法(积分配置 信息) | ||
| 66 | + MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class, | ||
| 67 | + o -> o.setPointTradeDeductEnable(true) // 启用积分折扣 | ||
| 68 | + .setPointTradeDeductUnitPrice(1) // 1 积分抵扣多少金额(单位分) | ||
| 69 | + .setPointTradeDeductMaxPrice(100)); // 积分抵扣最大值 | ||
| 70 | + when(memberConfigApi.getConfig()).thenReturn(memberConfig); | ||
| 71 | + // mock 方法(会员 信息) | ||
| 72 | + MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(100)); | ||
| 73 | + when(memberUserApi.getUser(user.getId())).thenReturn(user); | ||
| 74 | + | ||
| 75 | + // 调用 | ||
| 76 | + tradePointUsePriceCalculator.calculate(param, result); | ||
| 77 | + // 断言:使用了多少积分 | ||
| 78 | + assertEquals(result.getUsePoint(), 100); | ||
| 79 | + // 断言:Price 部分 | ||
| 80 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 81 | + assertEquals(price.getTotalPrice(), 350); | ||
| 82 | + assertEquals(price.getPayPrice(), 250); | ||
| 83 | + assertEquals(price.getPointPrice(), 100); | ||
| 84 | + // 断言:SKU 1 | ||
| 85 | + TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 86 | + assertEquals(orderItem01.getSkuId(), 10L); | ||
| 87 | + assertEquals(orderItem01.getCount(), 2); | ||
| 88 | + assertEquals(orderItem01.getPrice(), 100); | ||
| 89 | + assertEquals(orderItem01.getPointPrice(), 57); | ||
| 90 | + assertEquals(orderItem01.getPayPrice(), 143); | ||
| 91 | + // 断言:SKU 2 | ||
| 92 | + TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 93 | + assertEquals(orderItem02.getSkuId(), 20L); | ||
| 94 | + assertEquals(orderItem02.getCount(), 3); | ||
| 95 | + assertEquals(orderItem02.getPrice(), 50); | ||
| 96 | + assertEquals(orderItem02.getPointPrice(), 43); | ||
| 97 | + assertEquals(orderItem02.getPayPrice(), 107); | ||
| 98 | + // 断言:SKU 3 | ||
| 99 | + TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2); | ||
| 100 | + assertEquals(orderItem03.getSkuId(), 30L); | ||
| 101 | + assertEquals(orderItem03.getCount(), 5); | ||
| 102 | + assertEquals(orderItem03.getPrice(), 30); | ||
| 103 | + assertEquals(orderItem03.getPointPrice(), 0); | ||
| 104 | + assertEquals(orderItem03.getPayPrice(), 150); | ||
| 105 | + // 断言:Promotion 部分 | ||
| 106 | + assertEquals(result.getPromotions().size(), 1); | ||
| 107 | + TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); | ||
| 108 | + assertEquals(promotion01.getId(), user.getId()); | ||
| 109 | + assertEquals(promotion01.getName(), "积分抵扣"); | ||
| 110 | + assertEquals(promotion01.getType(), PromotionTypeEnum.POINT.getType()); | ||
| 111 | + assertEquals(promotion01.getTotalPrice(), 350); | ||
| 112 | + assertEquals(promotion01.getDiscountPrice(), 100); | ||
| 113 | + assertTrue(promotion01.getMatch()); | ||
| 114 | + assertEquals(promotion01.getDescription(), "积分抵扣:省 1.00 元"); | ||
| 115 | + assertEquals(promotion01.getItems().size(), 2); | ||
| 116 | + TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0); | ||
| 117 | + assertEquals(promotionItem011.getSkuId(), 10L); | ||
| 118 | + assertEquals(promotionItem011.getTotalPrice(), 200); | ||
| 119 | + assertEquals(promotionItem011.getDiscountPrice(), 57); | ||
| 120 | + TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1); | ||
| 121 | + assertEquals(promotionItem012.getSkuId(), 20L); | ||
| 122 | + assertEquals(promotionItem012.getTotalPrice(), 150); | ||
| 123 | + assertEquals(promotionItem012.getDiscountPrice(), 43); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + /** | ||
| 127 | + * 当用户积分充足时,抵扣的金额为:配置表的“积分抵扣最大值” | ||
| 128 | + */ | ||
| 129 | + @Test | ||
| 130 | + public void testCalculate_TradeDeductMaxPrice() { | ||
| 131 | + // 准备参数 | ||
| 132 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 133 | + .setUserId(233L).setPointStatus(true) // 是否使用积分 | ||
| 134 | + .setItems(asList( | ||
| 135 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分 | ||
| 136 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分 | ||
| 137 | + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分 | ||
| 138 | + )); | ||
| 139 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 140 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 141 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 142 | + .setPromotions(new ArrayList<>()) | ||
| 143 | + .setItems(asList( | ||
| 144 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 145 | + .setPrice(100).setSpuId(1L), | ||
| 146 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 147 | + .setPrice(50).setSpuId(2L), | ||
| 148 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false) | ||
| 149 | + .setPrice(30).setSpuId(3L) | ||
| 150 | + )); | ||
| 151 | + // 保证价格被初始化上 | ||
| 152 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 153 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 154 | + | ||
| 155 | + // mock 方法(积分配置 信息) | ||
| 156 | + MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class, | ||
| 157 | + o -> o.setPointTradeDeductEnable(true) // 启用积分折扣 | ||
| 158 | + .setPointTradeDeductUnitPrice(1) // 1 积分抵扣多少金额(单位分) | ||
| 159 | + .setPointTradeDeductMaxPrice(50)); // 积分抵扣最大值 | ||
| 160 | + when(memberConfigApi.getConfig()).thenReturn(memberConfig); | ||
| 161 | + // mock 方法(会员 信息) | ||
| 162 | + MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(100)); | ||
| 163 | + when(memberUserApi.getUser(user.getId())).thenReturn(user); | ||
| 164 | + | ||
| 165 | + // 调用 | ||
| 166 | + tradePointUsePriceCalculator.calculate(param, result); | ||
| 167 | + // 断言:使用了多少积分 | ||
| 168 | + assertEquals(result.getUsePoint(), 50); | ||
| 169 | + // 断言:Price 部分 | ||
| 170 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 171 | + assertEquals(price.getTotalPrice(), 350); | ||
| 172 | + assertEquals(price.getPayPrice(), 300); | ||
| 173 | + assertEquals(price.getPointPrice(), 50); | ||
| 174 | + // 断言:SKU 1 | ||
| 175 | + TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 176 | + assertEquals(orderItem01.getSkuId(), 10L); | ||
| 177 | + assertEquals(orderItem01.getCount(), 2); | ||
| 178 | + assertEquals(orderItem01.getPrice(), 100); | ||
| 179 | + assertEquals(orderItem01.getPointPrice(), 28); | ||
| 180 | + assertEquals(orderItem01.getPayPrice(), 172); | ||
| 181 | + // 断言:SKU 2 | ||
| 182 | + TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 183 | + assertEquals(orderItem02.getSkuId(), 20L); | ||
| 184 | + assertEquals(orderItem02.getCount(), 3); | ||
| 185 | + assertEquals(orderItem02.getPrice(), 50); | ||
| 186 | + assertEquals(orderItem02.getPointPrice(), 22); | ||
| 187 | + assertEquals(orderItem02.getPayPrice(), 128); | ||
| 188 | + // 断言:SKU 3 | ||
| 189 | + TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2); | ||
| 190 | + assertEquals(orderItem03.getSkuId(), 30L); | ||
| 191 | + assertEquals(orderItem03.getCount(), 5); | ||
| 192 | + assertEquals(orderItem03.getPrice(), 30); | ||
| 193 | + assertEquals(orderItem03.getPointPrice(), 0); | ||
| 194 | + assertEquals(orderItem03.getPayPrice(), 150); | ||
| 195 | + // 断言:Promotion 部分 | ||
| 196 | + assertEquals(result.getPromotions().size(), 1); | ||
| 197 | + TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); | ||
| 198 | + assertEquals(promotion01.getId(), user.getId()); | ||
| 199 | + assertEquals(promotion01.getName(), "积分抵扣"); | ||
| 200 | + assertEquals(promotion01.getType(), PromotionTypeEnum.POINT.getType()); | ||
| 201 | + assertEquals(promotion01.getTotalPrice(), 350); | ||
| 202 | + assertEquals(promotion01.getDiscountPrice(), 50); | ||
| 203 | + assertTrue(promotion01.getMatch()); | ||
| 204 | + assertEquals(promotion01.getDescription(), "积分抵扣:省 0.50 元"); | ||
| 205 | + assertEquals(promotion01.getItems().size(), 2); | ||
| 206 | + TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0); | ||
| 207 | + assertEquals(promotionItem011.getSkuId(), 10L); | ||
| 208 | + assertEquals(promotionItem011.getTotalPrice(), 200); | ||
| 209 | + assertEquals(promotionItem011.getDiscountPrice(), 28); | ||
| 210 | + TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1); | ||
| 211 | + assertEquals(promotionItem012.getSkuId(), 20L); | ||
| 212 | + assertEquals(promotionItem012.getTotalPrice(), 150); | ||
| 213 | + assertEquals(promotionItem012.getDiscountPrice(), 22); | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | + /** | ||
| 217 | + * 订单不使用积分,不会产生优惠 | ||
| 218 | + */ | ||
| 219 | + @Test | ||
| 220 | + public void testCalculate_PointStatusFalse() { | ||
| 221 | + // 准备参数 | ||
| 222 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 223 | + .setUserId(233L).setPointStatus(false) // 是否使用积分 | ||
| 224 | + .setItems(asList( | ||
| 225 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分 | ||
| 226 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分 | ||
| 227 | + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分 | ||
| 228 | + )); | ||
| 229 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 230 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 231 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 232 | + .setPromotions(new ArrayList<>()) | ||
| 233 | + .setItems(asList( | ||
| 234 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 235 | + .setPrice(100).setSpuId(1L), | ||
| 236 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 237 | + .setPrice(50).setSpuId(2L), | ||
| 238 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false) | ||
| 239 | + .setPrice(30).setSpuId(3L) | ||
| 240 | + )); | ||
| 241 | + // 保证价格被初始化上 | ||
| 242 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 243 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 244 | + | ||
| 245 | + // 调用 | ||
| 246 | + tradePointUsePriceCalculator.calculate(param, result); | ||
| 247 | + // 断言:没有使用积分 | ||
| 248 | + assertNotUsePoint(result); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + /** | ||
| 252 | + * 会员积分不足,不会产生优惠 | ||
| 253 | + */ | ||
| 254 | + @Test | ||
| 255 | + public void testCalculate_UserPointNotEnough() { | ||
| 256 | + // 准备参数 | ||
| 257 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 258 | + .setUserId(233L).setPointStatus(true) // 是否使用积分 | ||
| 259 | + .setItems(asList( | ||
| 260 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分 | ||
| 261 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分 | ||
| 262 | + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分 | ||
| 263 | + )); | ||
| 264 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 265 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 266 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 267 | + .setPromotions(new ArrayList<>()) | ||
| 268 | + .setItems(asList( | ||
| 269 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 270 | + .setPrice(100).setSpuId(1L), | ||
| 271 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 272 | + .setPrice(50).setSpuId(2L), | ||
| 273 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false) | ||
| 274 | + .setPrice(30).setSpuId(3L) | ||
| 275 | + )); | ||
| 276 | + // 保证价格被初始化上 | ||
| 277 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 278 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 279 | + | ||
| 280 | + // mock 方法(积分配置 信息) | ||
| 281 | + MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class, | ||
| 282 | + o -> o.setPointTradeDeductEnable(true) // 启用积分折扣 | ||
| 283 | + .setPointTradeDeductUnitPrice(1) // 1 积分抵扣多少金额(单位分) | ||
| 284 | + .setPointTradeDeductMaxPrice(100)); // 积分抵扣最大值 | ||
| 285 | + when(memberConfigApi.getConfig()).thenReturn(memberConfig); | ||
| 286 | + // mock 方法(会员 信息) | ||
| 287 | + MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(0)); | ||
| 288 | + when(memberUserApi.getUser(user.getId())).thenReturn(user); | ||
| 289 | + | ||
| 290 | + // 调用 | ||
| 291 | + tradePointUsePriceCalculator.calculate(param, result); | ||
| 292 | + | ||
| 293 | + // 断言:没有使用积分 | ||
| 294 | + assertNotUsePoint(result); | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + /** | ||
| 298 | + * 断言:没有使用积分 | ||
| 299 | + */ | ||
| 300 | + private static void assertNotUsePoint(TradePriceCalculateRespBO result) { | ||
| 301 | + // 断言:使用了多少积分 | ||
| 302 | + assertEquals(result.getUsePoint(), 0); | ||
| 303 | + // 断言:Price 部分 | ||
| 304 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 305 | + assertEquals(price.getTotalPrice(), 350); | ||
| 306 | + assertEquals(price.getPayPrice(), 350); | ||
| 307 | + assertEquals(price.getPointPrice(), 0); | ||
| 308 | + // 断言:SKU 1 | ||
| 309 | + TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 310 | + assertEquals(orderItem01.getSkuId(), 10L); | ||
| 311 | + assertEquals(orderItem01.getCount(), 2); | ||
| 312 | + assertEquals(orderItem01.getPrice(), 100); | ||
| 313 | + assertEquals(orderItem01.getPointPrice(), 0); | ||
| 314 | + assertEquals(orderItem01.getPayPrice(), 200); | ||
| 315 | + // 断言:SKU 2 | ||
| 316 | + TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 317 | + assertEquals(orderItem02.getSkuId(), 20L); | ||
| 318 | + assertEquals(orderItem02.getCount(), 3); | ||
| 319 | + assertEquals(orderItem02.getPrice(), 50); | ||
| 320 | + assertEquals(orderItem02.getPointPrice(), 0); | ||
| 321 | + assertEquals(orderItem02.getPayPrice(), 150); | ||
| 322 | + // 断言:SKU 3 | ||
| 323 | + TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2); | ||
| 324 | + assertEquals(orderItem03.getSkuId(), 30L); | ||
| 325 | + assertEquals(orderItem03.getCount(), 5); | ||
| 326 | + assertEquals(orderItem03.getPrice(), 30); | ||
| 327 | + assertEquals(orderItem03.getPointPrice(), 0); | ||
| 328 | + assertEquals(orderItem03.getPayPrice(), 150); | ||
| 329 | + // 断言:Promotion 部分 | ||
| 330 | + assertEquals(result.getPromotions().size(), 0); | ||
| 331 | + } | ||
| 332 | +} | ||
| 0 | \ No newline at end of file | 333 | \ No newline at end of file |
yudao-module-member/yudao-module-member-api/pom.xml
| @@ -22,6 +22,11 @@ | @@ -22,6 +22,11 @@ | ||
| 22 | <artifactId>yudao-common</artifactId> | 22 | <artifactId>yudao-common</artifactId> |
| 23 | </dependency> | 23 | </dependency> |
| 24 | 24 | ||
| 25 | + <dependency> | ||
| 26 | + <groupId>cn.iocoder.boot</groupId> | ||
| 27 | + <artifactId>yudao-spring-boot-starter-mq</artifactId> | ||
| 28 | + <scope>compile</scope> | ||
| 29 | + </dependency> | ||
| 25 | <!-- 参数校验 --> | 30 | <!-- 参数校验 --> |
| 26 | <dependency> | 31 | <dependency> |
| 27 | <groupId>org.springframework.boot</groupId> | 32 | <groupId>org.springframework.boot</groupId> |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.api.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 用户配置 API 接口 | ||
| 7 | + * | ||
| 8 | + * @author owen | ||
| 9 | + */ | ||
| 10 | +public interface MemberConfigApi { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 获得积分配置 | ||
| 14 | + * | ||
| 15 | + * @return 积分配置 | ||
| 16 | + */ | ||
| 17 | + MemberConfigRespDTO getConfig(); | ||
| 18 | +} |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/dto/MemberPointConfigRespDTO.java renamed to yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/config/dto/MemberConfigRespDTO.java
| 1 | -package cn.iocoder.yudao.module.member.api.point.dto; | 1 | +package cn.iocoder.yudao.module.member.api.config.dto; |
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | 4 | ||
| @@ -8,25 +8,25 @@ import lombok.Data; | @@ -8,25 +8,25 @@ import lombok.Data; | ||
| 8 | * @author 芋道源码 | 8 | * @author 芋道源码 |
| 9 | */ | 9 | */ |
| 10 | @Data | 10 | @Data |
| 11 | -public class MemberPointConfigRespDTO { | 11 | +public class MemberConfigRespDTO { |
| 12 | 12 | ||
| 13 | /** | 13 | /** |
| 14 | * 积分抵扣开关 | 14 | * 积分抵扣开关 |
| 15 | */ | 15 | */ |
| 16 | - private Boolean tradeDeductEnable; | 16 | + private Boolean pointTradeDeductEnable; |
| 17 | /** | 17 | /** |
| 18 | * 积分抵扣,单位:分 | 18 | * 积分抵扣,单位:分 |
| 19 | * <p> | 19 | * <p> |
| 20 | * 1 积分抵扣多少分 | 20 | * 1 积分抵扣多少分 |
| 21 | */ | 21 | */ |
| 22 | - private Integer tradeDeductUnitPrice; | 22 | + private Integer pointTradeDeductUnitPrice; |
| 23 | /** | 23 | /** |
| 24 | * 积分抵扣最大值 | 24 | * 积分抵扣最大值 |
| 25 | */ | 25 | */ |
| 26 | - private Integer tradeDeductMaxPrice; | 26 | + private Integer pointTradeDeductMaxPrice; |
| 27 | /** | 27 | /** |
| 28 | * 1 元赠送多少分 | 28 | * 1 元赠送多少分 |
| 29 | */ | 29 | */ |
| 30 | - private Integer tradeGivePoint; | 30 | + private Integer pointTradeGivePoint; |
| 31 | 31 | ||
| 32 | } | 32 | } |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApi.java
| 1 | package cn.iocoder.yudao.module.member.api.point; | 1 | package cn.iocoder.yudao.module.member.api.point; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO; | ||
| 4 | import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | 3 | import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; |
| 5 | 4 | ||
| 6 | import javax.validation.constraints.Min; | 5 | import javax.validation.constraints.Min; |
| @@ -12,14 +11,6 @@ import javax.validation.constraints.Min; | @@ -12,14 +11,6 @@ import javax.validation.constraints.Min; | ||
| 12 | */ | 11 | */ |
| 13 | public interface MemberPointApi { | 12 | public interface MemberPointApi { |
| 14 | 13 | ||
| 15 | - // TODO @疯狂:这个我们要不要搞成通用的会员配置?MemberConfig? | ||
| 16 | - /** | ||
| 17 | - * 获得积分配置 | ||
| 18 | - * | ||
| 19 | - * @return 积分配置 | ||
| 20 | - */ | ||
| 21 | - MemberPointConfigRespDTO getConfig(); | ||
| 22 | - | ||
| 23 | /** | 14 | /** |
| 24 | * 增加用户积分 | 15 | * 增加用户积分 |
| 25 | * | 16 | * |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
| @@ -38,6 +38,7 @@ public interface ErrorCodeConstants { | @@ -38,6 +38,7 @@ public interface ErrorCodeConstants { | ||
| 38 | //========== 签到配置 1-004-009-000 ========== | 38 | //========== 签到配置 1-004-009-000 ========== |
| 39 | ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(1_004_009_000, "签到天数规则不存在"); | 39 | ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(1_004_009_000, "签到天数规则不存在"); |
| 40 | ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1_004_009_001, "签到天数规则已存在"); | 40 | ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1_004_009_001, "签到天数规则已存在"); |
| 41 | + ErrorCode SIGN_IN_CONFIG_AWARD_EMPTY = new ErrorCode(1_004_009_002, "签到奖励积分和经验不能同时为空"); | ||
| 41 | 42 | ||
| 42 | //========== 签到配置 1-004-010-000 ========== | 43 | //========== 签到配置 1-004-010-000 ========== |
| 43 | ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1_004_010_000,"今日已签到,请勿重复签到"); | 44 | ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1_004_010_000,"今日已签到,请勿重复签到"); |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java
| @@ -17,6 +17,7 @@ import java.util.Objects; | @@ -17,6 +17,7 @@ import java.util.Objects; | ||
| 17 | public enum MemberPointBizTypeEnum implements IntArrayValuable { | 17 | public enum MemberPointBizTypeEnum implements IntArrayValuable { |
| 18 | 18 | ||
| 19 | SIGN(1, "签到", "签到获得 {} 积分", true), | 19 | SIGN(1, "签到", "签到获得 {} 积分", true), |
| 20 | + ADMIN(2, "管理员修改", "管理员修改 {} 积分", true), | ||
| 20 | ORDER_GIVE(10, "订单奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 | 21 | ORDER_GIVE(10, "订单奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 |
| 21 | ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 取消订单时,退回积分 | 22 | ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 取消订单时,退回积分 |
| 22 | ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 下单时,扣减积分 | 23 | ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 下单时,扣减积分 |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/RegisterCouponSendMessage.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.mq.message.user; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 新人券发放消息 | ||
| 11 | + * | ||
| 12 | + * @author owen | ||
| 13 | + */ | ||
| 14 | +@Data | ||
| 15 | +@EqualsAndHashCode(callSuper = true) | ||
| 16 | +public class RegisterCouponSendMessage extends AbstractStreamMessage { | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 用户编号 | ||
| 20 | + */ | ||
| 21 | + @NotNull(message = "用户编号不能为空") | ||
| 22 | + private Long userId; | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public String getStreamKey() { | ||
| 26 | + return "member.register-coupon.send"; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/config/MemberConfigApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.api.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 4 | +import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert; | ||
| 5 | +import cn.iocoder.yudao.module.member.service.config.MemberConfigService; | ||
| 6 | +import org.springframework.stereotype.Service; | ||
| 7 | +import org.springframework.validation.annotation.Validated; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 用户配置 API 实现类 | ||
| 13 | + * | ||
| 14 | + * @author owen | ||
| 15 | + */ | ||
| 16 | +@Service | ||
| 17 | +@Validated | ||
| 18 | +public class MemberConfigApiImpl implements MemberConfigApi { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private MemberConfigService memberConfigService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public MemberConfigRespDTO getConfig() { | ||
| 25 | + return MemberConfigConvert.INSTANCE.convert01(memberConfigService.getConfig()); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | +} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApiImpl.java
| 1 | package cn.iocoder.yudao.module.member.api.point; | 1 | package cn.iocoder.yudao.module.member.api.point; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 4 | -import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO; | ||
| 5 | -import cn.iocoder.yudao.module.member.convert.point.MemberPointConfigConvert; | ||
| 6 | import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | 4 | import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; |
| 7 | -import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; | ||
| 8 | import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; | 5 | import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; |
| 9 | import org.springframework.stereotype.Service; | 6 | import org.springframework.stereotype.Service; |
| 10 | import org.springframework.validation.annotation.Validated; | 7 | import org.springframework.validation.annotation.Validated; |
| @@ -25,13 +22,6 @@ public class MemberPointApiImpl implements MemberPointApi { | @@ -25,13 +22,6 @@ public class MemberPointApiImpl implements MemberPointApi { | ||
| 25 | 22 | ||
| 26 | @Resource | 23 | @Resource |
| 27 | private MemberPointRecordService memberPointRecordService; | 24 | private MemberPointRecordService memberPointRecordService; |
| 28 | - @Resource | ||
| 29 | - private MemberPointConfigService memberPointConfigService; | ||
| 30 | - | ||
| 31 | - @Override | ||
| 32 | - public MemberPointConfigRespDTO getConfig() { | ||
| 33 | - return MemberPointConfigConvert.INSTANCE.convert01(memberPointConfigService.getPointConfig()); | ||
| 34 | - } | ||
| 35 | 25 | ||
| 36 | @Override | 26 | @Override |
| 37 | public void addPoint(Long userId, Integer point, Integer bizType, String bizId) { | 27 | public void addPoint(Long userId, Integer point, Integer bizType, String bizId) { |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/MemberConfigController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.controller.admin.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert; | ||
| 7 | +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; | ||
| 8 | +import cn.iocoder.yudao.module.member.service.config.MemberConfigService; | ||
| 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("/member/config") | ||
| 23 | +@Validated | ||
| 24 | +public class MemberConfigController { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private MemberConfigService memberConfigService; | ||
| 28 | + | ||
| 29 | + @PutMapping("/save") | ||
| 30 | + @Operation(summary = "保存会员配置") | ||
| 31 | + @PreAuthorize("@ss.hasPermission('member:config:save')") | ||
| 32 | + public CommonResult<Boolean> saveConfig(@Valid @RequestBody MemberConfigSaveReqVO saveReqVO) { | ||
| 33 | + memberConfigService.saveConfig(saveReqVO); | ||
| 34 | + return success(true); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @GetMapping("/get") | ||
| 38 | + @Operation(summary = "获得会员配置") | ||
| 39 | + @PreAuthorize("@ss.hasPermission('member:config:query')") | ||
| 40 | + public CommonResult<MemberConfigRespVO> getConfig() { | ||
| 41 | + MemberConfigDO config = memberConfigService.getConfig(); | ||
| 42 | + return success(MemberConfigConvert.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 renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigBaseVO.java
| 1 | -package cn.iocoder.yudao.module.member.controller.admin.point.vo.config; | 1 | +package cn.iocoder.yudao.module.member.controller.admin.config.vo; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| @@ -6,26 +6,26 @@ import lombok.Data; | @@ -6,26 +6,26 @@ import lombok.Data; | ||
| 6 | import javax.validation.constraints.NotNull; | 6 | import javax.validation.constraints.NotNull; |
| 7 | 7 | ||
| 8 | /** | 8 | /** |
| 9 | - * 会员积分配置 Base VO,提供给添加、修改、详细的子 VO 使用 | 9 | + * 会员配置 Base VO,提供给添加、修改、详细的子 VO 使用 |
| 10 | * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | 10 | * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 |
| 11 | */ | 11 | */ |
| 12 | @Data | 12 | @Data |
| 13 | -public class MemberPointConfigBaseVO { | 13 | +public class MemberConfigBaseVO { |
| 14 | 14 | ||
| 15 | @Schema(description = "积分抵扣开关", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | 15 | @Schema(description = "积分抵扣开关", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") |
| 16 | @NotNull(message = "积分抵扣开发不能为空") | 16 | @NotNull(message = "积分抵扣开发不能为空") |
| 17 | - private Boolean tradeDeductEnable; | 17 | + private Boolean pointTradeDeductEnable; |
| 18 | 18 | ||
| 19 | @Schema(description = "积分抵扣,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "13506") | 19 | @Schema(description = "积分抵扣,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "13506") |
| 20 | @NotNull(message = "积分抵扣不能为空") | 20 | @NotNull(message = "积分抵扣不能为空") |
| 21 | - private Integer tradeDeductUnitPrice; | 21 | + private Integer pointTradeDeductUnitPrice; |
| 22 | 22 | ||
| 23 | @Schema(description = "积分抵扣最大值", requiredMode = Schema.RequiredMode.REQUIRED, example = "32428") | 23 | @Schema(description = "积分抵扣最大值", requiredMode = Schema.RequiredMode.REQUIRED, example = "32428") |
| 24 | @NotNull(message = "积分抵扣最大值不能为空") | 24 | @NotNull(message = "积分抵扣最大值不能为空") |
| 25 | - private Integer tradeDeductMaxPrice; | 25 | + private Integer pointTradeDeductMaxPrice; |
| 26 | 26 | ||
| 27 | @Schema(description = "1 元赠送多少分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | 27 | @Schema(description = "1 元赠送多少分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 28 | @NotNull(message = "1 元赠送积分不能为空") | 28 | @NotNull(message = "1 元赠送积分不能为空") |
| 29 | - private Integer tradeGivePoint; | 29 | + private Integer pointTradeGivePoint; |
| 30 | 30 | ||
| 31 | } | 31 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigRespVO.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigRespVO.java
| 1 | -package cn.iocoder.yudao.module.member.controller.admin.point.vo.config; | 1 | +package cn.iocoder.yudao.module.member.controller.admin.config.vo; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | import lombok.ToString; | 6 | import lombok.ToString; |
| 7 | 7 | ||
| 8 | -@Schema(description = "管理后台 - 会员积分配置 Response VO") | 8 | +@Schema(description = "管理后台 - 会员配置 Response VO") |
| 9 | @Data | 9 | @Data |
| 10 | @EqualsAndHashCode(callSuper = true) | 10 | @EqualsAndHashCode(callSuper = true) |
| 11 | @ToString(callSuper = true) | 11 | @ToString(callSuper = true) |
| 12 | -public class MemberPointConfigRespVO extends MemberPointConfigBaseVO { | 12 | +public class MemberConfigRespVO extends MemberConfigBaseVO { |
| 13 | 13 | ||
| 14 | @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 14 | @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 15 | private Long id; | 15 | private Long id; |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/vo/config/MemberPointConfigSaveReqVO.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/config/vo/MemberConfigSaveReqVO.java
| 1 | -package cn.iocoder.yudao.module.member.controller.admin.point.vo.config; | 1 | +package cn.iocoder.yudao.module.member.controller.admin.config.vo; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | import lombok.ToString; | 6 | import lombok.ToString; |
| 7 | 7 | ||
| 8 | -@Schema(description = "管理后台 - 会员积分配置保存 Request VO") | 8 | +@Schema(description = "管理后台 - 会员配置保存 Request VO") |
| 9 | @Data | 9 | @Data |
| 10 | @EqualsAndHashCode(callSuper = true) | 10 | @EqualsAndHashCode(callSuper = true) |
| 11 | @ToString(callSuper = true) | 11 | @ToString(callSuper = true) |
| 12 | -public class MemberPointConfigSaveReqVO extends MemberPointConfigBaseVO { | 12 | +public class MemberConfigSaveReqVO extends MemberConfigBaseVO { |
| 13 | } | 13 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointConfigController.java deleted
| 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("/member/point/config") | ||
| 23 | -@Validated | ||
| 24 | -public class MemberPointConfigController { | ||
| 25 | - | ||
| 26 | - @Resource | ||
| 27 | - private MemberPointConfigService memberPointConfigService; | ||
| 28 | - | ||
| 29 | - @PutMapping("/save") | ||
| 30 | - @Operation(summary = "保存会员积分配置") | ||
| 31 | - @PreAuthorize("@ss.hasPermission('point:config:save')") | ||
| 32 | - public CommonResult<Boolean> savePointConfig(@Valid @RequestBody MemberPointConfigSaveReqVO saveReqVO) { | ||
| 33 | - memberPointConfigService.savePointConfig(saveReqVO); | ||
| 34 | - return success(true); | ||
| 35 | - } | ||
| 36 | - | ||
| 37 | - @GetMapping("/get") | ||
| 38 | - @Operation(summary = "获得会员积分配置") | ||
| 39 | - @PreAuthorize("@ss.hasPermission('point:config:query')") | ||
| 40 | - public CommonResult<MemberPointConfigRespVO> getPointConfig() { | ||
| 41 | - MemberPointConfigDO config = memberPointConfigService.getPointConfig(); | ||
| 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/signin/vo/config/MemberSignInConfigBaseVO.java
| @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema; | @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | import lombok.Data; | 6 | import lombok.Data; |
| 7 | 7 | ||
| 8 | import javax.validation.constraints.NotNull; | 8 | import javax.validation.constraints.NotNull; |
| 9 | +import javax.validation.constraints.PositiveOrZero; | ||
| 9 | 10 | ||
| 10 | /** | 11 | /** |
| 11 | * 签到规则 Base VO,提供给添加、修改、详细的子 VO 使用 | 12 | * 签到规则 Base VO,提供给添加、修改、详细的子 VO 使用 |
| @@ -20,8 +21,14 @@ public class MemberSignInConfigBaseVO { | @@ -20,8 +21,14 @@ public class MemberSignInConfigBaseVO { | ||
| 20 | 21 | ||
| 21 | @Schema(description = "奖励积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | 22 | @Schema(description = "奖励积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 22 | @NotNull(message = "奖励积分不能为空") | 23 | @NotNull(message = "奖励积分不能为空") |
| 24 | + @PositiveOrZero(message = "奖励积分不能小于 0") | ||
| 23 | private Integer point; | 25 | private Integer point; |
| 24 | 26 | ||
| 27 | + @Schema(description = "奖励经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 28 | + @NotNull(message = "奖励经验不能为空") | ||
| 29 | + @PositiveOrZero(message = "奖励经验不能小于 0") | ||
| 30 | + private Integer experience; | ||
| 31 | + | ||
| 25 | @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 32 | @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 26 | @NotNull(message = "状态不能为空") | 33 | @NotNull(message = "状态不能为空") |
| 27 | @InEnum(CommonStatusEnum.class) | 34 | @InEnum(CommonStatusEnum.class) |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/record/MemberSignInRecordRespVO.java
| @@ -21,7 +21,7 @@ public class MemberSignInRecordRespVO { | @@ -21,7 +21,7 @@ public class MemberSignInRecordRespVO { | ||
| 21 | @Schema(description = "第几天签到", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 21 | @Schema(description = "第几天签到", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 22 | private Integer day; | 22 | private Integer day; |
| 23 | 23 | ||
| 24 | - @Schema(description = "签到的分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | 24 | + @Schema(description = "签到的积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 25 | private Integer point; | 25 | private Integer point; |
| 26 | 26 | ||
| 27 | @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) | 27 | @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java
| @@ -3,17 +3,16 @@ package cn.iocoder.yudao.module.member.controller.admin.user; | @@ -3,17 +3,16 @@ package cn.iocoder.yudao.module.member.controller.admin.user; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; | ||
| 7 | -import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserRespVO; | ||
| 8 | -import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateLevelReqVO; | ||
| 9 | -import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; | 6 | +import cn.iocoder.yudao.module.member.controller.admin.user.vo.*; |
| 10 | import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; | 7 | import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; |
| 11 | import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; | 8 | import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO; |
| 12 | import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; | 9 | import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; |
| 13 | import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; | 10 | import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; |
| 14 | import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; | 11 | import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; |
| 12 | +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | ||
| 15 | import cn.iocoder.yudao.module.member.service.group.MemberGroupService; | 13 | import cn.iocoder.yudao.module.member.service.group.MemberGroupService; |
| 16 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; | 14 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; |
| 15 | +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; | ||
| 17 | import cn.iocoder.yudao.module.member.service.tag.MemberTagService; | 16 | import cn.iocoder.yudao.module.member.service.tag.MemberTagService; |
| 18 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; | 17 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 19 | import io.swagger.v3.oas.annotations.Operation; | 18 | import io.swagger.v3.oas.annotations.Operation; |
| @@ -33,6 +32,7 @@ import java.util.stream.Collectors; | @@ -33,6 +32,7 @@ import java.util.stream.Collectors; | ||
| 33 | 32 | ||
| 34 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 33 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 35 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 34 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 35 | +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; | ||
| 36 | 36 | ||
| 37 | @Tag(name = "管理后台 - 会员用户") | 37 | @Tag(name = "管理后台 - 会员用户") |
| 38 | @RestController | 38 | @RestController |
| @@ -48,6 +48,8 @@ public class MemberUserController { | @@ -48,6 +48,8 @@ public class MemberUserController { | ||
| 48 | private MemberLevelService memberLevelService; | 48 | private MemberLevelService memberLevelService; |
| 49 | @Resource | 49 | @Resource |
| 50 | private MemberGroupService memberGroupService; | 50 | private MemberGroupService memberGroupService; |
| 51 | + @Resource | ||
| 52 | + private MemberPointRecordService memberPointRecordService; | ||
| 51 | 53 | ||
| 52 | @PutMapping("/update") | 54 | @PutMapping("/update") |
| 53 | @Operation(summary = "更新会员用户") | 55 | @Operation(summary = "更新会员用户") |
| @@ -65,6 +67,23 @@ public class MemberUserController { | @@ -65,6 +67,23 @@ public class MemberUserController { | ||
| 65 | return success(true); | 67 | return success(true); |
| 66 | } | 68 | } |
| 67 | 69 | ||
| 70 | + @PutMapping("/update-point") | ||
| 71 | + @Operation(summary = "更新会员用户积分") | ||
| 72 | + @PreAuthorize("@ss.hasPermission('member:user:update-point')") | ||
| 73 | + public CommonResult<Boolean> updateUserPoint(@Valid @RequestBody MemberUserUpdatePointReqVO updateReqVO) { | ||
| 74 | + memberPointRecordService.createPointRecord(updateReqVO.getId(), updateReqVO.getPoint(), | ||
| 75 | + MemberPointBizTypeEnum.ADMIN, String.valueOf(getLoginUserId())); | ||
| 76 | + return success(true); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + @PutMapping("/update-balance") | ||
| 80 | + @Operation(summary = "更新会员用户余额") | ||
| 81 | + @PreAuthorize("@ss.hasPermission('member:user:update-balance')") | ||
| 82 | + public CommonResult<Boolean> updateUserBalance(@Valid @RequestBody Long id) { | ||
| 83 | + // todo @jason:增加一个【修改余额】 | ||
| 84 | + return success(true); | ||
| 85 | + } | ||
| 86 | + | ||
| 68 | @GetMapping("/get") | 87 | @GetMapping("/get") |
| 69 | @Operation(summary = "获得会员用户") | 88 | @Operation(summary = "获得会员用户") |
| 70 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 89 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.member.controller.admin.user.vo; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.member.controller.admin.user.vo; | ||
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | -import lombok.EqualsAndHashCode; | ||
| 6 | import lombok.ToString; | 5 | import lombok.ToString; |
| 7 | 6 | ||
| 8 | import javax.validation.constraints.NotBlank; | 7 | import javax.validation.constraints.NotBlank; |
| @@ -10,9 +9,8 @@ import javax.validation.constraints.NotNull; | @@ -10,9 +9,8 @@ import javax.validation.constraints.NotNull; | ||
| 10 | 9 | ||
| 11 | @Schema(description = "管理后台 - 会员用户 修改等级 Request VO") | 10 | @Schema(description = "管理后台 - 会员用户 修改等级 Request VO") |
| 12 | @Data | 11 | @Data |
| 13 | -@EqualsAndHashCode(callSuper = true) | ||
| 14 | @ToString(callSuper = true) | 12 | @ToString(callSuper = true) |
| 15 | -public class MemberUserUpdateLevelReqVO extends MemberUserBaseVO { | 13 | +public class MemberUserUpdateLevelReqVO { |
| 16 | 14 | ||
| 17 | @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") | 15 | @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") |
| 18 | @NotNull(message = "用户编号不能为空") | 16 | @NotNull(message = "用户编号不能为空") |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdatePointReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.controller.admin.user.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.ToString; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - 会员用户 修改积分 Request VO") | ||
| 10 | +@Data | ||
| 11 | +@ToString(callSuper = true) | ||
| 12 | +public class MemberUserUpdatePointReqVO { | ||
| 13 | + | ||
| 14 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788") | ||
| 15 | + @NotNull(message = "用户编号不能为空") | ||
| 16 | + private Long id; | ||
| 17 | + | ||
| 18 | + @Schema(description = "变动积分,正数为增加,负数为减少", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 19 | + @NotNull(message = "变动积分不能为空") | ||
| 20 | + private Integer point; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInController.java
| 1 | package cn.iocoder.yudao.module.member.controller.app.signin; | 1 | package cn.iocoder.yudao.module.member.controller.app.signin; |
| 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.member.convert.signin.MemberSignInRecordConvert; | ||
| 5 | -import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; | ||
| 6 | import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; | 4 | import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; |
| 7 | import io.swagger.v3.oas.annotations.Operation; | 5 | import io.swagger.v3.oas.annotations.Operation; |
| 8 | import io.swagger.v3.oas.annotations.tags.Tag; | 6 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 9 | import org.springframework.web.bind.annotation.GetMapping; | 7 | import org.springframework.web.bind.annotation.GetMapping; |
| 10 | -import org.springframework.web.bind.annotation.PostMapping; | ||
| 11 | import org.springframework.web.bind.annotation.RequestMapping; | 8 | import org.springframework.web.bind.annotation.RequestMapping; |
| 12 | import org.springframework.web.bind.annotation.RestController; | 9 | import org.springframework.web.bind.annotation.RestController; |
| 13 | 10 | ||
| @@ -29,17 +26,8 @@ public class AppMemberSignInController { | @@ -29,17 +26,8 @@ public class AppMemberSignInController { | ||
| 29 | // TODO @xiaqing:合并到 AppMemberSignInRecordController 的 getSignInRecordSummary 里哈。 | 26 | // TODO @xiaqing:合并到 AppMemberSignInRecordController 的 getSignInRecordSummary 里哈。 |
| 30 | @Operation(summary = "个人签到信息") | 27 | @Operation(summary = "个人签到信息") |
| 31 | @GetMapping("/get-summary") | 28 | @GetMapping("/get-summary") |
| 32 | - public CommonResult getUserSummary(){ | 29 | + public CommonResult getUserSummary() { |
| 33 | return success(signInRecordService.getSignInRecordSummary(getLoginUserId())); | 30 | return success(signInRecordService.getSignInRecordSummary(getLoginUserId())); |
| 34 | } | 31 | } |
| 35 | 32 | ||
| 36 | - // TODO @xiaqing:泛型: | ||
| 37 | - // TODO @xiaqing:合并到 AppMemberSignInRecordController 的 createSignInRecord 里哈。 | ||
| 38 | - @Operation(summary = "会员签到") | ||
| 39 | - @PostMapping("/create") | ||
| 40 | - public CommonResult create(){ | ||
| 41 | - MemberSignInRecordDO recordDO = signInRecordService.createSignRecord(getLoginUserId()); | ||
| 42 | - return success(MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO)); | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | } | 33 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java
| @@ -18,7 +18,6 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -18,7 +18,6 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
| 18 | import org.springframework.web.bind.annotation.RestController; | 18 | import org.springframework.web.bind.annotation.RestController; |
| 19 | 19 | ||
| 20 | import javax.annotation.Resource; | 20 | import javax.annotation.Resource; |
| 21 | -import java.time.LocalDateTime; | ||
| 22 | 21 | ||
| 23 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 24 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 23 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| @@ -50,16 +49,12 @@ public class AppMemberSignInRecordController { | @@ -50,16 +49,12 @@ public class AppMemberSignInRecordController { | ||
| 50 | return success(respVO); | 49 | return success(respVO); |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | - // TODO 芋艿:临时 mock => UserSignController.info | ||
| 54 | @PostMapping("/create") | 52 | @PostMapping("/create") |
| 55 | @Operation(summary = "签到") | 53 | @Operation(summary = "签到") |
| 56 | @PreAuthenticated | 54 | @PreAuthenticated |
| 57 | public CommonResult<AppMemberSignInRecordRespVO> createSignInRecord() { | 55 | public CommonResult<AppMemberSignInRecordRespVO> createSignInRecord() { |
| 58 | - AppMemberSignInRecordRespVO respVO = new AppMemberSignInRecordRespVO() | ||
| 59 | - .setPoint(10) | ||
| 60 | - .setDay(10) | ||
| 61 | - .setCreateTime(LocalDateTime.now()); | ||
| 62 | - return success(respVO); | 56 | + MemberSignInRecordDO recordDO = signInRecordService.createSignRecord(getLoginUserId()); |
| 57 | + return success(MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO)); | ||
| 63 | } | 58 | } |
| 64 | 59 | ||
| 65 | @GetMapping("/page") | 60 | @GetMapping("/page") |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/AppMemberSignInRecordRespVO.java
| @@ -12,9 +12,12 @@ public class AppMemberSignInRecordRespVO { | @@ -12,9 +12,12 @@ public class AppMemberSignInRecordRespVO { | ||
| 12 | @Schema(description = "第几天签到", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 12 | @Schema(description = "第几天签到", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 13 | private Integer day; | 13 | private Integer day; |
| 14 | 14 | ||
| 15 | - @Schema(description = "签到的分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | 15 | + @Schema(description = "签到的积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 16 | private Integer point; | 16 | private Integer point; |
| 17 | 17 | ||
| 18 | + @Schema(description = "签到的经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 19 | + private Integer experience; | ||
| 20 | + | ||
| 18 | @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) | 21 | @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 19 | private LocalDateTime createTime; | 22 | private LocalDateTime createTime; |
| 20 | 23 |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java
| @@ -15,6 +15,9 @@ public class AppMemberSignInRecordRespVO { | @@ -15,6 +15,9 @@ public class AppMemberSignInRecordRespVO { | ||
| 15 | @Schema(description = "签到的分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | 15 | @Schema(description = "签到的分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 16 | private Integer point; | 16 | private Integer point; |
| 17 | 17 | ||
| 18 | + @Schema(description = "签到的经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 19 | + private Integer experience; | ||
| 20 | + | ||
| 18 | @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) | 21 | @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 19 | private LocalDateTime createTime; | 22 | private LocalDateTime createTime; |
| 20 | 23 |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/config/MemberConfigConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.convert.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO; | ||
| 4 | +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; | ||
| 7 | +import org.mapstruct.Mapper; | ||
| 8 | +import org.mapstruct.factory.Mappers; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 会员配置 Convert | ||
| 12 | + * | ||
| 13 | + * @author QingX | ||
| 14 | + */ | ||
| 15 | +@Mapper | ||
| 16 | +public interface MemberConfigConvert { | ||
| 17 | + | ||
| 18 | + MemberConfigConvert INSTANCE = Mappers.getMapper(MemberConfigConvert.class); | ||
| 19 | + | ||
| 20 | + MemberConfigRespVO convert(MemberConfigDO bean); | ||
| 21 | + | ||
| 22 | + MemberConfigDO convert(MemberConfigSaveReqVO bean); | ||
| 23 | + | ||
| 24 | + MemberConfigRespDTO convert01(MemberConfigDO config); | ||
| 25 | +} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointConfigConvert.java deleted
| 1 | -package cn.iocoder.yudao.module.member.convert.point; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO; | ||
| 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.dal.dataobject.point.MemberPointConfigDO; | ||
| 7 | -import org.mapstruct.Mapper; | ||
| 8 | -import org.mapstruct.factory.Mappers; | ||
| 9 | - | ||
| 10 | -/** | ||
| 11 | - * 会员积分配置 Convert | ||
| 12 | - * | ||
| 13 | - * @author QingX | ||
| 14 | - */ | ||
| 15 | -@Mapper | ||
| 16 | -public interface MemberPointConfigConvert { | ||
| 17 | - | ||
| 18 | - MemberPointConfigConvert INSTANCE = Mappers.getMapper(MemberPointConfigConvert.class); | ||
| 19 | - | ||
| 20 | - MemberPointConfigRespVO convert(MemberPointConfigDO bean); | ||
| 21 | - | ||
| 22 | - MemberPointConfigDO convert(MemberPointConfigSaveReqVO bean); | ||
| 23 | - | ||
| 24 | - MemberPointConfigRespDTO convert01(MemberPointConfigDO pointConfig); | ||
| 25 | -} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/point/MemberPointConfigDO.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/config/MemberConfigDO.java
| 1 | -package cn.iocoder.yudao.module.member.dal.dataobject.point; | 1 | +package cn.iocoder.yudao.module.member.dal.dataobject.config; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | import com.baomidou.mybatisplus.annotation.KeySequence; | 4 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| @@ -7,19 +7,19 @@ import com.baomidou.mybatisplus.annotation.TableName; | @@ -7,19 +7,19 @@ import com.baomidou.mybatisplus.annotation.TableName; | ||
| 7 | import lombok.*; | 7 | import lombok.*; |
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | - * 会员积分配置 DO | 10 | + * 会员配置 DO |
| 11 | * | 11 | * |
| 12 | * @author QingX | 12 | * @author QingX |
| 13 | */ | 13 | */ |
| 14 | -@TableName(value = "member_point_config", autoResultMap = true) | ||
| 15 | -@KeySequence("member_point_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | 14 | +@TableName(value = "member_config", autoResultMap = true) |
| 15 | +@KeySequence("member_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | ||
| 16 | @Data | 16 | @Data |
| 17 | @EqualsAndHashCode(callSuper = true) | 17 | @EqualsAndHashCode(callSuper = true) |
| 18 | @ToString(callSuper = true) | 18 | @ToString(callSuper = true) |
| 19 | @Builder | 19 | @Builder |
| 20 | @NoArgsConstructor | 20 | @NoArgsConstructor |
| 21 | @AllArgsConstructor | 21 | @AllArgsConstructor |
| 22 | -public class MemberPointConfigDO extends BaseDO { | 22 | +public class MemberConfigDO extends BaseDO { |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * 自增主键 | 25 | * 自增主键 |
| @@ -29,20 +29,20 @@ public class MemberPointConfigDO extends BaseDO { | @@ -29,20 +29,20 @@ public class MemberPointConfigDO extends BaseDO { | ||
| 29 | /** | 29 | /** |
| 30 | * 积分抵扣开关 | 30 | * 积分抵扣开关 |
| 31 | */ | 31 | */ |
| 32 | - private Boolean tradeDeductEnable; | 32 | + private Boolean pointTradeDeductEnable; |
| 33 | /** | 33 | /** |
| 34 | * 积分抵扣,单位:分 | 34 | * 积分抵扣,单位:分 |
| 35 | * | 35 | * |
| 36 | * 1 积分抵扣多少分 | 36 | * 1 积分抵扣多少分 |
| 37 | */ | 37 | */ |
| 38 | - private Integer tradeDeductUnitPrice; | 38 | + private Integer pointTradeDeductUnitPrice; |
| 39 | /** | 39 | /** |
| 40 | * 积分抵扣最大值 | 40 | * 积分抵扣最大值 |
| 41 | */ | 41 | */ |
| 42 | - private Integer tradeDeductMaxPrice; | 42 | + private Integer pointTradeDeductMaxPrice; |
| 43 | /** | 43 | /** |
| 44 | * 1 元赠送多少分 | 44 | * 1 元赠送多少分 |
| 45 | */ | 45 | */ |
| 46 | - private Integer tradeGivePoint; | 46 | + private Integer pointTradeGivePoint; |
| 47 | 47 | ||
| 48 | } | 48 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInConfigDO.java
| @@ -35,6 +35,10 @@ public class MemberSignInConfigDO extends BaseDO { | @@ -35,6 +35,10 @@ public class MemberSignInConfigDO extends BaseDO { | ||
| 35 | * 奖励积分 | 35 | * 奖励积分 |
| 36 | */ | 36 | */ |
| 37 | private Integer point; | 37 | private Integer point; |
| 38 | + /** | ||
| 39 | + * 奖励经验 | ||
| 40 | + */ | ||
| 41 | + private Integer experience; | ||
| 38 | 42 | ||
| 39 | /** | 43 | /** |
| 40 | * 状态 | 44 | * 状态 |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/signin/MemberSignInRecordDO.java
| @@ -35,10 +35,12 @@ public class MemberSignInRecordDO extends BaseDO { | @@ -35,10 +35,12 @@ public class MemberSignInRecordDO extends BaseDO { | ||
| 35 | */ | 35 | */ |
| 36 | private Integer day; | 36 | private Integer day; |
| 37 | /** | 37 | /** |
| 38 | - * 签到的分数 | 38 | + * 签到的积分 |
| 39 | */ | 39 | */ |
| 40 | private Integer point; | 40 | private Integer point; |
| 41 | - | ||
| 42 | - // TODO 疯狂:签到的经验 | 41 | + /** |
| 42 | + * 签到的经验 | ||
| 43 | + */ | ||
| 44 | + private Integer experience; | ||
| 43 | 45 | ||
| 44 | } | 46 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointConfigMapper.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/config/MemberConfigMapper.java
| 1 | -package cn.iocoder.yudao.module.member.dal.mysql.point; | 1 | +package cn.iocoder.yudao.module.member.dal.mysql.config; |
| 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.module.member.dal.dataobject.point.MemberPointConfigDO; | 4 | +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 5 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| @@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper; | @@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 10 | * @author QingX | 10 | * @author QingX |
| 11 | */ | 11 | */ |
| 12 | @Mapper | 12 | @Mapper |
| 13 | -public interface MemberPointConfigMapper extends BaseMapperX<MemberPointConfigDO> { | 13 | +public interface MemberConfigMapper extends BaseMapperX<MemberConfigDO> { |
| 14 | } | 14 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/RegisterCouponProducer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.mq.producer.user; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; | ||
| 4 | +import cn.iocoder.yudao.module.member.mq.message.user.RegisterCouponSendMessage; | ||
| 5 | +import lombok.extern.slf4j.Slf4j; | ||
| 6 | +import org.springframework.stereotype.Component; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 新人券发放 Producer | ||
| 12 | + * | ||
| 13 | + * @author owen | ||
| 14 | + */ | ||
| 15 | +@Slf4j | ||
| 16 | +@Component | ||
| 17 | +public class RegisterCouponProducer { | ||
| 18 | + | ||
| 19 | + @Resource | ||
| 20 | + private RedisMQTemplate redisMQTemplate; | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 发送 {@link RegisterCouponSendMessage} 消息 | ||
| 24 | + * | ||
| 25 | + * @param userId 用户编号 | ||
| 26 | + */ | ||
| 27 | + public void sendMailSendMessage(Long userId) { | ||
| 28 | + redisMQTemplate.send(new RegisterCouponSendMessage().setUserId(userId)); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | +} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointConfigService.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigService.java
| 1 | -package cn.iocoder.yudao.module.member.service.point; | 1 | +package cn.iocoder.yudao.module.member.service.config; |
| 2 | 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; | 3 | +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; |
| 4 | +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; | ||
| 5 | 5 | ||
| 6 | import javax.validation.Valid; | 6 | import javax.validation.Valid; |
| 7 | 7 | ||
| 8 | /** | 8 | /** |
| 9 | - * 会员积分配置 Service 接口 | 9 | + * 会员配置 Service 接口 |
| 10 | * | 10 | * |
| 11 | * @author QingX | 11 | * @author QingX |
| 12 | */ | 12 | */ |
| 13 | -public interface MemberPointConfigService { | 13 | +public interface MemberConfigService { |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | - * 保存会员积分配置 | 16 | + * 保存会员配置 |
| 17 | * | 17 | * |
| 18 | * @param saveReqVO 更新信息 | 18 | * @param saveReqVO 更新信息 |
| 19 | */ | 19 | */ |
| 20 | - void savePointConfig(@Valid MemberPointConfigSaveReqVO saveReqVO); | 20 | + void saveConfig(@Valid MemberConfigSaveReqVO saveReqVO); |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | - * 获得会员积分配置 | 23 | + * 获得会员配置 |
| 24 | * | 24 | * |
| 25 | * @return 积分配置 | 25 | * @return 积分配置 |
| 26 | */ | 26 | */ |
| 27 | - MemberPointConfigDO getPointConfig(); | 27 | + MemberConfigDO getConfig(); |
| 28 | 28 | ||
| 29 | } | 29 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointConfigServiceImpl.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/config/MemberConfigServiceImpl.java
| 1 | -package cn.iocoder.yudao.module.member.service.point; | 1 | +package cn.iocoder.yudao.module.member.service.config; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 3 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 4 | -import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigSaveReqVO; | ||
| 5 | -import cn.iocoder.yudao.module.member.convert.point.MemberPointConfigConvert; | ||
| 6 | -import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; | ||
| 7 | -import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointConfigMapper; | 4 | +import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigSaveReqVO; |
| 5 | +import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert; | ||
| 6 | +import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO; | ||
| 7 | +import cn.iocoder.yudao.module.member.dal.mysql.config.MemberConfigMapper; | ||
| 8 | import org.springframework.stereotype.Service; | 8 | import org.springframework.stereotype.Service; |
| 9 | import org.springframework.validation.annotation.Validated; | 9 | import org.springframework.validation.annotation.Validated; |
| 10 | 10 | ||
| @@ -12,32 +12,32 @@ import javax.annotation.Resource; | @@ -12,32 +12,32 @@ import javax.annotation.Resource; | ||
| 12 | import java.util.List; | 12 | import java.util.List; |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | - * 会员积分配置 Service 实现类 | 15 | + * 会员配置 Service 实现类 |
| 16 | * | 16 | * |
| 17 | * @author QingX | 17 | * @author QingX |
| 18 | */ | 18 | */ |
| 19 | @Service | 19 | @Service |
| 20 | @Validated | 20 | @Validated |
| 21 | -public class MemberPointConfigServiceImpl implements MemberPointConfigService { | 21 | +public class MemberConfigServiceImpl implements MemberConfigService { |
| 22 | 22 | ||
| 23 | @Resource | 23 | @Resource |
| 24 | - private MemberPointConfigMapper memberPointConfigMapper; | 24 | + private MemberConfigMapper memberConfigMapper; |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |
| 27 | - public void savePointConfig(MemberPointConfigSaveReqVO saveReqVO) { | 27 | + public void saveConfig(MemberConfigSaveReqVO saveReqVO) { |
| 28 | // 存在,则进行更新 | 28 | // 存在,则进行更新 |
| 29 | - MemberPointConfigDO dbConfig = getPointConfig(); | 29 | + MemberConfigDO dbConfig = getConfig(); |
| 30 | if (dbConfig != null) { | 30 | if (dbConfig != null) { |
| 31 | - memberPointConfigMapper.updateById(MemberPointConfigConvert.INSTANCE.convert(saveReqVO).setId(dbConfig.getId())); | 31 | + memberConfigMapper.updateById(MemberConfigConvert.INSTANCE.convert(saveReqVO).setId(dbConfig.getId())); |
| 32 | return; | 32 | return; |
| 33 | } | 33 | } |
| 34 | // 不存在,则进行插入 | 34 | // 不存在,则进行插入 |
| 35 | - memberPointConfigMapper.insert(MemberPointConfigConvert.INSTANCE.convert(saveReqVO)); | 35 | + memberConfigMapper.insert(MemberConfigConvert.INSTANCE.convert(saveReqVO)); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | @Override | 38 | @Override |
| 39 | - public MemberPointConfigDO getPointConfig() { | ||
| 40 | - List<MemberPointConfigDO> list = memberPointConfigMapper.selectList(); | 39 | + public MemberConfigDO getConfig() { |
| 40 | + List<MemberConfigDO> list = memberConfigMapper.selectList(); | ||
| 41 | return CollectionUtils.getFirst(list); | 41 | return CollectionUtils.getFirst(list); |
| 42 | } | 42 | } |
| 43 | 43 |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java
| @@ -239,7 +239,8 @@ public class MemberLevelServiceImpl implements MemberLevelService { | @@ -239,7 +239,8 @@ public class MemberLevelServiceImpl implements MemberLevelService { | ||
| 239 | 239 | ||
| 240 | // 1. 创建经验记录 | 240 | // 1. 创建经验记录 |
| 241 | MemberUserDO user = memberUserService.getUser(userId); | 241 | MemberUserDO user = memberUserService.getUser(userId); |
| 242 | - int userExperience = NumberUtil.max(user.getExperience() + experience, 0); // 防止扣出负数 | 242 | + Integer userExperience = ObjUtil.defaultIfNull(user.getExperience(), 0); |
| 243 | + userExperience = NumberUtil.max(userExperience + experience, 0); // 防止扣出负数 | ||
| 243 | MemberLevelRecordDO levelRecord = new MemberLevelRecordDO() | 244 | MemberLevelRecordDO levelRecord = new MemberLevelRecordDO() |
| 244 | .setUserId(user.getId()) | 245 | .setUserId(user.getId()) |
| 245 | .setExperience(experience) | 246 | .setExperience(experience) |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java
| @@ -66,6 +66,9 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService { | @@ -66,6 +66,9 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService { | ||
| 66 | @Override | 66 | @Override |
| 67 | @Transactional(rollbackFor = Exception.class) | 67 | @Transactional(rollbackFor = Exception.class) |
| 68 | public void createPointRecord(Long userId, Integer point, MemberPointBizTypeEnum bizType, String bizId) { | 68 | public void createPointRecord(Long userId, Integer point, MemberPointBizTypeEnum bizType, String bizId) { |
| 69 | + if (point == 0) { | ||
| 70 | + return; | ||
| 71 | + } | ||
| 69 | // 1. 校验用户积分余额 | 72 | // 1. 校验用户积分余额 |
| 70 | MemberUserDO user = memberUserService.getUser(userId); | 73 | MemberUserDO user = memberUserService.getUser(userId); |
| 71 | Integer userPoint = ObjectUtil.defaultIfNull(user.getPoint(), 0); | 74 | Integer userPoint = ObjectUtil.defaultIfNull(user.getPoint(), 0); |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigServiceImpl.java
| @@ -11,10 +11,10 @@ import org.springframework.validation.annotation.Validated; | @@ -11,10 +11,10 @@ import org.springframework.validation.annotation.Validated; | ||
| 11 | import javax.annotation.Resource; | 11 | import javax.annotation.Resource; |
| 12 | import java.util.Comparator; | 12 | import java.util.Comparator; |
| 13 | import java.util.List; | 13 | import java.util.List; |
| 14 | +import java.util.Objects; | ||
| 14 | 15 | ||
| 15 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 16 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 16 | -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_CONFIG_EXISTS; | ||
| 17 | -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_CONFIG_NOT_EXISTS; | 17 | +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; |
| 18 | 18 | ||
| 19 | /** | 19 | /** |
| 20 | * 签到规则 Service 实现类 | 20 | * 签到规则 Service 实现类 |
| @@ -30,6 +30,8 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | @@ -30,6 +30,8 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | ||
| 30 | 30 | ||
| 31 | @Override | 31 | @Override |
| 32 | public Long createSignInConfig(MemberSignInConfigCreateReqVO createReqVO) { | 32 | public Long createSignInConfig(MemberSignInConfigCreateReqVO createReqVO) { |
| 33 | + // 校验奖励积分、奖励经验 | ||
| 34 | + validatePointAndExperience(createReqVO.getPoint(), createReqVO.getExperience()); | ||
| 33 | // 判断是否重复插入签到天数 | 35 | // 判断是否重复插入签到天数 |
| 34 | validateSignInConfigDayDuplicate(createReqVO.getDay(), null); | 36 | validateSignInConfigDayDuplicate(createReqVO.getDay(), null); |
| 35 | 37 | ||
| @@ -42,6 +44,8 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | @@ -42,6 +44,8 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | ||
| 42 | 44 | ||
| 43 | @Override | 45 | @Override |
| 44 | public void updateSignInConfig(MemberSignInConfigUpdateReqVO updateReqVO) { | 46 | public void updateSignInConfig(MemberSignInConfigUpdateReqVO updateReqVO) { |
| 47 | + // 校验奖励积分、奖励经验 | ||
| 48 | + validatePointAndExperience(updateReqVO.getPoint(), updateReqVO.getExperience()); | ||
| 45 | // 校验存在 | 49 | // 校验存在 |
| 46 | validateSignInConfigExists(updateReqVO.getId()); | 50 | validateSignInConfigExists(updateReqVO.getId()); |
| 47 | // 判断是否重复插入签到天数 | 51 | // 判断是否重复插入签到天数 |
| @@ -70,7 +74,7 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | @@ -70,7 +74,7 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | ||
| 70 | * 校验 day 是否重复 | 74 | * 校验 day 是否重复 |
| 71 | * | 75 | * |
| 72 | * @param day 天 | 76 | * @param day 天 |
| 73 | - * @param id 编号,只有更新的时候会传递 | 77 | + * @param id 编号,只有更新的时候会传递 |
| 74 | */ | 78 | */ |
| 75 | private void validateSignInConfigDayDuplicate(Integer day, Long id) { | 79 | private void validateSignInConfigDayDuplicate(Integer day, Long id) { |
| 76 | MemberSignInConfigDO config = memberSignInConfigMapper.selectByDay(day); | 80 | MemberSignInConfigDO config = memberSignInConfigMapper.selectByDay(day); |
| @@ -84,13 +88,20 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | @@ -84,13 +88,20 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService | ||
| 84 | } | 88 | } |
| 85 | } | 89 | } |
| 86 | 90 | ||
| 91 | + private void validatePointAndExperience(Integer point, Integer experience) { | ||
| 92 | + // 奖励积分、经验 至少要配置一个,否则没有意义 | ||
| 93 | + if (Objects.equals(point, 0) && Objects.equals(experience, 0)) { | ||
| 94 | + throw exception(SIGN_IN_CONFIG_AWARD_EMPTY); | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 87 | @Override | 98 | @Override |
| 88 | public MemberSignInConfigDO getSignInConfig(Long id) { | 99 | public MemberSignInConfigDO getSignInConfig(Long id) { |
| 89 | return memberSignInConfigMapper.selectById(id); | 100 | return memberSignInConfigMapper.selectById(id); |
| 90 | } | 101 | } |
| 91 | 102 | ||
| 92 | @Override | 103 | @Override |
| 93 | - public List <MemberSignInConfigDO> getSignInConfigList() { | 104 | + public List<MemberSignInConfigDO> getSignInConfigList() { |
| 94 | List<MemberSignInConfigDO> list = memberSignInConfigMapper.selectList(); | 105 | List<MemberSignInConfigDO> list = memberSignInConfigMapper.selectList(); |
| 95 | list.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); | 106 | list.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); |
| 96 | return list; | 107 | return list; |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.service.signin; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.service.signin; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 7 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 7 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | 8 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; |
| 8 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 9 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| @@ -13,8 +14,13 @@ import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO | @@ -13,8 +14,13 @@ import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO | ||
| 13 | import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInConfigMapper; | 14 | import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInConfigMapper; |
| 14 | import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInRecordMapper; | 15 | import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInRecordMapper; |
| 15 | import cn.iocoder.yudao.module.member.enums.ErrorCodeConstants; | 16 | import cn.iocoder.yudao.module.member.enums.ErrorCodeConstants; |
| 17 | +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | ||
| 18 | +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | ||
| 19 | +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; | ||
| 20 | +import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; | ||
| 16 | import org.apache.commons.lang3.StringUtils; | 21 | import org.apache.commons.lang3.StringUtils; |
| 17 | import org.springframework.stereotype.Service; | 22 | import org.springframework.stereotype.Service; |
| 23 | +import org.springframework.transaction.annotation.Transactional; | ||
| 18 | import org.springframework.util.CollectionUtils; | 24 | import org.springframework.util.CollectionUtils; |
| 19 | import org.springframework.validation.annotation.Validated; | 25 | import org.springframework.validation.annotation.Validated; |
| 20 | 26 | ||
| @@ -40,20 +46,24 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -40,20 +46,24 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 40 | private MemberSignInRecordMapper signInRecordMapper; | 46 | private MemberSignInRecordMapper signInRecordMapper; |
| 41 | @Resource | 47 | @Resource |
| 42 | private MemberSignInConfigMapper signInConfigMapper; | 48 | private MemberSignInConfigMapper signInConfigMapper; |
| 49 | + @Resource | ||
| 50 | + private MemberPointRecordService pointRecordService; | ||
| 51 | + @Resource | ||
| 52 | + private MemberLevelService memberLevelService; | ||
| 43 | 53 | ||
| 44 | @Resource | 54 | @Resource |
| 45 | private MemberUserApi memberUserApi; | 55 | private MemberUserApi memberUserApi; |
| 46 | 56 | ||
| 47 | @Override | 57 | @Override |
| 48 | public AppMemberSignInSummaryRespVO getSignInRecordSummary(Long userId) { | 58 | public AppMemberSignInSummaryRespVO getSignInRecordSummary(Long userId) { |
| 49 | - AppMemberSignInSummaryRespVO vo = new AppMemberSignInSummaryRespVO(); | 59 | + AppMemberSignInSummaryRespVO vo = new AppMemberSignInSummaryRespVO(); |
| 50 | vo.setTotalDay(0); | 60 | vo.setTotalDay(0); |
| 51 | vo.setContinuousDay(0); | 61 | vo.setContinuousDay(0); |
| 52 | vo.setTodaySignIn(false); | 62 | vo.setTodaySignIn(false); |
| 53 | //获取用户签到的记录,按照天数倒序获取 | 63 | //获取用户签到的记录,按照天数倒序获取 |
| 54 | - List <MemberSignInRecordDO> signInRecordDOList = signInRecordMapper.selectListByUserId(userId); | 64 | + List<MemberSignInRecordDO> signInRecordDOList = signInRecordMapper.selectListByUserId(userId); |
| 55 | // TODO @xiaqing:if 空的时候,直接 return;这样括号少,逻辑更简洁; | 65 | // TODO @xiaqing:if 空的时候,直接 return;这样括号少,逻辑更简洁; |
| 56 | - if(!CollectionUtils.isEmpty(signInRecordDOList)){ | 66 | + if (!CollectionUtils.isEmpty(signInRecordDOList)) { |
| 57 | //设置总签到天数 | 67 | //设置总签到天数 |
| 58 | vo.setTotalDay(signInRecordDOList.size()); // TODO @xiaqing:是不是不用读取 signInRecordDOList 所有的,而是 count下,然后另外再读取一条最后一条; | 68 | vo.setTotalDay(signInRecordDOList.size()); // TODO @xiaqing:是不是不用读取 signInRecordDOList 所有的,而是 count下,然后另外再读取一条最后一条; |
| 59 | //判断当天是否有签到复用校验方法 | 69 | //判断当天是否有签到复用校验方法 |
| @@ -61,11 +71,11 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -61,11 +71,11 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 61 | try { | 71 | try { |
| 62 | validSignDay(signInRecordDOList.get(0)); | 72 | validSignDay(signInRecordDOList.get(0)); |
| 63 | vo.setTodaySignIn(false); | 73 | vo.setTodaySignIn(false); |
| 64 | - }catch (Exception e){ | 74 | + } catch (Exception e) { |
| 65 | vo.setTodaySignIn(true); | 75 | vo.setTodaySignIn(true); |
| 66 | } | 76 | } |
| 67 | //如果当天签到了则说明连续签到天数有意义,否则直接用默认值0 | 77 | //如果当天签到了则说明连续签到天数有意义,否则直接用默认值0 |
| 68 | - if(vo.getTodaySignIn()){ | 78 | + if (vo.getTodaySignIn()) { |
| 69 | //下方计算连续签到从2天开始,此处直接设置一天连续签到 | 79 | //下方计算连续签到从2天开始,此处直接设置一天连续签到 |
| 70 | vo.setContinuousDay(1); | 80 | vo.setContinuousDay(1); |
| 71 | //判断连续签到天数 | 81 | //判断连续签到天数 |
| @@ -73,10 +83,10 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -73,10 +83,10 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 73 | for (int i = 1; i < signInRecordDOList.size(); i++) { | 83 | for (int i = 1; i < signInRecordDOList.size(); i++) { |
| 74 | //前一天减1等于当前天数则说明连续,继续循环 | 84 | //前一天减1等于当前天数则说明连续,继续循环 |
| 75 | LocalDate cur = signInRecordDOList.get(i).getCreateTime().toLocalDate(); | 85 | LocalDate cur = signInRecordDOList.get(i).getCreateTime().toLocalDate(); |
| 76 | - LocalDate pre = signInRecordDOList.get(i-1).getCreateTime().toLocalDate(); | ||
| 77 | - if(1==daysBetween(cur,pre)){ | ||
| 78 | - vo.setContinuousDay(i+1); | ||
| 79 | - }else{ | 86 | + LocalDate pre = signInRecordDOList.get(i - 1).getCreateTime().toLocalDate(); |
| 87 | + if (1 == daysBetween(cur, pre)) { | ||
| 88 | + vo.setContinuousDay(i + 1); | ||
| 89 | + } else { | ||
| 80 | break; | 90 | break; |
| 81 | } | 91 | } |
| 82 | } | 92 | } |
| @@ -87,16 +97,16 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -87,16 +97,16 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 87 | return vo; | 97 | return vo; |
| 88 | } | 98 | } |
| 89 | 99 | ||
| 90 | - private long daysBetween(LocalDate date1,LocalDate date2){ | 100 | + private long daysBetween(LocalDate date1, LocalDate date2) { |
| 91 | return ChronoUnit.DAYS.between(date1, date2); | 101 | return ChronoUnit.DAYS.between(date1, date2); |
| 92 | } | 102 | } |
| 93 | 103 | ||
| 94 | @Override | 104 | @Override |
| 95 | - public PageResult <MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { | 105 | + public PageResult<MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { |
| 96 | // 根据用户昵称查询出用户ids | 106 | // 根据用户昵称查询出用户ids |
| 97 | - Set <Long> userIds = null; | 107 | + Set<Long> userIds = null; |
| 98 | if (StringUtils.isNotBlank(pageReqVO.getNickname())) { | 108 | if (StringUtils.isNotBlank(pageReqVO.getNickname())) { |
| 99 | - List <MemberUserRespDTO> users = memberUserApi.getUserListByNickname(pageReqVO.getNickname()); | 109 | + List<MemberUserRespDTO> users = memberUserApi.getUserListByNickname(pageReqVO.getNickname()); |
| 100 | // 如果查询用户结果为空直接返回无需继续查询 | 110 | // 如果查询用户结果为空直接返回无需继续查询 |
| 101 | if (CollectionUtils.isEmpty(users)) { | 111 | if (CollectionUtils.isEmpty(users)) { |
| 102 | return PageResult.empty(); | 112 | return PageResult.empty(); |
| @@ -113,50 +123,63 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -113,50 +123,63 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 113 | } | 123 | } |
| 114 | 124 | ||
| 115 | @Override | 125 | @Override |
| 126 | + @Transactional(rollbackFor = Exception.class) | ||
| 116 | public MemberSignInRecordDO createSignRecord(Long userId) { | 127 | public MemberSignInRecordDO createSignRecord(Long userId) { |
| 117 | // 获取当前用户签到的最大天数 | 128 | // 获取当前用户签到的最大天数 |
| 118 | // TODO @xiaqing:db 操作,dou封装到 mapper 中; | 129 | // TODO @xiaqing:db 操作,dou封装到 mapper 中; |
| 119 | // TODO @xiaqing:maxSignDay,是不是变量叫 lastRecord 会更容易理解哈; | 130 | // TODO @xiaqing:maxSignDay,是不是变量叫 lastRecord 会更容易理解哈; |
| 120 | - MemberSignInRecordDO maxSignDay = signInRecordMapper.selectOne(new LambdaQueryWrapperX <MemberSignInRecordDO>() | 131 | + MemberSignInRecordDO maxSignDay = signInRecordMapper.selectOne(new LambdaQueryWrapperX<MemberSignInRecordDO>() |
| 121 | .eq(MemberSignInRecordDO::getUserId, userId) | 132 | .eq(MemberSignInRecordDO::getUserId, userId) |
| 122 | .orderByDesc(MemberSignInRecordDO::getDay) | 133 | .orderByDesc(MemberSignInRecordDO::getDay) |
| 123 | .last("limit 1")); | 134 | .last("limit 1")); |
| 124 | // 判断是否重复签到 | 135 | // 判断是否重复签到 |
| 125 | validSignDay(maxSignDay); | 136 | validSignDay(maxSignDay); |
| 126 | 137 | ||
| 127 | - // TODO @xiaqing:可以使用 // 进行注释 | ||
| 128 | - /**1.查询出当前签到的天数**/ | 138 | + // 1. 查询出当前签到的天数 |
| 129 | MemberSignInRecordDO sign = new MemberSignInRecordDO().setUserId(userId); // TODO @xiaqing:应该使用 record 变量,会更合适 | 139 | MemberSignInRecordDO sign = new MemberSignInRecordDO().setUserId(userId); // TODO @xiaqing:应该使用 record 变量,会更合适 |
| 130 | sign.setDay(1); // 设置签到初始化天数 | 140 | sign.setDay(1); // 设置签到初始化天数 |
| 131 | - sign.setPoint(0); // 设置签到分数默认为 0 | 141 | + sign.setPoint(0); // 设置签到积分默认为 0 |
| 142 | + sign.setExperience(0); // 设置签到经验默认为 0 | ||
| 132 | // 如果不为空则修改当前签到对应的天数 | 143 | // 如果不为空则修改当前签到对应的天数 |
| 133 | // TODO @xiaqing:应该是要判断连续哈,就是昨天; | 144 | // TODO @xiaqing:应该是要判断连续哈,就是昨天; |
| 134 | if (maxSignDay != null) { | 145 | if (maxSignDay != null) { |
| 135 | sign.setDay(maxSignDay.getDay() + 1); | 146 | sign.setDay(maxSignDay.getDay() + 1); |
| 136 | } | 147 | } |
| 137 | - /**2.获取签到对应的分数**/ | 148 | + // 2. 获取签到对应的积分数 |
| 138 | // 获取所有的签到规则,按照天数排序,只获取启用的 TODO @xiaqing:不要使用 signInConfigMapper 直接查询,而是要通过 SigninConfigService; | 149 | // 获取所有的签到规则,按照天数排序,只获取启用的 TODO @xiaqing:不要使用 signInConfigMapper 直接查询,而是要通过 SigninConfigService; |
| 139 | - List <MemberSignInConfigDO> configDOList = signInConfigMapper.selectList(new LambdaQueryWrapperX <MemberSignInConfigDO>() | 150 | + List<MemberSignInConfigDO> configDOList = signInConfigMapper.selectList(new LambdaQueryWrapperX<MemberSignInConfigDO>() |
| 140 | .eq(MemberSignInConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) | 151 | .eq(MemberSignInConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) |
| 141 | .orderByAsc(MemberSignInConfigDO::getDay)); | 152 | .orderByAsc(MemberSignInConfigDO::getDay)); |
| 142 | - // 如果签到的天数大于最大启用的规则天数,直接给最大签到的分数 | 153 | + // 如果签到的天数大于最大启用的规则天数,直接给最大签到的积分数 |
| 143 | // TODO @xiaqing:超过最大配置的天数,应该直接重置到第一天哈; | 154 | // TODO @xiaqing:超过最大配置的天数,应该直接重置到第一天哈; |
| 144 | MemberSignInConfigDO lastConfig = configDOList.get(configDOList.size() - 1); | 155 | MemberSignInConfigDO lastConfig = configDOList.get(configDOList.size() - 1); |
| 145 | if (sign.getDay() > lastConfig.getDay()) { | 156 | if (sign.getDay() > lastConfig.getDay()) { |
| 146 | sign.setPoint(lastConfig.getPoint()); | 157 | sign.setPoint(lastConfig.getPoint()); |
| 158 | + sign.setExperience(lastConfig.getExperience()); | ||
| 147 | } else { | 159 | } else { |
| 148 | configDOList.forEach(el -> { | 160 | configDOList.forEach(el -> { |
| 149 | - // 循环匹配对应天数,设置对应分数 | 161 | + // 循环匹配对应天数,设置对应积分数 |
| 150 | // TODO @xiaqing:使用 equals;另外,这种不应该去遍历比较,从可读性来说,应该 CollUtil.findOne() | 162 | // TODO @xiaqing:使用 equals;另外,这种不应该去遍历比较,从可读性来说,应该 CollUtil.findOne() |
| 151 | if (el.getDay() == sign.getDay()) { | 163 | if (el.getDay() == sign.getDay()) { |
| 152 | sign.setPoint(el.getPoint()); | 164 | sign.setPoint(el.getPoint()); |
| 165 | + sign.setExperience(el.getExperience()); | ||
| 153 | } | 166 | } |
| 154 | 167 | ||
| 155 | }); | 168 | }); |
| 156 | } | 169 | } |
| 157 | 170 | ||
| 158 | - // 3. 插入当前签到获取的分数 | 171 | + // 3. 插入签到记录 |
| 159 | signInRecordMapper.insert(sign); | 172 | signInRecordMapper.insert(sign); |
| 173 | + | ||
| 174 | + // 4. 增加积分 | ||
| 175 | + if (!ObjectUtils.equalsAny(sign.getPoint(), null, 0)) { | ||
| 176 | + pointRecordService.createPointRecord(userId, sign.getPoint(), MemberPointBizTypeEnum.SIGN, String.valueOf(sign.getId())); | ||
| 177 | + } | ||
| 178 | + // 5. 增加经验 | ||
| 179 | + if (!ObjectUtils.equalsAny(sign.getPoint(), null, 0)) { | ||
| 180 | + memberLevelService.addExperience(userId, sign.getExperience(), MemberExperienceBizTypeEnum.SIGN_IN, String.valueOf(sign.getId())); | ||
| 181 | + } | ||
| 182 | + | ||
| 160 | return sign; | 183 | return sign; |
| 161 | } | 184 | } |
| 162 | 185 |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
| @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; | @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; | ||
| 18 | import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; | 18 | import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; |
| 19 | import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; | 19 | import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; |
| 20 | import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; | 20 | import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; |
| 21 | +import cn.iocoder.yudao.module.member.mq.producer.user.RegisterCouponProducer; | ||
| 21 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; | 22 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; |
| 22 | import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; | 23 | import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; |
| 23 | import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; | 24 | import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; |
| @@ -58,6 +59,9 @@ public class MemberUserServiceImpl implements MemberUserService { | @@ -58,6 +59,9 @@ public class MemberUserServiceImpl implements MemberUserService { | ||
| 58 | @Resource | 59 | @Resource |
| 59 | private PasswordEncoder passwordEncoder; | 60 | private PasswordEncoder passwordEncoder; |
| 60 | 61 | ||
| 62 | + @Resource | ||
| 63 | + private RegisterCouponProducer registerCouponProducer; | ||
| 64 | + | ||
| 61 | @Override | 65 | @Override |
| 62 | public MemberUserDO getUserByMobile(String mobile) { | 66 | public MemberUserDO getUserByMobile(String mobile) { |
| 63 | return memberUserMapper.selectByMobile(mobile); | 67 | return memberUserMapper.selectByMobile(mobile); |
| @@ -89,6 +93,9 @@ public class MemberUserServiceImpl implements MemberUserService { | @@ -89,6 +93,9 @@ public class MemberUserServiceImpl implements MemberUserService { | ||
| 89 | user.setPassword(encodePassword(password)); // 加密密码 | 93 | user.setPassword(encodePassword(password)); // 加密密码 |
| 90 | user.setRegisterIp(registerIp); | 94 | user.setRegisterIp(registerIp); |
| 91 | memberUserMapper.insert(user); | 95 | memberUserMapper.insert(user); |
| 96 | + | ||
| 97 | + // 发送 MQ 消息,发放新人券 | ||
| 98 | + registerCouponProducer.sendMailSendMessage(user.getId()); | ||
| 92 | return user; | 99 | return user; |
| 93 | } | 100 | } |
| 94 | 101 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.controller.admin.wallet; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.PayWalletRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.PayWalletUserReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletConvert; | ||
| 7 | +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; | ||
| 8 | +import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; | ||
| 9 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 10 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 11 | +import lombok.extern.slf4j.Slf4j; | ||
| 12 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 13 | +import org.springframework.validation.annotation.Validated; | ||
| 14 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 15 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 16 | +import org.springframework.web.bind.annotation.RestController; | ||
| 17 | + | ||
| 18 | +import javax.annotation.Resource; | ||
| 19 | + | ||
| 20 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 21 | + | ||
| 22 | +@Tag(name = "管理后台 - 用户钱包") | ||
| 23 | +@RestController | ||
| 24 | +@RequestMapping("/pay/wallet") | ||
| 25 | +@Validated | ||
| 26 | +@Slf4j | ||
| 27 | +public class PayWalletController { | ||
| 28 | + | ||
| 29 | + @Resource | ||
| 30 | + private PayWalletService payWalletService; | ||
| 31 | + | ||
| 32 | + @GetMapping("/user-wallet") | ||
| 33 | + @PreAuthorize("@ss.hasPermission('pay:wallet:query')") | ||
| 34 | + @Operation(summary = "获得用户钱包明细") | ||
| 35 | + public CommonResult<PayWalletRespVO> getByUser(PayWalletUserReqVO reqVO) { | ||
| 36 | + PayWalletDO wallet = payWalletService.getWalletByUserIdAndType(reqVO.getUserId(), reqVO.getUserType()); | ||
| 37 | + return success(PayWalletConvert.INSTANCE.convert02(wallet)); | ||
| 38 | + } | ||
| 39 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/PayWalletBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import javax.validation.constraints.NotNull; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 用户钱包 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 10 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +public class PayWalletBaseVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20020") | ||
| 16 | + @NotNull(message = "用户编号不能为空") | ||
| 17 | + private Long userId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 20 | + @NotNull(message = "用户类型不能为空") | ||
| 21 | + private Byte userType; | ||
| 22 | + | ||
| 23 | + @Schema(description = "余额,单位分", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 24 | + @NotNull(message = "余额,单位分不能为空") | ||
| 25 | + private Integer balance; | ||
| 26 | + | ||
| 27 | + @Schema(description = "累计支出,单位分", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 28 | + @NotNull(message = "累计支出,单位分不能为空") | ||
| 29 | + private Integer totalExpense; | ||
| 30 | + | ||
| 31 | + @Schema(description = "累计充值,单位分", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 32 | + @NotNull(message = "累计充值,单位分不能为空") | ||
| 33 | + private Integer totalRecharge; | ||
| 34 | + | ||
| 35 | + @Schema(description = "冻结金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "20737") | ||
| 36 | + @NotNull(message = "冻结金额,单位分不能为空") | ||
| 37 | + private Integer freezePrice; | ||
| 38 | + | ||
| 39 | +} | ||
| 0 | \ No newline at end of file | 40 | \ No newline at end of file |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/PayWalletRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | +import lombok.ToString; | ||
| 7 | + | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - 用户钱包 Response VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +@ToString(callSuper = true) | ||
| 14 | +public class PayWalletRespVO extends PayWalletBaseVO { | ||
| 15 | + | ||
| 16 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29528") | ||
| 17 | + private Long id; | ||
| 18 | + | ||
| 19 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 20 | + private LocalDateTime createTime; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/PayWalletUserReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - 用户钱包明细 Request VO") | ||
| 11 | +@Data | ||
| 12 | +public class PayWalletUserReqVO { | ||
| 13 | + | ||
| 14 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 15 | + @NotNull(message = "用户编号不能为空") | ||
| 16 | + private Long userId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 19 | + @NotNull(message = "用户类型不能为空") | ||
| 20 | + @InEnum(value = UserTypeEnum.class, message = "用户类型必须是 {value}") | ||
| 21 | + private Integer userType; | ||
| 22 | +} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java
| 1 | package cn.iocoder.yudao.module.pay.convert.wallet; | 1 | package cn.iocoder.yudao.module.pay.convert.wallet; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.PayWalletRespVO; | ||
| 3 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO; | 4 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO; |
| 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
| 5 | import org.mapstruct.Mapper; | 6 | import org.mapstruct.Mapper; |
| @@ -11,4 +12,6 @@ public interface PayWalletConvert { | @@ -11,4 +12,6 @@ public interface PayWalletConvert { | ||
| 11 | PayWalletConvert INSTANCE = Mappers.getMapper(PayWalletConvert.class); | 12 | PayWalletConvert INSTANCE = Mappers.getMapper(PayWalletConvert.class); |
| 12 | 13 | ||
| 13 | AppPayWalletRespVO convert(PayWalletDO bean); | 14 | AppPayWalletRespVO convert(PayWalletDO bean); |
| 15 | + | ||
| 16 | + PayWalletRespVO convert02(PayWalletDO wallet); | ||
| 14 | } | 17 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
| @@ -13,10 +13,10 @@ public interface PayWalletService { | @@ -13,10 +13,10 @@ public interface PayWalletService { | ||
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * 获取钱包信息 | 15 | * 获取钱包信息 |
| 16 | - * | 16 | + * <p> |
| 17 | * 如果不存在,则创建钱包。由于用户注册时候不会创建钱包 | 17 | * 如果不存在,则创建钱包。由于用户注册时候不会创建钱包 |
| 18 | * | 18 | * |
| 19 | - * @param userId 用户编号 | 19 | + * @param userId 用户编号 |
| 20 | * @param userType 用户类型 | 20 | * @param userType 用户类型 |
| 21 | */ | 21 | */ |
| 22 | PayWalletDO getOrCreateWallet(Long userId, Integer userType); | 22 | PayWalletDO getOrCreateWallet(Long userId, Integer userType); |
| @@ -31,10 +31,10 @@ public interface PayWalletService { | @@ -31,10 +31,10 @@ public interface PayWalletService { | ||
| 31 | /** | 31 | /** |
| 32 | * 钱包订单支付 | 32 | * 钱包订单支付 |
| 33 | * | 33 | * |
| 34 | - * @param userId 用户 id | ||
| 35 | - * @param userType 用户类型 | 34 | + * @param userId 用户 id |
| 35 | + * @param userType 用户类型 | ||
| 36 | * @param outTradeNo 外部订单号 | 36 | * @param outTradeNo 外部订单号 |
| 37 | - * @param price 金额 | 37 | + * @param price 金额 |
| 38 | */ | 38 | */ |
| 39 | PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price); | 39 | PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price); |
| 40 | 40 | ||
| @@ -43,17 +43,17 @@ public interface PayWalletService { | @@ -43,17 +43,17 @@ public interface PayWalletService { | ||
| 43 | * | 43 | * |
| 44 | * @param outRefundNo 外部退款号 | 44 | * @param outRefundNo 外部退款号 |
| 45 | * @param refundPrice 退款金额 | 45 | * @param refundPrice 退款金额 |
| 46 | - * @param reason 退款原因 | 46 | + * @param reason 退款原因 |
| 47 | */ | 47 | */ |
| 48 | PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason); | 48 | PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason); |
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * 扣减钱包余额 | 51 | * 扣减钱包余额 |
| 52 | * | 52 | * |
| 53 | - * @param walletId 钱包 id | ||
| 54 | - * @param bizId 业务关联 id | ||
| 55 | - * @param bizType 业务关联分类 | ||
| 56 | - * @param price 扣减金额 | 53 | + * @param walletId 钱包 id |
| 54 | + * @param bizId 业务关联 id | ||
| 55 | + * @param bizType 业务关联分类 | ||
| 56 | + * @param price 扣减金额 | ||
| 57 | * @return 钱包流水 | 57 | * @return 钱包流水 |
| 58 | */ | 58 | */ |
| 59 | PayWalletTransactionDO reduceWalletBalance(Long walletId, Long bizId, | 59 | PayWalletTransactionDO reduceWalletBalance(Long walletId, Long bizId, |
| @@ -63,9 +63,9 @@ public interface PayWalletService { | @@ -63,9 +63,9 @@ public interface PayWalletService { | ||
| 63 | * 增加钱包余额 | 63 | * 增加钱包余额 |
| 64 | * | 64 | * |
| 65 | * @param walletId 钱包 id | 65 | * @param walletId 钱包 id |
| 66 | - * @param bizId 业务关联 id | ||
| 67 | - * @param bizType 业务关联分类 | ||
| 68 | - * @param price 增加金额 | 66 | + * @param bizId 业务关联 id |
| 67 | + * @param bizType 业务关联分类 | ||
| 68 | + * @param price 增加金额 | ||
| 69 | * @return 钱包流水 | 69 | * @return 钱包流水 |
| 70 | */ | 70 | */ |
| 71 | PayWalletTransactionDO addWalletBalance(Long walletId, String bizId, | 71 | PayWalletTransactionDO addWalletBalance(Long walletId, String bizId, |
| @@ -74,15 +74,25 @@ public interface PayWalletService { | @@ -74,15 +74,25 @@ public interface PayWalletService { | ||
| 74 | /** | 74 | /** |
| 75 | * 冻结钱包部分余额 | 75 | * 冻结钱包部分余额 |
| 76 | * | 76 | * |
| 77 | - * @param id 钱包编号 | 77 | + * @param id 钱包编号 |
| 78 | * @param price 冻结金额 | 78 | * @param price 冻结金额 |
| 79 | */ | 79 | */ |
| 80 | void freezePrice(Long id, Integer price); | 80 | void freezePrice(Long id, Integer price); |
| 81 | 81 | ||
| 82 | /** | 82 | /** |
| 83 | * 解冻钱包余额 | 83 | * 解冻钱包余额 |
| 84 | - * @param id 钱包编号 | 84 | + * |
| 85 | + * @param id 钱包编号 | ||
| 85 | * @param price 解冻金额 | 86 | * @param price 解冻金额 |
| 86 | */ | 87 | */ |
| 87 | void unFreezePrice(Long id, Integer price); | 88 | void unFreezePrice(Long id, Integer price); |
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 获得用户的钱包明细 | ||
| 92 | + * | ||
| 93 | + * @param userId 用户编号 | ||
| 94 | + * @param userType 用户类型 | ||
| 95 | + * @return 用户的钱包明细 | ||
| 96 | + */ | ||
| 97 | + PayWalletDO getWalletByUserIdAndType(Long userId, Integer userType); | ||
| 88 | } | 98 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
| @@ -195,4 +195,9 @@ public class PayWalletServiceImpl implements PayWalletService { | @@ -195,4 +195,9 @@ public class PayWalletServiceImpl implements PayWalletService { | ||
| 195 | } | 195 | } |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | + @Override | ||
| 199 | + public PayWalletDO getWalletByUserIdAndType(Long userId, Integer userType) { | ||
| 200 | + return walletMapper.selectByUserIdAndType(userId, userType); | ||
| 201 | + } | ||
| 202 | + | ||
| 198 | } | 203 | } |