Commit 5235aff8ad4834a82f07d163c6a4329f24930c02
Committed by
Gitee
!610 营销活动+订单:完善大部分 TODO 提到的问题
Merge pull request !610 from puhui999/feature/mall_product
Showing
34 changed files
with
479 additions
and
198 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
| ... | ... | @@ -41,7 +41,7 @@ public class CommonResult<T> implements Serializable { |
| 41 | 41 | * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。 |
| 42 | 42 | * |
| 43 | 43 | * @param result 传入的 result 对象 |
| 44 | - * @param <T> 返回的泛型 | |
| 44 | + * @param <T> 返回的泛型 | |
| 45 | 45 | * @return 新的 CommonResult 对象 |
| 46 | 46 | */ |
| 47 | 47 | public static <T> CommonResult<T> error(CommonResult<?> result) { |
| ... | ... | @@ -68,6 +68,14 @@ public class CommonResult<T> implements Serializable { |
| 68 | 68 | return result; |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | + public static <T> CommonResult<T> success(T data, String msg) { | |
| 72 | + CommonResult<T> result = new CommonResult<>(); | |
| 73 | + result.code = GlobalErrorCodeConstants.SUCCESS.getCode(); | |
| 74 | + result.data = data; | |
| 75 | + result.msg = msg; | |
| 76 | + return result; | |
| 77 | + } | |
| 78 | + | |
| 71 | 79 | public static boolean isSuccess(Integer code) { |
| 72 | 80 | return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode()); |
| 73 | 81 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.bargain; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 砍价活动 Api 接口 | |
| 5 | + * | |
| 6 | + * @author HUIHUI | |
| 7 | + */ | |
| 8 | +public interface BargainActivityApi { | |
| 9 | + | |
| 10 | + /** | |
| 11 | + * 更新砍价活动库存 | |
| 12 | + * | |
| 13 | + * @param activityId 砍价活动编号 | |
| 14 | + * @param count 购买数量 | |
| 15 | + */ | |
| 16 | + void updateBargainActivityStock(Long activityId, Integer count); | |
| 17 | + | |
| 18 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java
| ... | ... | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.bargain.dto; |
| 2 | 2 | |
| 3 | 3 | import lombok.Data; |
| 4 | 4 | |
| 5 | -import javax.validation.constraints.NotEmpty; | |
| 6 | 5 | import javax.validation.constraints.NotNull; |
| 7 | 6 | |
| 8 | 7 | // TODO @芋艿:这块要在看看 |
| ... | ... | @@ -40,17 +39,7 @@ public class BargainRecordCreateReqDTO { |
| 40 | 39 | */ |
| 41 | 40 | @NotNull(message = "订单编号不能为空") |
| 42 | 41 | 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; | |
| 42 | + | |
| 54 | 43 | /** |
| 55 | 44 | * 砍价商品单价 |
| 56 | 45 | */ |
| ... | ... | @@ -61,17 +50,7 @@ public class BargainRecordCreateReqDTO { |
| 61 | 50 | */ |
| 62 | 51 | @NotNull(message = "商品原价不能为空") |
| 63 | 52 | 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; | |
| 53 | + | |
| 75 | 54 | /** |
| 76 | 55 | * 开团状态:进行中 砍价成功 砍价失败 |
| 77 | 56 | */ | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
| ... | ... | @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.promotion.api.combination; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 4 | 4 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; |
| 5 | -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; | |
| 6 | 5 | |
| 7 | 6 | import javax.validation.Valid; |
| 7 | +import java.time.LocalDateTime; | |
| 8 | 8 | import java.util.List; |
| 9 | 9 | |
| 10 | 10 | // TODO @芋艿:后面也再撸撸这几个接口 |
| ... | ... | @@ -51,13 +51,29 @@ public interface CombinationRecordApi { |
| 51 | 51 | */ |
| 52 | 52 | void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount); |
| 53 | 53 | |
| 54 | - // TODO @puhui999:是不是搞成具体的方法,拼团成功,拼团失败,这种方法; | |
| 54 | + /** | |
| 55 | + * 更新拼团状态为 成功 | |
| 56 | + * | |
| 57 | + * @param userId 用户编号 | |
| 58 | + * @param orderId 订单编号 | |
| 59 | + */ | |
| 60 | + void updateRecordStatusToSuccess(Long userId, Long orderId); | |
| 55 | 61 | |
| 56 | 62 | /** |
| 57 | - * 更新开团记录状态 | |
| 63 | + * 更新拼团状态为 失败 | |
| 58 | 64 | * |
| 59 | - * @param reqDTO 请求 DTO | |
| 65 | + * @param userId 用户编号 | |
| 66 | + * @param orderId 订单编号 | |
| 67 | + */ | |
| 68 | + void updateRecordStatusToFailed(Long userId, Long orderId); | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * 更新拼团状态为 进行中 | |
| 72 | + * | |
| 73 | + * @param userId 用户编号 | |
| 74 | + * @param orderId 订单编号 | |
| 75 | + * @param startTime 开始时间 | |
| 60 | 76 | */ |
| 61 | - void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO); | |
| 77 | + void updateRecordStatusToInProgress(Long userId, Long orderId, LocalDateTime startTime); | |
| 62 | 78 | |
| 63 | 79 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java deleted
| 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/api/seckill/SeckillActivityApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.seckill; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * 秒杀活动 API 接口 | |
| 7 | + * | |
| 8 | + * @author HUIHUI | |
| 9 | + */ | |
| 10 | +public interface SeckillActivityApi { | |
| 11 | + | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * 更新秒杀库存 | |
| 15 | + * | |
| 16 | + * @param updateStockReqDTO 请求 | |
| 17 | + */ | |
| 18 | + void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO); | |
| 19 | + | |
| 20 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.seckill.dto; | |
| 2 | + | |
| 3 | +import lombok.Data; | |
| 4 | + | |
| 5 | +import java.util.List; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 更新秒杀库存 request DTO | |
| 9 | + * | |
| 10 | + * @author HUIHUI | |
| 11 | + */ | |
| 12 | +@Data | |
| 13 | +public class SeckillActivityUpdateStockReqDTO { | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 活动编号 | |
| 17 | + */ | |
| 18 | + private Long activityId; | |
| 19 | + /** | |
| 20 | + * 总购买数量 | |
| 21 | + */ | |
| 22 | + private Integer count; | |
| 23 | + /** | |
| 24 | + * 活动商品 | |
| 25 | + */ | |
| 26 | + private List<Item> items; | |
| 27 | + | |
| 28 | + @Data | |
| 29 | + public static class Item { | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * SPU 编号 | |
| 33 | + */ | |
| 34 | + private Long spuId; | |
| 35 | + /** | |
| 36 | + * SKU 编号 | |
| 37 | + */ | |
| 38 | + private Long skuId; | |
| 39 | + /** | |
| 40 | + * 购买数量 | |
| 41 | + */ | |
| 42 | + private Integer count; | |
| 43 | + | |
| 44 | + } | |
| 45 | + | |
| 46 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
| ... | ... | @@ -51,10 +51,11 @@ public interface ErrorCodeConstants { |
| 51 | 51 | |
| 52 | 52 | // ========== 秒杀活动 1013008000 ========== |
| 53 | 53 | ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在"); |
| 54 | - ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动"); | |
| 54 | + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突"); | |
| 55 | 55 | ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); |
| 56 | 56 | ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); |
| 57 | 57 | ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); |
| 58 | + ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "更新秒杀活动库存失败,原因秒杀库存不足"); | |
| 58 | 59 | |
| 59 | 60 | // ========== 秒杀时段 1013009000 ========== |
| 60 | 61 | ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.bargain; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO; | |
| 4 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; | |
| 5 | +import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; | |
| 6 | +import org.springframework.stereotype.Service; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 11 | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.BARGAIN_ACTIVITY_NOT_EXISTS; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 砍价活动 Api 接口实现类 | |
| 15 | + * | |
| 16 | + * @author HUIHUI | |
| 17 | + */ | |
| 18 | +@Service | |
| 19 | +public class BargainActivityApiImpl implements BargainActivityApi { | |
| 20 | + | |
| 21 | + @Resource | |
| 22 | + private BargainActivityService bargainActivityService; | |
| 23 | + | |
| 24 | + @Override | |
| 25 | + public void updateBargainActivityStock(Long activityId, Integer count) { | |
| 26 | + // 查询砍价活动 | |
| 27 | + BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId); | |
| 28 | + if (activity == null) { | |
| 29 | + throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); | |
| 30 | + } | |
| 31 | + | |
| 32 | + // 更新砍价库存 | |
| 33 | + BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); | |
| 34 | + reqVO.setId(activityId); | |
| 35 | + reqVO.setStock(activity.getStock() - count); | |
| 36 | + bargainActivityService.updateBargainActivity(reqVO); | |
| 37 | + } | |
| 38 | + | |
| 39 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
| ... | ... | @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.promotion.api.combination; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 4 | 4 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; |
| 5 | -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; | |
| 6 | 5 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; |
| 7 | 6 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; |
| 8 | 7 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; |
| 9 | 8 | import org.springframework.stereotype.Service; |
| 10 | 9 | |
| 11 | 10 | import javax.annotation.Resource; |
| 11 | +import java.time.LocalDateTime; | |
| 12 | 12 | import java.util.List; |
| 13 | 13 | |
| 14 | 14 | /** |
| ... | ... | @@ -43,12 +43,19 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | @Override |
| 46 | - public void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO) { | |
| 47 | - if (null == reqDTO.getStartTime()) { | |
| 48 | - recordService.updateCombinationRecordStatusByUserIdAndOrderId(reqDTO); | |
| 49 | - } else { | |
| 50 | - recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(reqDTO); | |
| 51 | - } | |
| 46 | + public void updateRecordStatusToSuccess(Long userId, Long orderId) { | |
| 47 | + recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.SUCCESS.getStatus(), userId, orderId); | |
| 48 | + } | |
| 49 | + | |
| 50 | + @Override | |
| 51 | + public void updateRecordStatusToFailed(Long userId, Long orderId) { | |
| 52 | + recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.FAILED.getStatus(), userId, orderId); | |
| 53 | + } | |
| 54 | + | |
| 55 | + @Override | |
| 56 | + public void updateRecordStatusToInProgress(Long userId, Long orderId, LocalDateTime startTime) { | |
| 57 | + recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordStatusEnum.IN_PROGRESS.getStatus(), | |
| 58 | + userId, orderId, startTime); | |
| 52 | 59 | } |
| 53 | 60 | |
| 54 | 61 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.seckill; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 4 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; | |
| 5 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; | |
| 6 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; | |
| 7 | +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; | |
| 8 | +import org.springframework.stereotype.Service; | |
| 9 | + | |
| 10 | +import javax.annotation.Resource; | |
| 11 | +import java.util.ArrayList; | |
| 12 | +import java.util.HashMap; | |
| 13 | +import java.util.List; | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 17 | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_UPDATE_STOCK_FAIL; | |
| 18 | + | |
| 19 | +/** | |
| 20 | + * 秒杀活动接口 Api 接口实现类 | |
| 21 | + * | |
| 22 | + * @author HUIHUI | |
| 23 | + */ | |
| 24 | +@Service | |
| 25 | +public class SeckillActivityApiImpl implements SeckillActivityApi { | |
| 26 | + | |
| 27 | + @Resource | |
| 28 | + private SeckillActivityService activityService; | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { | |
| 32 | + SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId()); | |
| 33 | + if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { | |
| 34 | + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | |
| 35 | + } | |
| 36 | + // 获取活动商品 | |
| 37 | + List<SeckillProductDO> productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); | |
| 38 | + List<SeckillActivityUpdateStockReqDTO.Item> items = updateStockReqDTO.getItems(); | |
| 39 | + Map<Long, List<Long>> map = new HashMap<>(); | |
| 40 | + items.forEach(item -> { | |
| 41 | + if (map.containsKey(item.getSpuId())) { | |
| 42 | + List<Long> skuIds = map.get(item.getSpuId()); | |
| 43 | + skuIds.add(item.getSkuId()); | |
| 44 | + map.put(item.getSpuId(), skuIds); | |
| 45 | + } else { | |
| 46 | + List<Long> list = new ArrayList<>(); | |
| 47 | + list.add(item.getSkuId()); | |
| 48 | + map.put(item.getSpuId(), list); | |
| 49 | + } | |
| 50 | + }); | |
| 51 | + // 过滤出购买的商品 | |
| 52 | + List<SeckillProductDO> productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId())); | |
| 53 | + Map<Long, SeckillActivityUpdateStockReqDTO.Item> productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p); | |
| 54 | + // 检查活动商品库存是否充足 | |
| 55 | + boolean b = CollectionUtils.anyMatch(productDOList, item -> { | |
| 56 | + SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId()); | |
| 57 | + return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0; | |
| 58 | + }); | |
| 59 | + if (b) { | |
| 60 | + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | |
| 61 | + } | |
| 62 | + List<SeckillProductDO> doList = CollectionUtils.convertList(productDOList, item -> { | |
| 63 | + item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount()); | |
| 64 | + return item; | |
| 65 | + }); | |
| 66 | + | |
| 67 | + // 更新活动库存 | |
| 68 | + seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); | |
| 69 | + seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); | |
| 70 | + activityService.updateSeckillActivity(seckillActivity); | |
| 71 | + // 更新活动商品库存 | |
| 72 | + activityService.updateSeckillActivityProductByList(doList); | |
| 73 | + } | |
| 74 | + | |
| 75 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java
| ... | ... | @@ -86,11 +86,11 @@ public class CombinationRecordDO extends BaseDO { |
| 86 | 86 | */ |
| 87 | 87 | private Boolean virtualGroup; |
| 88 | 88 | /** |
| 89 | - * 过期时间,单位:小时 | |
| 89 | + * 过期时间 | |
| 90 | 90 | * |
| 91 | - * 关联 {@link CombinationActivityDO#getLimitDuration()} | |
| 91 | + * {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算 | |
| 92 | 92 | */ |
| 93 | - private Integer expireTime; | |
| 93 | + private LocalDateTime expireTime; | |
| 94 | 94 | /** |
| 95 | 95 | * 开始时间 (订单付款后开始的时间) |
| 96 | 96 | */ | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.service.combination; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 4 | -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; | |
| 5 | 4 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| 6 | 5 | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | 7 | import java.util.List; |
| 8 | 8 | |
| 9 | 9 | /** |
| ... | ... | @@ -16,9 +16,11 @@ public interface CombinationRecordService { |
| 16 | 16 | /** |
| 17 | 17 | * 更新拼团状态 |
| 18 | 18 | * |
| 19 | - * @param reqDTO 请求 DTO | |
| 19 | + * @param status 状态 | |
| 20 | + * @param userId 用户编号 | |
| 21 | + * @param orderId 订单编号 | |
| 20 | 22 | */ |
| 21 | - void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO); | |
| 23 | + void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId); | |
| 22 | 24 | |
| 23 | 25 | /** |
| 24 | 26 | * 创建拼团记录 |
| ... | ... | @@ -30,9 +32,12 @@ public interface CombinationRecordService { |
| 30 | 32 | /** |
| 31 | 33 | * 更新拼团状态和开始时间 |
| 32 | 34 | * |
| 33 | - * @param reqDTO 请求 DTO | |
| 35 | + * @param status 状态 | |
| 36 | + * @param userId 用户编号 | |
| 37 | + * @param orderId 订单编号 | |
| 38 | + * @param startTime 开始时间 | |
| 34 | 39 | */ |
| 35 | - void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO); | |
| 40 | + void updateRecordStatusAndStartTimeByUserIdAndOrderId(Integer status, Long userId, Long orderId, LocalDateTime startTime); | |
| 36 | 41 | |
| 37 | 42 | /** |
| 38 | 43 | * 获得拼团状态 | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
| ... | ... | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.combination; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | 5 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 6 | -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; | |
| 7 | 6 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; |
| 8 | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; |
| 9 | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| ... | ... | @@ -21,6 +20,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU |
| 21 | 20 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 22 | 21 | |
| 23 | 22 | // TODO 芋艿:等拼团记录做完,完整 review 下 |
| 23 | + | |
| 24 | 24 | /** |
| 25 | 25 | * 拼团记录 Service 实现类 |
| 26 | 26 | * |
| ... | ... | @@ -38,27 +38,27 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { |
| 38 | 38 | |
| 39 | 39 | @Override |
| 40 | 40 | @Transactional(rollbackFor = Exception.class) |
| 41 | - public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { | |
| 41 | + public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) { | |
| 42 | 42 | // 校验拼团是否存在 |
| 43 | - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); | |
| 43 | + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); | |
| 44 | 44 | |
| 45 | 45 | // 更新状态 |
| 46 | - recordDO.setStatus(reqDTO.getStatus()); | |
| 46 | + recordDO.setStatus(status); | |
| 47 | 47 | recordMapper.updateById(recordDO); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | @Override |
| 51 | 51 | @Transactional(rollbackFor = Exception.class) |
| 52 | - public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { | |
| 53 | - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); | |
| 52 | + public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Integer status, Long userId, Long orderId, LocalDateTime startTime) { | |
| 53 | + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); | |
| 54 | 54 | // 更新状态 |
| 55 | - recordDO.setStatus(reqDTO.getStatus()); | |
| 55 | + recordDO.setStatus(status); | |
| 56 | 56 | // 更新开始时间 |
| 57 | - recordDO.setStartTime(reqDTO.getStartTime()); | |
| 57 | + recordDO.setStartTime(startTime); | |
| 58 | 58 | recordMapper.updateById(recordDO); |
| 59 | 59 | |
| 60 | 60 | // 更新拼团参入人数 |
| 61 | - List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus()); | |
| 61 | + List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), status); | |
| 62 | 62 | if (CollUtil.isNotEmpty(recordDOs)) { |
| 63 | 63 | recordDOs.forEach(item -> { |
| 64 | 64 | item.setUserCount(recordDOs.size()); |
| ... | ... | @@ -115,8 +115,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { |
| 115 | 115 | // 2. 创建拼团记录 |
| 116 | 116 | CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); |
| 117 | 117 | record.setVirtualGroup(false); |
| 118 | - // TODO @puhui999:过期时间,应该是 Date 哈; | |
| 119 | - record.setExpireTime(activity.getLimitDuration()); | |
| 118 | + record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration())); | |
| 120 | 119 | record.setUserSize(activity.getUserSize()); |
| 121 | 120 | recordMapper.insert(record); |
| 122 | 121 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
| ... | ... | @@ -34,6 +34,20 @@ public interface SeckillActivityService { |
| 34 | 34 | void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); |
| 35 | 35 | |
| 36 | 36 | /** |
| 37 | + * 更新秒杀活动 | |
| 38 | + * | |
| 39 | + * @param activityDO 秒杀活动 | |
| 40 | + */ | |
| 41 | + void updateSeckillActivity(SeckillActivityDO activityDO); | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 更新秒杀活动商品 | |
| 45 | + * | |
| 46 | + * @param productDOList 活动商品列表 | |
| 47 | + */ | |
| 48 | + void updateSeckillActivityProductByList(List<SeckillProductDO> productDOList); | |
| 49 | + | |
| 50 | + /** | |
| 37 | 51 | * 关闭秒杀活动 |
| 38 | 52 | * |
| 39 | 53 | * @param id 编号 | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
| ... | ... | @@ -79,8 +79,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { |
| 79 | 79 | * 1. 校验秒杀时段是否存在 |
| 80 | 80 | * 2. 秒杀商品是否参加其它活动 |
| 81 | 81 | * |
| 82 | - * @param configIds 秒杀时段数组 | |
| 83 | - * @param spuId 商品 SPU 编号 | |
| 82 | + * @param configIds 秒杀时段数组 | |
| 83 | + * @param spuId 商品 SPU 编号 | |
| 84 | 84 | * @param activityId 秒杀活动编号 |
| 85 | 85 | */ |
| 86 | 86 | private void validateProductConflict(List<Long> configIds, Long spuId, Long activityId) { |
| ... | ... | @@ -92,15 +92,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { |
| 92 | 92 | if (activityId != null) { // 排除自己 |
| 93 | 93 | activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); |
| 94 | 94 | } |
| 95 | - // TODO @puhui999:一个 spu,参与两个活动应该没关系,关键是活动时间不充能重叠; | |
| 96 | - // 2.2 过滤出所有 spuId 有交集的活动,判断是否存在重叠 | |
| 97 | - List<SeckillActivityDO> activityDOs1 = filterList(activityList, s -> ObjectUtil.equal(s.getSpuId(), spuId)); | |
| 98 | - if (isNotEmpty(activityDOs1)) { | |
| 99 | - throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); | |
| 100 | - } | |
| 101 | - // 2.3 过滤出所有 configIds 有交集的活动,判断是否存在重叠 | |
| 102 | - List<SeckillActivityDO> activityDOs2 = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); | |
| 103 | - if (isNotEmpty(activityDOs2)) { | |
| 95 | + // 2.2 过滤出所有 configIds 有交集的活动,判断是否存在重叠 | |
| 96 | + List<SeckillActivityDO> activityDOs = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); | |
| 97 | + if (isNotEmpty(activityDOs)) { | |
| 104 | 98 | throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); |
| 105 | 99 | } |
| 106 | 100 | } |
| ... | ... | @@ -108,7 +102,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { |
| 108 | 102 | /** |
| 109 | 103 | * 校验秒杀商品是否都存在 |
| 110 | 104 | * |
| 111 | - * @param spuId 商品 SPU 编号 | |
| 105 | + * @param spuId 商品 SPU 编号 | |
| 112 | 106 | * @param products 秒杀商品 |
| 113 | 107 | */ |
| 114 | 108 | private void validateProductExists(Long spuId, List<SeckillProductBaseVO> products) { |
| ... | ... | @@ -150,11 +144,21 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { |
| 150 | 144 | updateSeckillProduct(updateObj, updateReqVO.getProducts()); |
| 151 | 145 | } |
| 152 | 146 | |
| 147 | + @Override | |
| 148 | + public void updateSeckillActivity(SeckillActivityDO activityDO) { | |
| 149 | + seckillActivityMapper.updateById(activityDO); | |
| 150 | + } | |
| 151 | + | |
| 152 | + @Override | |
| 153 | + public void updateSeckillActivityProductByList(List<SeckillProductDO> productDOList) { | |
| 154 | + seckillProductMapper.updateBatch(productDOList); | |
| 155 | + } | |
| 156 | + | |
| 153 | 157 | /** |
| 154 | 158 | * 更新秒杀商品 |
| 155 | 159 | * |
| 156 | 160 | * @param activity 秒杀活动 |
| 157 | - * @param products 该活动的最新商品配置 | |
| 161 | + * @param products 该活动的最新商品配置 | |
| 158 | 162 | */ |
| 159 | 163 | private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductBaseVO> products) { |
| 160 | 164 | // 第一步,对比新老数据,获得添加、修改、删除的列表 | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.util; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 5 | 4 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 6 | -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | |
| 7 | 5 | |
| 8 | 6 | import java.time.LocalDateTime; |
| 9 | -import java.util.List; | |
| 10 | -import java.util.Set; | |
| 11 | -import java.util.function.Function; | |
| 12 | - | |
| 13 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 14 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; | |
| 15 | -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | |
| 16 | 7 | |
| 17 | 8 | /** |
| 18 | 9 | * 活动工具类 |
| ... | ... | @@ -31,21 +22,4 @@ public class PromotionUtils { |
| 31 | 22 | return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); |
| 32 | 23 | } |
| 33 | 24 | |
| 34 | - /** | |
| 35 | - * 校验商品 sku 是否都存在 | |
| 36 | - * | |
| 37 | - * @param skus 数据库中的商品 skus | |
| 38 | - * @param products 需要校验的商品 | |
| 39 | - * @param func 获取需要校验的商品的 skuId | |
| 40 | - */ | |
| 41 | - public static <T> void validateProductSkuAllExists(List<ProductSkuRespDTO> skus, List<T> products, Function<T, Long> func) { | |
| 42 | - // 校验 sku 个数是否一致 | |
| 43 | - Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func); | |
| 44 | - Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId); | |
| 45 | - // 校验 skuId 是否存在 | |
| 46 | - if (anyMatch(skuIdsSet, s -> !skuIdsSet1.contains(s))) { | |
| 47 | - throw exception(SKU_NOT_EXISTS); | |
| 48 | - } | |
| 49 | - } | |
| 50 | - | |
| 51 | 25 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/pom.xml
| ... | ... | @@ -86,6 +86,11 @@ |
| 86 | 86 | <artifactId>yudao-spring-boot-starter-mybatis</artifactId> |
| 87 | 87 | </dependency> |
| 88 | 88 | |
| 89 | + <dependency> | |
| 90 | + <groupId>cn.iocoder.boot</groupId> | |
| 91 | + <artifactId>yudao-spring-boot-starter-redis</artifactId> | |
| 92 | + </dependency> | |
| 93 | + | |
| 89 | 94 | <!-- Test 测试相关 --> |
| 90 | 95 | <dependency> |
| 91 | 96 | <groupId>cn.iocoder.boot</groupId> | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
| ... | ... | @@ -36,6 +36,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 36 | 36 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 37 | 37 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; |
| 38 | 38 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 39 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.AFTER_SALE_NOT_FOUND; | |
| 39 | 40 | |
| 40 | 41 | @Tag(name = "管理后台 - 售后订单") |
| 41 | 42 | @RestController |
| ... | ... | @@ -76,6 +77,9 @@ public class TradeAfterSaleController { |
| 76 | 77 | public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) { |
| 77 | 78 | // 查询订单 |
| 78 | 79 | TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); |
| 80 | + if (afterSale == null) { | |
| 81 | + return success(null, AFTER_SALE_NOT_FOUND.getMsg()); | |
| 82 | + } | |
| 79 | 83 | // 查询订单 |
| 80 | 84 | TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); |
| 81 | 85 | // 查询订单项 |
| ... | ... | @@ -92,7 +96,11 @@ public class TradeAfterSaleController { |
| 92 | 96 | TradeAfterSaleLogRespDTO respVO = new TradeAfterSaleLogRespDTO(); |
| 93 | 97 | respVO.setId((long) i); |
| 94 | 98 | respVO.setUserId((long) i); |
| 95 | - respVO.setUserType(1); | |
| 99 | + respVO.setUserType(i % 2 == 0 ? 2 : 1); | |
| 100 | + // 模拟系统操作 | |
| 101 | + if (i == 2) { | |
| 102 | + respVO.setUserType(3); | |
| 103 | + } | |
| 96 | 104 | respVO.setAfterSaleId(id); |
| 97 | 105 | respVO.setOrderId((long) i); |
| 98 | 106 | respVO.setOrderItemId((long) i); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java
| ... | ... | @@ -35,7 +35,7 @@ public class TradeAfterSaleDetailRespVO extends TradeAfterSaleBaseVO { |
| 35 | 35 | /** |
| 36 | 36 | * 售后日志 |
| 37 | 37 | */ |
| 38 | - private List<TradeAfterSaleLogRespVO> afterSaleLog; | |
| 38 | + private List<TradeAfterSaleLogRespVO> logs; | |
| 39 | 39 | |
| 40 | 40 | @Schema(description = "管理后台 - 交易订单的详情的订单项目") |
| 41 | 41 | @Data | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java
| ... | ... | @@ -25,6 +25,7 @@ import java.util.Map; |
| 25 | 25 | |
| 26 | 26 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 27 | 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 28 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; | |
| 28 | 29 | |
| 29 | 30 | @Tag(name = "管理后台 - 交易订单") |
| 30 | 31 | @RestController |
| ... | ... | @@ -67,6 +68,9 @@ public class TradeOrderController { |
| 67 | 68 | public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) { |
| 68 | 69 | // 查询订单 |
| 69 | 70 | TradeOrderDO order = tradeOrderQueryService.getOrder(id); |
| 71 | + if (order == null) { | |
| 72 | + return success(null, ORDER_NOT_FOUND.getMsg()); | |
| 73 | + } | |
| 70 | 74 | // 查询订单项 |
| 71 | 75 | List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); |
| 72 | 76 | // orderLog | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java
| ... | ... | @@ -26,24 +26,23 @@ public class TradeOrderDetailRespVO extends TradeOrderBaseVO { |
| 26 | 26 | private MemberUserRespVO user; |
| 27 | 27 | |
| 28 | 28 | /** |
| 29 | - * TODO 订单操作日志, 先模拟一波;返回 logs,简洁,然后复数哈 | |
| 29 | + * TODO 订单操作日志, 先模拟一波 | |
| 30 | 30 | */ |
| 31 | - private List<OrderLog> orderLog; | |
| 31 | + private List<OrderLog> logs; | |
| 32 | 32 | |
| 33 | - // TODO @puhui999:swagger 注解 | |
| 33 | + @Schema(description = "管理后台 - 交易订单的操作日志") | |
| 34 | 34 | @Data |
| 35 | 35 | public static class OrderLog { |
| 36 | 36 | |
| 37 | - /** | |
| 38 | - * 内容 | |
| 39 | - */ | |
| 37 | + @Schema(description = "操作详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单发货") | |
| 40 | 38 | private String content; |
| 41 | 39 | |
| 42 | - /** | |
| 43 | - * 创建时间 | |
| 44 | - */ | |
| 40 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-01 10:50:20") | |
| 45 | 41 | private LocalDateTime createTime; |
| 46 | 42 | |
| 43 | + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 44 | + private Integer userType; | |
| 45 | + | |
| 47 | 46 | } |
| 48 | 47 | |
| 49 | 48 | @Schema(description = "管理后台 - 交易订单的详情的订单项目") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
| ... | ... | @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; |
| 6 | 6 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; |
| 7 | -import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; | |
| 8 | 7 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; |
| 9 | 8 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; |
| 10 | 9 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; |
| ... | ... | @@ -34,6 +33,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 34 | 33 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 35 | 34 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; |
| 36 | 35 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 36 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; | |
| 37 | 37 | |
| 38 | 38 | @Tag(name = "用户 App - 交易订单") |
| 39 | 39 | @RestController |
| ... | ... | @@ -83,7 +83,7 @@ public class AppTradeOrderController { |
| 83 | 83 | // 查询订单 |
| 84 | 84 | TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); |
| 85 | 85 | if (order == null) { |
| 86 | - return success(null); | |
| 86 | + return success(null, ORDER_NOT_FOUND.getMsg()); | |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | // 查询订单项 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
| ... | ... | @@ -56,6 +56,10 @@ public class AppTradeOrderSettlementReqVO { |
| 56 | 56 | @Schema(description = "拼团团长编号", example = "2048") |
| 57 | 57 | private Long combinationHeadId; |
| 58 | 58 | |
| 59 | + // ========== 砍价活动相关字段 ========== | |
| 60 | + @Schema(description = "砍价活动编号", example = "123") | |
| 61 | + private Long bargainActivityId; | |
| 62 | + | |
| 59 | 63 | @Data |
| 60 | 64 | @Schema(description = "用户 App - 商品项") |
| 61 | 65 | @Valid | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java
| ... | ... | @@ -78,7 +78,7 @@ public interface TradeAfterSaleConvert { |
| 78 | 78 | // 处理订单信息 |
| 79 | 79 | respVO.setOrder(convert(order)); |
| 80 | 80 | // 处理售后日志 |
| 81 | - respVO.setAfterSaleLog(convertList1(logs)); | |
| 81 | + respVO.setLogs(convertList1(logs)); | |
| 82 | 82 | return respVO; |
| 83 | 83 | } |
| 84 | 84 | List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespDTO> list); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| ... | ... | @@ -95,6 +95,7 @@ public interface TradeOrderConvert { |
| 95 | 95 | items.forEach(item -> item.setIncrCount(-item.getIncrCount())); |
| 96 | 96 | return new ProductSkuUpdateStockReqDTO(items); |
| 97 | 97 | } |
| 98 | + | |
| 98 | 99 | List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); |
| 99 | 100 | |
| 100 | 101 | @Mappings({ |
| ... | ... | @@ -153,9 +154,10 @@ public interface TradeOrderConvert { |
| 153 | 154 | TradeOrderDetailRespVO.OrderLog orderLog = new TradeOrderDetailRespVO.OrderLog(); |
| 154 | 155 | orderLog.setContent("订单操作" + i); |
| 155 | 156 | orderLog.setCreateTime(LocalDateTime.now()); |
| 157 | + orderLog.setUserType(i % 2 == 0 ? 2 : 1); | |
| 156 | 158 | orderLogs.add(orderLog); |
| 157 | 159 | } |
| 158 | - orderVO.setOrderLog(orderLogs); | |
| 160 | + orderVO.setLogs(orderLogs); | |
| 159 | 161 | return orderVO; |
| 160 | 162 | } |
| 161 | 163 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.dal.redis.no; | |
| 2 | + | |
| 3 | +import cn.hutool.core.date.DatePattern; | |
| 4 | +import cn.hutool.core.date.DateUtil; | |
| 5 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
| 6 | +import org.springframework.stereotype.Repository; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | +import java.time.LocalDateTime; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 订单序号的 Redis DAO | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Repository | |
| 17 | +public class TradeOrderNoRedisDAO { | |
| 18 | + public static final String TRADE_ORDER_NO_PREFIX = "O"; | |
| 19 | + | |
| 20 | + @Resource | |
| 21 | + private StringRedisTemplate stringRedisTemplate; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 生成序号 | |
| 25 | + * | |
| 26 | + * @param prefix 前缀 | |
| 27 | + * @return 序号 | |
| 28 | + */ | |
| 29 | + public String generate(String prefix) { | |
| 30 | + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN); | |
| 31 | + Long no = stringRedisTemplate.opsForValue().increment(noPrefix); | |
| 32 | + return noPrefix + no; | |
| 33 | + } | |
| 34 | + | |
| 35 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
| ... | ... | @@ -90,12 +90,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 90 | 90 | |
| 91 | 91 | @Override |
| 92 | 92 | public TradeAfterSaleDO getAfterSale(Long id) { |
| 93 | - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); | |
| 94 | - // TODO @puhui999;读不到,不要这里报错哈;交给前端报错;一般是读取信息不到,message 提示,然后 close tab; | |
| 95 | - if (afterSale == null) { | |
| 96 | - throw exception(AFTER_SALE_NOT_FOUND); | |
| 97 | - } | |
| 98 | - return afterSale; | |
| 93 | + return tradeAfterSaleMapper.selectById(id); | |
| 99 | 94 | } |
| 100 | 95 | |
| 101 | 96 | // TODO 芋艿:拼团失败,要不要发起售后的方式退款?还是走取消逻辑? | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| ... | ... | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.order; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.lang.Assert; |
| 5 | -import cn.hutool.core.util.IdUtil; | |
| 6 | 5 | import cn.hutool.core.util.ObjectUtil; |
| 7 | 6 | import cn.hutool.core.util.StrUtil; |
| 8 | 7 | import cn.hutool.extra.spring.SpringUtil; |
| ... | ... | @@ -27,12 +26,14 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 27 | 26 | import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; |
| 28 | 27 | import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; |
| 29 | 28 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; |
| 29 | +import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; | |
| 30 | 30 | import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; |
| 31 | 31 | import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; |
| 32 | 32 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; |
| 33 | -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; | |
| 34 | 33 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; |
| 35 | 34 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 35 | +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; | |
| 36 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; | |
| 36 | 37 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; |
| 37 | 38 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; |
| 38 | 39 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; |
| ... | ... | @@ -48,6 +49,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 48 | 49 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 49 | 50 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; |
| 50 | 51 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; |
| 52 | +import cn.iocoder.yudao.module.trade.dal.redis.no.TradeOrderNoRedisDAO; | |
| 51 | 53 | import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; |
| 52 | 54 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 53 | 55 | import cn.iocoder.yudao.module.trade.enums.order.*; |
| ... | ... | @@ -73,7 +75,7 @@ import java.util.Set; |
| 73 | 75 | |
| 74 | 76 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 75 | 77 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 76 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; | |
| 78 | +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_EQUAL; | |
| 77 | 79 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_PAID; |
| 78 | 80 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; |
| 79 | 81 | |
| ... | ... | @@ -91,6 +93,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 91 | 93 | private TradeOrderMapper tradeOrderMapper; |
| 92 | 94 | @Resource |
| 93 | 95 | private TradeOrderItemMapper tradeOrderItemMapper; |
| 96 | + @Resource | |
| 97 | + private TradeOrderNoRedisDAO orderNoRedisDAO; | |
| 94 | 98 | |
| 95 | 99 | @Resource |
| 96 | 100 | private CartService cartService; |
| ... | ... | @@ -114,6 +118,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 114 | 118 | @Resource |
| 115 | 119 | private BargainRecordApi bargainRecordApi; |
| 116 | 120 | @Resource |
| 121 | + private SeckillActivityApi seckillActivityApi; | |
| 122 | + @Resource | |
| 123 | + private BargainActivityApi bargainActivityApi; | |
| 124 | + @Resource | |
| 117 | 125 | private MemberUserApi memberUserApi; |
| 118 | 126 | @Resource |
| 119 | 127 | private MemberLevelApi memberLevelApi; |
| ... | ... | @@ -194,22 +202,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 194 | 202 | // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去 |
| 195 | 203 | // 拼团 |
| 196 | 204 | if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { |
| 197 | - MemberUserRespDTO user = memberUserApi.getUser(userId); | |
| 198 | - List<CombinationRecordRespDTO> recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); | |
| 199 | - // TODO 拼团一次应该只能选择一种规格的商品 | |
| 200 | - TradeOrderItemDO orderItemDO = orderItems.get(0); | |
| 201 | - if (CollUtil.isNotEmpty(recordRespDTOS)) { | |
| 202 | - List<Long> skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); | |
| 203 | - List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, | |
| 204 | - CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); | |
| 205 | - combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), | |
| 206 | - CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); | |
| 207 | - } | |
| 208 | - | |
| 209 | - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); | |
| 205 | + createCombinationRecord(userId, createReqVO, orderItems, order); | |
| 210 | 206 | } |
| 211 | 207 | // 3.2 秒杀的特殊逻辑 |
| 212 | - // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 | |
| 213 | 208 | if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { |
| 214 | 209 | |
| 215 | 210 | } |
| ... | ... | @@ -219,6 +214,22 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 219 | 214 | return order; |
| 220 | 215 | } |
| 221 | 216 | |
| 217 | + private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List<TradeOrderItemDO> orderItems, TradeOrderDO order) { | |
| 218 | + MemberUserRespDTO user = memberUserApi.getUser(userId); | |
| 219 | + List<CombinationRecordRespDTO> recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); | |
| 220 | + // TODO 拼团一次应该只能选择一种规格的商品 | |
| 221 | + TradeOrderItemDO orderItemDO = orderItems.get(0); | |
| 222 | + if (CollUtil.isNotEmpty(recordRespDTOS)) { | |
| 223 | + List<Long> skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); | |
| 224 | + List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, | |
| 225 | + CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); | |
| 226 | + combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), | |
| 227 | + CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); | |
| 228 | + } | |
| 229 | + | |
| 230 | + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); | |
| 231 | + } | |
| 232 | + | |
| 222 | 233 | // TODO @puhui999:订单超时,自动取消; |
| 223 | 234 | |
| 224 | 235 | /** |
| ... | ... | @@ -245,8 +256,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 245 | 256 | address = validateAddress(userId, createReqVO.getAddressId()); |
| 246 | 257 | } |
| 247 | 258 | TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address); |
| 259 | + String no = orderNoRedisDAO.generate(TradeOrderNoRedisDAO.TRADE_ORDER_NO_PREFIX); | |
| 248 | 260 | order.setType(validateActivity(createReqVO)); |
| 249 | - order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @puhui999: 参考支付订单,的 no 生成哈; | |
| 261 | + order.setNo(no); | |
| 250 | 262 | order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); |
| 251 | 263 | order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); |
| 252 | 264 | order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); |
| ... | ... | @@ -298,19 +310,23 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 298 | 310 | private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, |
| 299 | 311 | TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems, |
| 300 | 312 | TradePriceCalculateRespBO calculateRespBO) { |
| 301 | - // 下单时扣减商品库存 | |
| 302 | - // TODO @puhui999:扣库存,需要前置; | |
| 313 | + Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); | |
| 303 | 314 | // 1)如果是秒杀商品:额外扣减秒杀的库存; |
| 304 | - // 2)如果是拼团活动:额外扣减拼团的库存; | |
| 305 | - // 3)如果是砍价活动:额外扣减砍价的库存; | |
| 306 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); | |
| 307 | - | |
| 308 | - // 删除购物车商品 | |
| 309 | - Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); | |
| 310 | - if (CollUtil.isNotEmpty(cartIds)) { | |
| 311 | - cartService.deleteCart(userId, cartIds); | |
| 312 | - } | |
| 313 | - | |
| 315 | + if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { | |
| 316 | + SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); | |
| 317 | + updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); | |
| 318 | + updateStockReqDTO.setCount(count); | |
| 319 | + updateStockReqDTO.setItems(CollectionUtils.convertList(orderItems, item -> { | |
| 320 | + SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); | |
| 321 | + item1.setSpuId(item.getSpuId()); | |
| 322 | + item1.setSkuId(item.getSkuId()); | |
| 323 | + item1.setCount(item.getCount()); | |
| 324 | + return item1; | |
| 325 | + })); | |
| 326 | + seckillActivityApi.updateSeckillStock(updateStockReqDTO); | |
| 327 | + } | |
| 328 | + // 2)如果是砍价活动:额外扣减砍价的库存; | |
| 329 | + bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); | |
| 314 | 330 | // 扣减积分 TODO 芋艿:待实现,需要前置; |
| 315 | 331 | // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣 |
| 316 | 332 | |
| ... | ... | @@ -320,6 +336,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 320 | 336 | .setOrderId(tradeOrderDO.getId())); |
| 321 | 337 | } |
| 322 | 338 | |
| 339 | + // 下单时扣减商品库存 | |
| 340 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); | |
| 341 | + | |
| 342 | + // 删除购物车商品 | |
| 343 | + Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); | |
| 344 | + if (CollUtil.isNotEmpty(cartIds)) { | |
| 345 | + cartService.deleteCart(userId, cartIds); | |
| 346 | + } | |
| 347 | + | |
| 323 | 348 | // 生成预支付 |
| 324 | 349 | createPayOrder(tradeOrderDO, orderItems, calculateRespBO); |
| 325 | 350 | |
| ... | ... | @@ -356,8 +381,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 356 | 381 | // 1、拼团活动 |
| 357 | 382 | if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { |
| 358 | 383 | // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 |
| 359 | - combinationRecordApi.updateCombinationRecordStatus(new CombinationRecordUpdateStatusReqDTO().setUserId(order.getUserId()) | |
| 360 | - .setOrderId(order.getId()).setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()).setStartTime(LocalDateTime.now())); | |
| 384 | + combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now()); | |
| 361 | 385 | } |
| 362 | 386 | // TODO 芋艿:发送订单变化的消息 |
| 363 | 387 | |
| ... | ... | @@ -472,11 +496,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 472 | 496 | */ |
| 473 | 497 | private TradeOrderDO validateOrderDeliverable(Long id) { |
| 474 | 498 | TradeOrderDO order = validateOrderExists(id); |
| 475 | - // 校验订单是否是待发货状态 | |
| 476 | - // TODO @puhui999:已经发货,可以重新发货,修改信息; | |
| 477 | - if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) { | |
| 478 | - throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); | |
| 479 | - } | |
| 480 | 499 | // 校验订单是否退款 |
| 481 | 500 | if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { |
| 482 | 501 | throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); |
| ... | ... | @@ -548,14 +567,25 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 548 | 567 | if (order.getPayStatus()) { |
| 549 | 568 | throw exception(ORDER_UPDATE_PRICE_FAIL_PAID); |
| 550 | 569 | } |
| 551 | - // TODO @puhui999:如果改价,需要校验下是否真的变化; | |
| 570 | + if (ObjectUtil.equal(order.getAdjustPrice(), reqVO.getAdjustPrice())) { | |
| 571 | + throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL); | |
| 572 | + } | |
| 552 | 573 | |
| 553 | - // 更新 | |
| 554 | - // TODO @puhui999:TradeOrderItemDO 需要做 adjustPrice 的分摊;另外,支付订单那的价格,需要 update 下; | |
| 574 | + List<TradeOrderItemDO> itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId()); | |
| 575 | + // TradeOrderItemDO 需要做 adjustPrice 的分摊 | |
| 576 | + int price = reqVO.getAdjustPrice() / itemDOs.size(); | |
| 577 | + itemDOs.forEach(item -> { | |
| 578 | + item.setAdjustPrice(price); | |
| 579 | + }); | |
| 580 | + // 更新 TradeOrderItem | |
| 581 | + tradeOrderItemMapper.updateBatch(itemDOs); | |
| 582 | + // 更新订单 | |
| 555 | 583 | TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO); |
| 556 | 584 | update.setPayPrice(update.getPayPrice() + update.getAdjustPrice()); |
| 557 | 585 | // TODO @芋艿:改价时,赠送的积分,要不要做改动??? |
| 558 | 586 | tradeOrderMapper.updateById(update); |
| 587 | + // 更新支付订单 | |
| 588 | + payOrderApi.updatePayOrderPriceById(order.getPayOrderId(), update.getPayPrice()); | |
| 559 | 589 | } |
| 560 | 590 | |
| 561 | 591 | @Override | ... | ... |
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
| ... | ... | @@ -28,6 +28,7 @@ public interface ErrorCodeConstants { |
| 28 | 28 | ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); |
| 29 | 29 | ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); |
| 30 | 30 | ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1007002006, "支付订单调价失败,原因:支付订单已付款,不能调价"); |
| 31 | + ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1007002007, "支付订单调价失败,原因:价格没有变化"); | |
| 31 | 32 | |
| 32 | 33 | // ========== ORDER 模块(拓展单) 1007003000 ========== |
| 33 | 34 | ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java
| ... | ... | @@ -31,4 +31,10 @@ public class PayOrderApiImpl implements PayOrderApi { |
| 31 | 31 | return PayOrderConvert.INSTANCE.convert2(order); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | + @Override | |
| 35 | + public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { | |
| 36 | + payOrderService.updatePayOrderPriceById(payOrderId, payPrice); | |
| 37 | + } | |
| 38 | + | |
| 39 | + | |
| 34 | 40 | } | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
| ... | ... | @@ -33,7 +33,7 @@ public interface PayOrderService { |
| 33 | 33 | /** |
| 34 | 34 | * 获得支付订单 |
| 35 | 35 | * |
| 36 | - * @param appId 应用编号 | |
| 36 | + * @param appId 应用编号 | |
| 37 | 37 | * @param merchantOrderId 商户订单编号 |
| 38 | 38 | * @return 支付订单 |
| 39 | 39 | */ |
| ... | ... | @@ -75,7 +75,7 @@ public interface PayOrderService { |
| 75 | 75 | * 提交支付 |
| 76 | 76 | * 此时,会发起支付渠道的调用 |
| 77 | 77 | * |
| 78 | - * @param reqVO 提交请求 | |
| 78 | + * @param reqVO 提交请求 | |
| 79 | 79 | * @param userIp 提交 IP |
| 80 | 80 | * @return 提交结果 |
| 81 | 81 | */ |
| ... | ... | @@ -93,12 +93,20 @@ public interface PayOrderService { |
| 93 | 93 | /** |
| 94 | 94 | * 更新支付订单的退款金额 |
| 95 | 95 | * |
| 96 | - * @param id 编号 | |
| 96 | + * @param id 编号 | |
| 97 | 97 | * @param incrRefundPrice 增加的退款金额 |
| 98 | 98 | */ |
| 99 | 99 | void updateOrderRefundPrice(Long id, Integer incrRefundPrice); |
| 100 | 100 | |
| 101 | 101 | /** |
| 102 | + * 更新支付订单价格 | |
| 103 | + * | |
| 104 | + * @param payOrderId 支付单编号 | |
| 105 | + * @param payPrice 支付单价格 | |
| 106 | + */ | |
| 107 | + void updatePayOrderPriceById(Long payOrderId, Integer payPrice); | |
| 108 | + | |
| 109 | + /** | |
| 102 | 110 | * 获得支付订单 |
| 103 | 111 | * |
| 104 | 112 | * @param id 编号 | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
| ... | ... | @@ -412,6 +412,17 @@ public class PayOrderServiceImpl implements PayOrderService { |
| 412 | 412 | } |
| 413 | 413 | |
| 414 | 414 | @Override |
| 415 | + public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { | |
| 416 | + PayOrderDO order = orderMapper.selectById(payOrderId); | |
| 417 | + if (order == null) { | |
| 418 | + throw exception(ORDER_NOT_FOUND); | |
| 419 | + } | |
| 420 | + | |
| 421 | + order.setPrice(payPrice); | |
| 422 | + orderMapper.updateById(order); | |
| 423 | + } | |
| 424 | + | |
| 425 | + @Override | |
| 415 | 426 | public PayOrderExtensionDO getOrderExtension(Long id) { |
| 416 | 427 | return orderExtensionMapper.selectById(id); |
| 417 | 428 | } | ... | ... |