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 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 36 public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) {
29 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 6 import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO;
7 7 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
8 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  9 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
9 10 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
  11 +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
10 12 import io.swagger.v3.oas.annotations.Operation;
11 13 import io.swagger.v3.oas.annotations.Parameter;
12 14 import io.swagger.v3.oas.annotations.Parameters;
13 15 import io.swagger.v3.oas.annotations.tags.Tag;
  16 +import org.springframework.context.annotation.Lazy;
14 17 import org.springframework.validation.annotation.Validated;
15 18 import org.springframework.web.bind.annotation.GetMapping;
16 19 import org.springframework.web.bind.annotation.RequestMapping;
... ... @@ -35,6 +38,9 @@ public class AppCombinationRecordController {
35 38  
36 39 @Resource
37 40 private CombinationRecordService combinationRecordService;
  41 + @Resource
  42 + @Lazy
  43 + private TradeOrderApi tradeOrderApi;
38 44  
39 45 @GetMapping("/get-summary")
40 46 @Operation(summary = "获得拼团记录的概要信息", description = "用于小程序首页")
... ... @@ -96,9 +102,26 @@ public class AppCombinationRecordController {
96 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 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 158 * 【拼团活动】获得拼团记录数量 Map
159 159 *
160 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 163 * @return 拼团记录数量 Map
164 164 */
165 165 Map<Long, Integer> getCombinationRecordCountMapByActivity(Collection<Long> activityIds,
166 166 @Nullable Integer status,
167 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 28  
29 29 import javax.annotation.Nullable;
30 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 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 34 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
... ... @@ -180,7 +177,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
180 177 recordMapper.insert(recordDO);
181 178  
182 179 // 3、如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP
183   - if (reqDTO.getHeadId() == null) {
  180 + if (ObjUtil.equal(CombinationRecordDO.HEAD_ID_GROUP, reqDTO.getHeadId())) {
184 181 recordMapper.updateById(new CombinationRecordDO().setId(recordDO.getId()).setHeadId(CombinationRecordDO.HEAD_ID_GROUP));
185 182 return;
186 183 }
... ... @@ -212,13 +209,17 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
212 209 * @param headId 团长编号
213 210 */
214 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 217 List<CombinationRecordDO> updateRecords = new ArrayList<>();
217 218  
218 219 if (CollUtil.isEmpty(records)) {
219 220 return;
220 221 }
221   -
  222 + records.add(recordHead); // 加入团长,团长也需要更新
222 223 boolean isEqual = ObjUtil.equal(records.size(), activity.getUserSize());
223 224 records.forEach(item -> {
224 225 CombinationRecordDO recordDO = new CombinationRecordDO();
... ... @@ -305,4 +306,59 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
305 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 49 */
50 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 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 180 */
181 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 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 *
... ...