Commit 6636ee7420dcc55025d5d97d7e975b88936b63cd

Authored by puhui999
1 parent 1a0fda23

拼团记录(APP):新增一个取消拼团的接口

yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -25,6 +25,14 @@ public class CollectionUtils { @@ -25,6 +25,14 @@ public class CollectionUtils {
25 return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); 25 return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
26 } 26 }
27 27
  28 + public static <T, U extends Comparable<? super U>> List<T> sortedAsc(
  29 + Collection<T> from, Function<? super T, ? extends U> keyExtractor) {
  30 + // 按照升序排序
  31 + return from.stream()
  32 + .sorted(Comparator.comparing(keyExtractor))
  33 + .collect(Collectors.toList());
  34 + }
  35 +
28 public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) { 36 public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) {
29 return from.stream().anyMatch(predicate); 37 return from.stream().anyMatch(predicate);
30 } 38 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java
@@ -6,11 +6,14 @@ import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.Ap @@ -6,11 +6,14 @@ import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.Ap
6 import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO; 6 import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO;
7 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 7 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
8 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  9 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
9 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; 10 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
  11 +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
10 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
11 import io.swagger.v3.oas.annotations.Parameter; 13 import io.swagger.v3.oas.annotations.Parameter;
12 import io.swagger.v3.oas.annotations.Parameters; 14 import io.swagger.v3.oas.annotations.Parameters;
13 import io.swagger.v3.oas.annotations.tags.Tag; 15 import io.swagger.v3.oas.annotations.tags.Tag;
  16 +import org.springframework.context.annotation.Lazy;
14 import org.springframework.validation.annotation.Validated; 17 import org.springframework.validation.annotation.Validated;
15 import org.springframework.web.bind.annotation.GetMapping; 18 import org.springframework.web.bind.annotation.GetMapping;
16 import org.springframework.web.bind.annotation.RequestMapping; 19 import org.springframework.web.bind.annotation.RequestMapping;
@@ -35,6 +38,9 @@ public class AppCombinationRecordController { @@ -35,6 +38,9 @@ public class AppCombinationRecordController {
35 38
36 @Resource 39 @Resource
37 private CombinationRecordService combinationRecordService; 40 private CombinationRecordService combinationRecordService;
  41 + @Resource
  42 + @Lazy
  43 + private TradeOrderApi tradeOrderApi;
38 44
39 @GetMapping("/get-summary") 45 @GetMapping("/get-summary")
40 @Operation(summary = "获得拼团记录的概要信息", description = "用于小程序首页") 46 @Operation(summary = "获得拼团记录的概要信息", description = "用于小程序首页")
@@ -96,9 +102,26 @@ public class AppCombinationRecordController { @@ -96,9 +102,26 @@ public class AppCombinationRecordController {
96 return success(CombinationActivityConvert.INSTANCE.convert(getLoginUserId(), headRecord, memberRecords)); 102 return success(CombinationActivityConvert.INSTANCE.convert(getLoginUserId(), headRecord, memberRecords));
97 } 103 }
98 104
99 - // TODO @puhui:新增一个取消拼团的接口,cancel  
100 - // 1. 需要先校验拼团记录未完成;  
101 - // 2. 在 Order 那增加一个 cancelPaidOrder 接口,用于取消已支付的订单  
102 - // 3. order 完成后,取消拼团记录。另外,如果它是团长,则顺序(下单时间)继承 105 + @GetMapping("/cancel")
  106 + @Operation(summary = "取消拼团")
  107 + @Parameter(name = "id", description = "拼团记录编号", required = true, example = "1024")
  108 + public CommonResult<Boolean> cancelCombinationRecord(@RequestParam("id") Long id) {
  109 + Long userId = getLoginUserId();
  110 + // 1、查找这条拼团记录
  111 + CombinationRecordDO record = combinationRecordService.getCombinationRecordByIdAndUser(userId, id);
  112 + if (record == null) {
  113 + return success(Boolean.FALSE);
  114 + }
  115 + // 1.1、需要先校验拼团记录未完成;
  116 + if (!CombinationRecordStatusEnum.isInProgress(record.getStatus())) {
  117 + return success(Boolean.FALSE);
  118 + }
  119 +
  120 + // 2. 取消已支付的订单
  121 + tradeOrderApi.cancelPaidOrder(userId, record.getOrderId());
  122 + // 3. 取消拼团记录
  123 + combinationRecordService.cancelCombinationRecord(userId, record.getId(), record.getHeadId());
  124 + return success(Boolean.TRUE);
  125 + }
103 126
104 } 127 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
@@ -159,20 +159,4 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO @@ -159,20 +159,4 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO
159 .betweenIfPresent(CombinationRecordDO::getCreateTime, builderQueryTime(dateType))); 159 .betweenIfPresent(CombinationRecordDO::getCreateTime, builderQueryTime(dateType)));
160 } 160 }
161 161
162 - /**  
163 - * 查询指定团长的拼团记录(包括团长)  
164 - *  
165 - * @param activityId 活动编号  
166 - * @param headId 团长编号  
167 - * @return 拼团记录  
168 - */  
169 - default List<CombinationRecordDO> selectList(Long activityId, Long headId) {  
170 - return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()  
171 - .eq(CombinationRecordDO::getActivityId, activityId)  
172 - .eq(CombinationRecordDO::getHeadId, headId)  
173 - .or()  
174 - .eq(CombinationRecordDO::getId, headId));  
175 -  
176 - }  
177 -  
178 } 162 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
@@ -158,12 +158,32 @@ public interface CombinationRecordService { @@ -158,12 +158,32 @@ public interface CombinationRecordService {
158 * 【拼团活动】获得拼团记录数量 Map 158 * 【拼团活动】获得拼团记录数量 Map
159 * 159 *
160 * @param activityIds 活动记录编号数组 160 * @param activityIds 活动记录编号数组
161 - * @param status 拼团状态,允许空  
162 - * @param headId 团长编号,允许空。目的 headId 设置为 {@link CombinationRecordDO#HEAD_ID_GROUP} 时,可以设置 161 + * @param status 拼团状态,允许空
  162 + * @param headId 团长编号,允许空。目的 headId 设置为 {@link CombinationRecordDO#HEAD_ID_GROUP} 时,可以设置
163 * @return 拼团记录数量 Map 163 * @return 拼团记录数量 Map
164 */ 164 */
165 Map<Long, Integer> getCombinationRecordCountMapByActivity(Collection<Long> activityIds, 165 Map<Long, Integer> getCombinationRecordCountMapByActivity(Collection<Long> activityIds,
166 @Nullable Integer status, 166 @Nullable Integer status,
167 @Nullable Long headId); 167 @Nullable Long headId);
168 168
  169 +
  170 + /**
  171 + * 获取拼团记录
  172 + *
  173 + * @param userId 用户编号
  174 + * @param id 拼团记录编号
  175 + * @return 拼团记录
  176 + */
  177 + CombinationRecordDO getCombinationRecordByIdAndUser(Long userId, Long id);
  178 +
  179 + /**
  180 + * 取消拼团
  181 + *
  182 + * @param userId 用户编号
  183 + * @param id 拼团记录编号
  184 + * @param headId 团长编号
  185 + */
  186 + void cancelCombinationRecord(Long userId, Long id, Long headId);
  187 +
  188 +
169 } 189 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
@@ -28,10 +28,7 @@ import org.springframework.validation.annotation.Validated; @@ -28,10 +28,7 @@ import org.springframework.validation.annotation.Validated;
28 28
29 import javax.annotation.Nullable; 29 import javax.annotation.Nullable;
30 import javax.annotation.Resource; 30 import javax.annotation.Resource;
31 -import java.util.ArrayList;  
32 -import java.util.Collection;  
33 -import java.util.List;  
34 -import java.util.Map; 31 +import java.util.*;
35 32
36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 34 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -180,7 +177,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -180,7 +177,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
180 recordMapper.insert(recordDO); 177 recordMapper.insert(recordDO);
181 178
182 // 3、如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP 179 // 3、如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP
183 - if (reqDTO.getHeadId() == null) { 180 + if (ObjUtil.equal(CombinationRecordDO.HEAD_ID_GROUP, reqDTO.getHeadId())) {
184 recordMapper.updateById(new CombinationRecordDO().setId(recordDO.getId()).setHeadId(CombinationRecordDO.HEAD_ID_GROUP)); 181 recordMapper.updateById(new CombinationRecordDO().setId(recordDO.getId()).setHeadId(CombinationRecordDO.HEAD_ID_GROUP));
185 return; 182 return;
186 } 183 }
@@ -212,13 +209,17 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -212,13 +209,17 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
212 * @param headId 团长编号 209 * @param headId 团长编号
213 */ 210 */
214 private void updateCombinationRecords(CombinationActivityDO activity, Long headId) { 211 private void updateCombinationRecords(CombinationActivityDO activity, Long headId) {
215 - List<CombinationRecordDO> records = recordMapper.selectList(CombinationRecordDO::getHeadId, headId); 212 + // 团长
  213 + CombinationRecordDO recordHead = recordMapper.selectById(headId);
  214 + // 团员
  215 + List<CombinationRecordDO> records = getCombinationRecordListByHeadId(headId);
  216 + // 需要更新的记录
216 List<CombinationRecordDO> updateRecords = new ArrayList<>(); 217 List<CombinationRecordDO> updateRecords = new ArrayList<>();
217 218
218 if (CollUtil.isEmpty(records)) { 219 if (CollUtil.isEmpty(records)) {
219 return; 220 return;
220 } 221 }
221 - 222 + records.add(recordHead); // 加入团长,团长也需要更新
222 boolean isEqual = ObjUtil.equal(records.size(), activity.getUserSize()); 223 boolean isEqual = ObjUtil.equal(records.size(), activity.getUserSize());
223 records.forEach(item -> { 224 records.forEach(item -> {
224 CombinationRecordDO recordDO = new CombinationRecordDO(); 225 CombinationRecordDO recordDO = new CombinationRecordDO();
@@ -305,4 +306,59 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -305,4 +306,59 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
305 return recordMapper.selectCombinationRecordCountMapByActivityIdAndStatusAndHeadId(activityIds, status, headId); 306 return recordMapper.selectCombinationRecordCountMapByActivityIdAndStatusAndHeadId(activityIds, status, headId);
306 } 307 }
307 308
  309 + @Override
  310 + public CombinationRecordDO getCombinationRecordByIdAndUser(Long userId, Long id) {
  311 + return recordMapper.selectOne(CombinationRecordDO::getUserId, userId, CombinationRecordDO::getId, id);
  312 + }
  313 +
  314 + @Override
  315 + @Transactional(rollbackFor = Exception.class)
  316 + public void cancelCombinationRecord(Long userId, Long id, Long headId) {
  317 + // 删除记录
  318 + recordMapper.deleteById(id);
  319 +
  320 + // 需要更新的记录
  321 + List<CombinationRecordDO> updateRecords = new ArrayList<>();
  322 + // 如果它是团长,则顺序(下单时间)继承
  323 + if (Objects.equals(headId, CombinationRecordDO.HEAD_ID_GROUP)) { // 情况一:团长
  324 + // 团员
  325 + List<CombinationRecordDO> list = getCombinationRecordListByHeadId(id);
  326 + if (CollUtil.isEmpty(list)) {
  327 + return;
  328 + }
  329 + // 按照创建时间升序排序
  330 + List<CombinationRecordDO> recordsSort = sortedAsc(list, CombinationRecordDO::getCreateTime);
  331 + CombinationRecordDO newHead = recordsSort.get(0); // 新团长继位
  332 + recordsSort.forEach(item -> {
  333 + CombinationRecordDO recordDO = new CombinationRecordDO();
  334 + recordDO.setId(item.getId());
  335 + if (ObjUtil.equal(item.getId(), newHead.getId())) { // 新团长
  336 + recordDO.setHeadId(CombinationRecordDO.HEAD_ID_GROUP);
  337 + } else {
  338 + recordDO.setHeadId(newHead.getId());
  339 + }
  340 + recordDO.setUserCount(recordsSort.size());
  341 + updateRecords.add(recordDO);
  342 + });
  343 + } else { // 情况二:团员
  344 + // 团长
  345 + CombinationRecordDO recordHead = recordMapper.selectById(headId);
  346 + // 团员
  347 + List<CombinationRecordDO> records = getCombinationRecordListByHeadId(headId);
  348 + if (CollUtil.isEmpty(records)) {
  349 + return;
  350 + }
  351 + records.add(recordHead); // 加入团长,团长数据也需要更新
  352 + records.forEach(item -> {
  353 + CombinationRecordDO recordDO = new CombinationRecordDO();
  354 + recordDO.setId(item.getId());
  355 + recordDO.setUserCount(records.size());
  356 + updateRecords.add(recordDO);
  357 + });
  358 + }
  359 +
  360 + // 更新拼团记录
  361 + recordMapper.updateBatch(updateRecords);
  362 + }
  363 +
308 } 364 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
@@ -49,4 +49,12 @@ public interface TradeOrderApi { @@ -49,4 +49,12 @@ public interface TradeOrderApi {
49 */ 49 */
50 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId); 50 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId);
51 51
  52 + /**
  53 + * 取消支付订单
  54 + *
  55 + * @param userId 用户编号
  56 + * @param orderId 订单编号
  57 + */
  58 + void cancelPaidOrder(Long userId, Long orderId);
  59 +
52 } 60 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
@@ -47,4 +47,9 @@ public class TradeOrderApiImpl implements TradeOrderApi { @@ -47,4 +47,9 @@ public class TradeOrderApiImpl implements TradeOrderApi {
47 tradeOrderUpdateService.updateOrderCombinationInfo(orderId, activityId, combinationRecordId, headId); 47 tradeOrderUpdateService.updateOrderCombinationInfo(orderId, activityId, combinationRecordId, headId);
48 } 48 }
49 49
  50 + @Override
  51 + public void cancelPaidOrder(Long userId, Long orderId) {
  52 + tradeOrderUpdateService.cancelPaidOrder(userId, orderId);
  53 + }
  54 +
50 } 55 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
@@ -180,4 +180,12 @@ public interface TradeOrderUpdateService { @@ -180,4 +180,12 @@ public interface TradeOrderUpdateService {
180 */ 180 */
181 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId); 181 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId);
182 182
  183 + /**
  184 + * 取消支付订单
  185 + *
  186 + * @param userId 用户编号
  187 + * @param orderId 订单编号
  188 + */
  189 + void cancelPaidOrder(Long userId, Long orderId);
  190 +
183 } 191 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -918,6 +918,17 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -918,6 +918,17 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
918 .setCombinationRecordId(combinationRecordId).setCombinationHeadId(headId)); 918 .setCombinationRecordId(combinationRecordId).setCombinationHeadId(headId));
919 } 919 }
920 920
  921 + @Override
  922 + @Transactional(rollbackFor = Exception.class)
  923 + public void cancelPaidOrder(Long userId, Long orderId) {
  924 + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
  925 + if (order == null) {
  926 + throw exception(ORDER_NOT_FOUND);
  927 + }
  928 +
  929 + cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
  930 + }
  931 +
921 /** 932 /**
922 * 创建单个订单的评论 933 * 创建单个订单的评论
923 * 934 *