Merge branch 'feature/mall_product' of https://gitee.com/puhui999/ruoyi-vue-pro into feature/mall_product

 Conflicts:
	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
This commit is contained in:
YunaiV
2023-09-12 12:22:55 +08:00
54 changed files with 816 additions and 374 deletions

View File

@@ -6,6 +6,7 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;
@@ -32,4 +33,9 @@ public class TradeOrderApiImpl implements TradeOrderApi {
return item.getOrderId();
}
@Override
public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {
return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds);
}
}

View File

@@ -76,10 +76,9 @@ public class TradeAfterSaleController {
public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单
TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id);
// TODO @puhui999这里建议改成如果为 null直接返回 success null主要查询操作尽量不要有非空的提示哈交给前端处理
// if (afterSale == null) {
// return success(null, AFTER_SALE_NOT_FOUND.getMsg());
// }
if (afterSale == null) {
return success(null);
}
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId());

View File

@@ -67,10 +67,9 @@ public class TradeOrderController {
public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(id);
// TODO @puhui999这里建议改成如果为 null直接返回 success null主要查询操作尽量不要有非空的提示哈交给前端处理
// if (order == null) {
// return success(null, ORDER_NOT_FOUND.getMsg());
// }
if (order == null) {
return success(null);
}
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);

View File

@@ -31,19 +31,15 @@ public class TradeOrderPageReqVO extends PageParam {
@Mobile
private String userMobile;
@Schema(description = "配送方式", example = "1")
private Integer deliveryType;
@Schema(description = "发货物流公司编号", example = "1")
private Long logisticsId;
@Schema(description = "自提门店编号", example = "[1,2]")
private List<Long> pickUpStoreIds;
@Schema(description = "收件人名称", example = "小红")
private String receiverName;
@Schema(description = "收件人手机", example = "1560")
@Mobile
private String receiverMobile;
@Schema(description = "订单类型", example = "1")
private Integer type;
@@ -61,5 +57,5 @@ public class TradeOrderPageReqVO extends PageParam {
@Schema(description = "订单来源", example = "10")
@InEnum(value = TerminalEnum.class, message = "订单来源 {value}")
private Integer terminal;
// TODO 添加配送方式筛选
}

View File

@@ -81,10 +81,9 @@ public class AppTradeOrderController {
public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) {
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id);
// TODO @puhui999这里建议改成如果为 null直接返回 success null主要查询操作尽量不要有非空的提示哈交给前端处理
// if (order == null) {
// return success(null, ORDER_NOT_FOUND.getMsg());
// }
if (order == null) {
return success(null);
}
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());

View File

@@ -14,7 +14,9 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
@@ -32,6 +34,9 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.mapstruct.Mapper;
@@ -254,21 +259,15 @@ public interface TradeOrderConvert {
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
@Mappings({
@Mapping(target = "activityId", source = "createReqVO.combinationActivityId"),
@Mapping(target = "spuId", source = "orderItem.spuId"),
@Mapping(target = "skuId", source = "orderItem.skuId"),
@Mapping(target = "userId", source = "order.userId"),
@Mapping(target = "orderId", source = "order.id"),
@Mapping(target = "headId", source = "createReqVO.combinationHeadId"),
@Mapping(target = "spuName", source = "orderItem.spuName"),
@Mapping(target = "picUrl", source = "orderItem.picUrl"),
@Mapping(target = "combinationPrice", source = "orderItem.payPrice"),
@Mapping(target = "nickname", source = "user.nickname"),
@Mapping(target = "avatar", source = "user.avatar"),
@Mapping(target = "status", ignore = true)
@Mapping(target = "activityId", source = "afterOrderCreateReqBO.combinationActivityId"),
@Mapping(target = "spuId", source = "afterOrderCreateReqBO.spuId"),
@Mapping(target = "skuId", source = "afterOrderCreateReqBO.skuId"),
@Mapping(target = "orderId", source = "afterOrderCreateReqBO.orderId"),
@Mapping(target = "userId", source = "afterOrderCreateReqBO.userId"),
@Mapping(target = "headId", source = "afterOrderCreateReqBO.combinationHeadId"),
@Mapping(target = "combinationPrice", source = "afterOrderCreateReqBO.payPrice"),
})
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem,
AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO);
List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
@@ -282,6 +281,26 @@ public interface TradeOrderConvert {
return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId())
.setBasePrice(item.getPayPrice() * item.getCount())
.setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂标题类似木晴冰雪成功购买云时代的JVM原理与实战茫农成功购买深入拆解消息队列47讲
.setFirstFixedPrice(sku.getSubCommissionFirstPrice()).setSecondFixedPrice(sku.getSubCommissionSecondPrice());
.setFirstFixedPrice(sku.getFirstBrokerageRecord()).getSecondBrokerageRecord(sku.getSecondBrokerageRecord());
}
@Mapping(target = "activityId", source = "reqBO.seckillActivityId")
SeckillActivityUpdateStockReqDTO convert(TradeBeforeOrderCreateReqBO reqBO);
@Mapping(target = "activityId", source = "reqBO.combinationActivityId")
CombinationActivityUpdateStockReqDTO convert1(TradeBeforeOrderCreateReqBO reqBO);
TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO);
@Mappings({
@Mapping(target = "combinationActivityId", source = "createReqVO.combinationActivityId"),
@Mapping(target = "combinationHeadId", source = "createReqVO.combinationHeadId"),
@Mapping(target = "spuId", source = "orderItem.spuId"),
@Mapping(target = "skuId", source = "orderItem.skuId"),
@Mapping(target = "orderId", source = "tradeOrderDO.id"),
@Mapping(target = "userId", source = "userId"),
@Mapping(target = "payPrice", source = "tradeOrderDO.payPrice"),
})
TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, TradeOrderItemDO orderItem);
}

View File

@@ -29,7 +29,7 @@ public interface TradeOrderItemMapper extends BaseMapperX<TradeOrderItemDO> {
default List<TradeOrderItemDO> selectListByOrderIdAnSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {
return selectList(new LambdaQueryWrapperX<TradeOrderItemDO>()
.in(TradeOrderItemDO::getOrderId, orderIds)
.eq(TradeOrderItemDO::getSkuId, skuIds));
.in(TradeOrderItemDO::getSkuId, skuIds));
}
default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) {

View File

@@ -27,13 +27,12 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
return selectPage(reqVO, new LambdaQueryWrapperX<TradeOrderDO>()
.likeIfPresent(TradeOrderDO::getNo, reqVO.getNo())
.eqIfPresent(TradeOrderDO::getUserId, reqVO.getUserId())
.eqIfPresent(TradeOrderDO::getDeliveryType, reqVO.getDeliveryType())
.inIfPresent(TradeOrderDO::getUserId, userIds)
.likeIfPresent(TradeOrderDO::getReceiverName, reqVO.getReceiverName())
.likeIfPresent(TradeOrderDO::getReceiverMobile, reqVO.getReceiverMobile())
.eqIfPresent(TradeOrderDO::getType, reqVO.getType())
.eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus())
.eqIfPresent(TradeOrderDO::getPayChannelCode, reqVO.getPayChannelCode())
.eqIfPresent(TradeOrderDO::getTerminal,reqVO.getTerminal())
.eqIfPresent(TradeOrderDO::getTerminal, reqVO.getTerminal())
.eqIfPresent(TradeOrderDO::getLogisticsId, reqVO.getLogisticsId())
.inIfPresent(TradeOrderDO::getPickUpStoreId, reqVO.getPickUpStoreIds())
.betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime()));

View File

@@ -119,4 +119,13 @@ public interface TradeOrderQueryService {
*/
List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
/**
* 获取订单项商品购买数量总和
*
* @param orderIds 订单编号
* @param skuIds sku 编号
* @return 订单项商品购买数量总和
*/
Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds);
}

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
@@ -167,4 +168,10 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
return tradeOrderItemMapper.selectListByOrderId(orderIds);
}
@Override
public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {
List<TradeOrderItemDO> tradeOrderItems = tradeOrderItemMapper.selectListByOrderIdAnSkuId(orderIds, skuIds);
return CollectionUtils.getSumValue(tradeOrderItems, TradeOrderItemDO::getCount, Integer::sum);
}
}

View File

@@ -13,8 +13,6 @@ import cn.iocoder.yudao.module.member.api.address.AddressApi;
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
import cn.iocoder.yudao.module.member.api.point.MemberPointApi;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
@@ -24,15 +22,10 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
@@ -53,12 +46,14 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.*;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
import cn.iocoder.yudao.module.trade.service.cart.CartService;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
@@ -70,14 +65,13 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_EQUAL;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_PAID;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
/**
@@ -96,6 +90,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
private TradeOrderItemMapper tradeOrderItemMapper;
@Resource
private TradeOrderNoRedisDAO orderNoRedisDAO;
@Resource
private List<TradeOrderHandler> orderHandlers;
@Resource
private CartService cartService;
@@ -119,12 +115,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
@Resource
private BargainRecordApi bargainRecordApi;
@Resource
private SeckillActivityApi seckillActivityApi;
@Resource
private BargainActivityApi bargainActivityApi;
@Resource
private MemberUserApi memberUserApi;
@Resource
private MemberLevelApi memberLevelApi;
@Resource
private MemberPointApi memberPointApi;
@@ -189,7 +179,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
@Override
@Transactional(rollbackFor = Exception.class)
public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
// 1. 价格计算
// 1、执行订单创建前置处理器
TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO);
beforeOrderCreateReqBO.setOrderType(validateActivity(createReqVO));
beforeOrderCreateReqBO.setCount(CollectionUtils.getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum));
orderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO));
// 2. 价格计算
TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO);
// 2.1 插入 TradeOrderDO 订单
@@ -199,37 +195,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 3. 订单创建完后的逻辑
afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
// 3.1 拼团的特殊逻辑
// TODO @puhui999这个逻辑先抽个小方法未来要通过设计模式把这些拼团之类的逻辑抽象出去
// 拼团
if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
createCombinationRecord(userId, createReqVO, orderItems, order);
}
// 3.2 秒杀的特殊逻辑
if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) {
}
// 3.3 砍价的特殊逻辑
// TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
return order;
}
private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List<TradeOrderItemDO> orderItems, TradeOrderDO order) {
MemberUserRespDTO user = memberUserApi.getUser(userId);
List<CombinationRecordRespDTO> recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId());
// TODO 拼团一次应该只能选择一种规格的商品
TradeOrderItemDO orderItemDO = orderItems.get(0);
if (CollUtil.isNotEmpty(recordRespDTOS)) {
List<Long> skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS,
CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(),
CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount());
}
combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user));
}
// TODO @puhui999订单超时自动取消
@@ -311,23 +281,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
TradePriceCalculateRespBO calculateRespBO) {
Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum);
// 1如果是秒杀商品额外扣减秒杀的库存
if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) {
SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO();
updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId());
updateStockReqDTO.setCount(count);
updateStockReqDTO.setItems(CollectionUtils.convertList(orderItems, item -> {
SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item();
item1.setSpuId(item.getSpuId());
item1.setSkuId(item.getSkuId());
item1.setCount(item.getCount());
return item1;
}));
seckillActivityApi.updateSeckillStock(updateStockReqDTO);
}
// 2如果是砍价活动额外扣减砍价的库存
bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count);
// 执行订单创建后置处理器
orderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0))));
// 扣减积分 TODO 芋艿:待实现,需要前置;
// 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
@@ -352,6 +307,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 增加订单日志 TODO 芋艿:待实现
}
private void createPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems, TradePriceCalculateRespBO calculateRespBO) {
// 创建支付单,用于后续的支付
PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert(
@@ -562,35 +518,67 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
}
@Override
// TODO @puhui999考虑事务性
@Transactional(rollbackFor = Exception.class)
public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) {
// 校验交易订单
// 1、校验交易订单
TradeOrderDO order = validateOrderExists(reqVO.getId());
if (order.getPayStatus()) {
throw exception(ORDER_UPDATE_PRICE_FAIL_PAID);
}
// 2、校验订单项
List<TradeOrderItemDO> items = tradeOrderItemMapper.selectListByOrderId(order.getId());
if (CollUtil.isEmpty(items)) {
throw exception(ORDER_UPDATE_PRICE_FAIL_NOT_ITEM);
}
// 3、校验调价金额是否变化
if (ObjectUtil.equal(order.getAdjustPrice(), reqVO.getAdjustPrice())) {
throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL);
}
// TODO @puhui999应该是按照 payPrice 分配并且要考虑取余问题payPrice 也要考虑item 里的
List<TradeOrderItemDO> itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId());
// TradeOrderItemDO 需要做 adjustPrice 的分摊
int price = reqVO.getAdjustPrice() / itemDOs.size();
itemDOs.forEach(item -> {
item.setAdjustPrice(price);
});
// 更新 TradeOrderItem
// TODO @puhui999不要整个对象去更新哈应该 new 一下;
tradeOrderItemMapper.updateBatch(itemDOs);
// 更新订单
// TODO @puhui999要考虑多次修改价格不能单单的 payPrice + 价格;
TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO);
update.setPayPrice(update.getPayPrice() + update.getAdjustPrice());
// 4、更新订单
TradeOrderDO update = new TradeOrderDO();
update.setId(order.getId());
update.setAdjustPrice(reqVO.getAdjustPrice());
int orderPayPrice = order.getAdjustPrice() != null ? (order.getPayPrice() - order.getAdjustPrice())
+ reqVO.getAdjustPrice() : order.getPayPrice() + reqVO.getAdjustPrice();
update.setPayPrice(orderPayPrice);
// TODO @芋艿:改价时,赠送的积分,要不要做改动???
tradeOrderMapper.updateById(update);
// 更新支付订单
payOrderApi.updatePayOrderPriceById(order.getPayOrderId(), update.getPayPrice());
// TODO @puhui999应该是按照 payPrice 分配并且要考虑取余问题payPrice 也要考虑item 里的
// TODO先按 adjustPrice 实现,没明白 payPrice 怎么搞哈哈哈
// 5、更新 TradeOrderItem
if (items.size() > 1) {
// TradeOrderItemDO 需要做 adjustPrice 的分摊
int price = reqVO.getAdjustPrice() / items.size();
int remainderPrice = reqVO.getAdjustPrice() % items.size();
List<TradeOrderItemDO> orders = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
// 把平摊后剩余的金额加到第一个订单项
if (remainderPrice != 0 && i == 0) {
orders.add(convertOrderItemPrice(items.get(i), price + remainderPrice));
}
orders.add(convertOrderItemPrice(items.get(i), price));
}
tradeOrderItemMapper.updateBatch(orders);
} else {
TradeOrderItemDO orderItem = items.get(0);
TradeOrderItemDO updateItem = convertOrderItemPrice(orderItem, reqVO.getAdjustPrice());
tradeOrderItemMapper.updateById(updateItem);
}
// 6、更新支付订单
payOrderApi.updatePayOrderPrice(order.getPayOrderId(), update.getPayPrice());
}
private TradeOrderItemDO convertOrderItemPrice(TradeOrderItemDO orderItem, Integer price) {
TradeOrderItemDO newOrderItem = new TradeOrderItemDO();
newOrderItem.setId(orderItem.getId());
newOrderItem.setAdjustPrice(price);
int payPrice = orderItem.getAdjustPrice() != null ? (orderItem.getPayPrice() - orderItem.getAdjustPrice())
+ price : orderItem.getPayPrice() + price;
newOrderItem.setPayPrice(payPrice);
return newOrderItem;
}
@Override
@@ -733,6 +721,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
}
// TODO 活动相关库存回滚需要活动 id活动 id 怎么获取app 端能否传过来
orderHandlers.forEach(handler -> handler.rollbackStock());
// 2.回滚库存
List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));

View File

@@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.trade.service.order.bo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 订单创建之后 Request BO
*
* @author HUIHUI
*/
@Data
public class TradeAfterOrderCreateReqBO {
// ========== 拼团活动相关字段 ==========
@Schema(description = "拼团活动编号", example = "1024")
private Long combinationActivityId;
@Schema(description = "拼团团长编号", example = "2048")
private Long combinationHeadId;
@NotNull(message = "SPU 编号不能为空")
private Long spuId;
@NotNull(message = "SKU 编号活动商品不能为空")
private Long skuId;
@NotNull(message = "订单编号不能为空")
private Long orderId;
@NotNull(message = "用户编号不能为空")
private Long userId;
@NotNull(message = "支付金额不能为空")
private Integer payPrice;
}

View File

@@ -0,0 +1,57 @@
package cn.iocoder.yudao.module.trade.service.order.bo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
/**
* 订单创建之前 Request BO
*
* @author HUIHUI
*/
@Data
public class TradeBeforeOrderCreateReqBO {
@NotNull(message = "订单类型不能为空")
private Integer orderType;
// ========== 秒杀活动相关字段 ==========
@Schema(description = "秒杀活动编号", example = "1024")
private Long seckillActivityId;
// ========== 拼团活动相关字段 ==========
@Schema(description = "拼团活动编号", example = "1024")
private Long combinationActivityId;
@Schema(description = "拼团团长编号", example = "2048")
private Long combinationHeadId;
@Schema(description = "砍价活动编号", example = "123")
private Long bargainActivityId;
@NotNull(message = "购买数量不能为空")
private Integer count;
@NotNull(message = "活动商品不能为空")
private Item item;
@Data
@Valid
public static class Item {
@NotNull(message = "SPU 编号不能为空")
private Long spuId;
@NotNull(message = "SKU 编号活动商品不能为空")
private Long skuId;
@NotNull(message = "购买数量不能为空")
private Integer count;
}
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.trade.service.order.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 砍价订单 handler 实现类
*
* @author HUIHUI
*/
@Component
public class TradeBargainHandler implements TradeOrderHandler {
@Resource
private BargainActivityApi bargainActivityApi;
@Override
public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
// 如果是秒杀订单
if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) {
return;
}
// 额外扣减砍价的库存
bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount());
}
@Override
public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
}
@Override
public void rollbackStock() {
}
}

View File

@@ -0,0 +1,49 @@
package cn.iocoder.yudao.module.trade.service.order.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi;
import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 拼团订单 handler 接口实现类
*
* @author HUIHUI
*/
@Component
public class TradeCombinationHandler implements TradeOrderHandler {
@Resource
private CombinationApi combinationApi;
@Resource
private CombinationRecordApi combinationRecordApi;
@Override
public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
// 如果是拼团订单;
if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) {
return;
}
// 校验是否满足拼团活动相关限制
combinationApi.validateCombination(TradeOrderConvert.INSTANCE.convert1(reqBO));
}
@Override
public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
// 创建砍价记录
combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(reqBO));
}
@Override
public void rollbackStock() {
}
}

View File

@@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.trade.service.order.handler;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
/**
* 订单活动特殊逻辑处理器 handler 接口
*
* @author HUIHUI
*/
public interface TradeOrderHandler {
/**
* 订单创建前
*
* @param reqBO 请求
*/
void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO);
/**
* 订单创建后
*
* @param reqBO 请求
*/
void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO);
/**
* 回滚活动相关库存
*/
void rollbackStock();
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.trade.service.order.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 秒杀订单 handler 实现类
*
* @author HUIHUI
*/
@Component
public class TradeSeckillHandler implements TradeOrderHandler {
@Resource
private SeckillActivityApi seckillActivityApi;
@Override
public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
// 如果是秒杀订单:额外扣减秒杀的库存;
if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) {
return;
}
seckillActivityApi.updateSeckillStock(TradeOrderConvert.INSTANCE.convert(reqBO));
}
@Override
public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
}
@Override
public void rollbackStock() {
}
}