Commit cd2d0b708910d49399599446f2ec5c399234df13
Merge remote-tracking branch 'origin/feature/mall_product' into feature/mall_product
Showing
24 changed files
with
323 additions
and
188 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
| ... | ... | @@ -111,17 +111,19 @@ public class ProductSpuRespDTO { |
| 111 | 111 | // ========== 物流相关字段 ========= |
| 112 | 112 | |
| 113 | 113 | /** |
| 114 | - * 赠送积分 | |
| 115 | - */ | |
| 116 | - private Integer giveIntegral; | |
| 117 | - | |
| 118 | - /** | |
| 119 | 114 | * 物流配置模板编号 |
| 120 | 115 | * |
| 121 | 116 | * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 |
| 122 | 117 | */ |
| 123 | 118 | private Long deliveryTemplateId; |
| 124 | 119 | |
| 120 | + // ========== 营销相关字段 ========= | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * 赠送积分 | |
| 124 | + */ | |
| 125 | + private Integer giveIntegral; | |
| 126 | + | |
| 125 | 127 | // ========== 统计相关字段 ========= |
| 126 | 128 | |
| 127 | 129 | /** | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderOperateTypeEnum.java
| ... | ... | @@ -14,10 +14,12 @@ import lombok.RequiredArgsConstructor; |
| 14 | 14 | public enum TradeOrderOperateTypeEnum { |
| 15 | 15 | |
| 16 | 16 | MEMBER_CREATE(1, "用户下单"), |
| 17 | + MEMBER_PAY(20, "用户付款成功"), | |
| 17 | 18 | MEMBER_RECEIVE(30, "用户已收货"), |
| 18 | - MEMBER_COMMENT(31, "用户评价"), | |
| 19 | - MEMBER_CANCEL(40, "手动取消订单"), | |
| 20 | - SYSTEM_CANCEL(41, "系统取消订单"), | |
| 19 | + SYSTEM_RECEIVE(31, "到期未收货,系统自动确认收货"), | |
| 20 | + MEMBER_COMMENT(33, "用户评价"), | |
| 21 | + MEMBER_CANCEL(40, "取消订单"), | |
| 22 | + SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"), | |
| 21 | 23 | // 42 预留:管理员取消订单 |
| 22 | 24 | MEMBER_DELETE(43, "删除订单"), |
| 23 | 25 | ; | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
| ... | ... | @@ -140,7 +140,7 @@ public class AppTradeOrderController { |
| 140 | 140 | @Operation(summary = "确认交易订单收货") |
| 141 | 141 | @Parameter(name = "id", description = "交易订单编号") |
| 142 | 142 | public CommonResult<Boolean> receiveOrder(@RequestParam("id") Long id) { |
| 143 | - tradeOrderUpdateService.receiveOrder(getLoginUserId(), id); | |
| 143 | + tradeOrderUpdateService.receiveOrderByMember(getLoginUserId(), id); | |
| 144 | 144 | return success(true); |
| 145 | 145 | } |
| 146 | 146 | |
| ... | ... | @@ -148,7 +148,7 @@ public class AppTradeOrderController { |
| 148 | 148 | @Operation(summary = "取消交易订单") |
| 149 | 149 | @Parameter(name = "id", description = "交易订单编号") |
| 150 | 150 | public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) { |
| 151 | - tradeOrderUpdateService.cancelOrder(getLoginUserId(), id); | |
| 151 | + tradeOrderUpdateService.cancelOrderByMember(getLoginUserId(), id); | |
| 152 | 152 | return success(true); |
| 153 | 153 | } |
| 154 | 154 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| ... | ... | @@ -110,7 +110,7 @@ public interface TradeOrderConvert { |
| 110 | 110 | createReqDTO.setSubject(subject); |
| 111 | 111 | createReqDTO.setBody(subject); // TODO 芋艿:临时写死 |
| 112 | 112 | // 订单相关字段 |
| 113 | - createReqDTO.setPrice(order.getPayPrice()).setExpireTime(addTime(orderProperties.getExpireTime())); | |
| 113 | + createReqDTO.setPrice(order.getPayPrice()).setExpireTime(addTime(orderProperties.getPayExpireTime())); | |
| 114 | 114 | return createReqDTO; |
| 115 | 115 | } |
| 116 | 116 | |
| ... | ... | @@ -180,7 +180,7 @@ public interface TradeOrderConvert { |
| 180 | 180 | TradeOrderProperties tradeOrderProperties, |
| 181 | 181 | DeliveryExpressDO express) { |
| 182 | 182 | AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); |
| 183 | - orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime())); | |
| 183 | + orderVO.setPayExpireTime(addTime(tradeOrderProperties.getPayExpireTime())); | |
| 184 | 184 | if (StrUtil.isNotEmpty(order.getPayChannelCode())) { |
| 185 | 185 | orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode())); |
| 186 | 186 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
| ... | ... | @@ -146,18 +146,20 @@ public class TradeOrderItemDO extends BaseDO { |
| 146 | 146 | private Integer pointPrice; |
| 147 | 147 | /** |
| 148 | 148 | * 使用的积分 |
| 149 | + * | |
| 150 | + * 目的:用于后续取消或者售后订单时,需要归还赠送 | |
| 149 | 151 | */ |
| 150 | 152 | private Integer usePoint; |
| 151 | 153 | /** |
| 152 | 154 | * 赠送的积分 |
| 155 | + * | |
| 156 | + * 目的:用于后续取消或者售后订单时,需要扣减赠送 | |
| 153 | 157 | */ |
| 154 | 158 | private Integer givePoint; |
| 155 | 159 | /** |
| 156 | 160 | * VIP 减免金额,单位:分 |
| 157 | 161 | */ |
| 158 | 162 | private Integer vipPrice; |
| 159 | - // TODO @芋艿:如果商品 vip 折扣时,到底是新增一个 vipPrice 记录优惠记录,还是 vipDiscountPrice,记录 vip 的优惠;还是直接使用 vipPrice; | |
| 160 | - // 目前 crmeb 的选择,单独一个 vipPrice 记录优惠价格;感觉不一定合理,可以在看看有赞的; | |
| 161 | 163 | |
| 162 | 164 | // ========== 售后基本信息 ========== |
| 163 | 165 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java
| ... | ... | @@ -61,10 +61,16 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> { |
| 61 | 61 | .eq(TradeOrderDO::getUserId, loginUserId)); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | - default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status, LocalDateTime expireTime) { | |
| 64 | + default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status, LocalDateTime createTime) { | |
| 65 | 65 | return selectList(new LambdaUpdateWrapper<TradeOrderDO>() |
| 66 | 66 | .eq(TradeOrderDO::getStatus, status) |
| 67 | - .lt(TradeOrderDO::getCreateTime, expireTime)); | |
| 67 | + .lt(TradeOrderDO::getCreateTime, createTime)); | |
| 68 | + } | |
| 69 | + | |
| 70 | + default List<TradeOrderDO> selectListByStatusAndDeliveryTimeLt(Integer status, LocalDateTime deliveryTime) { | |
| 71 | + return selectList(new LambdaUpdateWrapper<TradeOrderDO>() | |
| 72 | + .eq(TradeOrderDO::getStatus, status) | |
| 73 | + .lt(TradeOrderDO::getDeliveryTime, deliveryTime)); | |
| 68 | 74 | } |
| 69 | 75 | |
| 70 | 76 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderProperties.java
| ... | ... | @@ -28,6 +28,12 @@ public class TradeOrderProperties { |
| 28 | 28 | * 支付超时时间 |
| 29 | 29 | */ |
| 30 | 30 | @NotNull(message = "支付超时时间不能为空") |
| 31 | - private Duration expireTime; | |
| 31 | + private Duration payExpireTime; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 收货超时时间 | |
| 35 | + */ | |
| 36 | + @NotNull(message = "收货超时时间不能为空") | |
| 37 | + private Duration receiveExpireTime; | |
| 32 | 38 | |
| 33 | 39 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/TradeOrderLog.java
| ... | ... | @@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.trade.framework.order.core.annotations; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderOperateTypeEnum; |
| 4 | 4 | |
| 5 | -import java.lang.annotation.*; | |
| 5 | +import java.lang.annotation.Documented; | |
| 6 | +import java.lang.annotation.Retention; | |
| 7 | +import java.lang.annotation.RetentionPolicy; | |
| 8 | +import java.lang.annotation.Target; | |
| 6 | 9 | |
| 7 | 10 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; |
| 8 | 11 | import static java.lang.annotation.ElementType.METHOD; | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java
| ... | ... | @@ -32,6 +32,16 @@ import static java.util.Collections.emptyMap; |
| 32 | 32 | public class TradeOrderLogAspect { |
| 33 | 33 | |
| 34 | 34 | /** |
| 35 | + * 用户编号 | |
| 36 | + * | |
| 37 | + * 目前的使用场景:支付回调时,需要强制设置下用户编号 | |
| 38 | + */ | |
| 39 | + private static final ThreadLocal<Long> USER_ID = new ThreadLocal<>(); | |
| 40 | + /** | |
| 41 | + * 用户类型 | |
| 42 | + */ | |
| 43 | + private static final ThreadLocal<Integer> USER_TYPE = new ThreadLocal<>(); | |
| 44 | + /** | |
| 35 | 45 | * 订单编号 |
| 36 | 46 | */ |
| 37 | 47 | private static final ThreadLocal<Long> ORDER_ID = new ThreadLocal<>(); |
| ... | ... | @@ -112,4 +122,9 @@ public class TradeOrderLogAspect { |
| 112 | 122 | EXTS.set(exts); |
| 113 | 123 | } |
| 114 | 124 | |
| 125 | + public static void setUserInfo(Long userId, Integer userType) { | |
| 126 | + USER_ID.set(userId); | |
| 127 | + USER_TYPE.set(userType); | |
| 128 | + } | |
| 129 | + | |
| 115 | 130 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/utils/TradeOrderLogUtils.java
| ... | ... | @@ -20,4 +20,8 @@ public class TradeOrderLogUtils { |
| 20 | 20 | TradeOrderLogAspect.setOrderInfo(id, beforeStatus, afterStatus, exts); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | + public static void setUserInfo(Long userId, Integer userType) { | |
| 24 | + TradeOrderLogAspect.setUserInfo(userId, userType); | |
| 25 | + } | |
| 26 | + | |
| 23 | 27 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/order/TradeOrderAutoCancelJob.java
| ... | ... | @@ -21,7 +21,7 @@ public class TradeOrderAutoCancelJob implements JobHandler { |
| 21 | 21 | |
| 22 | 22 | @Override |
| 23 | 23 | public String execute(String param) { |
| 24 | - int count = tradeOrderUpdateService.autoCancelOrder(); | |
| 24 | + int count = tradeOrderUpdateService.cancelOrderBySystem(); | |
| 25 | 25 | return String.format("过期订单 %s 个", count); |
| 26 | 26 | } |
| 27 | 27 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/order/TradeOrderAutoReceiveJob.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.job.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; | |
| 4 | +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; | |
| 5 | +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; | |
| 6 | +import org.springframework.stereotype.Component; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 交易订单的自动收货 Job | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@Component | |
| 16 | +@TenantJob | |
| 17 | +public class TradeOrderAutoReceiveJob implements JobHandler { | |
| 18 | + | |
| 19 | + @Resource | |
| 20 | + private TradeOrderUpdateService tradeOrderUpdateService; | |
| 21 | + | |
| 22 | + @Override | |
| 23 | + public String execute(String param) { | |
| 24 | + int count = tradeOrderUpdateService.receiveOrderBySystem(); | |
| 25 | + return String.format("自动收货 %s 个", count); | |
| 26 | + } | |
| 27 | + | |
| 28 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
| ... | ... | @@ -60,22 +60,29 @@ public interface TradeOrderUpdateService { |
| 60 | 60 | * @param userId 用户编号 |
| 61 | 61 | * @param id 订单编号 |
| 62 | 62 | */ |
| 63 | - void receiveOrder(Long userId, Long id); | |
| 63 | + void receiveOrderByMember(Long userId, Long id); | |
| 64 | 64 | |
| 65 | 65 | /** |
| 66 | - * 【会员】取消订单 | |
| 66 | + * 【系统】自动收货交易订单 | |
| 67 | + * | |
| 68 | + * @return 收货数量 | |
| 69 | + */ | |
| 70 | + int receiveOrderBySystem(); | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * 【会员】取消交易订单 | |
| 67 | 74 | * |
| 68 | 75 | * @param userId 用户编号 |
| 69 | 76 | * @param id 订单编号 |
| 70 | 77 | */ |
| 71 | - void cancelOrder(Long userId, Long id); | |
| 78 | + void cancelOrderByMember(Long userId, Long id); | |
| 72 | 79 | |
| 73 | 80 | /** |
| 74 | 81 | * 【系统】自动取消订单 |
| 75 | 82 | * |
| 76 | 83 | * @return 取消数量 |
| 77 | 84 | */ |
| 78 | - int autoCancelOrder(); | |
| 85 | + int cancelOrderBySystem(); | |
| 79 | 86 | |
| 80 | 87 | /** |
| 81 | 88 | * 【会员】删除订单 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| ... | ... | @@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil; |
| 8 | 8 | import cn.hutool.extra.spring.SpringUtil; |
| 9 | 9 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 10 | 10 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; |
| 11 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | |
| 11 | 12 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 12 | 13 | import cn.iocoder.yudao.module.member.api.address.AddressApi; |
| 13 | 14 | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; |
| ... | ... | @@ -321,38 +322,39 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 321 | 322 | |
| 322 | 323 | @Override |
| 323 | 324 | @Transactional(rollbackFor = Exception.class) |
| 325 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY) | |
| 324 | 326 | public void updateOrderPaid(Long id, Long payOrderId) { |
| 325 | - // 校验并获得交易订单(可支付) | |
| 327 | + // 1. 校验并获得交易订单(可支付) | |
| 326 | 328 | KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPayable(id, payOrderId); |
| 327 | 329 | TradeOrderDO order = orderResult.getKey(); |
| 328 | 330 | PayOrderRespDTO payOrder = orderResult.getValue(); |
| 329 | 331 | |
| 330 | - // 更新 TradeOrderDO 状态为已支付,等待发货 | |
| 332 | + // 2. 更新 TradeOrderDO 状态为已支付,等待发货 | |
| 331 | 333 | int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), |
| 332 | 334 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true) |
| 333 | 335 | .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode())); |
| 334 | 336 | if (updateCount == 0) { |
| 335 | 337 | throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); |
| 336 | 338 | } |
| 337 | - // 校验活动 | |
| 339 | + | |
| 340 | + // 3. 校验活动 | |
| 338 | 341 | // 1、拼团活动 |
| 339 | 342 | // TODO @puhui999:这块也抽象到 handler 里 |
| 340 | 343 | if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { |
| 341 | 344 | // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 |
| 342 | 345 | combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now()); |
| 343 | 346 | } |
| 344 | - // TODO 芋艿:发送订单变化的消息 | |
| 345 | - | |
| 346 | - // TODO 芋艿:发送站内信 | |
| 347 | 347 | |
| 348 | - // TODO 芋艿:OrderLog | |
| 349 | - | |
| 350 | - // 增加用户积分(赠送) | |
| 351 | - addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_REWARD, order.getId()); | |
| 352 | - // 增加用户经验 | |
| 348 | + // 4.1 增加用户积分(赠送) | |
| 349 | + addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, order.getId()); | |
| 350 | + // 4.2 增加用户经验 | |
| 353 | 351 | getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); |
| 354 | - // 增加用户佣金 | |
| 352 | + // 4.3 增加用户佣金 | |
| 355 | 353 | getSelf().addBrokerageAsync(order.getUserId(), order.getId()); |
| 354 | + | |
| 355 | + // 5. 记录订单日志 | |
| 356 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); | |
| 357 | + TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue()); | |
| 356 | 358 | } |
| 357 | 359 | |
| 358 | 360 | /** |
| ... | ... | @@ -435,8 +437,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 435 | 437 | throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); |
| 436 | 438 | } |
| 437 | 439 | |
| 438 | - // TODO 芋艿:发送订单变化的消息 | |
| 439 | - | |
| 440 | 440 | // 发送站内信 |
| 441 | 441 | tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId()) |
| 442 | 442 | .setUserId(order.getUserId()).setMessage(null)); |
| ... | ... | @@ -488,10 +488,54 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 488 | 488 | @Override |
| 489 | 489 | @Transactional(rollbackFor = Exception.class) |
| 490 | 490 | @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_RECEIVE) |
| 491 | - public void receiveOrder(Long userId, Long id) { | |
| 491 | + public void receiveOrderByMember(Long userId, Long id) { | |
| 492 | 492 | // 校验并获得交易订单(可收货) |
| 493 | 493 | TradeOrderDO order = validateOrderReceivable(userId, id); |
| 494 | 494 | |
| 495 | + // 收货订单 | |
| 496 | + receiveOrder0(order); | |
| 497 | + } | |
| 498 | + | |
| 499 | + @Override | |
| 500 | + public int receiveOrderBySystem() { | |
| 501 | + // 1. 查询过期的待支付订单 | |
| 502 | + LocalDateTime expireTime = addTime(tradeOrderProperties.getReceiveExpireTime()); | |
| 503 | + List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndDeliveryTimeLt( | |
| 504 | + TradeOrderStatusEnum.DELIVERED.getStatus(), expireTime); | |
| 505 | + if (CollUtil.isEmpty(orders)) { | |
| 506 | + return 0; | |
| 507 | + } | |
| 508 | + | |
| 509 | + // 2. 遍历执行,逐个取消 | |
| 510 | + int count = 0; | |
| 511 | + for (TradeOrderDO order : orders) { | |
| 512 | + try { | |
| 513 | + getSelf().receiveOrderBySystem(order); | |
| 514 | + count ++; | |
| 515 | + } catch (Throwable e) { | |
| 516 | + log.error("[autoReceiveOrder][order({}) 自动收货订单异常]", order.getId(), e); | |
| 517 | + } | |
| 518 | + } | |
| 519 | + return count; | |
| 520 | + } | |
| 521 | + | |
| 522 | + /** | |
| 523 | + * 自动收货单个订单 | |
| 524 | + * | |
| 525 | + * @param order 订单 | |
| 526 | + */ | |
| 527 | + @Transactional(rollbackFor = Exception.class) | |
| 528 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_RECEIVE) | |
| 529 | + public void receiveOrderBySystem(TradeOrderDO order) { | |
| 530 | + receiveOrder0(order); | |
| 531 | + } | |
| 532 | + | |
| 533 | + /** | |
| 534 | + * 收货订单的核心实现 | |
| 535 | + * | |
| 536 | + * @param order 订单 | |
| 537 | + */ | |
| 538 | + private void receiveOrder0(TradeOrderDO order) { | |
| 495 | 539 | // 更新 TradeOrderDO 状态为已完成 |
| 496 | 540 | int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), |
| 497 | 541 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now())); |
| ... | ... | @@ -499,14 +543,137 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 499 | 543 | throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); |
| 500 | 544 | } |
| 501 | 545 | |
| 502 | - // TODO 芋艿:lili 发送订单变化的消息 | |
| 546 | + // 插入订单日志 | |
| 547 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); | |
| 548 | + } | |
| 549 | + | |
| 550 | + /** | |
| 551 | + * 校验交易订单满足可售货的条件 | |
| 552 | + * | |
| 553 | + * 1. 交易订单待收货 | |
| 554 | + * | |
| 555 | + * @param userId 用户编号 | |
| 556 | + * @param id 交易订单编号 | |
| 557 | + * @return 交易订单 | |
| 558 | + */ | |
| 559 | + private TradeOrderDO validateOrderReceivable(Long userId, Long id) { | |
| 560 | + // 校验订单是否存在 | |
| 561 | + TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); | |
| 562 | + if (order == null) { | |
| 563 | + throw exception(ORDER_NOT_FOUND); | |
| 564 | + } | |
| 565 | + // 校验订单是否是待收货状态 | |
| 566 | + if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { | |
| 567 | + throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); | |
| 568 | + } | |
| 569 | + return order; | |
| 570 | + } | |
| 571 | + | |
| 572 | + @Override | |
| 573 | + @Transactional(rollbackFor = Exception.class) | |
| 574 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) | |
| 575 | + public void cancelOrderByMember(Long userId, Long id) { | |
| 576 | + // 1.1 校验存在 | |
| 577 | + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | |
| 578 | + if (order == null) { | |
| 579 | + throw exception(ORDER_NOT_FOUND); | |
| 580 | + } | |
| 581 | + // 1.2 校验状态 | |
| 582 | + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { | |
| 583 | + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | |
| 584 | + } | |
| 585 | + | |
| 586 | + // 2. 取消订单 | |
| 587 | + cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); | |
| 588 | + } | |
| 589 | + | |
| 590 | + @Override | |
| 591 | + public int cancelOrderBySystem() { | |
| 592 | + // 1. 查询过期的待支付订单 | |
| 593 | + LocalDateTime expireTime = addTime(tradeOrderProperties.getPayExpireTime()); | |
| 594 | + List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt( | |
| 595 | + TradeOrderStatusEnum.UNPAID.getStatus(), expireTime); | |
| 596 | + if (CollUtil.isEmpty(orders)) { | |
| 597 | + return 0; | |
| 598 | + } | |
| 503 | 599 | |
| 504 | - // TODO 芋艿:lili 发送商品被购买完成的数据 | |
| 600 | + // 2. 遍历执行,逐个取消 | |
| 601 | + int count = 0; | |
| 602 | + for (TradeOrderDO order : orders) { | |
| 603 | + try { | |
| 604 | + getSelf().cancelOrderBySystem(order); | |
| 605 | + count ++; | |
| 606 | + } catch (Throwable e) { | |
| 607 | + log.error("[autoCancelOrder][order({}) 过期订单异常]", order.getId(), e); | |
| 608 | + } | |
| 609 | + } | |
| 610 | + return count; | |
| 611 | + } | |
| 505 | 612 | |
| 506 | - // TODO 芋艿:销售佣金的记录; | |
| 613 | + /** | |
| 614 | + * 自动取消单个订单 | |
| 615 | + * | |
| 616 | + * @param order 订单 | |
| 617 | + */ | |
| 618 | + @Transactional(rollbackFor = Exception.class) | |
| 619 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL) | |
| 620 | + public void cancelOrderBySystem(TradeOrderDO order) { | |
| 621 | + cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT); | |
| 622 | + } | |
| 507 | 623 | |
| 508 | - // 插入订单日志 | |
| 509 | - TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); | |
| 624 | + /** | |
| 625 | + * 取消订单的核心实现 | |
| 626 | + * | |
| 627 | + * @param order 订单 | |
| 628 | + * @param cancelType 取消类型 | |
| 629 | + */ | |
| 630 | + private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { | |
| 631 | + Long id = order.getId(); | |
| 632 | + // 1. 更新 TradeOrderDO 状态为已取消 | |
| 633 | + int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | |
| 634 | + new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | |
| 635 | + .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); | |
| 636 | + if (updateCount == 0) { | |
| 637 | + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | |
| 638 | + } | |
| 639 | + | |
| 640 | + // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 | |
| 641 | + tradeOrderHandlers.forEach(handler -> handler.rollback()); | |
| 642 | + | |
| 643 | + // 3. 回滚库存 | |
| 644 | + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | |
| 645 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | |
| 646 | + | |
| 647 | + // 4. 回滚优惠券 | |
| 648 | + if (order.getCouponId() != null && order.getCouponId() > 0) { | |
| 649 | + couponApi.returnUsedCoupon(order.getCouponId()); | |
| 650 | + } | |
| 651 | + | |
| 652 | + // 5. 回滚积分(抵扣的) | |
| 653 | + addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); | |
| 654 | + | |
| 655 | + // 6. 增加订单日志 | |
| 656 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); | |
| 657 | + } | |
| 658 | + | |
| 659 | + @Override | |
| 660 | + @Transactional(rollbackFor = Exception.class) | |
| 661 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE) | |
| 662 | + public void deleteOrder(Long userId, Long id) { | |
| 663 | + // 1.1 校验存在 | |
| 664 | + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | |
| 665 | + if (order == null) { | |
| 666 | + throw exception(ORDER_NOT_FOUND); | |
| 667 | + } | |
| 668 | + // 1.2 校验状态 | |
| 669 | + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) { | |
| 670 | + throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL); | |
| 671 | + } | |
| 672 | + // 2. 删除订单 | |
| 673 | + tradeOrderMapper.deleteById(id); | |
| 674 | + | |
| 675 | + // 3. 记录日志 | |
| 676 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus()); | |
| 510 | 677 | } |
| 511 | 678 | |
| 512 | 679 | @Override |
| ... | ... | @@ -604,33 +771,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 604 | 771 | tradeOrderMapper.updateById(update); |
| 605 | 772 | } |
| 606 | 773 | |
| 607 | - /** | |
| 608 | - * 校验交易订单满足可售货的条件 | |
| 609 | - * | |
| 610 | - * 1. 交易订单待收货 | |
| 611 | - * | |
| 612 | - * @param userId 用户编号 | |
| 613 | - * @param id 交易订单编号 | |
| 614 | - * @return 交易订单 | |
| 615 | - */ | |
| 616 | - private TradeOrderDO validateOrderReceivable(Long userId, Long id) { | |
| 617 | - // 校验订单是否存在 | |
| 618 | - TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); | |
| 619 | - if (order == null) { | |
| 620 | - throw exception(ORDER_NOT_FOUND); | |
| 621 | - } | |
| 622 | - // 校验订单是否是待收货状态 | |
| 623 | - if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { | |
| 624 | - throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); | |
| 625 | - } | |
| 626 | - return order; | |
| 627 | - } | |
| 628 | - | |
| 629 | 774 | // =================== Order Item =================== |
| 630 | 775 | |
| 776 | + // TODO 疯狂:帮我重构下: | |
| 777 | + // 1. updateOrderItemAfterSaleStatus 拆分成三个方法:发起;同意;拒绝。原因是,职责更清晰,操作日志也更容易记录; | |
| 778 | + | |
| 631 | 779 | @Override |
| 632 | 780 | @Transactional(rollbackFor = Exception.class) |
| 633 | - // TODO 芋艿: | |
| 634 | 781 | public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, |
| 635 | 782 | Long afterSaleId, Integer refundPrice) { |
| 636 | 783 | // 如果退款成功,则 refundPrice 非空 |
| ... | ... | @@ -658,6 +805,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 658 | 805 | TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); |
| 659 | 806 | TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); |
| 660 | 807 | Integer orderRefundPrice = order.getRefundPrice() + refundPrice; |
| 808 | + // TODO @疯狂:809 到 817 改成:cancelOrderByAfterSale:相当于全部售后成功后,就是要取消胆子; | |
| 661 | 809 | if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 |
| 662 | 810 | tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) |
| 663 | 811 | .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()).setRefundPrice(orderRefundPrice).setRefundPoint(order.getRefundPoint() + orderItem.getUsePoint()) |
| ... | ... | @@ -667,7 +815,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 667 | 815 | |
| 668 | 816 | // TODO 芋艿:要不要退优惠劵 |
| 669 | 817 | |
| 670 | - // TODO 芋艿:站内信? | |
| 671 | 818 | } else { // 如果部分售后,则更新退款金额 |
| 672 | 819 | tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) |
| 673 | 820 | .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); |
| ... | ... | @@ -676,6 +823,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 676 | 823 | // TODO 芋艿:这块扣减规则,需要在考虑下 |
| 677 | 824 | // 售后成功后,执行数据回滚逻辑 |
| 678 | 825 | if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())) { |
| 826 | + // TODO @疯狂:这里库存也要扣减下; | |
| 679 | 827 | // 扣减用户积分(赠送的) |
| 680 | 828 | reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, afterSaleId); |
| 681 | 829 | // 增加用户积分(返还抵扣) |
| ... | ... | @@ -723,113 +871,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 723 | 871 | return comment; |
| 724 | 872 | } |
| 725 | 873 | |
| 726 | - @Override | |
| 727 | - @Transactional(rollbackFor = Exception.class) | |
| 728 | - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) | |
| 729 | - public void cancelOrder(Long userId, Long id) { | |
| 730 | - // 1.1 校验存在 | |
| 731 | - TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | |
| 732 | - if (order == null) { | |
| 733 | - throw exception(ORDER_NOT_FOUND); | |
| 734 | - } | |
| 735 | - // 1.2 校验状态 | |
| 736 | - if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { | |
| 737 | - throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | |
| 738 | - } | |
| 739 | - | |
| 740 | - // 2. 取消订单 | |
| 741 | - cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); | |
| 742 | - } | |
| 743 | - | |
| 744 | - @Override | |
| 745 | - public int autoCancelOrder() { | |
| 746 | - // 1. 查询过期的待支付订单 | |
| 747 | - LocalDateTime expireTime = addTime(tradeOrderProperties.getExpireTime()); | |
| 748 | - List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt( | |
| 749 | - TradeOrderStatusEnum.UNPAID.getStatus(), expireTime); | |
| 750 | - if (CollUtil.isEmpty(orders)) { | |
| 751 | - return 0; | |
| 752 | - } | |
| 753 | - | |
| 754 | - // 2. 遍历执行,逐个取消 | |
| 755 | - int count = 0; | |
| 756 | - for (TradeOrderDO order : orders) { | |
| 757 | - try { | |
| 758 | - getSelf().autoCancelOrder(order); | |
| 759 | - count ++; | |
| 760 | - } catch (Throwable e) { | |
| 761 | - log.error("[autoCancelOrder][order({}) 过期订单异常]", order.getId(), e); | |
| 762 | - } | |
| 763 | - } | |
| 764 | - return count; | |
| 765 | - } | |
| 766 | - | |
| 767 | - /** | |
| 768 | - * 自动取消单个订单 | |
| 769 | - * | |
| 770 | - * @param order 订单 | |
| 771 | - */ | |
| 772 | - @Transactional(rollbackFor = Exception.class) | |
| 773 | - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL) | |
| 774 | - public void autoCancelOrder(TradeOrderDO order) { | |
| 775 | - cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT); | |
| 776 | - } | |
| 777 | - | |
| 778 | - /** | |
| 779 | - * 取消订单的核心实现 | |
| 780 | - * | |
| 781 | - * @param order 订单 | |
| 782 | - * @param cancelType 取消类型 | |
| 783 | - */ | |
| 784 | - private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { | |
| 785 | - Long id = order.getId(); | |
| 786 | - // 1. 更新 TradeOrderDO 状态为已取消 | |
| 787 | - int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | |
| 788 | - new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | |
| 789 | - .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); | |
| 790 | - if (updateCount == 0) { | |
| 791 | - throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | |
| 792 | - } | |
| 793 | - | |
| 794 | - // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 | |
| 795 | - tradeOrderHandlers.forEach(handler -> handler.rollback()); | |
| 796 | - | |
| 797 | - // 3. 回滚库存 | |
| 798 | - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | |
| 799 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | |
| 800 | - | |
| 801 | - // 4. 回滚优惠券 | |
| 802 | - if (order.getCouponId() != null && order.getCouponId() > 0) { | |
| 803 | - couponApi.returnUsedCoupon(order.getCouponId()); | |
| 804 | - } | |
| 805 | - | |
| 806 | - // 5. 回滚积分(抵扣的) | |
| 807 | - addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); | |
| 808 | - | |
| 809 | - // 6. 增加订单日志 | |
| 810 | - TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); | |
| 811 | - } | |
| 812 | - | |
| 813 | - @Override | |
| 814 | - @Transactional(rollbackFor = Exception.class) | |
| 815 | - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE) | |
| 816 | - public void deleteOrder(Long userId, Long id) { | |
| 817 | - // 1.1 校验存在 | |
| 818 | - TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | |
| 819 | - if (order == null) { | |
| 820 | - throw exception(ORDER_NOT_FOUND); | |
| 821 | - } | |
| 822 | - // 1.2 校验状态 | |
| 823 | - if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) { | |
| 824 | - throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL); | |
| 825 | - } | |
| 826 | - // 2. 删除订单 | |
| 827 | - tradeOrderMapper.deleteById(id); | |
| 828 | - | |
| 829 | - // 3. 记录日志 | |
| 830 | - TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus()); | |
| 831 | - } | |
| 832 | - | |
| 833 | 874 | /** |
| 834 | 875 | * 判断指定订单的所有订单项,是不是都售后成功 |
| 835 | 876 | * |
| ... | ... | @@ -842,6 +883,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 842 | 883 | TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())); |
| 843 | 884 | } |
| 844 | 885 | |
| 886 | + // =================== 营销相关的操作 =================== | |
| 887 | + | |
| 845 | 888 | @Async |
| 846 | 889 | protected void addUserExperienceAsync(Long userId, Integer payPrice, Long orderId) { |
| 847 | 890 | int bizType = MemberExperienceBizTypeEnum.ORDER.getType(); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointGiveCalculator.java
| ... | ... | @@ -16,6 +16,7 @@ import java.util.Optional; |
| 16 | 16 | |
| 17 | 17 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| 18 | 18 | |
| 19 | +// TODO @疯狂:这个可以搞个单测; | |
| 19 | 20 | /** |
| 20 | 21 | * 赠送积分的 {@link TradePriceCalculator} 实现类 |
| 21 | 22 | * |
| ... | ... | @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. |
| 25 | 26 | @Order(TradePriceCalculator.ORDER_POINT_GIVE) |
| 26 | 27 | @Slf4j |
| 27 | 28 | public class TradePointGiveCalculator implements TradePriceCalculator { |
| 29 | + | |
| 28 | 30 | @Resource |
| 29 | 31 | private MemberPointApi memberPointApi; |
| 30 | 32 | |
| ... | ... | @@ -54,9 +56,10 @@ public class TradePointGiveCalculator implements TradePriceCalculator { |
| 54 | 56 | TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); |
| 55 | 57 | // 商品可能赠送了积分,所以这里要加上 |
| 56 | 58 | orderItem.setGivePoint(orderItem.getGivePoint() + dividePoints.get(i)); |
| 57 | - TradePriceCalculatorHelper.recountPayPrice(orderItem); | |
| 59 | + TradePriceCalculatorHelper.recountPayPrice(orderItem); // TODO @疯狂:这个应该不用调用哇?不影响支付金额 | |
| 58 | 60 | } |
| 59 | 61 | // 3.3 更新订单赠送积分 |
| 60 | 62 | TradePriceCalculatorHelper.recountAllGivePoint(result); |
| 61 | 63 | } |
| 64 | + | |
| 62 | 65 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointUsePriceCalculator.java
| ... | ... | @@ -20,6 +20,7 @@ import java.util.List; |
| 20 | 20 | |
| 21 | 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| 22 | 22 | |
| 23 | +// TODO @疯狂:搞个单测,嘿嘿; | |
| 23 | 24 | /** |
| 24 | 25 | * 使用积分的 {@link TradePriceCalculator} 实现类 |
| 25 | 26 | * |
| ... | ... | @@ -29,6 +30,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. |
| 29 | 30 | @Order(TradePriceCalculator.ORDER_POINT_USE) |
| 30 | 31 | @Slf4j |
| 31 | 32 | public class TradePointUsePriceCalculator implements TradePriceCalculator { |
| 33 | + | |
| 32 | 34 | @Resource |
| 33 | 35 | private MemberPointApi memberPointApi; |
| 34 | 36 | @Resource |
| ... | ... | @@ -48,13 +50,14 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { |
| 48 | 50 | } |
| 49 | 51 | // 1.3 校验用户积分余额 |
| 50 | 52 | MemberUserRespDTO user = memberUserApi.getUser(param.getUserId()); |
| 51 | - if (user.getPoint() == null || user.getPoint() < 0) { | |
| 53 | + if (user.getPoint() == null || user.getPoint() <= 0) { | |
| 52 | 54 | return; |
| 53 | 55 | } |
| 54 | 56 | |
| 55 | 57 | // 2.1 计算积分优惠金额 |
| 58 | + // TODO @疯狂:如果计算出来,优惠金额为 0,那是不是不用执行后续逻辑哈 | |
| 56 | 59 | int pointPrice = calculatePointPrice(config, user.getPoint(), result); |
| 57 | - // 2.1 计算分摊的积分、抵扣金额 | |
| 60 | + // 2.2 计算分摊的积分、抵扣金额 | |
| 58 | 61 | List<TradePriceCalculateRespBO.OrderItem> orderItems = filterList(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSelected); |
| 59 | 62 | List<Integer> dividePointPrices = TradePriceCalculatorHelper.dividePrice(orderItems, pointPrice); |
| 60 | 63 | List<Integer> divideUsePoints = TradePriceCalculatorHelper.dividePrice(orderItems, result.getUsePoint()); |
| ... | ... | @@ -74,7 +77,9 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { |
| 74 | 77 | TradePriceCalculatorHelper.recountAllPrice(result); |
| 75 | 78 | } |
| 76 | 79 | |
| 80 | + // TODO @疯狂:这个最好是 is 开头;因为 check 或者 validator,更多失败,会抛出异常; | |
| 77 | 81 | private boolean checkDeductPointEnable(MemberPointConfigRespDTO config) { |
| 82 | + // TODO @疯狂:这个要不直接写成 return config != null && config .... 多行这样一个形式; | |
| 78 | 83 | if (config == null) { |
| 79 | 84 | return false; |
| 80 | 85 | } |
| ... | ... | @@ -93,7 +98,7 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { |
| 93 | 98 | } |
| 94 | 99 | // 积分优惠金额(分) |
| 95 | 100 | int pointPrice = usePoint * config.getTradeDeductUnitPrice(); |
| 96 | - // 0元购!!!:用户积分比较多时,积分可以抵扣的金额要大于支付金额, 这时需要根据支付金额反推使用多少积分 | |
| 101 | + // 0 元购!!!:用户积分比较多时,积分可以抵扣的金额要大于支付金额,这时需要根据支付金额反推使用多少积分 | |
| 97 | 102 | if (result.getPrice().getPayPrice() < pointPrice) { |
| 98 | 103 | pointPrice = result.getPrice().getPayPrice(); |
| 99 | 104 | // 反推需要扣除的积分 |
| ... | ... | @@ -103,7 +108,7 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator { |
| 103 | 108 | } |
| 104 | 109 | // 记录使用的积分 |
| 105 | 110 | result.setUsePoint(usePoint); |
| 106 | - | |
| 107 | 111 | return pointPrice; |
| 108 | 112 | } |
| 113 | + | |
| 109 | 114 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java
| ... | ... | @@ -21,11 +21,13 @@ public interface TradePriceCalculator { |
| 21 | 21 | /** |
| 22 | 22 | * 快递运费的计算 |
| 23 | 23 | * |
| 24 | - * 放在各种营销活动、优惠劵后面 TODO | |
| 24 | + * 放在各种营销活动、优惠劵后面 | |
| 25 | 25 | */ |
| 26 | 26 | int ORDER_DELIVERY = 50; |
| 27 | 27 | /** |
| 28 | 28 | * 赠送积分,放最后 |
| 29 | + * | |
| 30 | + * 放在 {@link #ORDER_DELIVERY} 后面的原因,是运费也会产生费用,需要赠送对应积分 | |
| 29 | 31 | */ |
| 30 | 32 | int ORDER_POINT_GIVE = 999; |
| 31 | 33 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
| ... | ... | @@ -199,6 +199,8 @@ public class TradePriceCalculatorHelper { |
| 199 | 199 | /** |
| 200 | 200 | * 按照支付金额,返回每个订单项的分摊金额数组 |
| 201 | 201 | * |
| 202 | + * 实际上 price 不仅仅可以传递的是金额,也可以是积分。因为它的实现逻辑,就是根据 payPrice 做分摊而已 | |
| 203 | + * | |
| 202 | 204 | * @param orderItems 订单项数组 |
| 203 | 205 | * @param price 金额 |
| 204 | 206 | * @return 分摊金额数组,和传入的 orderItems 一一对应 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java
| ... | ... | @@ -87,7 +87,7 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { |
| 87 | 87 | @BeforeEach |
| 88 | 88 | public void setUp() { |
| 89 | 89 | when(tradeOrderProperties.getAppId()).thenReturn(888L); |
| 90 | - when(tradeOrderProperties.getExpireTime()).thenReturn(Duration.ofDays(1)); | |
| 90 | + when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1)); | |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | @Test |
| ... | ... | @@ -306,7 +306,7 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { |
| 306 | 306 | // mock 方法(支付单) |
| 307 | 307 | |
| 308 | 308 | // 调用 |
| 309 | - tradeOrderUpdateService.receiveOrder(userId, id); | |
| 309 | + tradeOrderUpdateService.receiveOrderByMember(userId, id); | |
| 310 | 310 | // 断言 |
| 311 | 311 | TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); |
| 312 | 312 | assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); | ... | ... |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/MemberPointApi.java
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/point/dto/MemberPointConfigRespDTO.java
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java
| ... | ... | @@ -17,11 +17,11 @@ import java.util.Objects; |
| 17 | 17 | public enum MemberPointBizTypeEnum implements IntArrayValuable { |
| 18 | 18 | |
| 19 | 19 | SIGN(1, "签到", "签到获得 {} 积分", true), |
| 20 | - ORDER_REWARD(10, "订单奖励", "下单获得 {} 积分", true), | |
| 21 | - ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 退回积分 | |
| 22 | - ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 扣减积分 | |
| 23 | - AFTER_SALE_REFUND_USED(13, "订单退款", "订单退款,退还 {} 积分", true), // 退回积分 | |
| 24 | - AFTER_SALE_DEDUCT_GIVE(14, "订单退款", "订单退款,扣除赠送的 {} 积分", false), // 扣减积分 | |
| 20 | + ORDER_GIVE(10, "订单奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 | |
| 21 | + ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 取消订单时,退回积分 | |
| 22 | + ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 下单时,扣减积分 | |
| 23 | + AFTER_SALE_REFUND_USED(13, "订单退款", "订单退款,退还 {} 积分", true), // 售后订单成功时,退回积分(对应 ORDER_USE 操作) | |
| 24 | + AFTER_SALE_DEDUCT_GIVE(14, "订单退款", "订单退款,扣除赠送的 {} 积分", false), // 售后订单成功时,扣减积分(对应 ORDER_GIVE 操作) | |
| 25 | 25 | ; |
| 26 | 26 | |
| 27 | 27 | /** | ... | ... |
yudao-server/src/main/resources/application.yaml