Commit 31249481759ed9a87653a1f2c04974a728cc533a

Authored by 芋道源码
Committed by Gitee
2 parents fe53e426 281ba1e3

!578 同步商城实现:会员列表、会员积分、会员签到、会员标签

Merge pull request !578 from 芋道源码/feature/mall_product
Showing 255 changed files with 5344 additions and 3288 deletions

Too many changes.

To preserve performance only 100 of 255 files are displayed.

@@ -16,11 +16,11 @@ @@ -16,11 +16,11 @@
16 <module>yudao-module-member</module> 16 <module>yudao-module-member</module>
17 <module>yudao-module-system</module> 17 <module>yudao-module-system</module>
18 <module>yudao-module-infra</module> 18 <module>yudao-module-infra</module>
19 -<!-- <module>yudao-module-pay</module>--> 19 + <module>yudao-module-pay</module>
20 <!-- <module>yudao-module-bpm</module>--> 20 <!-- <module>yudao-module-bpm</module>-->
21 <!-- <module>yudao-module-report</module>--> 21 <!-- <module>yudao-module-report</module>-->
22 <!-- <module>yudao-module-mp</module>--> 22 <!-- <module>yudao-module-mp</module>-->
23 -<!-- <module>yudao-module-mall</module>--> 23 + <module>yudao-module-mall</module>
24 <!-- 示例项目 --> 24 <!-- 示例项目 -->
25 <module>yudao-example</module> 25 <module>yudao-example</module>
26 </modules> 26 </modules>
sql/mysql/ruoyi-vue-pro.sql
@@ -1637,18 +1637,18 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i @@ -1637,18 +1637,18 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
1637 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'); 1637 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');
1638 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', 'date-range', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-06-10 00:42:03', '1', '2023-06-28 22:52:34', b'0'); 1638 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', 'date-range', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-06-10 00:42:03', '1', '2023-06-28 22:52:34', b'0');
1639 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', '', 'member/point/config/index', 'PointConfig', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 22:50:59', b'0'); 1639 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', '', 'member/point/config/index', 'PointConfig', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 22:50:59', b'0');
1640 -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');  
1641 -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'); 1640 +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:point:config:get', 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');
  1641 +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: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');
1642 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, 'sign-in-config', '', 'member/signin/config/index', 'SignInConfig', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-07-02 15:04:15', b'0'); 1642 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, 'sign-in-config', '', 'member/signin/config/index', 'SignInConfig', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-07-02 15:04:15', b'0');
1643 -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');  
1644 -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');  
1645 -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');  
1646 -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'); 1643 +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, '签到规则查询', 'member: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');
  1644 +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, '签到规则创建', 'member: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');
  1645 +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, '签到规则更新', 'member: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');
  1646 +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, '签到规则删除', 'member: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');
  1647 +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 (2286, '签到规则获取', 'member:point:sign-in-config:get', 3, 5, 2281, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-08-19 09:48:32', b'0');
1647 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', '', 'member/point/record/index', 'PointRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '1', '2023-06-27 22:51:07', b'0'); 1648 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', '', 'member/point/record/index', 'PointRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '1', '2023-06-27 22:51:07', b'0');
1648 -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'); 1649 +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, '用户积分记录查询', 'member: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');
1649 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, 'sign-in-record', '', 'member/signin/record/index', 'SignInRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '1', '2023-07-02 15:04:10', b'0'); 1650 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, 'sign-in-record', '', 'member/signin/record/index', 'SignInRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '1', '2023-07-02 15:04:10', b'0');
1650 -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');  
1651 -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'); 1651 +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, '签到记录查询', 'member: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');
1652 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, 1, 2262, 'point', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:48:51', '1', '2023-06-27 22:48:51', b'0'); 1652 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, 1, 2262, 'point', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:48:51', '1', '2023-06-27 22:48:51', b'0');
1653 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, 2, 2262, 'signin', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-06-27 22:49:53', b'0'); 1653 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, 2, 2262, 'signin', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-06-27 22:49:53', b'0');
1654 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'); 1654 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');
yudao-framework/yudao-common/pom.xml
@@ -133,6 +133,11 @@ @@ -133,6 +133,11 @@
133 <artifactId>transmittable-thread-local</artifactId> 133 <artifactId>transmittable-thread-local</artifactId>
134 </dependency> 134 </dependency>
135 135
  136 + <!-- Test 测试相关 -->
  137 + <dependency>
  138 + <groupId>org.springframework.boot</groupId>
  139 + <artifactId>spring-boot-starter-test</artifactId>
  140 + </dependency>
136 </dependencies> 141 </dependencies>
137 142
138 </project> 143 </project>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -5,12 +5,11 @@ import cn.hutool.core.collection.CollectionUtil; @@ -5,12 +5,11 @@ import cn.hutool.core.collection.CollectionUtil;
5 import com.google.common.collect.ImmutableMap; 5 import com.google.common.collect.ImmutableMap;
6 6
7 import java.util.*; 7 import java.util.*;
8 -import java.util.function.BinaryOperator;  
9 -import java.util.function.Function;  
10 -import java.util.function.Predicate;  
11 -import java.util.function.Supplier; 8 +import java.util.function.*;
12 import java.util.stream.Collectors; 9 import java.util.stream.Collectors;
13 10
  11 +import static java.util.Arrays.asList;
  12 +
14 /** 13 /**
15 * Collection 工具类 14 * Collection 工具类
16 * 15 *
@@ -19,13 +18,17 @@ import java.util.stream.Collectors; @@ -19,13 +18,17 @@ import java.util.stream.Collectors;
19 public class CollectionUtils { 18 public class CollectionUtils {
20 19
21 public static boolean containsAny(Object source, Object... targets) { 20 public static boolean containsAny(Object source, Object... targets) {
22 - return Arrays.asList(targets).contains(source); 21 + return asList(targets).contains(source);
23 } 22 }
24 23
25 public static boolean isAnyEmpty(Collection<?>... collections) { 24 public static boolean isAnyEmpty(Collection<?>... collections) {
26 return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); 25 return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
27 } 26 }
28 27
  28 + public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) {
  29 + return from.stream().anyMatch(predicate);
  30 + }
  31 +
29 public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) { 32 public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) {
30 if (CollUtil.isEmpty(from)) { 33 if (CollUtil.isEmpty(from)) {
31 return new ArrayList<>(); 34 return new ArrayList<>();
@@ -149,6 +152,46 @@ public class CollectionUtils { @@ -149,6 +152,46 @@ public class CollectionUtils {
149 return builder.build(); 152 return builder.build();
150 } 153 }
151 154
  155 + /**
  156 + * 对比老、新两个列表,找出新增、修改、删除的数据
  157 + *
  158 + * @param oldList 老列表
  159 + * @param newList 新列表
  160 + * @param sameFunc 对比函数,返回 true 表示相同,返回 false 表示不同
  161 + * 注意,same 是通过每个元素的“标识”,判断它们是不是同一个数据
  162 + * @return [新增列表、修改列表、删除列表]
  163 + */
  164 + public static <T> List<List<T>> diffList(Collection<T> oldList, Collection<T> newList,
  165 + BiFunction<T, T, Boolean> sameFunc) {
  166 + List<T> createList = new LinkedList<>(newList); // 默认都认为是新增的,后续会进行移除
  167 + List<T> updateList = new ArrayList<>();
  168 + List<T> deleteList = new ArrayList<>();
  169 +
  170 + // 通过以 oldList 为主遍历,找出 updateList 和 deleteList
  171 + for (T oldObj : oldList) {
  172 + // 1. 寻找是否有匹配的
  173 + T foundObj = null;
  174 + for (Iterator<T> iterator = createList.iterator(); iterator.hasNext(); ) {
  175 + T newObj = iterator.next();
  176 + // 1.1 不匹配,则直接跳过
  177 + if (!sameFunc.apply(oldObj, newObj)) {
  178 + continue;
  179 + }
  180 + // 1.2 匹配,则移除,并结束寻找
  181 + iterator.remove();
  182 + foundObj = newObj;
  183 + break;
  184 + }
  185 + // 2. 匹配添加到 updateList;不匹配则添加到 deleteList 中
  186 + if (foundObj != null) {
  187 + updateList.add(foundObj);
  188 + } else {
  189 + deleteList.add(oldObj);
  190 + }
  191 + }
  192 + return asList(createList, updateList, deleteList);
  193 + }
  194 +
152 public static boolean containsAny(Collection<?> source, Collection<?> candidates) { 195 public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
153 return org.springframework.util.CollectionUtils.containsAny(source, candidates); 196 return org.springframework.util.CollectionUtils.containsAny(source, candidates);
154 } 197 }
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java
@@ -23,6 +23,8 @@ public class DateUtils { @@ -23,6 +23,8 @@ public class DateUtils {
23 */ 23 */
24 public static final long SECOND_MILLIS = 1000; 24 public static final long SECOND_MILLIS = 1000;
25 25
  26 + public static final String FORMAT_YEAR_MONTH_DAY = "yyyy-MM-dd";
  27 +
26 public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; 28 public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
27 29
28 public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss"; 30 public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss";
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.date; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.date;
3 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
4 4
5 import java.time.Duration; 5 import java.time.Duration;
  6 +import java.time.LocalDate;
6 import java.time.LocalDateTime; 7 import java.time.LocalDateTime;
7 import java.time.LocalTime; 8 import java.time.LocalTime;
8 9
@@ -62,23 +63,18 @@ public class LocalDateTimeUtils { @@ -62,23 +63,18 @@ public class LocalDateTimeUtils {
62 } 63 }
63 64
64 /** 65 /**
65 - * 检查时间重叠 不包含日期 66 + * 判断时间段是否重叠
66 * 67 *
67 - * @param startTime1 需要校验的开始时间  
68 - * @param endTime1 需要校验的结束时间  
69 - * @param startTime2 校验所需的开始时间  
70 - * @param endTime2 校验所需的结束时间  
71 - * @return 是否重叠 68 + * @param startTime1 开始 time1
  69 + * @param endTime1 结束 time1
  70 + * @param startTime2 开始 time2
  71 + * @param endTime2 结束 time2
  72 + * @return 重叠:true 不重叠:false
72 */ 73 */
73 - // TODO @puhui999:LocalDateTimeUtil.isOverlap() 是不是可以满足呀?  
74 - public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {  
75 - // 判断时间是否重叠  
76 - // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []  
77 - return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)  
78 - // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()  
79 - || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)  
80 - // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()  
81 - || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2); 74 + public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
  75 + LocalDate nowDate = LocalDate.now();
  76 + return LocalDateTimeUtil.isOverlap(LocalDateTime.of(nowDate, startTime1), LocalDateTime.of(nowDate, endTime1),
  77 + LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2));
82 } 78 }
83 79
84 } 80 }
yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.common.util.collection;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import org.junit.jupiter.api.Test;
  6 +
  7 +import java.util.Arrays;
  8 +import java.util.Collection;
  9 +import java.util.List;
  10 +import java.util.function.BiFunction;
  11 +
  12 +import static org.junit.jupiter.api.Assertions.assertEquals;
  13 +
  14 +/**
  15 + * {@link CollectionUtils} 的单元测试
  16 + */
  17 +public class CollectionUtilsTest {
  18 +
  19 + @Data
  20 + @AllArgsConstructor
  21 + private static class Dog {
  22 +
  23 + private Integer id;
  24 + private String name;
  25 + private String code;
  26 +
  27 + }
  28 +
  29 + @Test
  30 + public void testDiffList() {
  31 + // 准备参数
  32 + Collection<Dog> oldList = Arrays.asList(
  33 + new Dog(1, "花花", "hh"),
  34 + new Dog(2, "旺财", "wc")
  35 + );
  36 + Collection<Dog> newList = Arrays.asList(
  37 + new Dog(null, "花花2", "hh"),
  38 + new Dog(null, "小白", "xb")
  39 + );
  40 + BiFunction<Dog, Dog, Boolean> sameFunc = (oldObj, newObj) -> {
  41 + boolean same = oldObj.getCode().equals(newObj.getCode());
  42 + // 如果相等的情况下,需要设置下 id,后续好更新
  43 + if (same) {
  44 + newObj.setId(oldObj.getId());
  45 + }
  46 + return same;
  47 + };
  48 +
  49 + // 调用
  50 + List<List<Dog>> result = CollectionUtils.diffList(oldList, newList, sameFunc);
  51 + // 断言
  52 + assertEquals(result.size(), 3);
  53 + // 断言 create
  54 + assertEquals(result.get(0).size(), 1);
  55 + assertEquals(result.get(0).get(0), new Dog(null, "小白", "xb"));
  56 + // 断言 update
  57 + assertEquals(result.get(1).size(), 1);
  58 + assertEquals(result.get(1).get(0), new Dog(1, "花花2", "hh"));
  59 + // 断言 delete
  60 + assertEquals(result.get(2).size(), 1);
  61 + assertEquals(result.get(2).get(0), new Dog(2, "旺财", "wc"));
  62 + }
  63 +
  64 +}
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
@@ -148,7 +148,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -148,7 +148,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
148 // 2.1 执行请求 148 // 2.1 执行请求
149 AlipayTradeRefundResponse response = client.execute(request); 149 AlipayTradeRefundResponse response = client.execute(request);
150 if (!response.isSuccess()) { 150 if (!response.isSuccess()) {
151 - return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response); 151 + return PayRefundRespDTO.failureOf(response.getSubCode(), response.getSubMsg(), reqDTO.getOutRefundNo(), response);
152 } 152 }
153 // 2.2 创建返回结果 153 // 2.2 创建返回结果
154 // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。 154 // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java
1 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; 1 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
  2 +
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.hutool.core.util.RandomUtil;
2 import cn.hutool.core.util.ReflectUtil; 5 import cn.hutool.core.util.ReflectUtil;
  6 +import cn.iocoder.yudao.framework.common.exception.ServiceException;
  7 +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
  8 +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
  9 +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; 10 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  11 +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
  12 +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  13 +import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
  14 +import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
  15 +import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
4 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; 16 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
5 import com.alipay.api.AlipayApiException; 17 import com.alipay.api.AlipayApiException;
6 import com.alipay.api.DefaultAlipayClient; 18 import com.alipay.api.DefaultAlipayClient;
  19 +import com.alipay.api.domain.AlipayTradeRefundModel;
7 import com.alipay.api.request.AlipayTradePrecreateRequest; 20 import com.alipay.api.request.AlipayTradePrecreateRequest;
  21 +import com.alipay.api.request.AlipayTradeRefundRequest;
8 import com.alipay.api.response.AlipayTradePrecreateResponse; 22 import com.alipay.api.response.AlipayTradePrecreateResponse;
9 -import org.junit.jupiter.api.Disabled; 23 +import com.alipay.api.response.AlipayTradeRefundResponse;
  24 +import org.junit.jupiter.api.DisplayName;
10 import org.junit.jupiter.api.Test; 25 import org.junit.jupiter.api.Test;
11 import org.mockito.ArgumentMatcher; 26 import org.mockito.ArgumentMatcher;
12 import org.mockito.InjectMocks; 27 import org.mockito.InjectMocks;
13 import org.mockito.Mock; 28 import org.mockito.Mock;
14 29
15 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
16 -import static org.junit.jupiter.api.Assertions.assertEquals;  
17 -import static org.junit.jupiter.api.Assertions.assertNotSame; 30 +import javax.validation.ConstraintViolationException;
  31 +import java.util.Date;
  32 +
  33 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_PUBLIC_KEY;
  34 +import static cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum.CLOSED;
  35 +import static cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum.WAITING;
  36 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  37 +import static org.junit.jupiter.api.Assertions.*;
18 import static org.mockito.ArgumentMatchers.argThat; 38 import static org.mockito.ArgumentMatchers.argThat;
19 import static org.mockito.Mockito.when; 39 import static org.mockito.Mockito.when;
20 - 40 +/**
  41 + * {@link AlipayQrPayClient} 单元测试
  42 + *
  43 + * @author jason
  44 + */
21 public class AlipayQrPayClientTest extends BaseMockitoUnitTest { 45 public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
22 46
23 - private static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do";  
24 -  
25 - private final AlipayPayClientConfig config = new AlipayPayClientConfig()  
26 - .setAppId("2021000118634035")  
27 - .setServerUrl(SERVER_URL_SANDBOX)  
28 - .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)  
29 - // TODO @tina:key 可以随机就好,简洁一点哈。  
30 - .setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJ" +  
31 - "v890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T" +  
32 - "01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH" +  
33 - "6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScw" +  
34 - "lSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63tr" +  
35 - "epo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdk" +  
36 - "USmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr" +  
37 - "8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w" +  
38 - "0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENi" +  
39 - "vAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPw" +  
40 - "YcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQO" +  
41 - "LFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsm" +  
42 - "yX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i9" +  
43 - "5Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOU" +  
44 - "hVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD" +  
45 - "/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v1" +  
46 - "8p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ" +  
47 - "8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4e" +  
48 - "N0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6p" +  
49 - "bKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erx" +  
50 - "TRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=")  
51 - .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0" +  
52 - "gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBN" +  
53 - "lrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZ" +  
54 - "ikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); 47 + private final AlipayPayClientConfig config = randomPojo(AlipayPayClientConfig.class, t -> {
  48 + t.setServerUrl(randomURL());
  49 + t.setMode(MODE_PUBLIC_KEY);
  50 + t.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
  51 + t.setAppCertContent("");
  52 + t.setAlipayPublicCertContent("");
  53 + t.setRootCertContent("");
  54 + });
55 55
56 @InjectMocks 56 @InjectMocks
57 - AlipayQrPayClient client = new AlipayQrPayClient(10L,config); 57 + AlipayQrPayClient client = new AlipayQrPayClient(randomLongId(), config);
58 58
59 @Mock 59 @Mock
60 private DefaultAlipayClient defaultAlipayClient; 60 private DefaultAlipayClient defaultAlipayClient;
61 61
62 @Test 62 @Test
63 - public void testDoInit(){ 63 + public void test_do_init() {
64 client.doInit(); 64 client.doInit();
65 assertNotSame(defaultAlipayClient, ReflectUtil.getFieldValue(client, "defaultAlipayClient")); 65 assertNotSame(defaultAlipayClient, ReflectUtil.getFieldValue(client, "defaultAlipayClient"));
66 } 66 }
67 67
68 @Test 68 @Test
69 - @Disabled // TODO 芋艿:临时禁用  
70 - public void create() throws AlipayApiException {  
71 - // TODO @tina:参数可以尽量随机一点,使用随机方法。这样的好处是,避免对固定参数的依赖,导致可能仅仅满足固定参数的结果  
72 - // 这里,设置可以直接随机整个对象。  
73 - Long shopOrderId = System.currentTimeMillis();  
74 - PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO();  
75 - reqDTO.setOutTradeNo(String.valueOf(System.currentTimeMillis()));  
76 - reqDTO.setPrice(1);  
77 - reqDTO.setBody("内容:" + shopOrderId);  
78 - reqDTO.setSubject("标题:"+shopOrderId);  
79 - String notify="http://niubi.natapp1.cc/api/pay/order/notify";  
80 - reqDTO.setNotifyUrl(notify);  
81 -  
82 - AlipayTradePrecreateResponse response=randomPojo(AlipayTradePrecreateResponse.class,o->o.setQrCode("success"));  
83 -  
84 - when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request ->{  
85 - assertEquals(notify,request.getNotifyUrl()); 69 + @DisplayName("支付包扫描支付下单成功")
  70 + public void test_unified_order_success() throws AlipayApiException {
  71 + // 准备返回对象
  72 + String notifyUrl = randomURL();
  73 + String qrCode = randomString();
  74 + AlipayTradePrecreateResponse response = randomPojo(AlipayTradePrecreateResponse.class, o -> {
  75 + o.setQrCode(qrCode);
  76 + o.setSubCode("");
  77 + });
  78 + // mock
  79 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
  80 + assertEquals(notifyUrl, request.getNotifyUrl());
  81 + return true;
  82 + }))).thenReturn(response);
  83 + // 准备请求参数
  84 + String outTradeNo = randomString();
  85 + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo);
  86 +
  87 + PayOrderRespDTO resp = client.unifiedOrder(reqDTO);
  88 + // 断言
  89 + assertEquals(WAITING.getStatus(), resp.getStatus());
  90 + assertEquals(PayOrderDisplayModeEnum.QR_CODE.getMode(), resp.getDisplayMode());
  91 + assertEquals(outTradeNo, resp.getOutTradeNo());
  92 + assertEquals(qrCode, resp.getDisplayContent());
  93 + assertSame(response, resp.getRawData());
  94 + }
  95 +
  96 + @Test
  97 + @DisplayName("支付包扫描支付,渠道返回失败")
  98 + public void test_unified_order_channel_failed() throws AlipayApiException {
  99 + String notifyUrl = randomURL();
  100 + String subCode = randomString();
  101 + String subMsg = randomString();
  102 + AlipayTradePrecreateResponse response = randomPojo(AlipayTradePrecreateResponse.class, o -> {
  103 + o.setSubCode(subCode);
  104 + o.setSubMsg(subMsg);
  105 + });
  106 + // mock
  107 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
  108 + assertEquals(notifyUrl, request.getNotifyUrl());
  109 + return true;
  110 + }))).thenReturn(response);
  111 + // 准备请求参数
  112 + String outTradeNo = randomString();
  113 + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo);
  114 +
  115 + PayOrderRespDTO resp = client.unifiedOrder(reqDTO);
  116 + // 断言
  117 + assertEquals(CLOSED.getStatus(), resp.getStatus());
  118 + assertEquals(subCode, resp.getChannelErrorCode());
  119 + assertEquals(subMsg, resp.getChannelErrorMsg());
  120 + assertSame(response, resp.getRawData());
  121 + }
  122 +
  123 + @Test
  124 + @DisplayName("支付包扫描支付,抛出系统异常")
  125 + public void test_unified_order_throw_pay_exception() throws AlipayApiException {
  126 + // 准备请求参数
  127 + String outTradeNo = randomString();
  128 + String notifyUrl = randomURL();
  129 + // mock
  130 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
  131 + assertEquals(notifyUrl, request.getNotifyUrl());
  132 + return true;
  133 + }))).thenThrow(new RuntimeException("系统异常"));
  134 + // 准备请求参数
  135 + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo);
  136 + // 断言
  137 + assertThrows(PayException.class, () -> client.unifiedOrder(reqDTO));
  138 + }
  139 +
  140 + @Test
  141 + @DisplayName("支付包扫描支付,抛出业务异常")
  142 + public void test_unified_order_throw_service_exception() throws AlipayApiException {
  143 + // 准备请求参数
  144 + String outTradeNo = randomString();
  145 + String notifyUrl = randomURL();
  146 + // mock
  147 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
  148 + assertEquals(notifyUrl, request.getNotifyUrl());
  149 + return true;
  150 + }))).thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR));
  151 + // 准备请求参数
  152 + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo);
  153 + // 断言
  154 + assertThrows(ServiceException.class, () -> client.unifiedOrder(reqDTO));
  155 + }
  156 +
  157 + @Test
  158 + @DisplayName("支付包扫描支付,参数校验不通过")
  159 + public void test_unified_order_param_validate() {
  160 + // 准备请求参数
  161 + String outTradeNo = randomString();
  162 + String notifyUrl = randomURL();
  163 + PayOrderUnifiedReqDTO reqDTO = randomPojo(PayOrderUnifiedReqDTO.class, o -> {
  164 + o.setOutTradeNo(outTradeNo);
  165 + o.setNotifyUrl(notifyUrl);
  166 + });
  167 + // 断言
  168 + assertThrows(ConstraintViolationException.class, () -> client.unifiedOrder(reqDTO));
  169 + }
  170 +
  171 + private PayOrderUnifiedReqDTO buildOrderUnifiedReqDTO(String notifyUrl, String outTradeNo) {
  172 + return randomPojo(PayOrderUnifiedReqDTO.class, o -> {
  173 + o.setOutTradeNo(outTradeNo);
  174 + o.setNotifyUrl(notifyUrl);
  175 + o.setSubject(RandomUtil.randomString(32));
  176 + o.setBody(RandomUtil.randomString(32));
  177 + });
  178 + }
  179 +
  180 + @Test
  181 + @DisplayName("支付包扫描退款成功")
  182 + public void test_unified_refund_success() throws AlipayApiException {
  183 + // 准备返回对象
  184 + String notifyUrl = randomURL();
  185 + Date refundTime = randomDate();
  186 + String outRefundNo = randomString();
  187 + String outTradeNo = randomString();
  188 + Integer refundAmount = randomInteger();
  189 + AlipayTradeRefundResponse response = randomPojo(AlipayTradeRefundResponse.class, o -> {
  190 + o.setSubCode("");
  191 + o.setGmtRefundPay(refundTime);
  192 + });
  193 + // mock
  194 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> {
  195 + assertInstanceOf(AlipayTradeRefundModel.class, request.getBizModel());
  196 + AlipayTradeRefundModel bizModel = (AlipayTradeRefundModel) request.getBizModel();
  197 + assertEquals(outRefundNo, bizModel.getOutRequestNo());
  198 + assertEquals(outTradeNo, bizModel.getOutTradeNo());
  199 + assertEquals(String.valueOf(refundAmount / 100.0), bizModel.getRefundAmount());
86 return true; 200 return true;
87 }))).thenReturn(response); 201 }))).thenReturn(response);
  202 + // 准备请求参数
  203 + PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
  204 + o.setOutRefundNo(outRefundNo);
  205 + o.setOutTradeNo(outTradeNo);
  206 + o.setNotifyUrl(notifyUrl);
  207 + o.setRefundPrice(refundAmount);
  208 + });
  209 + PayRefundRespDTO resp = client.unifiedRefund(refundReqDTO);
  210 + // 断言
  211 + assertEquals(PayRefundStatusRespEnum.SUCCESS.getStatus(), resp.getStatus());
  212 + assertNull(resp.getChannelRefundNo());
  213 + assertEquals(LocalDateTimeUtil.of(refundTime), resp.getSuccessTime());
  214 + assertEquals(outRefundNo, resp.getOutRefundNo());
  215 + assertSame(response, resp.getRawData());
  216 + }
88 217
  218 + @Test
  219 + @DisplayName("支付包扫描退款,渠道返回失败")
  220 + public void test_unified_refund_channel_failed() throws AlipayApiException {
  221 + // 准备返回对象
  222 + String notifyUrl = randomURL();
  223 + String subCode = randomString();
  224 + String subMsg = randomString();
  225 + AlipayTradeRefundResponse response = randomPojo(AlipayTradeRefundResponse.class, o -> {
  226 + o.setSubCode(subCode);
  227 + o.setSubMsg(subMsg);
  228 + });
  229 + // mock
  230 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> {
  231 + assertInstanceOf(AlipayTradeRefundModel.class, request.getBizModel());
  232 + return true;
  233 + }))).thenReturn(response);
  234 + // 准备请求参数
  235 + String outRefundNo = randomString();
  236 + String outTradeNo = randomString();
  237 + PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
  238 + o.setOutRefundNo(outRefundNo);
  239 + o.setOutTradeNo(outTradeNo);
  240 + o.setNotifyUrl(notifyUrl);
  241 + });
  242 + PayRefundRespDTO resp = client.unifiedRefund(refundReqDTO);
  243 + // 断言
  244 + assertEquals(PayRefundStatusRespEnum.FAILURE.getStatus(), resp.getStatus());
  245 + assertNull(resp.getChannelRefundNo());
  246 + assertEquals(subCode, resp.getChannelErrorCode());
  247 + assertEquals(subMsg, resp.getChannelErrorMsg());
  248 + assertNull(resp.getSuccessTime());
  249 + assertEquals(outRefundNo, resp.getOutRefundNo());
  250 + assertSame(response, resp.getRawData());
  251 + }
89 252
90 -// PayCommonResult<PayOrderUnifiedRespDTO> result = client.doUnifiedOrder(reqDTO);  
91 -// // 断言  
92 -// assertEquals(response.getCode(), result.getApiCode());  
93 -// assertEquals(response.getMsg(), result.getApiMsg());  
94 -// // TODO @tina:这个断言木有过?  
95 -// assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode());  
96 -// assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); 253 + @Test
  254 + @DisplayName("支付包扫描退款,参数校验不通过")
  255 + public void test_unified_refund_param_validate() {
  256 + // 准备请求参数
  257 + String notifyUrl = randomURL();
  258 + PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
  259 + o.setOutTradeNo("");
  260 + o.setNotifyUrl(notifyUrl);
  261 + });
  262 + // 断言
  263 + assertThrows(ConstraintViolationException.class, () -> client.unifiedRefund(refundReqDTO));
  264 + }
97 265
  266 + @Test
  267 + @DisplayName("支付包扫描退款,抛出业务异常")
  268 + public void test_unified_refund_throw_service_exception() throws AlipayApiException {
  269 + // mock
  270 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> true)))
  271 + .thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR));
  272 + // 准备请求参数
  273 + String notifyUrl = randomURL();
  274 + PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
  275 + o.setNotifyUrl(notifyUrl);
  276 + });
  277 + // 断言
  278 + assertThrows(ServiceException.class, () -> client.unifiedRefund(refundReqDTO));
  279 + }
  280 + @Test
  281 + @DisplayName("支付包扫描退款,抛出系统异常")
  282 + public void test_unified_refund_throw_pay_exception() throws AlipayApiException {
  283 + // mock
  284 + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> true)))
  285 + .thenThrow(new RuntimeException("系统异常"));
  286 + // 准备请求参数
  287 + String notifyUrl = randomURL();
  288 + PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
  289 + o.setNotifyUrl(notifyUrl);
  290 + });
  291 + // 断言
  292 + assertThrows(PayException.class, () -> client.unifiedRefund(refundReqDTO));
98 } 293 }
99 } 294 }
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -44,6 +44,12 @@ public interface BaseMapperX&lt;T&gt; extends BaseMapper&lt;T&gt; { @@ -44,6 +44,12 @@ public interface BaseMapperX&lt;T&gt; extends BaseMapper&lt;T&gt; {
44 return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)); 44 return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
45 } 45 }
46 46
  47 + default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
  48 + SFunction<T, ?> field3, Object value3) {
  49 + return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
  50 + .eq(field3, value3));
  51 + }
  52 +
47 default Long selectCount() { 53 default Long selectCount() {
48 return selectCount(new QueryWrapper<T>()); 54 return selectCount(new QueryWrapper<T>());
49 } 55 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java
1 package cn.iocoder.yudao.framework.jackson.core.databind; 1 package cn.iocoder.yudao.framework.jackson.core.databind;
2 2
3 import com.fasterxml.jackson.core.JsonParser; 3 import com.fasterxml.jackson.core.JsonParser;
4 -import com.fasterxml.jackson.core.JsonProcessingException;  
5 import com.fasterxml.jackson.databind.DeserializationContext; 4 import com.fasterxml.jackson.databind.DeserializationContext;
6 import com.fasterxml.jackson.databind.JsonDeserializer; 5 import com.fasterxml.jackson.databind.JsonDeserializer;
7 6
@@ -20,7 +19,7 @@ public class LocalDateTimeDeserializer extends JsonDeserializer&lt;LocalDateTime&gt; { @@ -20,7 +19,7 @@ public class LocalDateTimeDeserializer extends JsonDeserializer&lt;LocalDateTime&gt; {
20 public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer(); 19 public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer();
21 20
22 @Override 21 @Override
23 - public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { 22 + public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
24 return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault()); 23 return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
25 } 24 }
26 } 25 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java deleted
1 -package cn.iocoder.yudao.framework.jackson.core.databind;  
2 -  
3 -import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;  
4 -import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;  
5 -  
6 -import java.time.ZoneId;  
7 -import java.time.format.DateTimeFormatter;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;  
10 -  
11 -public class LocalTimeJson {  
12 -  
13 - public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter  
14 - .ofPattern(FORMAT_HOUR_MINUTE_SECOND)  
15 - .withZone(ZoneId.systemDefault()));  
16 -  
17 - public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter  
18 - .ofPattern(FORMAT_HOUR_MINUTE_SECOND)  
19 - .withZone(ZoneId.systemDefault()));  
20 -  
21 -}  
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.app.file;
  2 +
  3 +import cn.hutool.core.io.IoUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.module.infra.controller.app.file.vo.AppFileUploadReqVO;
  6 +import cn.iocoder.yudao.module.infra.service.file.FileService;
  7 +import io.swagger.v3.oas.annotations.Operation;
  8 +import io.swagger.v3.oas.annotations.tags.Tag;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.validation.annotation.Validated;
  11 +import org.springframework.web.bind.annotation.PostMapping;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RestController;
  14 +import org.springframework.web.multipart.MultipartFile;
  15 +
  16 +import javax.annotation.Resource;
  17 +
  18 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  19 +
  20 +@Tag(name = "用户 App - 文件存储")
  21 +@RestController
  22 +@RequestMapping("/infra/file")
  23 +@Validated
  24 +@Slf4j
  25 +public class AppFileController {
  26 +
  27 + @Resource
  28 + private FileService fileService;
  29 +
  30 + @PostMapping("/upload")
  31 + @Operation(summary = "上传文件")
  32 + public CommonResult<String> uploadFile(AppFileUploadReqVO uploadReqVO) throws Exception {
  33 + MultipartFile file = uploadReqVO.getFile();
  34 + String path = uploadReqVO.getPath();
  35 + return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
  36 + }
  37 +
  38 +}
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.app.file.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.web.multipart.MultipartFile;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@Schema(description = "用户 App - 上传文件 Request VO")
  10 +@Data
  11 +public class AppFileUploadReqVO {
  12 +
  13 + @Schema(description = "文件附件", requiredMode = Schema.RequiredMode.REQUIRED)
  14 + @NotNull(message = "文件附件不能为空")
  15 + private MultipartFile file;
  16 +
  17 + @Schema(description = "文件附件", example = "yudaoyuanma.png")
  18 + private String path;
  19 +
  20 +}
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
@@ -120,7 +120,6 @@ @@ -120,7 +120,6 @@
120 <!-- 列表 --> 120 <!-- 列表 -->
121 <ContentWrap> 121 <ContentWrap>
122 <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> 122 <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
123 - <el-table-column label="序号" type="index" width="70px" />  
124 #foreach($column in $columns) 123 #foreach($column in $columns)
125 #if ($column.listOperationResult) 124 #if ($column.listOperationResult)
126 #set ($dictType=$column.dictType) 125 #set ($dictType=$column.dictType)
@@ -142,7 +141,7 @@ @@ -142,7 +141,7 @@
142 </template> 141 </template>
143 </el-table-column> 142 </el-table-column>
144 #else 143 #else
145 - <el-table-column label="${comment}" align="center" prop="${javaField}" width="150px"/> 144 + <el-table-column label="${comment}" align="center" prop="${javaField}" width="150px" />
146 #end 145 #end
147 #end 146 #end
148 #end 147 #end
@@ -180,7 +179,7 @@ @@ -180,7 +179,7 @@
180 <${simpleClassName}Form ref="formRef" @success="getList" /> 179 <${simpleClassName}Form ref="formRef" @success="getList" />
181 </template> 180 </template>
182 181
183 -<script setup lang="ts" name="${table.className}"> 182 +<script setup lang="ts">
184 #if ($dictMethods.size() > 0) 183 #if ($dictMethods.size() > 0)
185 import { DICT_TYPE#foreach ($dictMethod in $dictMethods), ${dictMethod}#end } from '@/utils/dict' 184 import { DICT_TYPE#foreach ($dictMethod in $dictMethods), ${dictMethod}#end } from '@/utils/dict'
186 #end 185 #end
@@ -193,6 +192,9 @@ import { dateFormatter } from &#39;@/utils/formatTime&#39; @@ -193,6 +192,9 @@ import { dateFormatter } from &#39;@/utils/formatTime&#39;
193 import download from '@/utils/download' 192 import download from '@/utils/download'
194 import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}' 193 import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
195 import ${simpleClassName}Form from './${simpleClassName}Form.vue' 194 import ${simpleClassName}Form from './${simpleClassName}Form.vue'
  195 +
  196 +defineOptions({ name: '${table.className}' })
  197 +
196 const message = useMessage() // 消息弹窗 198 const message = useMessage() // 消息弹窗
197 const { t } = useI18n() // 国际化 199 const { t } = useI18n() // 国际化
198 200
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
@@ -21,4 +21,11 @@ public interface ProductSpuApi { @@ -21,4 +21,11 @@ public interface ProductSpuApi {
21 */ 21 */
22 List<ProductSpuRespDTO> getSpuList(Collection<Long> ids); 22 List<ProductSpuRespDTO> getSpuList(Collection<Long> ids);
23 23
  24 + /**
  25 + * 获得 SPU
  26 + *
  27 + * @return SPU
  28 + */
  29 + ProductSpuRespDTO getSpu(Long id);
  30 +
24 } 31 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
@@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -5,6 +5,8 @@ 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; 6 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
7 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; 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;
8 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
9 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
10 12
@@ -24,15 +26,19 @@ import java.util.List; @@ -24,15 +26,19 @@ import java.util.List;
24 public class ProductSpuApiImpl implements ProductSpuApi { 26 public class ProductSpuApiImpl implements ProductSpuApi {
25 27
26 @Resource 28 @Resource
27 - private ProductSpuMapper productSpuMapper; 29 + private ProductSpuService spuService;
28 30
29 @Override 31 @Override
30 - public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {  
31 - if (CollectionUtil.isEmpty(spuIds)) { 32 + public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
  33 + if (CollectionUtil.isEmpty(ids)) {
32 return Collections.emptyList(); 34 return Collections.emptyList();
33 } 35 }
34 - List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds);  
35 - return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList); 36 + return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
  37 + }
  38 +
  39 + @Override
  40 + public ProductSpuRespDTO getSpu(Long id) {
  41 + return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id));
36 } 42 }
37 43
38 } 44 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
@@ -3,16 +3,13 @@ package cn.iocoder.yudao.module.product.controller.app.comment; @@ -3,16 +3,13 @@ package cn.iocoder.yudao.module.product.controller.app.comment;
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.framework.common.util.collection.CollectionUtils;  
7 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; 6 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; 7 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
9 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; 8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
10 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; 9 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
11 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 10 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
12 -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;  
13 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; 11 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
14 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 12 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
15 -import com.google.common.collect.Maps;  
16 import io.swagger.v3.oas.annotations.Operation; 13 import io.swagger.v3.oas.annotations.Operation;
17 import io.swagger.v3.oas.annotations.Parameter; 14 import io.swagger.v3.oas.annotations.Parameter;
18 import io.swagger.v3.oas.annotations.Parameters; 15 import io.swagger.v3.oas.annotations.Parameters;
@@ -27,10 +24,10 @@ import org.springframework.web.bind.annotation.RestController; @@ -27,10 +24,10 @@ import org.springframework.web.bind.annotation.RestController;
27 import javax.annotation.Resource; 24 import javax.annotation.Resource;
28 import javax.validation.Valid; 25 import javax.validation.Valid;
29 import java.util.List; 26 import java.util.List;
30 -import java.util.Map;  
31 import java.util.Set; 27 import java.util.Set;
32 28
33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 29 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
34 31
35 @Tag(name = "用户 APP - 商品评价") 32 @Tag(name = "用户 APP - 商品评价")
36 @RestController 33 @RestController
@@ -60,16 +57,17 @@ public class AppProductCommentController { @@ -60,16 +57,17 @@ public class AppProductCommentController {
60 @GetMapping("/page") 57 @GetMapping("/page")
61 @Operation(summary = "获得商品评价分页") 58 @Operation(summary = "获得商品评价分页")
62 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { 59 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
63 - // TODO @puhui999:写到 convert 里,可以更简洁哈。  
64 - PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);  
65 - Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);  
66 - List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);  
67 - Map<Long, ProductSkuDO> skuDOMap = Maps.newLinkedHashMapWithExpectedSize(skuIds.size());  
68 - if (CollUtil.isNotEmpty(skuList)) {  
69 - skuDOMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId, c -> c)); 60 + // 查询评论分页
  61 + PageResult<ProductCommentDO> commentPageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
  62 + if (CollUtil.isEmpty(commentPageResult.getList())) {
  63 + return success(PageResult.empty(commentPageResult.getTotal()));
70 } 64 }
71 - PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, skuDOMap);  
72 - return success(page); 65 +
  66 + // 拼接返回
  67 + Set<Long> skuIds = convertSet(commentPageResult.getList(), ProductCommentDO::getSkuId);
  68 + PageResult<AppProductCommentRespVO> commentVOPageResult = ProductCommentConvert.INSTANCE.convertPage02(
  69 + commentPageResult, productSkuService.getSkuList(skuIds));
  70 + return success(commentVOPageResult);
73 } 71 }
74 72
75 // TODO 芋艿:需要搞下 73 // TODO 芋艿:需要搞下
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java
@@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.*; @@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.*;
20 import javax.annotation.Resource; 20 import javax.annotation.Resource;
21 import javax.validation.Valid; 21 import javax.validation.Valid;
22 import java.util.List; 22 import java.util.List;
23 -import java.util.Objects;  
24 23
25 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
26 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 25 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -84,8 +83,15 @@ public class AppFavoriteController { @@ -84,8 +83,15 @@ public class AppFavoriteController {
84 @Operation(summary = "检查是否收藏过商品") 83 @Operation(summary = "检查是否收藏过商品")
85 @PreAuthenticated 84 @PreAuthenticated
86 public CommonResult<Boolean> isFavoriteExists(AppFavoriteReqVO reqVO) { 85 public CommonResult<Boolean> isFavoriteExists(AppFavoriteReqVO reqVO) {
87 - ProductFavoriteDO favoriteDO = productFavoriteService.getFavorite(getLoginUserId(), reqVO.getSpuId());  
88 - return success(Objects.nonNull(favoriteDO)); 86 + ProductFavoriteDO favorite = productFavoriteService.getFavorite(getLoginUserId(), reqVO.getSpuId());
  87 + return success(favorite != null);
  88 + }
  89 +
  90 + @GetMapping(value = "/get-count")
  91 + @Operation(summary = "获得商品收藏数量")
  92 + @PreAuthenticated
  93 + public CommonResult<Long> getFavoriteCount() {
  94 + return success(productFavoriteService.getFavoriteCount(getLoginUserId()));
89 } 95 }
90 96
91 } 97 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.convert.comment; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.convert.comment;
2 2
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 7 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 8 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
@@ -37,11 +38,12 @@ public interface ProductCommentConvert { @@ -37,11 +38,12 @@ public interface ProductCommentConvert {
37 38
38 @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))") 39 @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))")
39 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount); 40 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount);
  41 +
40 @Named("calculateOverallScore") 42 @Named("calculateOverallScore")
41 default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) { 43 default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) {
42 return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount); 44 return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount);
43 } 45 }
44 - 46 +
45 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list); 47 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
46 48
47 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page); 49 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
@@ -49,18 +51,21 @@ public interface ProductCommentConvert { @@ -49,18 +51,21 @@ public interface ProductCommentConvert {
49 PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult); 51 PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
50 52
51 default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult, 53 default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult,
52 - Map<Long, ProductSkuDO> skuMap) { 54 + List<ProductSkuDO> skuList) {
  55 + Map<Long, ProductSkuDO> skuMap = CollectionUtils.convertMap(skuList, ProductSkuDO::getId);
53 PageResult<AppProductCommentRespVO> page = convertPage01(pageResult); 56 PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
54 page.getList().forEach(item -> { 57 page.getList().forEach(item -> {
55 // 判断用户是否选择匿名 58 // 判断用户是否选择匿名
56 if (ObjectUtil.equal(item.getAnonymous(), true)) { 59 if (ObjectUtil.equal(item.getAnonymous(), true)) {
57 item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS); 60 item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
58 } 61 }
  62 + // 设置 SKU 规格值
59 MapUtils.findAndThen(skuMap, item.getSkuId(), 63 MapUtils.findAndThen(skuMap, item.getSkuId(),
60 sku -> item.setSkuProperties(convertList01(sku.getProperties()))); 64 sku -> item.setSkuProperties(convertList01(sku.getProperties())));
61 }); 65 });
62 return page; 66 return page;
63 } 67 }
  68 +
64 List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties); 69 List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);
65 70
66 /** 71 /**
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
1 package cn.iocoder.yudao.module.product.convert.spu; 1 package cn.iocoder.yudao.module.product.convert.spu;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; 5 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 6 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 7 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
@@ -63,6 +64,8 @@ public interface ProductSpuConvert { @@ -63,6 +64,8 @@ public interface ProductSpuConvert {
63 64
64 ProductSpuDetailRespVO convert03(ProductSpuDO spu); 65 ProductSpuDetailRespVO convert03(ProductSpuDO spu);
65 66
  67 + ProductSpuRespDTO convert02(ProductSpuDO bean);
  68 +
66 // ========== 用户 App 相关 ========== 69 // ========== 用户 App 相关 ==========
67 70
68 PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page); 71 PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page);
@@ -81,6 +84,7 @@ public interface ProductSpuConvert { @@ -81,6 +84,7 @@ public interface ProductSpuConvert {
81 } 84 }
82 return voList; 85 return voList;
83 } 86 }
  87 +
84 @Named("convertListForGetSpuList0") 88 @Named("convertListForGetSpuList0")
85 List<AppProductSpuPageRespVO> convertListForGetSpuList0(List<ProductSpuDO> list); 89 List<AppProductSpuPageRespVO> convertListForGetSpuList0(List<ProductSpuDO> list);
86 90
@@ -110,15 +114,9 @@ public interface ProductSpuConvert { @@ -110,15 +114,9 @@ public interface ProductSpuConvert {
110 } 114 }
111 115
112 default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) { 116 default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
113 - List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size());  
114 Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId); 117 Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
115 - // TODO @puhui999:可以直接使用 CollUtils.convertList  
116 - spus.forEach(spu -> {  
117 - ProductSpuDetailRespVO detailRespVO = convert03(spu);  
118 - detailRespVO.setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())));  
119 - vos.add(detailRespVO);  
120 - });  
121 - return vos; 118 + return CollectionUtils.convertList(spus, spu -> convert03(spu)
  119 + .setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId()))));
122 } 120 }
123 121
124 } 122 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
@@ -26,18 +26,19 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; { @@ -26,18 +26,19 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; {
26 } 26 }
27 27
28 static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) { 28 static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
29 - // TODO @puhui999:是不是不用 apply 拉?直接用 mybatis 的方法就好啦 29 + LambdaQueryWrapperX<ProductCommentDO> queryWrapperX = new LambdaQueryWrapperX<>();
30 // 构建好评查询语句:好评计算 总评 >= 4 30 // 构建好评查询语句:好评计算 总评 >= 4
31 if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) { 31 if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
32 - queryWrapper.apply("scores >= 4"); 32 + queryWrapperX.ge(ProductCommentDO::getScores, 4);
33 } 33 }
34 // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4 34 // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4
35 if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) { 35 if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) {
36 - queryWrapper.apply("scores >=3 and scores < 4"); 36 + queryWrapperX.ge(ProductCommentDO::getScores, 3);
  37 + queryWrapperX.lt(ProductCommentDO::getScores, 4);
37 } 38 }
38 // 构建差评查询语句:差评计算 总评 < 3 39 // 构建差评查询语句:差评计算 总评 < 3
39 if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) { 40 if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) {
40 - queryWrapper.apply("scores < 3"); 41 + queryWrapperX.lt(ProductCommentDO::getScores, 3);
41 } 42 }
42 } 43 }
43 44
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/favorite/ProductFavoriteMapper.java
@@ -21,4 +21,8 @@ public interface ProductFavoriteMapper extends BaseMapperX&lt;ProductFavoriteDO&gt; { @@ -21,4 +21,8 @@ public interface ProductFavoriteMapper extends BaseMapperX&lt;ProductFavoriteDO&gt; {
21 .orderByDesc(ProductFavoriteDO::getId)); 21 .orderByDesc(ProductFavoriteDO::getId));
22 } 22 }
23 23
  24 + default Long selectCountByUserId(Long userId) {
  25 + return selectCount(ProductFavoriteDO::getUserId, userId);
  26 + }
  27 +
24 } 28 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteService.java
@@ -16,7 +16,7 @@ public interface ProductFavoriteService { @@ -16,7 +16,7 @@ public interface ProductFavoriteService {
16 /** 16 /**
17 * 创建商品收藏 17 * 创建商品收藏
18 * 18 *
19 - * @param userId 用户 id 19 + * @param userId 用户编号
20 * @param spuId SPU 编号 20 * @param spuId SPU 编号
21 */ 21 */
22 Long createFavorite(Long userId, Long spuId); 22 Long createFavorite(Long userId, Long spuId);
@@ -24,7 +24,7 @@ public interface ProductFavoriteService { @@ -24,7 +24,7 @@ public interface ProductFavoriteService {
24 /** 24 /**
25 * 取消商品收藏 25 * 取消商品收藏
26 * 26 *
27 - * @param userId 用户 id 27 + * @param userId 用户编号
28 * @param spuId SPU 编号 28 * @param spuId SPU 编号
29 */ 29 */
30 void deleteFavorite(Long userId, Long spuId); 30 void deleteFavorite(Long userId, Long spuId);
@@ -32,7 +32,7 @@ public interface ProductFavoriteService { @@ -32,7 +32,7 @@ public interface ProductFavoriteService {
32 /** 32 /**
33 * 分页查询用户收藏列表 33 * 分页查询用户收藏列表
34 * 34 *
35 - * @param userId 用户 id 35 + * @param userId 用户编号
36 * @param reqVO 请求 vo 36 * @param reqVO 请求 vo
37 */ 37 */
38 PageResult<ProductFavoriteDO> getFavoritePage(Long userId, @Valid AppFavoritePageReqVO reqVO); 38 PageResult<ProductFavoriteDO> getFavoritePage(Long userId, @Valid AppFavoritePageReqVO reqVO);
@@ -40,9 +40,17 @@ public interface ProductFavoriteService { @@ -40,9 +40,17 @@ public interface ProductFavoriteService {
40 /** 40 /**
41 * 获取收藏过商品 41 * 获取收藏过商品
42 * 42 *
43 - * @param userId 用户id 43 + * @param userId 用户编号
44 * @param spuId SPU 编号 44 * @param spuId SPU 编号
45 */ 45 */
46 ProductFavoriteDO getFavorite(Long userId, Long spuId); 46 ProductFavoriteDO getFavorite(Long userId, Long spuId);
47 47
  48 + /**
  49 + * 获取用户收藏数量
  50 + *
  51 + * @param userId 用户编号
  52 + * @return 数量
  53 + */
  54 + Long getFavoriteCount(Long userId);
  55 +
48 } 56 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/favorite/ProductFavoriteServiceImpl.java
@@ -10,7 +10,6 @@ import org.springframework.validation.annotation.Validated; @@ -10,7 +10,6 @@ import org.springframework.validation.annotation.Validated;
10 10
11 import javax.annotation.Resource; 11 import javax.annotation.Resource;
12 import javax.validation.Valid; 12 import javax.validation.Valid;
13 -import java.util.Objects;  
14 13
15 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 14 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
16 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.FAVORITE_EXISTS; 15 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.FAVORITE_EXISTS;
@@ -31,7 +30,7 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { @@ -31,7 +30,7 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService {
31 @Override 30 @Override
32 public Long createFavorite(Long userId, Long spuId) { 31 public Long createFavorite(Long userId, Long spuId) {
33 ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); 32 ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId);
34 - if (Objects.nonNull(favorite)) { 33 + if (favorite != null) {
35 throw exception(FAVORITE_EXISTS); 34 throw exception(FAVORITE_EXISTS);
36 } 35 }
37 36
@@ -43,7 +42,7 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { @@ -43,7 +42,7 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService {
43 @Override 42 @Override
44 public void deleteFavorite(Long userId, Long spuId) { 43 public void deleteFavorite(Long userId, Long spuId) {
45 ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); 44 ProductFavoriteDO favorite = productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId);
46 - if (Objects.isNull(favorite)) { 45 + if (favorite == null) {
47 throw exception(FAVORITE_NOT_EXISTS); 46 throw exception(FAVORITE_NOT_EXISTS);
48 } 47 }
49 48
@@ -60,4 +59,9 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService { @@ -60,4 +59,9 @@ public class ProductFavoriteServiceImpl implements ProductFavoriteService {
60 return productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId); 59 return productFavoriteMapper.selectByUserIdAndSpuId(userId, spuId);
61 } 60 }
62 61
  62 + @Override
  63 + public Long getFavoriteCount(Long userId) {
  64 + return productFavoriteMapper.selectCountByUserId(userId);
  65 + }
  66 +
63 } 67 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.bargain;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.bargain.dto.BargainRecordCreateReqDTO;
  4 +
  5 +import javax.validation.Valid;
  6 +
  7 +// TODO @芋艿:后面也再撸撸这几个接口
  8 +
  9 +/**
  10 + * 砍价记录 API 接口
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +public interface BargainRecordApi {
  15 +
  16 + /**
  17 + * 创建砍价记录
  18 + *
  19 + * @param reqDTO 请求 DTO
  20 + */
  21 + void createBargainRecord(@Valid BargainRecordCreateReqDTO reqDTO);
  22 +
  23 + /**
  24 + * 查询砍价是否成功
  25 + *
  26 + * @param userId 用户编号
  27 + * @param orderId 订单编号
  28 + * @return 砍价是否成功
  29 + */
  30 + boolean isBargainRecordSuccess(Long userId, Long orderId);
  31 +
  32 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.bargain.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +// TODO @芋艿:这块要在看看
  9 +
  10 +/**
  11 + * 砍价记录的创建 Request DTO
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Data
  16 +public class BargainRecordCreateReqDTO {
  17 +
  18 + /**
  19 + * 砍价活动编号
  20 + */
  21 + @NotNull(message = "砍价活动编号不能为空")
  22 + private Long activityId;
  23 + /**
  24 + * spu 编号
  25 + */
  26 + @NotNull(message = "spu 编号不能为空")
  27 + private Long spuId;
  28 + /**
  29 + * sku 编号
  30 + */
  31 + @NotNull(message = "sku 编号不能为空")
  32 + private Long skuId;
  33 + /**
  34 + * 用户编号
  35 + */
  36 + @NotNull(message = "用户编号不能为空")
  37 + private Long userId;
  38 + /**
  39 + * 订单编号
  40 + */
  41 + @NotNull(message = "订单编号不能为空")
  42 + private Long orderId;
  43 + // TODO @puhui999:spuName、picUrl、 之类字段不用传递;
  44 + /**
  45 + * 商品名字
  46 + */
  47 + @NotEmpty(message = "商品名字不能为空")
  48 + private String spuName;
  49 + /**
  50 + * 商品图片
  51 + */
  52 + @NotEmpty(message = "商品图片不能为空")
  53 + private String picUrl;
  54 + /**
  55 + * 砍价商品单价
  56 + */
  57 + @NotNull(message = "砍价底价不能为空")
  58 + private Integer bargainPrice;
  59 + /**
  60 + * 商品原价,单位分
  61 + */
  62 + @NotNull(message = "商品原价不能为空")
  63 + private Integer price;
  64 + // TODO @puhui999:nickname、avatar 不用传递,去查询;
  65 + /**
  66 + * 用户昵称
  67 + */
  68 + @NotEmpty(message = "用户昵称不能为空")
  69 + private String nickname;
  70 + /**
  71 + * 用户头像
  72 + */
  73 + @NotEmpty(message = "用户头像不能为空")
  74 + private String avatar;
  75 + /**
  76 + * 开团状态:进行中 砍价成功 砍价失败
  77 + */
  78 + @NotNull(message = "开团状态不能为空")
  79 + private Integer status;
  80 +
  81 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java renamed to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
1 package cn.iocoder.yudao.module.promotion.api.combination; 1 package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO; 3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  4 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
  5 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
4 6
5 import javax.validation.Valid; 7 import javax.validation.Valid;
  8 +import java.util.List;
6 9
7 -// TODO @puhui999:CombinationRecordApi 分成活动、记录哈  
8 // TODO @芋艿:后面也再撸撸这几个接口 10 // TODO @芋艿:后面也再撸撸这几个接口
  11 +
9 /** 12 /**
10 - * 拼团活动 API 接口 13 + * 拼团记录 API 接口
11 * 14 *
12 * @author HUIHUI 15 * @author HUIHUI
13 */ 16 */
14 -public interface CombinationApi { 17 +public interface CombinationRecordApi {
15 18
16 /** 19 /**
17 * 创建开团记录 20 * 创建开团记录
18 * 21 *
19 * @param reqDTO 请求 DTO 22 * @param reqDTO 请求 DTO
20 */ 23 */
21 - void createRecord(@Valid CombinationRecordReqDTO reqDTO); 24 + void createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO);
22 25
23 /** 26 /**
24 - * 获取开团记录状态 27 + * 查询拼团记录是否成功
25 * 28 *
26 * @param userId 用户编号 29 * @param userId 用户编号
27 * @param orderId 订单编号 30 * @param orderId 订单编号
  31 + * @return 拼团是否成功
28 */ 32 */
29 - boolean validateRecordStatusIsSuccess(Long userId, Long orderId); 33 + boolean isCombinationRecordSuccess(Long userId, Long orderId);
30 34
31 /** 35 /**
32 - * 更新开团记录状态 36 + * 获取拼团记录
33 * 37 *
34 - * @param userId 用户编号  
35 - * @param orderId 订单编号  
36 - * @param status 状态值 38 + * @param userId 用户编号
  39 + * @param activityId 活动编号
  40 + * @return 拼团记录列表
37 */ 41 */
38 - void updateRecordStatus(Long userId, Long orderId, Integer status); 42 + List<CombinationRecordRespDTO> getRecordListByUserIdAndActivityId(Long userId, Long activityId);
39 43
40 /** 44 /**
41 - * 更新开团记录状态和开始时间 45 + * 验证组合限制数
  46 + * 校验是否满足限购要求
42 * 47 *
43 - * @param userId 用户编号  
44 - * @param orderId 订单编号  
45 - * @param status 状态值 48 + * @param count 本次购买数量
  49 + * @param sumCount 已购买数量合计
  50 + * @param activityId 活动编号
  51 + */
  52 + void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount);
  53 +
  54 + // TODO @puhui999:是不是搞成具体的方法,拼团成功,拼团失败,这种方法;
  55 +
  56 + /**
  57 + * 更新开团记录状态
  58 + *
  59 + * @param reqDTO 请求 DTO
46 */ 60 */
47 - void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status); 61 + void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO);
48 62
49 } 63 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java renamed to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
@@ -5,14 +5,14 @@ import lombok.Data; @@ -5,14 +5,14 @@ import lombok.Data;
5 import javax.validation.constraints.NotEmpty; 5 import javax.validation.constraints.NotEmpty;
6 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
7 7
8 -// TODO @puhui999:CombinationRecordCreateReqDTO,这样更容易知道是创建噢 8 +// TODO @芋艿:这块要在看看
9 /** 9 /**
10 - * 拼团记录 Request DTO 10 + * 拼团记录的创建 Request DTO
11 * 11 *
12 * @author HUIHUI 12 * @author HUIHUI
13 */ 13 */
14 @Data 14 @Data
15 -public class CombinationRecordReqDTO { 15 +public class CombinationRecordCreateReqDTO {
16 16
17 /** 17 /**
18 * 拼团活动编号 18 * 拼团活动编号
@@ -70,7 +70,7 @@ public class CombinationRecordReqDTO { @@ -70,7 +70,7 @@ public class CombinationRecordReqDTO {
70 @NotEmpty(message = "用户头像不能为空") 70 @NotEmpty(message = "用户头像不能为空")
71 private String avatar; 71 private String avatar;
72 /** 72 /**
73 - * 开团状态:正在开团 拼团成功 拼团失败 TODO 等待支付 73 + * 开团状态:正在开团 拼团成功 拼团失败
74 */ 74 */
75 @NotNull(message = "开团状态不能为空") 75 @NotNull(message = "开团状态不能为空")
76 private Integer status; 76 private Integer status;
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination.dto;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * 拼团记录 Response DTO
  8 + *
  9 + * @author HUIHUI
  10 + */
  11 +@Data
  12 +public class CombinationRecordRespDTO {
  13 +
  14 + /**
  15 + * 拼团活动编号
  16 + */
  17 + private Long activityId;
  18 + /**
  19 + * SPU 编号
  20 + */
  21 + private Long spuId;
  22 + /**
  23 + * SKU 编号
  24 + */
  25 + private Long skuId;
  26 + /**
  27 + * 用户编号
  28 + */
  29 + private Long userId;
  30 + /**
  31 + * 订单编号
  32 + */
  33 + private Long orderId;
  34 + /**
  35 + * 开团状态
  36 + *
  37 + * 枚举 {@link CombinationRecordStatusEnum}
  38 + */
  39 + private Integer status;
  40 +
  41 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotNull;
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * 拼团记录的更新状态 Request DTO
  10 + *
  11 + * @author HUIHUI
  12 + */
  13 +@Data
  14 +public class CombinationRecordUpdateStatusReqDTO {
  15 +
  16 + /**
  17 + * 用户编号
  18 + */
  19 + @NotNull(message = "用户编号不能为空")
  20 + private Long userId;
  21 +
  22 + /**
  23 + * 订单编号
  24 + */
  25 + @NotNull(message = "订单编号不能为空")
  26 + private Long orderId;
  27 +
  28 + /**
  29 + * 开团状态:正在开团 拼团成功 拼团失败
  30 + */
  31 + @NotNull(message = "开团状态不能为空")
  32 + private Integer status;
  33 +
  34 + /**
  35 + * 团开始时间
  36 + */
  37 + private LocalDateTime startTime;
  38 +
  39 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -50,14 +50,11 @@ public interface ErrorCodeConstants { @@ -50,14 +50,11 @@ public interface ErrorCodeConstants {
50 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); 50 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
51 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); 51 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
52 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); 52 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
53 - ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013008006, "秒杀活动已结束,不能关闭");  
54 53
55 // ========== 秒杀时段 1013009000 ========== 54 // ========== 秒杀时段 1013009000 ==========
56 - ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");  
57 - ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");  
58 - ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");  
59 - ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");  
60 - ErrorCode SECKILL_TIME_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭"); 55 + ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
  56 + ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
  57 + ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
61 58
62 // ========== 拼团活动 1013010000 ========== 59 // ========== 拼团活动 1013010000 ==========
63 ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); 60 ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
@@ -66,4 +63,25 @@ public interface ErrorCodeConstants { @@ -66,4 +63,25 @@ public interface ErrorCodeConstants {
66 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除"); 63 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
67 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在"); 64 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在");
68 65
  66 + // ========== 拼团记录 1013011000 ==========
  67 + ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011000, "拼团失败,已参与过该拼团");
  68 + ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011001, "拼团失败,父拼团不存在");
  69 + ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011002, "拼团失败,拼团人数已满");
  70 + ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011003, "拼团失败,已参与其它拼团");
  71 + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011004, "拼团失败,活动已经结束");
  72 + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011005, "拼团失败,单次限购超出");
  73 + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,单次限购超出");
  74 +
  75 + // ========== 砍价活动 1013012000 ==========
  76 + ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
  77 + ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
  78 + ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
  79 + ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
  80 +
  81 + // ========== 砍价记录 1013013000 ==========
  82 + ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在");
  83 + ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1013013001, "砍价失败,已参与过该砍价");
  84 + ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013013002, "砍价失败,父砍价不存在");
  85 + ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1013013003, "砍价失败,砍价人数已满");
  86 +
69 } 87 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
1 package cn.iocoder.yudao.module.promotion.enums.combination; 1 package cn.iocoder.yudao.module.promotion.enums.combination;
2 2
  3 +import cn.hutool.core.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable; 4 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.AllArgsConstructor; 5 import lombok.AllArgsConstructor;
5 import lombok.Getter; 6 import lombok.Getter;
@@ -15,10 +16,9 @@ import java.util.Arrays; @@ -15,10 +16,9 @@ import java.util.Arrays;
15 @Getter 16 @Getter
16 public enum CombinationRecordStatusEnum implements IntArrayValuable { 17 public enum CombinationRecordStatusEnum implements IntArrayValuable {
17 18
18 - WAITING(0, "未付款"),  
19 - IN_PROGRESS(1, "进行中"),  
20 - SUCCESS(2, "拼团成功"),  
21 - FAILED(3, "拼团失败"); 19 + IN_PROGRESS(0, "进行中"),
  20 + SUCCESS(1, "拼团成功"),
  21 + FAILED(2, "拼团失败");
22 22
23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CombinationRecordStatusEnum::getStatus).toArray(); 23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CombinationRecordStatusEnum::getStatus).toArray();
24 24
@@ -36,4 +36,8 @@ public enum CombinationRecordStatusEnum implements IntArrayValuable { @@ -36,4 +36,8 @@ public enum CombinationRecordStatusEnum implements IntArrayValuable {
36 return ARRAYS; 36 return ARRAYS;
37 } 37 }
38 38
  39 + public static boolean isSuccess(Integer status) {
  40 + return ObjectUtil.equal(status, SUCCESS.getStatus());
  41 + }
  42 +
39 } 43 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/decorate/DecorateComponentEnum.java
1 package cn.iocoder.yudao.module.promotion.enums.decorate; 1 package cn.iocoder.yudao.module.promotion.enums.decorate;
2 2
  3 +import lombok.AllArgsConstructor;
3 import lombok.Getter; 4 import lombok.Getter;
4 5
5 /** 6 /**
@@ -8,11 +9,44 @@ import lombok.Getter; @@ -8,11 +9,44 @@ import lombok.Getter;
8 * @author jason 9 * @author jason
9 */ 10 */
10 @Getter 11 @Getter
  12 +@AllArgsConstructor
  13 +@SuppressWarnings("JavadocLinkAsPlainText")
11 public enum DecorateComponentEnum { 14 public enum DecorateComponentEnum {
12 15
13 - NAV_MENU("nav-menu", "导航菜单"),  
14 - ROLLING_BANNER("rolling-banner", "滚动横幅广告"),  
15 - PRODUCT_CATEGORY("product-category", "商品分类"); 16 + /**
  17 + * 格式:[{
  18 + * "name": "标题"
  19 + * "picUrl": "https://www.iocoder.cn/xxx.png",
  20 + * "url": "/pages/users/index"
  21 + * }]
  22 + *
  23 + * 最多 10 个
  24 + */
  25 + MENU("menu", "菜单"),
  26 + /**
  27 + * 格式:[{
  28 + * "name": "标题"
  29 + * "url": "/pages/users/index"
  30 + * }]
  31 + */
  32 + ROLLING_NEWS("scrolling-news", "滚动新闻"),
  33 + /**
  34 + * 格式:[{
  35 + * "picUrl": "https://www.iocoder.cn/xxx.png",
  36 + * "url": "/pages/users/index"
  37 + * }]
  38 + */
  39 + SLIDE_SHOW("slide-show", "轮播图"),
  40 + /**
  41 + * 格式:[{
  42 + * "name": "标题"
  43 + * "type": "类型", // best、hot、new、benefit、good
  44 + * "tag": "标签" // 例如说:多买多省
  45 + * }]
  46 + *
  47 + * 最多 4 个
  48 + */
  49 + PRODUCT_RECOMMEND("product-recommend", "商品推荐");
16 50
17 /** 51 /**
18 * 页面组件代码 52 * 页面组件代码
@@ -24,9 +58,4 @@ public enum DecorateComponentEnum { @@ -24,9 +58,4 @@ public enum DecorateComponentEnum {
24 */ 58 */
25 private final String desc; 59 private final String desc;
26 60
27 - DecorateComponentEnum(String code, String desc) {  
28 - this.code = code;  
29 - this.desc = desc;  
30 - }  
31 -  
32 } 61 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/decorate/DecoratePageEnum.java
@@ -15,14 +15,17 @@ import java.util.Arrays; @@ -15,14 +15,17 @@ import java.util.Arrays;
15 @Getter 15 @Getter
16 public enum DecoratePageEnum implements IntArrayValuable { 16 public enum DecoratePageEnum implements IntArrayValuable {
17 17
18 - INDEX(1, "首页"); 18 + INDEX(1, "首页"),
  19 + MY(2, "个人中心"),
  20 + ;
19 21
20 - private static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DecoratePageEnum::getId).toArray(); 22 + private static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DecoratePageEnum::getPage).toArray();
21 23
22 /** 24 /**
23 - * 页面 id 25 + * 页面编号
24 */ 26 */
25 - private final Integer id; 27 + private final Integer page;
  28 +
26 /** 29 /**
27 * 页面名称 30 * 页面名称
28 */ 31 */
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.bargain;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.bargain.dto.BargainRecordCreateReqDTO;
  4 +import org.springframework.stereotype.Service;
  5 +
  6 +/**
  7 + * 砍价活动 API 实现类 TODO @puhui999
  8 + *
  9 + * @author HUIHUI
  10 + */
  11 +@Service
  12 +public class BargainRecordApiImpl implements BargainRecordApi {
  13 +
  14 + @Override
  15 + public void createBargainRecord(BargainRecordCreateReqDTO reqDTO) {
  16 +
  17 + }
  18 +
  19 + @Override
  20 + public boolean isBargainRecordSuccess(Long userId, Long orderId) {
  21 + return false;
  22 + }
  23 +
  24 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.combination;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;  
4 -import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;  
5 -import org.springframework.stereotype.Service;  
6 -  
7 -import javax.annotation.Resource;  
8 -import java.time.LocalDateTime;  
9 -  
10 -/**  
11 - * 拼团活动 API 实现类  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 -@Service  
16 -public class CombinationApiImpl implements CombinationApi {  
17 -  
18 - @Resource  
19 - private CombinationActivityService activityService;  
20 -  
21 - @Override  
22 - public void createRecord(CombinationRecordReqDTO reqDTO) {  
23 - activityService.createRecord(reqDTO);  
24 - }  
25 -  
26 - @Override  
27 - public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {  
28 - return activityService.validateRecordStatusIsSuccess(userId, orderId);  
29 - }  
30 -  
31 - @Override  
32 - public void updateRecordStatus(Long userId, Long orderId, Integer status) {  
33 - activityService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status);  
34 - }  
35 -  
36 - @Override  
37 - public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {  
38 - activityService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());  
39 - }  
40 -  
41 -  
42 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  4 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
  5 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
  6 +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
  7 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  8 +import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
  9 +import org.springframework.stereotype.Service;
  10 +
  11 +import javax.annotation.Resource;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 拼团活动 API 实现类
  16 + *
  17 + * @author HUIHUI
  18 + */
  19 +@Service
  20 +public class CombinationRecordApiImpl implements CombinationRecordApi {
  21 +
  22 + @Resource
  23 + private CombinationRecordService recordService;
  24 +
  25 + @Override
  26 + public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
  27 + recordService.createCombinationRecord(reqDTO);
  28 + }
  29 +
  30 + @Override
  31 + public boolean isCombinationRecordSuccess(Long userId, Long orderId) {
  32 + return CombinationRecordStatusEnum.isSuccess(recordService.getCombinationRecord(userId, orderId).getStatus());
  33 + }
  34 +
  35 + @Override
  36 + public List<CombinationRecordRespDTO> getRecordListByUserIdAndActivityId(Long userId, Long activityId) {
  37 + return CombinationActivityConvert.INSTANCE.convert(recordService.getRecordListByUserIdAndActivityId(userId, activityId));
  38 + }
  39 +
  40 + @Override
  41 + public void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount) {
  42 + recordService.validateCombinationLimitCount(activityId, count, sumCount);
  43 + }
  44 +
  45 + @Override
  46 + public void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO) {
  47 + if (null == reqDTO.getStartTime()) {
  48 + recordService.updateCombinationRecordStatusByUserIdAndOrderId(reqDTO);
  49 + } else {
  50 + recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(reqDTO);
  51 + }
  52 + }
  53 +
  54 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.bargain;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityCreateReqVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
  8 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityRespVO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO;
  10 +import cn.iocoder.yudao.module.promotion.convert.bargain.BargainActivityConvert;
  11 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
  12 +import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
  13 +import io.swagger.v3.oas.annotations.Operation;
  14 +import io.swagger.v3.oas.annotations.Parameter;
  15 +import io.swagger.v3.oas.annotations.tags.Tag;
  16 +import org.springframework.security.access.prepost.PreAuthorize;
  17 +import org.springframework.validation.annotation.Validated;
  18 +import org.springframework.web.bind.annotation.*;
  19 +
  20 +import javax.annotation.Resource;
  21 +import javax.validation.Valid;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +
  25 +@Tag(name = "管理后台 - 砍价活动")
  26 +@RestController
  27 +@RequestMapping("/promotion/bargain-activity")
  28 +@Validated
  29 +public class BargainActivityController {
  30 +
  31 + @Resource
  32 + private BargainActivityService activityService;
  33 +
  34 + @PostMapping("/create")
  35 + @Operation(summary = "创建砍价活动")
  36 + @PreAuthorize("@ss.hasPermission('promotion:bargain-activity:create')")
  37 + public CommonResult<Long> createBargainActivity(@Valid @RequestBody BargainActivityCreateReqVO createReqVO) {
  38 + return success(activityService.createBargainActivity(createReqVO));
  39 + }
  40 +
  41 + @PutMapping("/update")
  42 + @Operation(summary = "更新砍价活动")
  43 + @PreAuthorize("@ss.hasPermission('promotion:bargain-activity:update')")
  44 + public CommonResult<Boolean> updateBargainActivity(@Valid @RequestBody BargainActivityUpdateReqVO updateReqVO) {
  45 + activityService.updateBargainActivity(updateReqVO);
  46 + return success(true);
  47 + }
  48 +
  49 + @DeleteMapping("/delete")
  50 + @Operation(summary = "删除砍价活动")
  51 + @Parameter(name = "id", description = "编号", required = true)
  52 + @PreAuthorize("@ss.hasPermission('promotion:bargain-activity:delete')")
  53 + public CommonResult<Boolean> deleteBargainActivity(@RequestParam("id") Long id) {
  54 + activityService.deleteBargainActivity(id);
  55 + return success(true);
  56 + }
  57 +
  58 + @GetMapping("/get")
  59 + @Operation(summary = "获得砍价活动")
  60 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  61 + @PreAuthorize("@ss.hasPermission('promotion:bargain-activity:query')")
  62 + public CommonResult<BargainActivityRespVO> getBargainActivity(@RequestParam("id") Long id) {
  63 + return success(BargainActivityConvert.INSTANCE.convert(activityService.getBargainActivity(id)));
  64 + }
  65 +
  66 + @GetMapping("/page")
  67 + @Operation(summary = "获得砍价活动分页")
  68 + @PreAuthorize("@ss.hasPermission('promotion:bargain-activity:query')")
  69 + public CommonResult<PageResult<BargainActivityRespVO>> getBargainActivityPage(
  70 + @Valid BargainActivityPageReqVO pageVO) {
  71 + // 查询砍价活动
  72 + PageResult<BargainActivityDO> pageResult = activityService.getBargainActivityPage(pageVO);
  73 + if (CollUtil.isEmpty(pageResult.getList())) {
  74 + return success(PageResult.empty(pageResult.getTotal()));
  75 + }
  76 + return success(BargainActivityConvert.INSTANCE.convertPage(activityService.getBargainActivityPage(pageVO)));
  77 + }
  78 +
  79 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +/**
  13 + * 砍价活动 Base VO,提供给添加、修改、详细的子 VO 使用
  14 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@Data
  19 +public class BargainActivityBaseVO {
  20 +
  21 + @Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "越拼越省钱")
  22 + @NotNull(message = "砍价名称不能为空")
  23 + private String name;
  24 +
  25 + @Schema(description = "商品 SPU 编号", example = "1")
  26 + @NotNull(message = "砍价商品不能为空")
  27 + private Long spuId;
  28 +
  29 + @Schema(description = "商品 skuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "23")
  30 + @NotNull(message = "商品 skuId 不能为空")
  31 + private Long skuId;
  32 +
  33 + @Schema(description = "砍价起始价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "23")
  34 + @NotNull(message = "砍价起始价格不能为空")
  35 + private Integer bargainFirstPrice;
  36 +
  37 + @Schema(description = "砍价底价", requiredMode = Schema.RequiredMode.REQUIRED, example = "23")
  38 + @NotNull(message = "砍价底价不能为空")
  39 + private Integer bargainPrice;
  40 +
  41 + @Schema(description = "活动库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "23")
  42 + @NotNull(message = "活动库存不能为空")
  43 + private Integer stock;
  44 +
  45 + @Schema(description = "总限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "16218")
  46 + @NotNull(message = "总限购数量不能为空")
  47 + private Integer totalLimitCount;
  48 +
  49 + @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 23:59:59]")
  50 + @NotNull(message = "活动开始时间不能为空")
  51 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  52 + private LocalDateTime startTime;
  53 +
  54 + @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 23:59:59]")
  55 + @NotNull(message = "活动结束时间不能为空")
  56 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  57 + private LocalDateTime endTime;
  58 +
  59 + @Schema(description = "砍价人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
  60 + @NotNull(message = "砍价人数不能为空")
  61 + private Integer userSize;
  62 +
  63 + @Schema(description = "最大帮砍次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
  64 + @NotNull(message = "最大帮砍次数不能为空")
  65 + private Integer bargainCount;
  66 +
  67 + @Schema(description = "用户每次砍价的最小金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
  68 + @NotNull(message = "用户每次砍价的最小金额不能为空")
  69 + private Integer randomMinPrice;
  70 +
  71 + @Schema(description = "用户每次砍价的最大金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
  72 + @NotNull(message = "用户每次砍价的最大金额不能为空")
  73 + private Integer randomMaxPrice;
  74 +
  75 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityCreateReqVO.java
1 -package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; 1 +package cn.iocoder.yudao.module.promotion.controller.admin.bargain.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 -@Schema(description = "管理后台 - 秒杀参与商品创建 Request VO") 7 +
  8 +@Schema(description = "管理后台 - 砍价活动创建 Request VO")
8 @Data 9 @Data
9 @EqualsAndHashCode(callSuper = true) 10 @EqualsAndHashCode(callSuper = true)
10 @ToString(callSuper = true) 11 @ToString(callSuper = true)
11 -public class SeckillProductCreateReqVO extends SeckillProductBaseVO { 12 +public class BargainActivityCreateReqVO extends BargainActivityBaseVO {
12 13
13 } 14 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityPageReqVO.java
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product; 1 +package cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
3 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 5 import lombok.Data;
5 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
6 import lombok.ToString; 7 import lombok.ToString;
7 8
8 -@Schema(description = "管理后台 - 拼团商品更新 Request VO") 9 +@Schema(description = "管理后台 - 砍价活动分页 Request VO")
9 @Data 10 @Data
10 @EqualsAndHashCode(callSuper = true) 11 @EqualsAndHashCode(callSuper = true)
11 @ToString(callSuper = true) 12 @ToString(callSuper = true)
12 -public class CombinationProductUpdateReqVO extends CombinationProductBaseVO { 13 +public class BargainActivityPageReqVO extends PageParam {
  14 +
  15 + @Schema(description = "砍价名称", example = "赵六")
  16 + private String name;
  17 +
  18 + @Schema(description = "活动状态", example = "0")
  19 + private Integer status;
13 20
14 } 21 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.bargain.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 javax.validation.constraints.NotNull;
  9 +import java.time.LocalDateTime;
  10 +@Schema(description = "管理后台 - 砍价活动 Response VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class BargainActivityRespVO extends BargainActivityBaseVO {
  15 +
  16 + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
  17 + private String spuName;
  18 +
  19 + @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
  20 + private String picUrl;
  21 +
  22 + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
  23 + private Long id;
  24 +
  25 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022-07-01 23:59:59")
  26 + private LocalDateTime createTime;
  27 +
  28 + @Schema(description = "砍价成功数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "999")
  29 + private Integer successCount;
  30 +
  31 + @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
  32 + @NotNull(message = "活动状态不能为空")
  33 + private Integer status;
  34 +
  35 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/MemberSignInRecordUpdateReqVO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityUpdateReqVO.java
1 -package cn.iocoder.yudao.module.member.controller.admin.signin.vo; 1 +package cn.iocoder.yudao.module.promotion.controller.admin.bargain.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;
@@ -7,14 +7,14 @@ import lombok.ToString; @@ -7,14 +7,14 @@ import lombok.ToString;
7 7
8 import javax.validation.constraints.NotNull; 8 import javax.validation.constraints.NotNull;
9 9
10 -@Schema(description = "管理后台 - 用户签到积分更新 Request VO") 10 +@Schema(description = "管理后台 - 砍价活动更新 Request VO")
11 @Data 11 @Data
12 @EqualsAndHashCode(callSuper = true) 12 @EqualsAndHashCode(callSuper = true)
13 @ToString(callSuper = true) 13 @ToString(callSuper = true)
14 -public class MemberSignInRecordUpdateReqVO extends MemberSignInRecordBaseVO { 14 +public class BargainActivityUpdateReqVO extends BargainActivityBaseVO {
15 15
16 - @Schema(description = "签到自增id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11903")  
17 - @NotNull(message = "签到自增id不能为空") 16 + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
  17 + @NotNull(message = "活动编号不能为空")
18 private Long id; 18 private Long id;
19 19
20 } 20 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.combination; 1 package cn.iocoder.yudao.module.promotion.controller.admin.combination;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
6 -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;  
7 -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;  
8 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 6 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
9 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 7 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
10 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.*; 8 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
  10 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
  11 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
11 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 12 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
12 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
13 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO; 13 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  14 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
14 import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; 15 import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
15 import io.swagger.v3.oas.annotations.Operation; 16 import io.swagger.v3.oas.annotations.Operation;
16 import io.swagger.v3.oas.annotations.Parameter; 17 import io.swagger.v3.oas.annotations.Parameter;
@@ -20,16 +21,12 @@ import org.springframework.validation.annotation.Validated; @@ -20,16 +21,12 @@ import org.springframework.validation.annotation.Validated;
20 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
21 22
22 import javax.annotation.Resource; 23 import javax.annotation.Resource;
23 -import javax.servlet.http.HttpServletResponse;  
24 import javax.validation.Valid; 24 import javax.validation.Valid;
25 -import java.io.IOException;  
26 -import java.util.Collection;  
27 import java.util.List; 25 import java.util.List;
28 -import java.util.Set;  
29 26
30 import static cn.hutool.core.collection.CollectionUtil.newArrayList; 27 import static cn.hutool.core.collection.CollectionUtil.newArrayList;
31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 28 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
32 -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
33 30
34 @Tag(name = "管理后台 - 拼团活动") 31 @Tag(name = "管理后台 - 拼团活动")
35 @RestController 32 @RestController
@@ -39,8 +36,9 @@ public class CombinationActivityController { @@ -39,8 +36,9 @@ public class CombinationActivityController {
39 36
40 @Resource 37 @Resource
41 private CombinationActivityService combinationActivityService; 38 private CombinationActivityService combinationActivityService;
  39 +
42 @Resource 40 @Resource
43 - private ProductSpuApi spuApi; 41 + private ProductSpuApi productSpuApi;
44 42
45 @PostMapping("/create") 43 @PostMapping("/create")
46 @Operation(summary = "创建拼团活动") 44 @Operation(summary = "创建拼团活动")
@@ -72,43 +70,27 @@ public class CombinationActivityController { @@ -72,43 +70,27 @@ public class CombinationActivityController {
72 @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") 70 @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
73 public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) { 71 public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) {
74 CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id); 72 CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id);
75 - List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(newArrayList(id)); 73 + List<CombinationProductDO> products = combinationActivityService.getCombinationProductsByActivityIds(newArrayList(id));
76 return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); 74 return success(CombinationActivityConvert.INSTANCE.convert(activity, products));
77 } 75 }
78 76
79 - @GetMapping("/list")  
80 - @Operation(summary = "获得拼团活动列表")  
81 - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")  
82 - @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")  
83 - public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) {  
84 - List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids);  
85 - return success(CombinationActivityConvert.INSTANCE.convertList(list));  
86 - }  
87 -  
88 @GetMapping("/page") 77 @GetMapping("/page")
89 @Operation(summary = "获得拼团活动分页") 78 @Operation(summary = "获得拼团活动分页")
90 @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") 79 @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
91 public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage( 80 public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage(
92 @Valid CombinationActivityPageReqVO pageVO) { 81 @Valid CombinationActivityPageReqVO pageVO) {
  82 + // 查询拼团活动
93 PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO); 83 PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
94 - // TODO @puhui999:可以不一定 aIds,直接批量查询结果出来;下面也是类似;  
95 - Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId);  
96 - List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(aIds);  
97 - Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);  
98 - List<ProductSpuRespDTO> spus = spuApi.getSpuList(spuIds);  
99 - return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));  
100 - } 84 + if (CollUtil.isEmpty(pageResult.getList())) {
  85 + return success(PageResult.empty(pageResult.getTotal()));
  86 + }
101 87
102 - @GetMapping("/export-excel")  
103 - @Operation(summary = "导出拼团活动 Excel")  
104 - @PreAuthorize("@ss.hasPermission('promotion:combination-activity:export')")  
105 - @OperateLog(type = EXPORT)  
106 - public void exportCombinationActivityExcel(@Valid CombinationActivityExportReqVO exportReqVO,  
107 - HttpServletResponse response) throws IOException {  
108 - List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(exportReqVO);  
109 - // 导出 Excel  
110 - List<CombinationActivityExcelVO> datas = CombinationActivityConvert.INSTANCE.convertList02(list);  
111 - ExcelUtils.write(response, "拼团活动.xls", "数据", CombinationActivityExcelVO.class, datas); 88 + // 拼接数据
  89 + List<CombinationProductDO> products = combinationActivityService.getCombinationProductsByActivityIds(
  90 + convertSet(pageResult.getList(), CombinationActivityDO::getId));
  91 + List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(
  92 + convertSet(pageResult.getList(), CombinationActivityDO::getSpuId));
  93 + return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));
112 } 94 }
113 95
114 } 96 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
@@ -12,6 +12,8 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -12,6 +12,8 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
12 /** 12 /**
13 * 拼团活动 Base VO,提供给添加、修改、详细的子 VO 使用 13 * 拼团活动 Base VO,提供给添加、修改、详细的子 VO 使用
14 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 14 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  15 + *
  16 + * @author HUIHUI
15 */ 17 */
16 @Data 18 @Data
17 public class CombinationActivityBaseVO { 19 public class CombinationActivityBaseVO {
@@ -20,7 +22,7 @@ public class CombinationActivityBaseVO { @@ -20,7 +22,7 @@ public class CombinationActivityBaseVO {
20 @NotNull(message = "拼团名称不能为空") 22 @NotNull(message = "拼团名称不能为空")
21 private String name; 23 private String name;
22 24
23 - @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]") 25 + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
24 @NotNull(message = "拼团商品不能为空") 26 @NotNull(message = "拼团商品不能为空")
25 private Long spuId; 27 private Long spuId;
26 28
@@ -32,17 +34,21 @@ public class CombinationActivityBaseVO { @@ -32,17 +34,21 @@ public class CombinationActivityBaseVO {
32 @NotNull(message = "单次限购数量不能为空") 34 @NotNull(message = "单次限购数量不能为空")
33 private Integer singleLimitCount; 35 private Integer singleLimitCount;
34 36
35 - // TODO @puhui999:是不是弄成 2 个字段会好点哈。开始、结束  
36 - @Schema(description = "活动时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") 37 + @Schema(description = "活动时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 23:59:59]")
37 @NotNull(message = "活动时间不能为空") 38 @NotNull(message = "活动时间不能为空")
38 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 39 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
39 - private LocalDateTime[] activityTime; 40 + private LocalDateTime startTime;
  41 +
  42 + @Schema(description = "活动时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 23:59:59]")
  43 + @NotNull(message = "活动时间不能为空")
  44 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  45 + private LocalDateTime endTime;
40 46
41 @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222") 47 @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
42 @NotNull(message = "开团人数不能为空") 48 @NotNull(message = "开团人数不能为空")
43 private Integer userSize; 49 private Integer userSize;
44 50
45 - @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED) 51 + @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
46 @NotNull(message = "限制时长不能为空") 52 @NotNull(message = "限制时长不能为空")
47 private Integer limitDuration; 53 private Integer limitDuration;
48 54
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
2 2
3 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO; 3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
4 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
@@ -17,6 +17,6 @@ public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO { @@ -17,6 +17,6 @@ public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO {
17 17
18 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) 18 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
19 @Valid 19 @Valid
20 - private List<CombinationProductCreateReqVO> products; 20 + private List<CombinationProductBaseVO> products;
21 21
22 } 22 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;  
2 -  
3 -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;  
4 -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;  
5 -import com.alibaba.excel.annotation.ExcelProperty;  
6 -import lombok.Data;  
7 -  
8 -import java.time.LocalDateTime;  
9 -  
10 -// TODO @puhui999:如无必要,导出都可以删除哈  
11 -/**  
12 - * 拼团活动 Excel VO  
13 - *  
14 - * @author HUIHUI  
15 - */  
16 -@Data  
17 -public class CombinationActivityExcelVO {  
18 -  
19 - @ExcelProperty("活动编号")  
20 - private Long id;  
21 -  
22 - @ExcelProperty("拼团名称")  
23 - private String name;  
24 -  
25 - @ExcelProperty("商品 SPU 编号关联 ProductSpuDO 的 id")  
26 - private Long spuId;  
27 -  
28 - @ExcelProperty("总限购数量")  
29 - private Integer totalLimitCount;  
30 -  
31 - @ExcelProperty("单次限购数量")  
32 - private Integer singleLimitCount;  
33 -  
34 - @ExcelProperty("开始时间")  
35 - private LocalDateTime startTime;  
36 -  
37 - @ExcelProperty("结束时间")  
38 - private LocalDateTime endTime;  
39 -  
40 - @ExcelProperty("开团人数")  
41 - private Integer userSize;  
42 -  
43 - @ExcelProperty("开团组数")  
44 - private Integer totalNum;  
45 -  
46 - @ExcelProperty("成团组数")  
47 - private Integer successNum;  
48 -  
49 - @ExcelProperty("参与人数")  
50 - private Integer orderUserCount;  
51 -  
52 - @ExcelProperty("虚拟成团")  
53 - private Integer virtualGroup;  
54 -  
55 - @ExcelProperty(value = "活动状态:0开启 1关闭", converter = DictConvert.class)  
56 - @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中  
57 - private Integer status;  
58 -  
59 - @ExcelProperty("限制时长(小时)")  
60 - private Integer limitDuration;  
61 -  
62 - @ExcelProperty("创建时间")  
63 - private LocalDateTime createTime;  
64 -  
65 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import org.springframework.format.annotation.DateTimeFormat;  
6 -  
7 -import java.time.LocalDateTime;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
10 -  
11 -// TODO @puhui999:如无必要,导出都可以删除哈  
12 -@Schema(description = "管理后台 - 拼团活动 Excel 导出 Request VO,参数和 CombinationActivityPageReqVO 是一致的")  
13 -@Data  
14 -public class CombinationActivityExportReqVO {  
15 -  
16 - @Schema(description = "拼团名称", example = "赵六")  
17 - private String name;  
18 -  
19 - @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")  
20 - private Long spuId;  
21 -  
22 - @Schema(description = "总限购数量", example = "16218")  
23 - private Integer totalLimitCount;  
24 -  
25 - @Schema(description = "单次限购数量", example = "28265")  
26 - private Integer singleLimitCount;  
27 -  
28 - @Schema(description = "开始时间")  
29 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
30 - private LocalDateTime[] startTime;  
31 -  
32 - @Schema(description = "结束时间")  
33 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
34 - private LocalDateTime[] endTime;  
35 -  
36 - @Schema(description = "开团人数")  
37 - private Integer userSize;  
38 -  
39 - @Schema(description = "开团组数")  
40 - private Integer totalNum;  
41 -  
42 - @Schema(description = "成团组数")  
43 - private Integer successNum;  
44 -  
45 - @Schema(description = "参与人数", example = "25222")  
46 - private Integer orderUserCount;  
47 -  
48 - @Schema(description = "虚拟成团")  
49 - private Integer virtualGroup;  
50 -  
51 - @Schema(description = "活动状态:0开启 1关闭", example = "0")  
52 - private Integer status;  
53 -  
54 - @Schema(description = "限制时长(小时)")  
55 - private Integer limitDuration;  
56 -  
57 - @Schema(description = "创建时间")  
58 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
59 - private LocalDateTime[] createTime;  
60 -  
61 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
@@ -5,11 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema; @@ -5,11 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
7 import lombok.ToString; 7 import lombok.ToString;
8 -import org.springframework.format.annotation.DateTimeFormat;  
9 -  
10 -import java.time.LocalDateTime;  
11 -  
12 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
13 8
14 @Schema(description = "管理后台 - 拼团活动分页 Request VO") 9 @Schema(description = "管理后台 - 拼团活动分页 Request VO")
15 @Data 10 @Data
@@ -20,46 +15,8 @@ public class CombinationActivityPageReqVO extends PageParam { @@ -20,46 +15,8 @@ public class CombinationActivityPageReqVO extends PageParam {
20 @Schema(description = "拼团名称", example = "赵六") 15 @Schema(description = "拼团名称", example = "赵六")
21 private String name; 16 private String name;
22 17
23 - @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")  
24 - private Long spuId;  
25 -  
26 - @Schema(description = "总限购数量", example = "16218")  
27 - private Integer totalLimitCount;  
28 -  
29 - @Schema(description = "单次限购数量", example = "28265")  
30 - private Integer singleLimitCount;  
31 -  
32 - @Schema(description = "开始时间")  
33 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
34 - private LocalDateTime[] startTime;  
35 -  
36 - @Schema(description = "结束时间")  
37 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
38 - private LocalDateTime[] endTime;  
39 -  
40 - @Schema(description = "开团人数")  
41 - private Integer userSize;  
42 -  
43 - @Schema(description = "开团组数")  
44 - private Integer totalNum;  
45 -  
46 - @Schema(description = "成团组数")  
47 - private Integer successNum;  
48 -  
49 - @Schema(description = "参与人数", example = "25222")  
50 - private Integer orderUserCount;  
51 -  
52 - @Schema(description = "虚拟成团")  
53 - private Integer virtualGroup;  
54 -  
55 @Schema(description = "活动状态:0开启 1关闭", example = "0") 18 @Schema(description = "活动状态:0开启 1关闭", example = "0")
56 private Integer status; 19 private Integer status;
57 20
58 - @Schema(description = "限制时长(小时)")  
59 - private Integer limitDuration;  
60 -  
61 - @Schema(description = "创建时间")  
62 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
63 - private LocalDateTime[] createTime;  
64 21
65 } 22 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
@@ -17,40 +17,34 @@ import java.util.List; @@ -17,40 +17,34 @@ import java.util.List;
17 @ToString(callSuper = true) 17 @ToString(callSuper = true)
18 public class CombinationActivityRespVO extends CombinationActivityBaseVO { 18 public class CombinationActivityRespVO extends CombinationActivityBaseVO {
19 19
20 - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促") 20 + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
  21 + private Long id;
  22 +
  23 + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促")
21 private String spuName; 24 private String spuName;
22 25
23 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") 26 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
24 private String picUrl; 27 private String picUrl;
25 28
26 - @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")  
27 - private Long id;  
28 -  
29 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 29 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
30 private LocalDateTime createTime; 30 private LocalDateTime createTime;
31 31
32 - @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED)  
33 - @NotNull(message = "开团人数不能为空") 32 + @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
34 private Integer userSize; 33 private Integer userSize;
35 34
36 - @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED)  
37 - @NotNull(message = "开团组数不能为空")  
38 - private Integer totalNum; 35 + @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "33")
  36 + private Integer totalCount;
39 37
40 - @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED)  
41 - @NotNull(message = "成团组数不能为空")  
42 - private Integer successNum; 38 + @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
  39 + private Integer successCount;
43 40
44 - @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED)  
45 - @NotNull(message = "虚拟成团不能为空") 41 + @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
46 private Integer virtualGroup; 42 private Integer virtualGroup;
47 43
48 @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 44 @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
49 - @NotNull(message = "活动状态不能为空")  
50 private Integer status; 45 private Integer status;
51 46
52 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) 47 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
53 - @Valid  
54 private List<CombinationProductRespVO> products; 48 private List<CombinationProductRespVO> products;
55 49
56 } 50 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
2 2
3 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO; 3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
4 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
@@ -22,6 +22,6 @@ public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO { @@ -22,6 +22,6 @@ public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO {
22 22
23 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) 23 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
24 @Valid 24 @Valid
25 - private List<CombinationProductUpdateReqVO> products; 25 + private List<CombinationProductBaseVO> products;
26 26
27 } 27 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
@@ -21,7 +21,7 @@ public class CombinationProductBaseVO { @@ -21,7 +21,7 @@ public class CombinationProductBaseVO {
21 private Long skuId; 21 private Long skuId;
22 22
23 @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682") 23 @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682")
24 - @NotNull(message = "拼团价格,单位分不能为空")  
25 - private Integer activePrice; 24 + @NotNull(message = "拼团价格不能为空")
  25 + private Integer combinationPrice;
26 26
27 } 27 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;  
2 -  
3 -import com.alibaba.excel.annotation.ExcelProperty;  
4 -import lombok.Data;  
5 -  
6 -import java.time.LocalDateTime;  
7 -  
8 -// TODO @puhui999:可以考虑删除 excel 导出哈  
9 -/**  
10 - * 拼团商品 Excel VO  
11 - *  
12 - * @author HUIHUI  
13 - */  
14 -@Data  
15 -public class CombinationProductExcelVO {  
16 -  
17 - @ExcelProperty("编号")  
18 - private Long id;  
19 -  
20 - @ExcelProperty("拼团活动编号")  
21 - private Long activityId;  
22 -  
23 - @ExcelProperty("商品 SPU 编号")  
24 - private Long spuId;  
25 -  
26 - @ExcelProperty("商品 SKU 编号")  
27 - private Long skuId;  
28 -  
29 - @ExcelProperty("拼团商品状态")  
30 - private Integer activityStatus;  
31 -  
32 - @ExcelProperty("活动开始时间点")  
33 - private LocalDateTime activityStartTime;  
34 -  
35 - @ExcelProperty("活动结束时间点")  
36 - private LocalDateTime activityEndTime;  
37 -  
38 - @ExcelProperty("拼团价格,单位分")  
39 - private Integer activePrice;  
40 -  
41 - @ExcelProperty("创建时间")  
42 - private LocalDateTime createTime;  
43 -  
44 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import org.springframework.format.annotation.DateTimeFormat;  
6 -  
7 -import java.time.LocalDateTime;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
10 -  
11 -// TODO @puhui999:可以考虑删除 excel 导出哈  
12 -@Schema(description = "管理后台 - 拼团商品 Excel 导出 Request VO,参数和 CombinationProductPageReqVO 是一致的")  
13 -@Data  
14 -public class CombinationProductExportReqVO {  
15 -  
16 - @Schema(description = "拼团活动编号", example = "6829")  
17 - private Long activityId;  
18 -  
19 - @Schema(description = "商品 SPU 编号", example = "18731")  
20 - private Long spuId;  
21 -  
22 - @Schema(description = "商品 SKU 编号", example = "31675")  
23 - private Long skuId;  
24 -  
25 - @Schema(description = "拼团商品状态", example = "2")  
26 - private Integer activityStatus;  
27 -  
28 - @Schema(description = "活动开始时间点")  
29 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
30 - private LocalDateTime[] activityStartTime;  
31 -  
32 - @Schema(description = "活动结束时间点")  
33 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
34 - private LocalDateTime[] activityEndTime;  
35 -  
36 - @Schema(description = "拼团价格,单位分", example = "27682")  
37 - private Integer activePrice;  
38 -  
39 - @Schema(description = "创建时间")  
40 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
41 - private LocalDateTime[] createTime;  
42 -  
43 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/DecorateComponentController.http 0 → 100644
  1 +### /promotion/decorate/save 保存页面装修组件
  2 +POST {{baseUrl}}/promotion/decorate/save
  3 +Content-Type: application/json
  4 +Authorization: Bearer {{token}}
  5 +tenant-id: {{adminTenentId}}
  6 +
  7 +{
  8 + "page": 1,
  9 + "code": "slide-show",
  10 + "status": 0,
  11 + "value": "null"
  12 +}
  13 +
  14 +### /promotion/decorate/list 获取指定页面的组件列表
  15 +GET {{baseUrl}}/promotion/decorate/list?page=1
  16 +Content-Type: application/json
  17 +Authorization: Bearer {{token}}
  18 +tenant-id: {{adminTenentId}}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/DecorateComponentController.java
@@ -2,45 +2,49 @@ package cn.iocoder.yudao.module.promotion.controller.admin.decorate; @@ -2,45 +2,49 @@ package cn.iocoder.yudao.module.promotion.controller.admin.decorate;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 -import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO;  
6 import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentRespVO; 5 import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentRespVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO;
  7 +import cn.iocoder.yudao.module.promotion.convert.decorate.DecorateComponentConvert;
7 import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum; 8 import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum;
8 import cn.iocoder.yudao.module.promotion.service.decorate.DecorateComponentService; 9 import cn.iocoder.yudao.module.promotion.service.decorate.DecorateComponentService;
9 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
10 import io.swagger.v3.oas.annotations.Parameter; 11 import io.swagger.v3.oas.annotations.Parameter;
11 import io.swagger.v3.oas.annotations.tags.Tag; 12 import io.swagger.v3.oas.annotations.tags.Tag;
  13 +import org.springframework.security.access.prepost.PreAuthorize;
12 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
13 import org.springframework.web.bind.annotation.*; 15 import org.springframework.web.bind.annotation.*;
14 16
15 import javax.annotation.Resource; 17 import javax.annotation.Resource;
16 import javax.validation.Valid; 18 import javax.validation.Valid;
  19 +import java.util.List;
17 20
18 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
19 -import static cn.iocoder.yudao.module.promotion.convert.decorate.DecorateComponentConvert.INSTANCE;  
20 22
21 @Tag(name = "管理后台 - 店铺页面装修") 23 @Tag(name = "管理后台 - 店铺页面装修")
22 @RestController 24 @RestController
23 @RequestMapping("/promotion/decorate") 25 @RequestMapping("/promotion/decorate")
24 @Validated 26 @Validated
25 public class DecorateComponentController { 27 public class DecorateComponentController {
  28 +
26 @Resource 29 @Resource
27 private DecorateComponentService decorateComponentService; 30 private DecorateComponentService decorateComponentService;
28 31
29 - @PostMapping("/page-save")  
30 - @Operation(summary = "保存页面装修")  
31 - // TODO 加权限  
32 - public CommonResult<Boolean> savePageComponents(@Valid @RequestBody DecorateComponentSaveReqVO reqVO) {  
33 - decorateComponentService.savePageComponents(reqVO); 32 + @PostMapping("/save")
  33 + @Operation(summary = "保存页面装修组件")
  34 + @PreAuthorize("@ss.hasPermission('promotion:decorate:save')")
  35 + public CommonResult<Boolean> saveDecorateComponent(@Valid @RequestBody DecorateComponentSaveReqVO reqVO) {
  36 + decorateComponentService.saveDecorateComponent(reqVO);
34 return success(true); 37 return success(true);
35 } 38 }
36 39
37 - @GetMapping("/get-page-components")  
38 - @Operation(summary = "获取装修页面组件")  
39 - @Parameter(name = "pageId", description = "页面 id", required = true)  
40 - // TODO 加权限  
41 - public CommonResult<DecorateComponentRespVO> getPageComponents(  
42 - @RequestParam("pageId") @InEnum(DecoratePageEnum.class) Integer pageId) {  
43 - return success(INSTANCE.convert2(pageId, decorateComponentService.getPageComponents(pageId))); 40 + @GetMapping("/list")
  41 + @Operation(summary = "获取指定页面的组件列表")
  42 + @Parameter(name = "page", description = "页面 id", required = true)
  43 + @PreAuthorize("@ss.hasPermission('promotion:decorate:query')")
  44 + public CommonResult<List<DecorateComponentRespVO>> getDecorateComponentListByPage(
  45 + @RequestParam("page") @InEnum(DecoratePageEnum.class) Integer page) {
  46 + return success(DecorateComponentConvert.INSTANCE.convertList02(
  47 + decorateComponentService.getDecorateComponentListByPage(page, null)));
44 } 48 }
45 49
46 } 50 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/vo/DecorateComponentRespVO.java
@@ -3,31 +3,17 @@ package cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo; @@ -3,31 +3,17 @@ package cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo;
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 5
6 -import java.util.List;  
7 -  
8 @Schema(description = "管理后台 - 页面装修 Resp VO") 6 @Schema(description = "管理后台 - 页面装修 Resp VO")
9 @Data 7 @Data
10 public class DecorateComponentRespVO { 8 public class DecorateComponentRespVO {
11 9
12 - @Schema(description = "页面 id ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
13 - private Integer pageId;  
14 -  
15 - @Schema(description = "页面组件", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")  
16 - private List<ComponentRespVO> components;  
17 -  
18 - @Schema(description = "管理后台 - 页面组件 Resp VO")  
19 - @Data  
20 - public static class ComponentRespVO {  
21 -  
22 - @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
23 - private Long id;  
24 -  
25 - @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")  
26 - private String code; 10 + @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")
  11 + private String code;
27 12
28 - @Schema(description = "组件的内容配置项", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")  
29 - private String value; 13 + @Schema(description = "组件的内容配置项", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")
  14 + private String value;
30 15
31 - } 16 + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + private Integer status;
32 18
33 } 19 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/decorate/vo/DecorateComponentSaveReqVO.java
@@ -5,10 +5,8 @@ import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum; @@ -5,10 +5,8 @@ import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum;
5 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 6 import lombok.Data;
7 7
8 -import javax.validation.Valid;  
9 import javax.validation.constraints.NotEmpty; 8 import javax.validation.constraints.NotEmpty;
10 import javax.validation.constraints.NotNull; 9 import javax.validation.constraints.NotNull;
11 -import java.util.List;  
12 10
13 @Schema(description = "管理后台 - 页面装修的保存 Request VO ") 11 @Schema(description = "管理后台 - 页面装修的保存 Request VO ")
14 @Data 12 @Data
@@ -17,28 +15,17 @@ public class DecorateComponentSaveReqVO { @@ -17,28 +15,17 @@ public class DecorateComponentSaveReqVO {
17 @Schema(description = "页面 id ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 15 @Schema(description = "页面 id ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
18 @NotNull(message = "页面 id 不能为空") 16 @NotNull(message = "页面 id 不能为空")
19 @InEnum(DecoratePageEnum.class) 17 @InEnum(DecoratePageEnum.class)
20 - private Integer pageId; 18 + private Integer page;
21 19
22 - @Schema(description = "页面组件列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")  
23 - @NotEmpty(message = "页面组件列表不能为空")  
24 - @Valid  
25 - private List<ComponentReqVO> components; 20 + @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")
  21 + @NotEmpty(message = "组件编码不能为空")
  22 + private String code;
26 23
27 - @Schema(description = "管理后台 - 页面装修组件 Request VO")  
28 - @Data  
29 - public static class ComponentReqVO { 24 + @Schema(description = "组件对应值, json 字符串, 含内容配置,具体数据", requiredMode = Schema.RequiredMode.REQUIRED)
  25 + @NotEmpty(message = "组件值为空")
  26 + private String value;
30 27
31 - @Schema(description = "组件编码", example = "1")  
32 - private Long id;  
33 -  
34 - @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")  
35 - @NotEmpty(message = "组件编码不能为空")  
36 - private String code;  
37 -  
38 - @Schema(description = "组件对应值, json 字符串, 含内容配置,具体数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")  
39 - @NotEmpty(message = "组件值为空")  
40 - private String value;  
41 -  
42 - } 28 + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  29 + private Integer status;
43 30
44 } 31 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
6 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 6 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
7 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 7 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*; 8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*;
9 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; 9 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
10 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
11 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; 11 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
12 -import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityService; 12 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
13 import io.swagger.v3.oas.annotations.Operation; 13 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 14 import io.swagger.v3.oas.annotations.Parameter;
15 import io.swagger.v3.oas.annotations.tags.Tag; 15 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -19,11 +19,10 @@ import org.springframework.web.bind.annotation.*; @@ -19,11 +19,10 @@ import org.springframework.web.bind.annotation.*;
19 19
20 import javax.annotation.Resource; 20 import javax.annotation.Resource;
21 import javax.validation.Valid; 21 import javax.validation.Valid;
22 -import java.util.Collection;  
23 import java.util.List; 22 import java.util.List;
24 -import java.util.Set;  
25 23
26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
27 26
28 @Tag(name = "管理后台 - 秒杀活动") 27 @Tag(name = "管理后台 - 秒杀活动")
29 @RestController 28 @RestController
@@ -34,7 +33,7 @@ public class SeckillActivityController { @@ -34,7 +33,7 @@ public class SeckillActivityController {
34 @Resource 33 @Resource
35 private SeckillActivityService seckillActivityService; 34 private SeckillActivityService seckillActivityService;
36 @Resource 35 @Resource
37 - private ProductSpuApi spuApi; 36 + private ProductSpuApi productSpuApi;
38 37
39 @PostMapping("/create") 38 @PostMapping("/create")
40 @Operation(summary = "创建秒杀活动") 39 @Operation(summary = "创建秒杀活动")
@@ -74,30 +73,27 @@ public class SeckillActivityController { @@ -74,30 +73,27 @@ public class SeckillActivityController {
74 @Parameter(name = "id", description = "编号", required = true, example = "1024") 73 @Parameter(name = "id", description = "编号", required = true, example = "1024")
75 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 74 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
76 public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) { 75 public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
77 - SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);  
78 - List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);  
79 - return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts));  
80 - }  
81 -  
82 - @GetMapping("/list")  
83 - @Operation(summary = "获得秒杀活动列表")  
84 - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")  
85 - @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")  
86 - public CommonResult<List<SeckillActivityRespVO>> getSeckillActivityList(@RequestParam("ids") Collection<Long> ids) {  
87 - List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(ids);  
88 - return success(SeckillActivityConvert.INSTANCE.convertList(list)); 76 + SeckillActivityDO activity = seckillActivityService.getSeckillActivity(id);
  77 + List<SeckillProductDO> products = seckillActivityService.getSeckillProductListByActivityId(id);
  78 + return success(SeckillActivityConvert.INSTANCE.convert(activity, products));
89 } 79 }
90 80
91 @GetMapping("/page") 81 @GetMapping("/page")
92 @Operation(summary = "获得秒杀活动分页") 82 @Operation(summary = "获得秒杀活动分页")
93 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 83 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
94 public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) { 84 public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
  85 + // 查询活动列表
95 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO); 86 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
96 - Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getId);  
97 - List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds);  
98 - Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getSpuId);  
99 - List<ProductSpuRespDTO> spuList = spuApi.getSpuList(spuIds);  
100 - return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList)); 87 + if (CollUtil.isEmpty(pageResult.getList())) {
  88 + return success(PageResult.empty(pageResult.getTotal()));
  89 + }
  90 +
  91 + // 拼接数据
  92 + List<SeckillProductDO> products = seckillActivityService.getSeckillProductListByActivityId(
  93 + convertSet(pageResult.getList(), SeckillActivityDO::getId));
  94 + List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(
  95 + convertSet(pageResult.getList(), SeckillActivityDO::getSpuId));
  96 + return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, products, spuList));
101 } 97 }
102 98
103 } 99 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
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.seckill.vo.config.*; 6 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*;
6 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert; 7 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
8 -import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService; 9 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
9 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
10 import io.swagger.v3.oas.annotations.Parameter; 11 import io.swagger.v3.oas.annotations.Parameter;
11 import io.swagger.v3.oas.annotations.tags.Tag; 12 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -80,7 +81,7 @@ public class SeckillConfigController { @@ -80,7 +81,7 @@ public class SeckillConfigController {
80 @GetMapping("/list-all-simple") 81 @GetMapping("/list-all-simple")
81 @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项") 82 @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项")
82 public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() { 83 public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() {
83 - List<SeckillConfigDO> list = seckillConfigService.getListAllSimple(); 84 + List<SeckillConfigDO> list = seckillConfigService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
84 return success(SeckillConfigConvert.INSTANCE.convertList1(list)); 85 return success(SeckillConfigConvert.INSTANCE.convertList1(list));
85 } 86 }
86 87
@@ -91,4 +92,5 @@ public class SeckillConfigController { @@ -91,4 +92,5 @@ public class SeckillConfigController {
91 PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO); 92 PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO);
92 return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult)); 93 return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult));
93 } 94 }
  95 +
94 } 96 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
@@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
20 @Data 20 @Data
21 public class SeckillActivityBaseVO { 21 public class SeckillActivityBaseVO {
22 22
23 - @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") 23 + @Schema(description = "秒杀活动商品 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
24 @NotNull(message = "秒杀活动商品不能为空") 24 @NotNull(message = "秒杀活动商品不能为空")
25 private Long spuId; 25 private Long spuId;
26 26
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
2 2
3 3
4 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO; 4 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
5 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 6 import lombok.Data;
7 import lombok.EqualsAndHashCode; 7 import lombok.EqualsAndHashCode;
@@ -16,6 +16,6 @@ import java.util.List; @@ -16,6 +16,6 @@ import java.util.List;
16 public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO { 16 public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
17 17
18 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 18 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
19 - private List<SeckillProductCreateReqVO> products; 19 + private List<SeckillProductBaseVO> products;
20 20
21 } 21 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
@@ -21,28 +21,28 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { @@ -21,28 +21,28 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
21 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") 21 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
22 private String picUrl; 22 private String picUrl;
23 23
24 - @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 24 + @Schema(description = "秒杀活动 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
25 private Long id; 25 private Long id;
26 26
27 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 27 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
28 private List<SeckillProductRespVO> products; 28 private List<SeckillProductRespVO> products;
29 29
30 - @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 30 + @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
31 private Integer status; 31 private Integer status;
32 32
33 @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354") 33 @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354")
34 private Integer totalPrice; 34 private Integer totalPrice;
35 35
36 - @Schema(description = "秒杀库存", example = "10") 36 + @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
37 private Integer stock; 37 private Integer stock;
38 38
39 - @Schema(description = "秒杀总库存", example = "20") 39 + @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
40 private Integer totalStock; 40 private Integer totalStock;
41 41
42 - @Schema(description = "新增订单数", example = "20") 42 + @Schema(description = "新增订单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
43 private Integer orderCount; 43 private Integer orderCount;
44 44
45 - @Schema(description = "付款人数", example = "20") 45 + @Schema(description = "付款人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
46 private Integer userCount; 46 private Integer userCount;
47 47
48 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 48 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
2 2
3 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; 3 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
4 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
@@ -18,6 +18,6 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO { @@ -18,6 +18,6 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
18 private Long id; 18 private Long id;
19 19
20 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 20 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
21 - private List<SeckillProductUpdateReqVO> products; 21 + private List<SeckillProductBaseVO> products;
22 22
23 } 23 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
@@ -22,7 +22,7 @@ public class SeckillProductBaseVO { @@ -22,7 +22,7 @@ public class SeckillProductBaseVO {
22 @NotNull(message = "秒杀金额,单位:分不能为空") 22 @NotNull(message = "秒杀金额,单位:分不能为空")
23 private Integer seckillPrice; 23 private Integer seckillPrice;
24 24
25 - @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED) 25 + @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
26 @NotNull(message = "秒杀库存不能为空") 26 @NotNull(message = "秒杀库存不能为空")
27 private Integer stock; 27 private Integer stock;
28 28
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
@@ -2,22 +2,26 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon; @@ -2,22 +2,26 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
5 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO;
6 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO; 7 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO;
7 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; 8 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO;
8 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; 9 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO;
9 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO; 10 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
  11 +import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
10 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
11 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
12 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
13 import org.springframework.web.bind.annotation.*; 15 import org.springframework.web.bind.annotation.*;
14 16
  17 +import javax.annotation.Resource;
15 import java.time.LocalDateTime; 18 import java.time.LocalDateTime;
16 import java.util.ArrayList; 19 import java.util.ArrayList;
17 import java.util.List; 20 import java.util.List;
18 import java.util.Random; 21 import java.util.Random;
19 22
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
21 25
22 @Tag(name = "用户 App - 优惠劵") 26 @Tag(name = "用户 App - 优惠劵")
23 @RestController 27 @RestController
@@ -25,6 +29,9 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -25,6 +29,9 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 @Validated 29 @Validated
26 public class AppCouponController { 30 public class AppCouponController {
27 31
  32 + @Resource
  33 + private CouponService couponService;
  34 +
28 // TODO 芋艿:待实现 35 // TODO 芋艿:待实现
29 @PostMapping("/take") 36 @PostMapping("/take")
30 @Operation(summary = "领取优惠劵") 37 @Operation(summary = "领取优惠劵")
@@ -93,4 +100,11 @@ public class AppCouponController { @@ -93,4 +100,11 @@ public class AppCouponController {
93 return success(new PageResult<>(list, 20L)); 100 return success(new PageResult<>(list, 20L));
94 } 101 }
95 102
  103 + @GetMapping(value = "/get-unused-count")
  104 + @Operation(summary = "获得未使用的优惠劵数量")
  105 + @PreAuthenticated
  106 + public CommonResult<Long> getUnusedCouponCount() {
  107 + return success(couponService.getUnusedCouponCount(getLoginUserId()));
  108 + }
  109 +
96 } 110 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/decorate/AppDecorateController.java
1 package cn.iocoder.yudao.module.promotion.controller.app.decorate; 1 package cn.iocoder.yudao.module.promotion.controller.app.decorate;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 5 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 import cn.iocoder.yudao.module.promotion.controller.app.decorate.vo.AppDecorateComponentRespVO; 6 import cn.iocoder.yudao.module.promotion.controller.app.decorate.vo.AppDecorateComponentRespVO;
  7 +import cn.iocoder.yudao.module.promotion.convert.decorate.DecorateComponentConvert;
6 import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum; 8 import cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum;
7 import cn.iocoder.yudao.module.promotion.service.decorate.DecorateComponentService; 9 import cn.iocoder.yudao.module.promotion.service.decorate.DecorateComponentService;
8 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
@@ -15,9 +17,9 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -15,9 +17,9 @@ import org.springframework.web.bind.annotation.RequestParam;
15 import org.springframework.web.bind.annotation.RestController; 17 import org.springframework.web.bind.annotation.RestController;
16 18
17 import javax.annotation.Resource; 19 import javax.annotation.Resource;
  20 +import java.util.List;
18 21
19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
20 -import static cn.iocoder.yudao.module.promotion.convert.decorate.DecorateComponentConvert.INSTANCE;  
21 23
22 @Tag(name = "用户 APP - 店铺装修") 24 @Tag(name = "用户 APP - 店铺装修")
23 @RestController 25 @RestController
@@ -28,12 +30,13 @@ public class AppDecorateController { @@ -28,12 +30,13 @@ public class AppDecorateController {
28 @Resource 30 @Resource
29 private DecorateComponentService decorateComponentService; 31 private DecorateComponentService decorateComponentService;
30 32
31 - @GetMapping("/get-page-components")  
32 - @Operation(summary = "获取装修页面组件")  
33 - @Parameter(name = "pageId", description = "页面 id", required = true)  
34 - public CommonResult<AppDecorateComponentRespVO> getPageComponents(  
35 - @RequestParam("pageId") @InEnum(DecoratePageEnum.class) Integer pageId) {  
36 - return success(INSTANCE.appConvert(pageId, decorateComponentService.getPageComponents(pageId))); 33 + @GetMapping("/list")
  34 + @Operation(summary = "获取指定页面的组件列表")
  35 + @Parameter(name = "page", description = "页面编号", required = true)
  36 + public CommonResult<List<AppDecorateComponentRespVO>> getDecorateComponentListByPage(
  37 + @RequestParam("page") @InEnum(DecoratePageEnum.class) Integer page) {
  38 + return success(DecorateComponentConvert.INSTANCE.convertList(
  39 + decorateComponentService.getDecorateComponentListByPage(page, CommonStatusEnum.ENABLE.getStatus())));
37 } 40 }
38 41
39 } 42 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/decorate/vo/AppDecorateComponentRespVO.java
@@ -3,28 +3,14 @@ package cn.iocoder.yudao.module.promotion.controller.app.decorate.vo; @@ -3,28 +3,14 @@ package cn.iocoder.yudao.module.promotion.controller.app.decorate.vo;
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 5
6 -import java.util.List;  
7 -  
8 -@Schema(description = "用户 App - 页面装修 Resp VO") 6 +@Schema(description = "用户 App - 页面组件 Resp VO")
9 @Data 7 @Data
10 public class AppDecorateComponentRespVO { 8 public class AppDecorateComponentRespVO {
11 9
12 - @Schema(description = "页面 id ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
13 - private Integer pageId;  
14 -  
15 - @Schema(description = "页面组件", requiredMode = Schema.RequiredMode.REQUIRED, example = "TODO")  
16 - private List<AppComponentRespVO> components;  
17 -  
18 - @Schema(description = "用户 App - 页面组件 Resp VO")  
19 - @Data  
20 - public static class AppComponentRespVO {  
21 -  
22 - @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")  
23 - private String code;  
24 -  
25 - @Schema(description = "组件的内容配置项", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")  
26 - private String value; 10 + @Schema(description = "组件编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "nav-menu")
  11 + private String code;
27 12
28 - } 13 + @Schema(description = "组件的内容配置项", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "TODO")
  14 + private String value;
29 15
30 } 16 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/bargain/BargainActivityConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.convert.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityBaseVO;
  5 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityRespVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO;
  7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
  8 +import org.mapstruct.Mapper;
  9 +import org.mapstruct.factory.Mappers;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 拼团活动 Convert
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@Mapper
  19 +public interface BargainActivityConvert {
  20 +
  21 + BargainActivityConvert INSTANCE = Mappers.getMapper(BargainActivityConvert.class);
  22 +
  23 + BargainActivityDO convert(BargainActivityBaseVO bean);
  24 +
  25 + BargainActivityDO convert(BargainActivityUpdateReqVO bean);
  26 +
  27 + BargainActivityRespVO convert(BargainActivityDO bean);
  28 +
  29 + List<BargainActivityRespVO> convertList(List<BargainActivityDO> list);
  30 +
  31 + PageResult<BargainActivityRespVO> convertPage(PageResult<BargainActivityDO> page);
  32 +
  33 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.combination; 1 package cn.iocoder.yudao.module.promotion.convert.combination;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 6 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO; 7 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  8 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 9 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
8 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExcelVO;  
9 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO; 10 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
10 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 11 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
11 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; 12 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
12 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO; 13 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
13 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;  
14 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
15 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;  
16 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO; 14 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  15 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
  16 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
17 import org.mapstruct.Mapper; 17 import org.mapstruct.Mapper;
18 import org.mapstruct.Mapping; 18 import org.mapstruct.Mapping;
19 import org.mapstruct.Mappings; 19 import org.mapstruct.Mappings;
20 -import org.mapstruct.Named;  
21 import org.mapstruct.factory.Mappers; 20 import org.mapstruct.factory.Mappers;
22 21
23 -import java.time.LocalDateTime;  
24 -import java.util.ArrayList;  
25 import java.util.List; 22 import java.util.List;
26 import java.util.Map; 23 import java.util.Map;
27 24
@@ -37,38 +34,16 @@ public interface CombinationActivityConvert { @@ -37,38 +34,16 @@ public interface CombinationActivityConvert {
37 34
38 CombinationActivityConvert INSTANCE = Mappers.getMapper(CombinationActivityConvert.class); 35 CombinationActivityConvert INSTANCE = Mappers.getMapper(CombinationActivityConvert.class);
39 36
40 - @Mappings({  
41 - @Mapping(target = "startTime", expression = "java(bean.getActivityTime()[0])"),  
42 - @Mapping(target = "endTime", expression = "java(bean.getActivityTime()[1])")  
43 - })  
44 CombinationActivityDO convert(CombinationActivityCreateReqVO bean); 37 CombinationActivityDO convert(CombinationActivityCreateReqVO bean);
45 38
46 - @Mappings({  
47 - @Mapping(target = "startTime", expression = "java(bean.getActivityTime()[0])"),  
48 - @Mapping(target = "endTime", expression = "java(bean.getActivityTime()[1])")  
49 - })  
50 CombinationActivityDO convert(CombinationActivityUpdateReqVO bean); 39 CombinationActivityDO convert(CombinationActivityUpdateReqVO bean);
51 40
52 - @Named("mergeTime")  
53 - default LocalDateTime[] mergeTime(LocalDateTime startTime, LocalDateTime endTime) {  
54 - // TODO 有点怪第一次这样写 hh  
55 - LocalDateTime[] localDateTime = new LocalDateTime[2];  
56 - localDateTime[0] = startTime;  
57 - localDateTime[1] = endTime;  
58 - return localDateTime;  
59 - }  
60 -  
61 - @Mappings({  
62 - @Mapping(target = "activityTime", expression = "java(mergeTime(bean.getStartTime(),bean.getEndTime()))")  
63 - })  
64 CombinationActivityRespVO convert(CombinationActivityDO bean); 41 CombinationActivityRespVO convert(CombinationActivityDO bean);
65 42
66 CombinationProductRespVO convert(CombinationProductDO bean); 43 CombinationProductRespVO convert(CombinationProductDO bean);
67 44
68 - default CombinationActivityRespVO convert(CombinationActivityDO bean, List<CombinationProductDO> productDOs) {  
69 - CombinationActivityRespVO respVO = convert(bean);  
70 - respVO.setProducts(convertList2(productDOs));  
71 - return respVO; 45 + default CombinationActivityRespVO convert(CombinationActivityDO activity, List<CombinationProductDO> products) {
  46 + return convert(activity).setProducts(convertList2(products));
72 } 47 }
73 48
74 List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list); 49 List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
@@ -78,13 +53,13 @@ public interface CombinationActivityConvert { @@ -78,13 +53,13 @@ public interface CombinationActivityConvert {
78 default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page, 53 default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page,
79 List<CombinationProductDO> productList, 54 List<CombinationProductDO> productList,
80 List<ProductSpuRespDTO> spuList) { 55 List<ProductSpuRespDTO> spuList) {
81 - // TODO @puhui999:c -> c 可以去掉哈  
82 - Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId, c -> c); 56 + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
83 PageResult<CombinationActivityRespVO> pageResult = convertPage(page); 57 PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
84 pageResult.getList().forEach(item -> { 58 pageResult.getList().forEach(item -> {
85 - // TODO @puhui999:最好 MapUtils.findAndThen,万一没找到呢,啊哈哈。  
86 - item.setSpuName(spuMap.get(item.getSpuId()).getName());  
87 - item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl()); 59 + MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
  60 + item.setSpuName(spu.getName());
  61 + item.setPicUrl(spu.getPicUrl());
  62 + });
88 item.setProducts(convertList2(productList)); 63 item.setProducts(convertList2(productList));
89 }); 64 });
90 return pageResult; 65 return pageResult;
@@ -92,47 +67,31 @@ public interface CombinationActivityConvert { @@ -92,47 +67,31 @@ public interface CombinationActivityConvert {
92 67
93 List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs); 68 List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs);
94 69
95 - List<CombinationActivityExcelVO> convertList02(List<CombinationActivityDO> list);  
96 -  
97 @Mappings({ 70 @Mappings({
98 @Mapping(target = "id", ignore = true), 71 @Mapping(target = "id", ignore = true),
99 - @Mapping(target = "activityId", source = "activityDO.id"),  
100 - @Mapping(target = "spuId", source = "activityDO.spuId"),  
101 - @Mapping(target = "skuId", source = "vo.skuId"),  
102 - @Mapping(target = "activePrice", source = "vo.activePrice"),  
103 - @Mapping(target = "activityStartTime", source = "activityDO.startTime"),  
104 - @Mapping(target = "activityEndTime", source = "activityDO.endTime") 72 + @Mapping(target = "activityId", source = "activity.id"),
  73 + @Mapping(target = "spuId", source = "activity.spuId"),
  74 + @Mapping(target = "skuId", source = "product.skuId"),
  75 + @Mapping(target = "combinationPrice", source = "product.combinationPrice"),
  76 + @Mapping(target = "activityStartTime", source = "activity.startTime"),
  77 + @Mapping(target = "activityEndTime", source = "activity.endTime")
105 }) 78 })
106 - CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);  
107 -  
108 - default List<CombinationProductDO> convertList(CombinationActivityDO activityDO, List<? extends CombinationProductBaseVO> products) {  
109 - List<CombinationProductDO> list = new ArrayList<>();  
110 - products.forEach(sku -> {  
111 - CombinationProductDO productDO = convert(activityDO, sku);  
112 - // TODO 状态设置  
113 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());  
114 - list.add(productDO);  
115 - });  
116 - return list; 79 + CombinationProductDO convert(CombinationActivityDO activity, CombinationProductBaseVO product);
  80 +
  81 + default List<CombinationProductDO> convertList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activity) {
  82 + return CollectionUtils.convertList(products, item -> convert(activity, item).setActivityStatus(activity.getStatus()));
117 } 83 }
118 84
119 - // TODO @puhui999:这个方法的参数,调整成 productDOs、vos、activityDO;因为 productDOs 是主角;  
120 - // 然后,这个方法,感觉不是为了 convert,而是为了补全;  
121 - default List<CombinationProductDO> convertList1(CombinationActivityDO activityDO,  
122 - List<CombinationProductUpdateReqVO> vos,  
123 - List<CombinationProductDO> productDOs) {  
124 - Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId);  
125 - List<CombinationProductDO> list = new ArrayList<>();  
126 - vos.forEach(sku -> {  
127 - CombinationProductDO productDO = convert(activityDO, sku);  
128 - productDO.setId(longMap.get(sku.getSkuId()));  
129 - // TODO @puhui999:是是不是用 activityDO 的状态;  
130 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());  
131 - list.add(productDO);  
132 - });  
133 - return list; 85 + default List<CombinationProductDO> convertList(List<CombinationProductBaseVO> updateProductVOs,
  86 + List<CombinationProductDO> products, CombinationActivityDO activity) {
  87 + Map<Long, Long> productMap = convertMap(products, CombinationProductDO::getSkuId, CombinationProductDO::getId);
  88 + return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)
  89 + .setId(productMap.get(updateProductVO.getSkuId()))
  90 + .setActivityStatus(activity.getStatus()));
134 } 91 }
135 92
136 - CombinationRecordDO convert(CombinationRecordReqDTO reqDTO); 93 + CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO);
  94 +
  95 + List<CombinationRecordRespDTO> convert(List<CombinationRecordDO> bean);
137 96
138 } 97 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/decorate/DecorateComponentConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.decorate; 1 package cn.iocoder.yudao.module.promotion.convert.decorate;
2 2
3 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
4 -import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO;  
5 import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentRespVO; 3 import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentRespVO;
  4 +import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO;
6 import cn.iocoder.yudao.module.promotion.controller.app.decorate.vo.AppDecorateComponentRespVO; 5 import cn.iocoder.yudao.module.promotion.controller.app.decorate.vo.AppDecorateComponentRespVO;
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.DecorateComponentDO; 6 import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.DecorateComponentDO;
8 import org.mapstruct.Mapper; 7 import org.mapstruct.Mapper;
@@ -10,33 +9,15 @@ import org.mapstruct.factory.Mappers; @@ -10,33 +9,15 @@ import org.mapstruct.factory.Mappers;
10 9
11 import java.util.List; 10 import java.util.List;
12 11
13 -import static cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentRespVO.*;  
14 -import static cn.iocoder.yudao.module.promotion.controller.app.decorate.vo.AppDecorateComponentRespVO.*;  
15 -  
16 @Mapper 12 @Mapper
17 public interface DecorateComponentConvert { 13 public interface DecorateComponentConvert {
18 14
19 DecorateComponentConvert INSTANCE = Mappers.getMapper(DecorateComponentConvert.class); 15 DecorateComponentConvert INSTANCE = Mappers.getMapper(DecorateComponentConvert.class);
20 16
21 - default List<DecorateComponentDO> convertList(Integer pageId, List<DecorateComponentSaveReqVO.ComponentReqVO> components) {  
22 - return CollectionUtils.convertList(components, c -> convert(pageId, c));  
23 - }  
24 -  
25 - default DecorateComponentRespVO convert2(Integer pageId, List<DecorateComponentDO> list) {  
26 - List<ComponentRespVO> components = CollectionUtils.convertList(list, this::convert3);  
27 - return new DecorateComponentRespVO().setPageId(pageId).setComponents(components);  
28 - }  
29 -  
30 - DecorateComponentDO convert(Integer pageId, DecorateComponentSaveReqVO.ComponentReqVO reqVO);  
31 -  
32 - ComponentRespVO convert3(DecorateComponentDO componentDO); 17 + List<DecorateComponentRespVO> convertList02(List<DecorateComponentDO> list);
33 18
34 - // ========== App convert ==========  
35 - default AppDecorateComponentRespVO appConvert(Integer pageId, List<DecorateComponentDO> list) {  
36 - List<AppComponentRespVO> components = CollectionUtils.convertList(list, this::appConvert2);  
37 - return new AppDecorateComponentRespVO().setPageId(pageId).setComponents(components);  
38 - } 19 + DecorateComponentDO convert(DecorateComponentSaveReqVO bean);
39 20
40 - AppComponentRespVO appConvert2(DecorateComponentDO bean); 21 + List<AppDecorateComponentRespVO> convertList(List<DecorateComponentDO> list);
41 22
42 } 23 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
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.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; 7 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; 8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se
10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; 10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO; 11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
12 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO; 12 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
13 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;  
14 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; 13 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
15 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; 14 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
16 import org.mapstruct.Mapper; 15 import org.mapstruct.Mapper;
@@ -18,7 +17,6 @@ import org.mapstruct.Mapping; @@ -18,7 +17,6 @@ import org.mapstruct.Mapping;
18 import org.mapstruct.Mappings; 17 import org.mapstruct.Mappings;
19 import org.mapstruct.factory.Mappers; 18 import org.mapstruct.factory.Mappers;
20 19
21 -import java.util.ArrayList;  
22 import java.util.List; 20 import java.util.List;
23 import java.util.Map; 21 import java.util.Map;
24 22
@@ -42,61 +40,43 @@ public interface SeckillActivityConvert { @@ -42,61 +40,43 @@ public interface SeckillActivityConvert {
42 40
43 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page); 41 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
44 42
45 - default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page, List<SeckillProductDO> seckillProducts, List<ProductSpuRespDTO> spuList) {  
46 - Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId, c -> c); 43 + default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page,
  44 + List<SeckillProductDO> seckillProducts,
  45 + List<ProductSpuRespDTO> spuList) {
47 PageResult<SeckillActivityRespVO> pageResult = convertPage(page); 46 PageResult<SeckillActivityRespVO> pageResult = convertPage(page);
  47 + // 拼接商品
  48 + Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId);
48 pageResult.getList().forEach(item -> { 49 pageResult.getList().forEach(item -> {
49 - item.setSpuName(spuMap.get(item.getSpuId()).getName());  
50 - item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());  
51 item.setProducts(convertList2(seckillProducts)); 50 item.setProducts(convertList2(seckillProducts));
  51 + MapUtils.findAndThen(spuMap, item.getSpuId(),
  52 + spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
52 }); 53 });
53 return pageResult; 54 return pageResult;
54 } 55 }
55 56
56 - SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity); 57 + SeckillActivityDetailRespVO convert1(SeckillActivityDO activity);
57 58
58 - default SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts) {  
59 - SeckillActivityDetailRespVO respVO = convert1(seckillActivity);  
60 - respVO.setProducts(convertList2(seckillProducts));  
61 - return respVO; 59 + default SeckillActivityDetailRespVO convert(SeckillActivityDO activity, List<SeckillProductDO> products) {
  60 + return convert1(activity).setProducts(convertList2(products));
62 } 61 }
63 62
64 @Mappings({ 63 @Mappings({
65 @Mapping(target = "id", ignore = true), 64 @Mapping(target = "id", ignore = true),
66 - @Mapping(target = "activityId", source = "activityDO.id"),  
67 - @Mapping(target = "configIds", source = "activityDO.configIds"),  
68 - @Mapping(target = "spuId", source = "activityDO.spuId"),  
69 - @Mapping(target = "skuId", source = "vo.skuId"),  
70 - @Mapping(target = "seckillPrice", source = "vo.seckillPrice"),  
71 - @Mapping(target = "stock", source = "vo.stock"),  
72 - @Mapping(target = "activityStartTime", source = "activityDO.startTime"),  
73 - @Mapping(target = "activityEndTime", source = "activityDO.endTime") 65 + @Mapping(target = "activityId", source = "activity.id"),
  66 + @Mapping(target = "configIds", source = "activity.configIds"),
  67 + @Mapping(target = "spuId", source = "activity.spuId"),
  68 + @Mapping(target = "skuId", source = "product.skuId"),
  69 + @Mapping(target = "seckillPrice", source = "product.seckillPrice"),
  70 + @Mapping(target = "stock", source = "product.stock"),
  71 + @Mapping(target = "activityStartTime", source = "activity.startTime"),
  72 + @Mapping(target = "activityEndTime", source = "activity.endTime")
74 }) 73 })
75 - SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);  
76 -  
77 - default List<SeckillProductDO> convertList(SeckillActivityDO activityDO, List<? extends SeckillProductBaseVO> products) {  
78 - List<SeckillProductDO> list = new ArrayList<>();  
79 - products.forEach(sku -> {  
80 - SeckillProductDO productDO = convert(activityDO, sku);  
81 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());  
82 - list.add(productDO);  
83 - });  
84 - return list;  
85 - } 74 + SeckillProductDO convert(SeckillActivityDO activity, SeckillProductBaseVO product);
86 75
87 - // TODO @puhui999:同拼团那个 convert 想通的情况哈。  
88 - default List<SeckillProductDO> convertList1(SeckillActivityDO activityDO, List<SeckillProductUpdateReqVO> vos, List<SeckillProductDO> productDOs) {  
89 - Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);  
90 - List<SeckillProductDO> list = new ArrayList<>();  
91 - vos.forEach(sku -> {  
92 - SeckillProductDO productDO = convert(activityDO, sku);  
93 - productDO.setId(longMap.get(sku.getSkuId()));  
94 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());  
95 - list.add(productDO);  
96 - });  
97 - return list; 76 + default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activity) {
  77 + return CollectionUtils.convertList(products, item -> convert(activity, item).setActivityStatus(activity.getStatus()));
98 } 78 }
99 79
100 - List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs); 80 + List<SeckillProductRespVO> convertList2(List<SeckillProductDO> list);
101 81
102 } 82 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/bargain/BargainActivityDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +/**
  13 + * 砍价活动 DO
  14 + *
  15 + * @author HUIHUI
  16 + */
  17 +@TableName("promotion_bargain_activity")
  18 +@KeySequence("promotion_bargain_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class BargainActivityDO extends BaseDO {
  26 +
  27 + /**
  28 + * 砍价活动编号
  29 + */
  30 + @TableId
  31 + private Long id;
  32 +
  33 + /**
  34 + * 砍价活动名称
  35 + */
  36 + private String name;
  37 +
  38 + /**
  39 + * 活动开始时间
  40 + */
  41 + private LocalDateTime startTime;
  42 + /**
  43 + * 活动结束时间
  44 + */
  45 + private LocalDateTime endTime;
  46 +
  47 + /**
  48 + * 活动状态
  49 + *
  50 + * 枚举 {@link CommonStatusEnum}
  51 + */
  52 + private Integer status;
  53 +
  54 + /**
  55 + * 商品 SPU 编号
  56 + */
  57 + private Long spuId;
  58 + /**
  59 + * 商品 SKU 编号
  60 + */
  61 + private Long skuId;
  62 + /**
  63 + * 砍价起始价格,单位分
  64 + */
  65 + private Integer bargainFirstPrice;
  66 + /**
  67 + * 砍价底价,单位:分
  68 + */
  69 + private Integer bargainPrice;
  70 + /**
  71 + * 砍价活动库存
  72 + */
  73 + private Integer stock;
  74 +
  75 + /**
  76 + * 达到该人数,才能砍到低价
  77 + */
  78 + private Integer userSize;
  79 + /**
  80 + * 最大帮砍次数
  81 + */
  82 + private Integer bargainCount;
  83 +
  84 + /**
  85 + * 总限购数量
  86 + */
  87 + private Integer totalLimitCount;
  88 + /**
  89 + * 用户每次砍价的最小金额,单位:分
  90 + */
  91 + private Integer randomMinPrice;
  92 + /**
  93 + * 用户每次砍价的最大金额,单位:分
  94 + */
  95 + private Integer randomMaxPrice;
  96 + /**
  97 + * 砍价成功数量
  98 + */
  99 + private Integer successCount;
  100 +
  101 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDeliveryDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/bargain/BargainAssistDO.java
1 -package cn.iocoder.yudao.module.trade.dal.dataobject.order; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.bargain;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;  
5 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
7 import lombok.*; 7 import lombok.*;
8 8
9 -// TODO @puhui999:  
10 /** 9 /**
11 - * 交易订单发货记录 DO 10 + * 砍价助力 DO TODO 芋艿:表结构
12 * 11 *
13 * @author HUIHUI 12 * @author HUIHUI
14 */ 13 */
15 -@TableName("trade_order_delivery")  
16 -@KeySequence("trade_order_delivery_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 14 +@TableName("promotion_bargain_assist")
  15 +@KeySequence("promotion_bargain_assist_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
17 @Data 16 @Data
18 @EqualsAndHashCode(callSuper = true) 17 @EqualsAndHashCode(callSuper = true)
19 @ToString(callSuper = true) 18 @ToString(callSuper = true)
20 @Builder 19 @Builder
21 @NoArgsConstructor 20 @NoArgsConstructor
22 @AllArgsConstructor 21 @AllArgsConstructor
23 -public class TradeOrderDeliveryDO extends BaseDO { 22 +public class BargainAssistDO extends BaseDO {
24 23
25 /** 24 /**
26 - * 订单发货记录 id 25 + * 编号
27 */ 26 */
  27 + @TableId
28 private Long id; 28 private Long id;
  29 +
29 /** 30 /**
30 - * 订单 id 31 + * 砍价活动编号
31 */ 32 */
32 - private Long orderId; 33 + private Long activityId;
  34 +
33 /** 35 /**
34 - * 订单项 id TODO 要不要一个发货记录可对应多个订单项? 36 + * 砍价记录编号
35 */ 37 */
36 - private Long orderItemId; 38 + private Long recordId;
  39 +
37 /** 40 /**
38 * 用户编号 41 * 用户编号
39 - *  
40 - * 关联 MemberUserDO 的 id 编号  
41 */ 42 */
42 private Long userId; 43 private Long userId;
  44 +
43 /** 45 /**
44 - * 配送方式  
45 - *  
46 - * 枚举 {@link DeliveryTypeEnum}  
47 - */  
48 - private Integer deliveryType;  
49 - /**  
50 - * 发货物流公司编号  
51 - */  
52 - private Long logisticsId;  
53 - /**  
54 - * 发货物流单号 46 + * 减少价格。单位分
55 */ 47 */
56 - private String logisticsNo;  
57 -  
58 - // TODO 同城配送 48 + private Integer reducePrice;
59 49
60 } 50 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/bargain/BargainRecordDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 砍价记录 DO TODO
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@TableName("promotion_bargain_record")
  17 +@KeySequence("promotion_bargain_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class BargainRecordDO extends BaseDO {
  25 +
  26 + /**
  27 + * 编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 +
  32 + /**
  33 + * 砍价活动编号
  34 + */
  35 + private Long activityId;
  36 +
  37 + /**
  38 + * 用户编号
  39 + */
  40 + private Long userId;
  41 +
  42 + /**
  43 + * 商品 SPU 编号
  44 + */
  45 + private Long spuId;
  46 +
  47 + /**
  48 + * 商品 SKU 编号
  49 + */
  50 + private Long skuId;
  51 +
  52 + /**
  53 + * 砍价底价,单位分
  54 + */
  55 + private Integer bargainPrice;
  56 +
  57 + /**
  58 + * 商品原价,单位分
  59 + */
  60 + private Integer price;
  61 +
  62 + /**
  63 + * 应付金额,单位分
  64 + */
  65 + private Integer payPrice;
  66 +
  67 + /**
  68 + * 状态1 - 砍价中;2- 砍价成功;3 - 砍价失败
  69 + */
  70 + private Integer status;
  71 +
  72 + /**
  73 + * 订单编号
  74 + */
  75 + private Long orderId;
  76 +
  77 + /**
  78 + * 结束时间
  79 + */
  80 + private LocalDateTime endTime;
  81 +
  82 + /**
  83 + * 过期时间
  84 + */
  85 + private Data expireTime;
  86 +
  87 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java
1 -package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination;
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.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@@ -9,7 +9,6 @@ import lombok.*; @@ -9,7 +9,6 @@ import lombok.*;
9 9
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
11 11
12 -// TODO @puhui999:是不是应该在 combination 哈?  
13 /** 12 /**
14 * 拼团活动 DO 13 * 拼团活动 DO
15 * 14 *
@@ -63,11 +62,11 @@ public class CombinationActivityDO extends BaseDO { @@ -63,11 +62,11 @@ public class CombinationActivityDO extends BaseDO {
63 /** 62 /**
64 * 开团组数 63 * 开团组数
65 */ 64 */
66 - private Integer totalNum; 65 + private Integer totalCount;
67 /** 66 /**
68 * 成团组数 67 * 成团组数
69 */ 68 */
70 - private Integer successNum; 69 + private Integer successCount;
71 /** 70 /**
72 * 参与人数 71 * 参与人数
73 */ 72 */
@@ -77,7 +76,7 @@ public class CombinationActivityDO extends BaseDO { @@ -77,7 +76,7 @@ public class CombinationActivityDO extends BaseDO {
77 */ 76 */
78 private Integer virtualGroup; 77 private Integer virtualGroup;
79 /** 78 /**
80 - * 活动状态:0开启 1关闭 79 + * 活动状态
81 * 80 *
82 * 枚举 {@link CommonStatusEnum} 81 * 枚举 {@link CommonStatusEnum}
83 */ 82 */
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java
1 -package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination;
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;
@@ -41,20 +41,27 @@ public class CombinationProductDO extends BaseDO { @@ -41,20 +41,27 @@ public class CombinationProductDO extends BaseDO {
41 */ 41 */
42 private Long skuId; 42 private Long skuId;
43 /** 43 /**
  44 + * 拼团价格,单位分
  45 + */
  46 + private Integer combinationPrice;
  47 +
  48 + /**
44 * 拼团商品状态 49 * 拼团商品状态
  50 + *
  51 + * 关联 {@link CombinationActivityDO#getStatus()}
45 */ 52 */
46 private Integer activityStatus; 53 private Integer activityStatus;
47 /** 54 /**
48 * 活动开始时间点 55 * 活动开始时间点
  56 + *
  57 + * 冗余 {@link CombinationActivityDO#getStartTime()}
49 */ 58 */
50 private LocalDateTime activityStartTime; 59 private LocalDateTime activityStartTime;
51 /** 60 /**
52 * 活动结束时间点 61 * 活动结束时间点
  62 + *
  63 + * 冗余 {@link CombinationActivityDO#getEndTime()}
53 */ 64 */
54 private LocalDateTime activityEndTime; 65 private LocalDateTime activityEndTime;
55 - /**  
56 - * 拼团价格,单位分  
57 - */  
58 - private Integer activePrice;  
59 66
60 } 67 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java
1 -package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 4 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
@@ -12,6 +12,9 @@ import java.time.LocalDateTime; @@ -12,6 +12,9 @@ import java.time.LocalDateTime;
12 /** 12 /**
13 * 拼团记录 DO 13 * 拼团记录 DO
14 * 14 *
  15 + * 1. 用户参与拼团时,会创建一条记录
  16 + * 2. 团长的拼团记录,和参团人的拼团记录,通过 {@link #headId} 关联
  17 + *
15 * @author HUIHUI 18 * @author HUIHUI
16 */ 19 */
17 @TableName("promotion_combination_record") 20 @TableName("promotion_combination_record")
@@ -49,7 +52,7 @@ public class CombinationRecordDO extends BaseDO { @@ -49,7 +52,7 @@ public class CombinationRecordDO extends BaseDO {
49 /** 52 /**
50 * 团长编号 53 * 团长编号
51 * 54 *
52 - * 关联 {@link CombinationRecordDO#getUserId()} 55 + * 关联 {@link CombinationRecordDO#getId()}
53 */ 56 */
54 private Long headId; 57 private Long headId;
55 /** 58 /**
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/decorate/DecorateComponentDO.java
@@ -26,13 +26,14 @@ public class DecorateComponentDO extends BaseDO { @@ -26,13 +26,14 @@ public class DecorateComponentDO extends BaseDO {
26 26
27 /** 27 /**
28 * 所属页面 id 28 * 所属页面 id
29 - * 枚举 {@link DecoratePageEnum#getId()} 29 + *
  30 + * 枚举 {@link DecoratePageEnum#getPage()}
30 */ 31 */
31 - private Integer pageId; 32 + private Integer page;
32 33
33 /** 34 /**
34 - * 组件编码  
35 - * 枚举 {@link DecorateComponentEnum#getCode()} 35 + * 组件编码
  36 + * 枚举 {@link DecorateComponentEnum#getCode()}
36 */ 37 */
37 private String code; 38 private String code;
38 39
@@ -47,4 +48,5 @@ public class DecorateComponentDO extends BaseDO { @@ -47,4 +48,5 @@ public class DecorateComponentDO extends BaseDO {
47 * 枚举 {@link CommonStatusEnum} 48 * 枚举 {@link CommonStatusEnum}
48 */ 49 */
49 private Integer status; 50 private Integer status;
  51 +
50 } 52 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.mysql.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
  7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 砍价活动 Mapper
  14 + *
  15 + * @author HUIHUI
  16 + */
  17 +@Mapper
  18 +public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> {
  19 +
  20 + default PageResult<BargainActivityDO> selectPage(BargainActivityPageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<BargainActivityDO>()
  22 + .likeIfPresent(BargainActivityDO::getName, reqVO.getName())
  23 + .eqIfPresent(BargainActivityDO::getStatus, reqVO.getStatus())
  24 + .orderByDesc(BargainActivityDO::getId));
  25 + }
  26 +
  27 + default List<BargainActivityDO> selectListByStatus(Integer status) {
  28 + return selectList(BargainActivityDO::getStatus, status);
  29 + }
  30 +
  31 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainRecordMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.mysql.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainRecordDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * 砍价记录 Mapper
  9 + *
  10 + * @author HUIHUI
  11 + */
  12 +@Mapper
  13 +public interface BargainRecordMapper extends BaseMapperX<BargainRecordDO> {
  14 +
  15 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
1 -package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
8 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO; 7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 9
11 import java.util.List; 10 import java.util.List;
12 11
13 -// TODO @puhui999:是不是应该在 combination 哈?  
14 /** 12 /**
15 * 拼团活动 Mapper 13 * 拼团活动 Mapper
16 * 14 *
@@ -22,12 +20,6 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi @@ -22,12 +20,6 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi
22 default PageResult<CombinationActivityDO> selectPage(CombinationActivityPageReqVO reqVO) { 20 default PageResult<CombinationActivityDO> selectPage(CombinationActivityPageReqVO reqVO) {
23 return selectPage(reqVO, new LambdaQueryWrapperX<CombinationActivityDO>() 21 return selectPage(reqVO, new LambdaQueryWrapperX<CombinationActivityDO>()
24 .likeIfPresent(CombinationActivityDO::getName, reqVO.getName()) 22 .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
25 - .orderByDesc(CombinationActivityDO::getId));  
26 - }  
27 -  
28 - default List<CombinationActivityDO> selectList(CombinationActivityExportReqVO reqVO) {  
29 - return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()  
30 - .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())  
31 .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus()) 23 .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())
32 .orderByDesc(CombinationActivityDO::getId)); 24 .orderByDesc(CombinationActivityDO::getId));
33 } 25 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java
1 -package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductPageReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductPageReqVO;
8 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO; 7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 9
11 import java.util.Collection; 10 import java.util.Collection;
@@ -27,20 +26,7 @@ public interface CombinationProductMapper extends BaseMapperX&lt;CombinationProduct @@ -27,20 +26,7 @@ public interface CombinationProductMapper extends BaseMapperX&lt;CombinationProduct
27 .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus()) 26 .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
28 .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime()) 27 .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
29 .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime()) 28 .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
30 - .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())  
31 - .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())  
32 - .orderByDesc(CombinationProductDO::getId));  
33 - }  
34 -  
35 - default List<CombinationProductDO> selectList(CombinationProductExportReqVO reqVO) {  
36 - return selectList(new LambdaQueryWrapperX<CombinationProductDO>()  
37 - .eqIfPresent(CombinationProductDO::getActivityId, reqVO.getActivityId())  
38 - .eqIfPresent(CombinationProductDO::getSpuId, reqVO.getSpuId())  
39 - .eqIfPresent(CombinationProductDO::getSkuId, reqVO.getSkuId())  
40 - .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())  
41 - .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())  
42 - .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())  
43 - .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice()) 29 + .eqIfPresent(CombinationProductDO::getCombinationPrice, reqVO.getActivePrice())
44 .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime()) 30 .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
45 .orderByDesc(CombinationProductDO::getId)); 31 .orderByDesc(CombinationProductDO::getId));
46 } 32 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
1 -package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO; 5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
7 7
8 import java.util.List; 8 import java.util.List;
@@ -15,11 +15,28 @@ import java.util.List; @@ -15,11 +15,28 @@ import java.util.List;
15 @Mapper 15 @Mapper
16 public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> { 16 public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> {
17 17
18 - default CombinationRecordDO selectRecord(Long userId, Long orderId) { 18 + default CombinationRecordDO selectByUserIdAndOrderId(Long userId, Long orderId) {
19 return selectOne(CombinationRecordDO::getUserId, userId, 19 return selectOne(CombinationRecordDO::getUserId, userId,
20 CombinationRecordDO::getOrderId, orderId); 20 CombinationRecordDO::getOrderId, orderId);
21 } 21 }
22 22
  23 + default List<CombinationRecordDO> selectListByUserIdAndStatus(Long userId, Integer status) {
  24 + return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
  25 + .eq(CombinationRecordDO::getUserId, userId)
  26 + .eq(CombinationRecordDO::getStatus, status));
  27 + }
  28 + /**
  29 + * 查询拼团记录
  30 + *
  31 + * @param headId 团长编号
  32 + * @return 拼团记录
  33 + */
  34 + default CombinationRecordDO selectOneByHeadId(Long headId, Integer status) {
  35 + return selectOne(new LambdaQueryWrapperX<CombinationRecordDO>()
  36 + .eq(CombinationRecordDO::getId, headId)
  37 + .eq(CombinationRecordDO::getStatus, status));
  38 + }
  39 +
23 default List<CombinationRecordDO> selectListByHeadIdAndStatus(Long headId, Integer status) { 40 default List<CombinationRecordDO> selectListByHeadIdAndStatus(Long headId, Integer status) {
24 return selectList(new LambdaQueryWrapperX<CombinationRecordDO>() 41 return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
25 .eq(CombinationRecordDO::getHeadId, headId) 42 .eq(CombinationRecordDO::getHeadId, headId)
@@ -30,4 +47,16 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO @@ -30,4 +47,16 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO
30 return selectList(CombinationRecordDO::getStatus, status); 47 return selectList(CombinationRecordDO::getStatus, status);
31 } 48 }
32 49
  50 + /**
  51 + * 查询拼团记录
  52 + *
  53 + * @param userId 用户 id
  54 + * @param activityId 活动 id
  55 + * @return 拼团记录
  56 + */
  57 + default List<CombinationRecordDO> selectListByUserIdAndActivityId(Long userId, Long activityId) {
  58 + return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
  59 + .eq(CombinationRecordDO::getUserId, userId)
  60 + .eq(CombinationRecordDO::getActivityId, activityId));
  61 + }
33 } 62 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
@@ -49,4 +49,10 @@ public interface CouponMapper extends BaseMapperX&lt;CouponDO&gt; { @@ -49,4 +49,10 @@ public interface CouponMapper extends BaseMapperX&lt;CouponDO&gt; {
49 .eq(CouponDO::getId, id).eq(CouponDO::getStatus, status)); 49 .eq(CouponDO::getId, id).eq(CouponDO::getStatus, status));
50 } 50 }
51 51
  52 + default Long selectCountByUserIdAndStatus(Long userId, Integer status) {
  53 + return selectCount(new LambdaQueryWrapperX<CouponDO>()
  54 + .eq(CouponDO::getUserId, userId)
  55 + .eq(CouponDO::getStatus, status));
  56 + }
  57 +
52 } 58 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/decorate/DecorateComponentMapper.java
1 package cn.iocoder.yudao.module.promotion.dal.mysql.decorate; 1 package cn.iocoder.yudao.module.promotion.dal.mysql.decorate;
2 2
3 -import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.DecorateComponentDO;  
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.DecorateComponentDO;
5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
6 7
7 import java.util.List; 8 import java.util.List;
@@ -9,8 +10,15 @@ import java.util.List; @@ -9,8 +10,15 @@ import java.util.List;
9 @Mapper 10 @Mapper
10 public interface DecorateComponentMapper extends BaseMapperX<DecorateComponentDO> { 11 public interface DecorateComponentMapper extends BaseMapperX<DecorateComponentDO> {
11 12
12 - default List<DecorateComponentDO> selectByPage(Integer pageId){  
13 - return selectList(DecorateComponentDO::getPageId, pageId); 13 + default List<DecorateComponentDO> selectListByPageAndStatus(Integer page, Integer status) {
  14 + return selectList(new LambdaQueryWrapperX<DecorateComponentDO>()
  15 + .eq(DecorateComponentDO::getPage, page)
  16 + .eqIfPresent(DecorateComponentDO::getStatus, status));
  17 + }
  18 +
  19 + default DecorateComponentDO selectByPageAndCode(Integer page, String code) {
  20 + return selectOne(DecorateComponentDO::getPage, page,
  21 + DecorateComponentDO::getCode, code);
14 } 22 }
15 23
16 } 24 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
1 package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; 4 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
6 -import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;  
7 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Mapper;
8 6
9 import java.util.Collection; 7 import java.util.Collection;
@@ -25,15 +23,4 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; { @@ -25,15 +23,4 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; {
25 return selectList(SeckillProductDO::getActivityId, ids); 23 return selectList(SeckillProductDO::getActivityId, ids);
26 } 24 }
27 25
28 - default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) {  
29 - return selectList(SeckillProductDO::getSkuId, skuIds);  
30 - }  
31 -  
32 - default void updateTimeIdsByActivityId(Long id, List<Long> timeIds) {  
33 - new LambdaUpdateChainWrapper<>(this)  
34 - .set(SeckillProductDO::getConfigIds, CollUtil.join(timeIds, ","))  
35 - .eq(SeckillProductDO::getActivityId, id)  
36 - .update();  
37 - }  
38 -  
39 } 26 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityCreateReqVO;
  5 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO;
  7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
  8 +
  9 +import javax.validation.Valid;
  10 +
  11 +/**
  12 + * 砍价活动 Service 接口
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +public interface BargainActivityService {
  17 +
  18 + /**
  19 + * 创建砍价活动
  20 + *
  21 + * @param createReqVO 创建信息
  22 + * @return 编号
  23 + */
  24 + Long createBargainActivity(@Valid BargainActivityCreateReqVO createReqVO);
  25 +
  26 + /**
  27 + * 更新砍价活动
  28 + *
  29 + * @param updateReqVO 更新信息
  30 + */
  31 + void updateBargainActivity(@Valid BargainActivityUpdateReqVO updateReqVO);
  32 +
  33 + /**
  34 + * 删除砍价活动
  35 + *
  36 + * @param id 编号
  37 + */
  38 + void deleteBargainActivity(Long id);
  39 +
  40 + /**
  41 + * 获得砍价活动
  42 + *
  43 + * @param id 编号
  44 + * @return 砍价活动
  45 + */
  46 + BargainActivityDO getBargainActivity(Long id);
  47 +
  48 + /**
  49 + * 获得砍价活动分页
  50 + *
  51 + * @param pageReqVO 分页查询
  52 + * @return 砍价活动分页
  53 + */
  54 + PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO);
  55 +
  56 +
  57 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.bargain;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  7 +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  8 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityCreateReqVO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
  10 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO;
  11 +import cn.iocoder.yudao.module.promotion.convert.bargain.BargainActivityConvert;
  12 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
  13 +import cn.iocoder.yudao.module.promotion.dal.mysql.bargain.BargainActivityMapper;
  14 +import org.springframework.stereotype.Service;
  15 +import org.springframework.transaction.annotation.Transactional;
  16 +import org.springframework.validation.annotation.Validated;
  17 +
  18 +import javax.annotation.Resource;
  19 +import java.util.List;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;
  23 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
  24 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  25 +
  26 +/**
  27 + * 砍价活动 Service 实现类
  28 + *
  29 + * @author HUIHUI
  30 + */
  31 +@Service
  32 +@Validated
  33 +public class BargainActivityServiceImpl implements BargainActivityService {
  34 +
  35 + @Resource
  36 + private BargainActivityMapper bargainActivityMapper;
  37 +
  38 + @Resource
  39 + private ProductSkuApi productSkuApi;
  40 +
  41 + @Override
  42 + public Long createBargainActivity(BargainActivityCreateReqVO createReqVO) {
  43 + // 校验商品 SPU 是否存在是否参加的别的活动
  44 + validateBargainConflict(createReqVO.getSpuId(), null);
  45 + // 校验商品 sku 是否存在
  46 + validateSku(createReqVO.getSkuId());
  47 +
  48 + // 插入砍价活动
  49 + BargainActivityDO activityDO = BargainActivityConvert.INSTANCE.convert(createReqVO)
  50 + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setSuccessCount(0);
  51 + bargainActivityMapper.insert(activityDO);
  52 + return activityDO.getId();
  53 + }
  54 +
  55 + @Override
  56 + public void updateBargainActivity(BargainActivityUpdateReqVO updateReqVO) {
  57 + // 校验存在
  58 + BargainActivityDO activityDO = validateBargainActivityExists(updateReqVO.getId());
  59 + // 校验状态
  60 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
  61 + throw exception(BARGAIN_ACTIVITY_STATUS_DISABLE);
  62 + }
  63 + // 校验商品冲突
  64 + validateBargainConflict(updateReqVO.getSpuId(), updateReqVO.getId());
  65 + // 校验商品 sku 是否存在
  66 + validateSku(updateReqVO.getSkuId());
  67 +
  68 + // 更新
  69 + BargainActivityDO updateObj = BargainActivityConvert.INSTANCE.convert(updateReqVO);
  70 + bargainActivityMapper.updateById(updateObj);
  71 + }
  72 +
  73 + private void validateBargainConflict(Long spuId, Long activityId) {
  74 + // 查询所有开启的砍价活动
  75 + List<BargainActivityDO> activityList = bargainActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
  76 + if (activityId != null) { // 更新时排除自己
  77 + activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
  78 + }
  79 + // 校验商品 spu 是否参加了其它活动
  80 + if (anyMatch(activityList, activity -> ObjectUtil.equal(activity.getSpuId(), spuId))) {
  81 + throw exception(BARGAIN_ACTIVITY_SPU_CONFLICTS);
  82 + }
  83 + }
  84 +
  85 + private void validateSku(Long skuId) {
  86 + ProductSkuRespDTO sku = productSkuApi.getSku(skuId);
  87 + if (sku == null) {
  88 + throw exception(SKU_NOT_EXISTS);
  89 + }
  90 + }
  91 +
  92 + @Override
  93 + @Transactional(rollbackFor = Exception.class)
  94 + public void deleteBargainActivity(Long id) {
  95 + // 校验存在
  96 + BargainActivityDO activityDO = validateBargainActivityExists(id);
  97 + // 校验状态
  98 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
  99 + throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
  100 + }
  101 +
  102 + // 删除
  103 + bargainActivityMapper.deleteById(id);
  104 + }
  105 +
  106 + private BargainActivityDO validateBargainActivityExists(Long id) {
  107 + BargainActivityDO activityDO = bargainActivityMapper.selectById(id);
  108 + if (activityDO == null) {
  109 + throw exception(BARGAIN_ACTIVITY_NOT_EXISTS);
  110 + }
  111 + return activityDO;
  112 + }
  113 +
  114 + @Override
  115 + public BargainActivityDO getBargainActivity(Long id) {
  116 + return bargainActivityMapper.selectById(id);
  117 + }
  118 +
  119 + @Override
  120 + public PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO) {
  121 + return bargainActivityMapper.selectPage(pageReqVO);
  122 + }
  123 +
  124 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainRecordService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.bargain;
  2 +
  3 +
  4 +/**
  5 + * 砍价记录 service 接口
  6 + *
  7 + * @author HUIHUI
  8 + */
  9 +public interface BargainRecordService {
  10 +
  11 +// TODO
  12 +
  13 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainRecordServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.bargain;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +import org.springframework.validation.annotation.Validated;
  5 +
  6 +/**
  7 + * 砍价记录 Service 实现类
  8 + *
  9 + * @author HUIHUI
  10 + */
  11 +@Service
  12 +@Validated
  13 +public class BargainRecordServiceImpl implements BargainRecordService {
  14 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
1 package cn.iocoder.yudao.module.promotion.service.combination; 1 package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;  
5 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 4 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 5 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
8 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
9 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
10 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO; 7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
11 9
12 import javax.validation.Valid; 10 import javax.validation.Valid;
13 -import java.time.LocalDateTime;  
14 import java.util.Collection; 11 import java.util.Collection;
15 import java.util.List; 12 import java.util.List;
16 13
@@ -44,20 +41,20 @@ public interface CombinationActivityService { @@ -44,20 +41,20 @@ public interface CombinationActivityService {
44 void deleteCombinationActivity(Long id); 41 void deleteCombinationActivity(Long id);
45 42
46 /** 43 /**
47 - * 获得拼团活动 44 + * 校验拼团活动是否存在
48 * 45 *
49 * @param id 编号 46 * @param id 编号
50 * @return 拼团活动 47 * @return 拼团活动
51 */ 48 */
52 - CombinationActivityDO getCombinationActivity(Long id); 49 + CombinationActivityDO validateCombinationActivityExists(Long id);
53 50
54 /** 51 /**
55 - * 获得拼团活动列表 52 + * 获得拼团活动
56 * 53 *
57 - * @param ids 编号  
58 - * @return 拼团活动列表 54 + * @param id 编号
  55 + * @return 拼团活动
59 */ 56 */
60 - List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids); 57 + CombinationActivityDO getCombinationActivity(Long id);
61 58
62 /** 59 /**
63 * 获得拼团活动分页 60 * 获得拼团活动分页
@@ -68,56 +65,11 @@ public interface CombinationActivityService { @@ -68,56 +65,11 @@ public interface CombinationActivityService {
68 PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO); 65 PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO);
69 66
70 /** 67 /**
71 - * 获得拼团活动列表, 用于 Excel 导出  
72 - *  
73 - * @param exportReqVO 查询条件  
74 - * @return 拼团活动列表  
75 - */  
76 - List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO);  
77 -  
78 - /**  
79 * 获得拼团活动商品列表 68 * 获得拼团活动商品列表
80 * 69 *
81 - * @param ids 拼团活动 ids 70 + * @param activityIds 拼团活动 ids
82 * @return 拼团活动的商品列表 71 * @return 拼团活动的商品列表
83 */ 72 */
84 - List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids);  
85 -  
86 - // TODO @puhui999:拆一个 CombinationRecordService 里,方法名可以简洁成 updateRecordStatusByOrderId;service 方法可以稍微简单一点,如果是 update 方法  
87 - /**  
88 - * 更新拼团状态  
89 - *  
90 - * @param userId 用户编号  
91 - * @param orderId 订单编号  
92 - * @param status 状态  
93 - */  
94 - void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);  
95 -  
96 - /**  
97 - * 更新拼团状态和开始时间  
98 - *  
99 - * @param userId 用户编号  
100 - * @param orderId 订单编号  
101 - * @param status 状态  
102 - * @param startTime 开始时间  
103 - */  
104 - void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime);  
105 -  
106 - // TODO @puhui999:拆一个 CombinationRecordService 里  
107 - /**  
108 - * 创建拼团记录  
109 - *  
110 - * @param reqDTO 创建信息  
111 - */  
112 - void createRecord(CombinationRecordReqDTO reqDTO);  
113 -  
114 - /**  
115 - * 获得拼团状态  
116 - *  
117 - * @param userId 用户编号  
118 - * @param orderId 订单编号  
119 - * @return 拼团状态  
120 - */  
121 - boolean validateRecordStatusIsSuccess(Long userId, Long orderId); 73 + List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
122 74
123 } 75 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.combination; 1 package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.collection.CollectionUtil;  
5 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -10,35 +9,31 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; @@ -10,35 +9,31 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
10 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 9 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
11 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 10 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
12 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 11 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
13 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;  
14 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 12 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
15 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
16 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 13 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
17 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 14 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
18 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;  
19 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO; 15 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
20 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 16 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
21 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
22 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;  
23 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;  
24 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper;  
25 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationProductMapper;  
26 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationRecordMapper;  
27 -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 17 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  18 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
  19 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
  20 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
28 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
29 import org.springframework.transaction.annotation.Transactional; 22 import org.springframework.transaction.annotation.Transactional;
30 import org.springframework.validation.annotation.Validated; 23 import org.springframework.validation.annotation.Validated;
31 24
32 import javax.annotation.Resource; 25 import javax.annotation.Resource;
33 -import java.time.LocalDateTime;  
34 import java.util.Collection; 26 import java.util.Collection;
35 import java.util.List; 27 import java.util.List;
36 -import java.util.Set; 28 +import java.util.Map;
37 29
38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  31 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  32 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
  33 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
39 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 34 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
40 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 35 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
41 -import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence; 36 +import static java.util.Collections.singletonList;
42 37
43 /** 38 /**
44 * 拼团活动 Service 实现类 39 * 拼团活动 Service 实现类
@@ -52,61 +47,77 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -52,61 +47,77 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
52 @Resource 47 @Resource
53 private CombinationActivityMapper combinationActivityMapper; 48 private CombinationActivityMapper combinationActivityMapper;
54 @Resource 49 @Resource
55 - private CombinationRecordMapper recordMapper;  
56 - @Resource  
57 private CombinationProductMapper combinationProductMapper; 50 private CombinationProductMapper combinationProductMapper;
  51 +
58 @Resource 52 @Resource
59 private ProductSpuApi productSpuApi; 53 private ProductSpuApi productSpuApi;
60 @Resource 54 @Resource
61 private ProductSkuApi productSkuApi; 55 private ProductSkuApi productSkuApi;
62 56
63 @Override 57 @Override
  58 + @Transactional(rollbackFor = Exception.class)
64 public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) { 59 public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
65 // 校验商品 SPU 是否存在是否参加的别的活动 60 // 校验商品 SPU 是否存在是否参加的别的活动
66 - validateProductCombinationConflict(createReqVO.getSpuId(), null);  
67 - // 获取所选 spu下的所有 sku  
68 - List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));  
69 - // 校验商品 sku 是否存在  
70 - validateProductSkuExistence(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId); 61 + validateProductConflict(createReqVO.getSpuId(), null);
  62 + // 校验商品是否存在
  63 + validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts());
71 64
72 - // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:  
73 - // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时  
74 // 插入拼团活动 65 // 插入拼团活动
75 - CombinationActivityDO activityDO = CombinationActivityConvert.INSTANCE.convert(createReqVO);  
76 - // TODO 营销相关属性初始化  
77 - activityDO.setTotalNum(0);  
78 - activityDO.setSuccessNum(0);  
79 - activityDO.setOrderUserCount(0);  
80 - activityDO.setVirtualGroup(0);  
81 - activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());  
82 - combinationActivityMapper.insert(activityDO); 66 + CombinationActivityDO activity = CombinationActivityConvert.INSTANCE.convert(createReqVO)
  67 + .setStatus(CommonStatusEnum.ENABLE.getStatus())
  68 + .setTotalCount(0).setSuccessCount(0).setOrderUserCount(0).setVirtualGroup(0);
  69 + combinationActivityMapper.insert(activity);
83 // 插入商品 70 // 插入商品
84 - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(activityDO, createReqVO.getProducts());  
85 - combinationProductMapper.insertBatch(productDOs); 71 + List<CombinationProductDO> products = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
  72 + combinationProductMapper.insertBatch(products);
86 // 返回 73 // 返回
87 - return activityDO.getId(); 74 + return activity.getId();
88 } 75 }
89 76
90 - private void validateProductCombinationConflict(Long spuId, Long activityId) {  
91 - // 校验商品 spu 是否存在  
92 - List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));  
93 - if (CollUtil.isEmpty(spuList)) {  
94 - throw exception(SPU_NOT_EXISTS);  
95 - } 77 + /**
  78 + * 校验拼团商品参与的活动是否存在冲突
  79 + *
  80 + * @param spuId 商品 SPU 编号
  81 + * @param activityId 拼团活动编号
  82 + */
  83 + private void validateProductConflict(Long spuId, Long activityId) {
96 // 查询所有开启的拼团活动 84 // 查询所有开启的拼团活动
97 - List<CombinationActivityDO> activityDOs = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());  
98 - // 更新时排除自己  
99 - if (activityId != null) {  
100 - activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); 85 + List<CombinationActivityDO> activityList = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
  86 + if (activityId != null) { // 时排除自己
  87 + activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
101 } 88 }
102 - // 过滤出所有 spuIds 有交集的活动  
103 - List<CombinationActivityDO> doList = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getId(), spuId));  
104 - if (CollUtil.isNotEmpty(doList)) { 89 + // 查找是否有其它活动,选择了该产品
  90 + List<CombinationActivityDO> matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getId(), spuId));
  91 + if (CollUtil.isNotEmpty(matchActivityList)) {
105 throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS); 92 throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
106 } 93 }
107 } 94 }
108 95
  96 + /**
  97 + * 校验拼团商品是否都存在
  98 + *
  99 + * @param spuId 商品 SPU 编号
  100 + * @param products 秒杀商品
  101 + */
  102 + private void validateProductExists(Long spuId, List<CombinationProductBaseVO> products) {
  103 + // 1. 校验商品 spu 是否存在
  104 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
  105 + if (spu == null) {
  106 + throw exception(SPU_NOT_EXISTS);
  107 + }
  108 +
  109 + // 2. 校验商品 sku 都存在
  110 + Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
  111 + ProductSkuRespDTO::getId);
  112 + products.forEach(product -> {
  113 + if (!skuMap.containsKey(product.getSkuId())) {
  114 + throw exception(SKU_NOT_EXISTS);
  115 + }
  116 + });
  117 + }
  118 +
109 @Override 119 @Override
  120 + @Transactional(rollbackFor = Exception.class)
110 public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) { 121 public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
111 // 校验存在 122 // 校验存在
112 CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId()); 123 CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
@@ -115,13 +126,11 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -115,13 +126,11 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
115 throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); 126 throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
116 } 127 }
117 // 校验商品冲突 128 // 校验商品冲突
118 - validateProductCombinationConflict(updateReqVO.getSpuId(), updateReqVO.getId());  
119 - // 获取所选 spu下的所有 sku  
120 - List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));  
121 - // 校验商品 sku 是否存在  
122 - validateProductSkuExistence(skus, updateReqVO.getProducts(), CombinationProductUpdateReqVO::getSkuId); 129 + validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId());
  130 + // 校验商品是否存在
  131 + validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts());
123 132
124 - // 更新 133 + // 更新活动
125 CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO); 134 CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
126 combinationActivityMapper.updateById(updateObj); 135 combinationActivityMapper.updateById(updateObj);
127 // 更新商品 136 // 更新商品
@@ -129,40 +138,37 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -129,40 +138,37 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
129 } 138 }
130 139
131 /** 140 /**
132 - * 更新秒杀商品  
133 - * TODO 更新商品要不要封装成通用方法 141 + * 更新拼团商品
134 * 142 *
135 - * @param updateObj DO  
136 - * @param products 商品配置 143 + * @param activity 拼团活动
  144 + * @param products 该活动的最新商品配置
137 */ 145 */
138 - private void updateCombinationProduct(CombinationActivityDO updateObj, List<CombinationProductUpdateReqVO> products) {  
139 - List<CombinationProductDO> combinationProductDOs = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(updateObj.getId()));  
140 - // 数据库中的活动商品  
141 - Set<Long> convertSet = CollectionUtils.convertSet(combinationProductDOs, CombinationProductDO::getSkuId);  
142 - // 前端传过来的活动商品  
143 - Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId);  
144 - // 删除后台存在的前端不存在的商品  
145 - List<Long> d = CollectionUtils.filterList(convertSet, item -> !convertSet1.contains(item));  
146 - if (CollUtil.isNotEmpty(d)) {  
147 - combinationProductMapper.deleteBatchIds(d); 146 + private void updateCombinationProduct(CombinationActivityDO activity, List<CombinationProductBaseVO> products) {
  147 + // 第一步,对比新老数据,获得添加、修改、删除的列表
  148 + List<CombinationProductDO> newList = CombinationActivityConvert.INSTANCE.convertList(products, activity);
  149 + List<CombinationProductDO> oldList = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(activity.getId()));
  150 + List<List<CombinationProductDO>> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> {
  151 + boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId());
  152 + if (same) {
  153 + newVal.setId(oldVal.getId());
  154 + }
  155 + return same;
  156 + });
  157 +
  158 + // 第二步,批量添加、修改、删除
  159 + if (CollUtil.isNotEmpty(diffList.get(0))) {
  160 + combinationProductMapper.insertBatch(diffList.get(0));
148 } 161 }
149 - // 前端存在的后端不存在的商品  
150 - List<Long> c = CollectionUtils.filterList(convertSet1, item -> !convertSet.contains(item));  
151 - if (CollUtil.isNotEmpty(c)) {  
152 - List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));  
153 - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(updateObj, vos);  
154 - combinationProductMapper.insertBatch(productDOs); 162 + if (CollUtil.isNotEmpty(diffList.get(1))) {
  163 + combinationProductMapper.updateBatch(diffList.get(1));
155 } 164 }
156 - // 更新已存在的商品  
157 - List<Long> u = CollectionUtils.filterList(convertSet1, convertSet::contains);  
158 - if (CollUtil.isNotEmpty(u)) {  
159 - List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));  
160 - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList1(updateObj, vos, combinationProductDOs);  
161 - combinationProductMapper.updateBatch(productDOs); 165 + if (CollUtil.isNotEmpty(diffList.get(2))) {
  166 + combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId));
162 } 167 }
163 } 168 }
164 169
165 @Override 170 @Override
  171 + @Transactional(rollbackFor = Exception.class)
166 public void deleteCombinationActivity(Long id) { 172 public void deleteCombinationActivity(Long id) {
167 // 校验存在 173 // 校验存在
168 CombinationActivityDO activityDO = validateCombinationActivityExists(id); 174 CombinationActivityDO activityDO = validateCombinationActivityExists(id);
@@ -175,7 +181,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -175,7 +181,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
175 combinationActivityMapper.deleteById(id); 181 combinationActivityMapper.deleteById(id);
176 } 182 }
177 183
178 - private CombinationActivityDO validateCombinationActivityExists(Long id) { 184 + @Override
  185 + public CombinationActivityDO validateCombinationActivityExists(Long id) {
179 CombinationActivityDO activityDO = combinationActivityMapper.selectById(id); 186 CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
180 if (activityDO == null) { 187 if (activityDO == null) {
181 throw exception(COMBINATION_ACTIVITY_NOT_EXISTS); 188 throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
@@ -189,98 +196,13 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -189,98 +196,13 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
189 } 196 }
190 197
191 @Override 198 @Override
192 - public List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids) {  
193 - return combinationActivityMapper.selectBatchIds(ids);  
194 - }  
195 -  
196 - @Override  
197 public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) { 199 public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
198 return combinationActivityMapper.selectPage(pageReqVO); 200 return combinationActivityMapper.selectPage(pageReqVO);
199 } 201 }
200 202
201 @Override 203 @Override
202 - public List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO) {  
203 - return combinationActivityMapper.selectList(exportReqVO);  
204 - }  
205 -  
206 - @Override  
207 - public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) {  
208 - return combinationProductMapper.selectListByActivityIds(ids);  
209 - }  
210 -  
211 - @Override  
212 - public void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) {  
213 - // 校验拼团是否存在  
214 - CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);  
215 -  
216 - // 更新状态  
217 - recordDO.setStatus(status);  
218 - recordMapper.updateById(recordDO);  
219 - }  
220 -  
221 - @Override  
222 - @Transactional(rollbackFor = Exception.class)  
223 - public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) {  
224 - CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);  
225 - // 更新状态  
226 - recordDO.setStatus(status);  
227 - // 更新开始时间  
228 - recordDO.setStartTime(startTime);  
229 - recordMapper.updateById(recordDO);  
230 -  
231 - // 更新拼团参入人数  
232 - List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), status);  
233 - if (CollUtil.isNotEmpty(recordDOs)) {  
234 - recordDOs.forEach(item -> {  
235 - item.setUserCount(recordDOs.size());  
236 - // 校验拼团是否满足要求  
237 - if (recordDOs.size() >= recordDO.getUserSize()) {  
238 - item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());  
239 - }  
240 - });  
241 - }  
242 - recordMapper.updateBatch(recordDOs);  
243 - }  
244 -  
245 - private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {  
246 - // 校验拼团是否存在  
247 - CombinationRecordDO recordDO = recordMapper.selectRecord(userId, orderId);  
248 - if (recordDO == null) {  
249 - throw exception(COMBINATION_RECORD_NOT_EXISTS);  
250 - }  
251 - return recordDO;  
252 - }  
253 -  
254 - @Override  
255 - public void createRecord(CombinationRecordReqDTO reqDTO) {  
256 - // 校验拼团活动  
257 - CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());  
258 - // TODO @puhui999:需要校验下,它当前是不是已经参加了该拼团;  
259 - // TODO @puhui999: 父拼团是否存在,是否已经满了  
260 -  
261 - CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);  
262 - record.setVirtualGroup(false);  
263 - // TODO @puhui999:过期时间,应该是 Date 哈;  
264 - record.setExpireTime(activity.getLimitDuration());  
265 - record.setUserSize(activity.getUserSize());  
266 - recordMapper.insert(record);  
267 - }  
268 -  
269 - @Override  
270 - public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {  
271 - CombinationRecordDO record = validateCombinationRecord(userId, orderId);  
272 - // TODO @puhui999:可以搞个 getRecrod 方法,然后业务通过 CombinationRecordStatusEnum.isSuccess 方法校验  
273 - return ObjectUtil.equal(record.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus());  
274 - }  
275 -  
276 - // TODO @puhui999:status 传入进来搞哈;  
277 - /**  
278 - * APP 端获取开团记录  
279 - *  
280 - * @return 开团记录  
281 - */  
282 - public List<CombinationRecordDO> getRecordList() {  
283 - return recordMapper.selectListByStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); 204 + public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds) {
  205 + return combinationProductMapper.selectListByActivityIds(activityIds);
284 } 206 }
285 207
286 } 208 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  4 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
  5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * 拼团记录 Service 接口
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +public interface CombinationRecordService {
  15 +
  16 + /**
  17 + * 更新拼团状态
  18 + *
  19 + * @param reqDTO 请求 DTO
  20 + */
  21 + void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO);
  22 +
  23 + /**
  24 + * 创建拼团记录
  25 + *
  26 + * @param reqDTO 创建信息
  27 + */
  28 + void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO);
  29 +
  30 + /**
  31 + * 更新拼团状态和开始时间
  32 + *
  33 + * @param reqDTO 请求 DTO
  34 + */
  35 + void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO);
  36 +
  37 + /**
  38 + * 获得拼团状态
  39 + *
  40 + * @param userId 用户编号
  41 + * @param orderId 订单编号
  42 + * @return 拼团状态
  43 + */
  44 + CombinationRecordDO getCombinationRecord(Long userId, Long orderId);
  45 +
  46 + /**
  47 + * 获取拼团记录
  48 + *
  49 + * @param userId 用户 id
  50 + * @param activityId 活动 id
  51 + * @return 拼团记录列表
  52 + */
  53 + List<CombinationRecordDO> getRecordListByUserIdAndActivityId(Long userId, Long activityId);
  54 +
  55 + /**
  56 + * 验证组合限制数
  57 + * 校验是否满足限购要求
  58 + *
  59 + * @param count 本次购买数量
  60 + * @param sumCount 已购买数量合计
  61 + * @param activityId 活动编号
  62 + */
  63 + void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount);
  64 +
  65 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  6 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
  7 +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  9 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  10 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
  11 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  12 +import org.springframework.stereotype.Service;
  13 +import org.springframework.transaction.annotation.Transactional;
  14 +import org.springframework.validation.annotation.Validated;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.time.LocalDateTime;
  18 +import java.util.List;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  21 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  22 +
  23 +// TODO 芋艿:等拼团记录做完,完整 review 下
  24 +/**
  25 + * 拼团记录 Service 实现类
  26 + *
  27 + * @author HUIHUI
  28 + */
  29 +@Service
  30 +@Validated
  31 +public class CombinationRecordServiceImpl implements CombinationRecordService {
  32 +
  33 + @Resource
  34 + private CombinationActivityService combinationActivityService;
  35 +
  36 + @Resource
  37 + private CombinationRecordMapper recordMapper;
  38 +
  39 + @Override
  40 + @Transactional(rollbackFor = Exception.class)
  41 + public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
  42 + // 校验拼团是否存在
  43 + CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
  44 +
  45 + // 更新状态
  46 + recordDO.setStatus(reqDTO.getStatus());
  47 + recordMapper.updateById(recordDO);
  48 + }
  49 +
  50 + @Override
  51 + @Transactional(rollbackFor = Exception.class)
  52 + public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
  53 + CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
  54 + // 更新状态
  55 + recordDO.setStatus(reqDTO.getStatus());
  56 + // 更新开始时间
  57 + recordDO.setStartTime(reqDTO.getStartTime());
  58 + recordMapper.updateById(recordDO);
  59 +
  60 + // 更新拼团参入人数
  61 + List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus());
  62 + if (CollUtil.isNotEmpty(recordDOs)) {
  63 + recordDOs.forEach(item -> {
  64 + item.setUserCount(recordDOs.size());
  65 + // 校验拼团是否满足要求
  66 + if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) {
  67 + item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
  68 + }
  69 + });
  70 + }
  71 + recordMapper.updateBatch(recordDOs);
  72 + }
  73 +
  74 + private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
  75 + // 校验拼团是否存在
  76 + CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId);
  77 + if (recordDO == null) {
  78 + throw exception(COMBINATION_RECORD_NOT_EXISTS);
  79 + }
  80 + return recordDO;
  81 + }
  82 +
  83 + @Override
  84 + @Transactional(rollbackFor = Exception.class)
  85 + public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
  86 + // 1.1 校验拼团活动
  87 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
  88 + // 1.2 需要校验下,他当前是不是已经参加了该拼团;
  89 + CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
  90 + if (recordDO != null) {
  91 + throw exception(COMBINATION_RECORD_EXISTS);
  92 + }
  93 + // 1.3 校验用户是否参加了其它拼团
  94 + List<CombinationRecordDO> recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
  95 + if (CollUtil.isNotEmpty(recordDOList)) {
  96 + throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);
  97 + }
  98 + // 1.4 校验当前活动是否过期
  99 + if (LocalDateTime.now().isAfter(activity.getEndTime())) {
  100 + throw exception(COMBINATION_RECORD_FAILED_TIME_END);
  101 + }
  102 + // 1.5 父拼团是否存在,是否已经满了
  103 + if (reqDTO.getHeadId() != null) {
  104 + // 查询进行中的父拼团
  105 + CombinationRecordDO recordDO1 = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
  106 + if (recordDO1 == null) {
  107 + throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
  108 + }
  109 + // 校验拼团是否满足要求
  110 + if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
  111 + throw exception(COMBINATION_RECORD_USER_FULL);
  112 + }
  113 + }
  114 +
  115 + // 2. 创建拼团记录
  116 + CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
  117 + record.setVirtualGroup(false);
  118 + // TODO @puhui999:过期时间,应该是 Date 哈;
  119 + record.setExpireTime(activity.getLimitDuration());
  120 + record.setUserSize(activity.getUserSize());
  121 + recordMapper.insert(record);
  122 + }
  123 +
  124 + @Override
  125 + public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
  126 + return validateCombinationRecord(userId, orderId);
  127 + }
  128 +
  129 + @Override
  130 + public List<CombinationRecordDO> getRecordListByUserIdAndActivityId(Long userId, Long activityId) {
  131 + return recordMapper.selectListByUserIdAndActivityId(userId, activityId);
  132 + }
  133 +
  134 + @Override
  135 + public void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount) {
  136 + // 1.1 校验拼团活动
  137 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId);
  138 + // 校验是否达到限购总限购标准
  139 + if ((sumCount + count) > activity.getTotalLimitCount()) {
  140 + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
  141 + }
  142 + // 单次购买是否达到限购标准
  143 + if (count > activity.getSingleLimitCount()) {
  144 + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
  145 + }
  146 + }
  147 +
  148 + /**
  149 + * APP 端获取开团记录
  150 + *
  151 + * @return 开团记录
  152 + */
  153 + public List<CombinationRecordDO> getRecordListByStatus(Integer status) {
  154 + return recordMapper.selectListByStatus(status);
  155 + }
  156 +
  157 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
@@ -67,4 +67,12 @@ public interface CouponService { @@ -67,4 +67,12 @@ public interface CouponService {
67 */ 67 */
68 List<CouponDO> getCouponList(Long userId, Integer status); 68 List<CouponDO> getCouponList(Long userId, Integer status);
69 69
  70 + /**
  71 + * 获得未使用的优惠劵数量
  72 + *
  73 + * @param userId 用户编号
  74 + * @return 未使用的优惠劵数量
  75 + */
  76 + Long getUnusedCouponCount(Long userId);
  77 +
70 } 78 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
@@ -120,4 +120,9 @@ public class CouponServiceImpl implements CouponService { @@ -120,4 +120,9 @@ public class CouponServiceImpl implements CouponService {
120 } 120 }
121 } 121 }
122 122
  123 + @Override
  124 + public Long getUnusedCouponCount(Long userId) {
  125 + return couponMapper.selectCountByUserIdAndStatus(userId, CouponStatusEnum.UNUSED.getStatus());
  126 + }
  127 +
123 } 128 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/decorate/DecorateComponentService.java
@@ -14,17 +14,18 @@ import java.util.List; @@ -14,17 +14,18 @@ import java.util.List;
14 public interface DecorateComponentService { 14 public interface DecorateComponentService {
15 15
16 /** 16 /**
17 - * 店铺装修页面保存 17 + * 保存页面的组件信息
18 * 18 *
19 * @param reqVO 请求 VO 19 * @param reqVO 请求 VO
20 */ 20 */
21 - void savePageComponents(DecorateComponentSaveReqVO reqVO); 21 + void saveDecorateComponent(DecorateComponentSaveReqVO reqVO);
22 22
23 /** 23 /**
24 - * 根据页面 id。获取页面的组件信息 24 + * 根据页面 id,获取页面的组件信息
25 * 25 *
26 - * @param pageId 页面类型 {@link DecoratePageEnum#getId()} 26 + * @param page 页面编号 {@link DecoratePageEnum#getPage()}
  27 + * @param status 状态
27 */ 28 */
28 - List<DecorateComponentDO> getPageComponents(Integer pageId); 29 + List<DecorateComponentDO> getDecorateComponentListByPage(Integer page, Integer status);
29 30
30 } 31 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/decorate/DecorateComponentServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.decorate; 1 package cn.iocoder.yudao.module.promotion.service.decorate;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO; 3 import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO;
5 -import cn.iocoder.yudao.module.promotion.controller.admin.decorate.vo.DecorateComponentSaveReqVO.ComponentReqVO; 4 +import cn.iocoder.yudao.module.promotion.convert.decorate.DecorateComponentConvert;
6 import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.DecorateComponentDO; 5 import cn.iocoder.yudao.module.promotion.dal.dataobject.decorate.DecorateComponentDO;
7 import cn.iocoder.yudao.module.promotion.dal.mysql.decorate.DecorateComponentMapper; 6 import cn.iocoder.yudao.module.promotion.dal.mysql.decorate.DecorateComponentMapper;
8 import org.springframework.stereotype.Service; 7 import org.springframework.stereotype.Service;
9 8
10 import javax.annotation.Resource; 9 import javax.annotation.Resource;
11 import java.util.List; 10 import java.util.List;
12 -import java.util.Objects;  
13 -import java.util.Set;  
14 -  
15 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
16 -import static cn.iocoder.yudao.module.promotion.convert.decorate.DecorateComponentConvert.INSTANCE;  
17 11
18 /** 12 /**
19 * 装修组件 Service 实现 13 * 装修组件 Service 实现
@@ -27,22 +21,20 @@ public class DecorateComponentServiceImpl implements DecorateComponentService { @@ -27,22 +21,20 @@ public class DecorateComponentServiceImpl implements DecorateComponentService {
27 private DecorateComponentMapper decorateComponentMapper; 21 private DecorateComponentMapper decorateComponentMapper;
28 22
29 @Override 23 @Override
30 - public void savePageComponents(DecorateComponentSaveReqVO reqVO) {  
31 - // 1.新增或修改页面组件  
32 - List<DecorateComponentDO> oldList = decorateComponentMapper.selectByPage(reqVO.getPageId());  
33 -  
34 - decorateComponentMapper.saveOrUpdateBatch(INSTANCE.convertList(reqVO.getPageId(), reqVO.getComponents()));  
35 - // 2.删除相关组件  
36 - Set<Long> deleteIds = convertSet(oldList, DecorateComponentDO::getId);  
37 - deleteIds.removeAll(convertSet(reqVO.getComponents(), ComponentReqVO::getId, vo->Objects.nonNull(vo.getId())));  
38 - if (CollUtil.isNotEmpty(deleteIds)) {  
39 - decorateComponentMapper.deleteBatchIds(deleteIds); 24 + public void saveDecorateComponent(DecorateComponentSaveReqVO reqVO) {
  25 + // 1. 如果存在,则进行更新
  26 + DecorateComponentDO dbComponent = decorateComponentMapper.selectByPageAndCode(reqVO.getPage(), reqVO.getCode());
  27 + if (dbComponent != null) {
  28 + decorateComponentMapper.updateById(DecorateComponentConvert.INSTANCE.convert(reqVO).setId(dbComponent.getId()));
  29 + return;
40 } 30 }
  31 + // 2. 不存在,则进行新增
  32 + decorateComponentMapper.insert(DecorateComponentConvert.INSTANCE.convert(reqVO));
41 } 33 }
42 34
43 @Override 35 @Override
44 - public List<DecorateComponentDO> getPageComponents(Integer pageId) {  
45 - return decorateComponentMapper.selectByPage(pageId); 36 + public List<DecorateComponentDO> getDecorateComponentListByPage(Integer page, Integer status) {
  37 + return decorateComponentMapper.selectListByPageAndStatus(page, status);
46 } 38 }
47 39
48 } 40 }