!1207 【缺陷修复】商城

Merge pull request !1207 from puhui999/develop
This commit is contained in:
芋道源码 2025-01-23 04:41:00 +00:00 committed by Gitee
commit 2ceca1a20d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 58 additions and 28 deletions

View File

@ -375,7 +375,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId()) CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId())
.setStatus(status.getStatus()).setEndTime(now); .setStatus(status.getStatus()).setEndTime(now);
if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数 if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
updateRecord.setUserCount(records.size()); updateRecord.setUserCount(records.size()).setVirtualGroup(Boolean.TRUE); // 标记为虚拟成团
} }
updateRecords.add(updateRecord); updateRecords.add(updateRecord);
}); });

View File

@ -100,7 +100,7 @@ public class PointActivityServiceImpl implements PointActivityService {
} }
pointActivityMapper.updateById(updateObj); pointActivityMapper.updateById(updateObj);
// 2.2 更新商品 // 2.2 更新商品
updateSeckillProduct(updateObj, updateReqVO.getProducts()); updatePointProduct(updateObj, updateReqVO.getProducts());
} }
@Override @Override
@ -157,12 +157,12 @@ public class PointActivityServiceImpl implements PointActivityService {
} }
/** /**
* 更新秒杀商品 * 更新积分商品
* *
* @param activity 秒杀活动 * @param activity 积分活动
* @param products 该活动的最新商品配置 * @param products 该活动的最新商品配置
*/ */
private void updateSeckillProduct(PointActivityDO activity, List<PointProductSaveReqVO> products) { private void updatePointProduct(PointActivityDO activity, List<PointProductSaveReqVO> products) {
// 第一步对比新老数据获得添加修改删除的列表 // 第一步对比新老数据获得添加修改删除的列表
List<PointProductDO> newList = buildPointProductDO(activity, products); List<PointProductDO> newList = buildPointProductDO(activity, products);
List<PointProductDO> oldList = pointProductMapper.selectListByActivityId(activity.getId()); List<PointProductDO> oldList = pointProductMapper.selectListByActivityId(activity.getId());
@ -211,10 +211,10 @@ public class PointActivityServiceImpl implements PointActivityService {
} }
/** /**
* 校验秒杀商品是否都存在 * 校验积分商品是否都存在
* *
* @param spuId 商品 SPU 编号 * @param spuId 商品 SPU 编号
* @param products 秒杀商品 * @param products 积分商品
*/ */
private void validateProductExists(Long spuId, List<PointProductSaveReqVO> products) { private void validateProductExists(Long spuId, List<PointProductSaveReqVO> products) {
// 1. 校验商品 spu 是否存在 // 1. 校验商品 spu 是否存在

View File

@ -37,6 +37,7 @@ public interface ErrorCodeConstants {
ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单"); ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单");
ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态"); ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态");
ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_034, "交易订单自提失败,原因:你没有核销该门店订单的权限"); ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_034, "交易订单自提失败,原因:你没有核销该门店订单的权限");
ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_035, "交易订单创建失败,原因:用户积分不足");
// ========== After Sale 模块 1-011-000-100 ========== // ========== After Sale 模块 1-011-000-100 ==========
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -106,10 +107,22 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
.eq(TradeOrderDO::getCommentStatus, commentStatus)); .eq(TradeOrderDO::getCommentStatus, commentStatus));
} }
default List<TradeOrderDO> selectListByUserIdAndSeckillActivityId(Long userId, Long seckillActivityId) { default List<TradeOrderDO> selectListByUserIdAndActivityId(Long userId, Long activityId, TradeOrderTypeEnum type) {
return selectList(new LambdaUpdateWrapper<>(TradeOrderDO.class) LambdaQueryWrapperX<TradeOrderDO> queryWrapperX = new LambdaQueryWrapperX<>();
.eq(TradeOrderDO::getUserId, userId) queryWrapperX.eq(TradeOrderDO::getUserId, userId);
.eq(TradeOrderDO::getSeckillActivityId, seckillActivityId)); if (TradeOrderTypeEnum.isSeckill(type.getType())) {
queryWrapperX.eq(TradeOrderDO::getSeckillActivityId, activityId);
}
if (TradeOrderTypeEnum.isBargain(type.getType())) {
queryWrapperX.eq(TradeOrderDO::getBargainActivityId, activityId);
}
if (TradeOrderTypeEnum.isCombination(type.getType())) {
queryWrapperX.eq(TradeOrderDO::getCombinationActivityId, activityId);
}
if (TradeOrderTypeEnum.isPoint(type.getType())) {
queryWrapperX.eq(TradeOrderDO::getPointActivityId, activityId);
}
return selectList(queryWrapperX);
} }
default TradeOrderDO selectOneByPickUpVerifyCode(String pickUpVerifyCode) { default TradeOrderDO selectOneByPickUpVerifyCode(String pickUpVerifyCode) {

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummary
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import java.util.Collection; import java.util.Collection;
@ -110,13 +111,14 @@ public interface TradeOrderQueryService {
List<ExpressTrackRespDTO> getExpressTrackList(Long id); List<ExpressTrackRespDTO> getExpressTrackList(Long id);
/** /**
* 会员在指定秒杀活动下用户购买的商品数量 * 会员在指定活动下用户购买的商品数量
* *
* @param userId 用户编号 * @param userId 用户编号
* @param activityId 活动编号 * @param activityId 活动编号
* @return 秒杀商品数量 * @param type 订单类型
* @return 活动商品数量
*/ */
int getSeckillProductCount(Long userId, Long activityId); int getActivityProductCount(Long userId, Long activityId, TradeOrderTypeEnum type);
// =================== Order Item =================== // =================== Order Item ===================

View File

@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
@ -174,9 +175,9 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
} }
@Override @Override
public int getSeckillProductCount(Long userId, Long activityId) { public int getActivityProductCount(Long userId, Long activityId, TradeOrderTypeEnum type) {
// 获得订单列表 // 获得订单列表
List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndSeckillActivityId(userId, activityId); List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndActivityId(userId, activityId, type);
orders.removeIf(order -> TradeOrderStatusEnum.isCanceled(order.getStatus())); // 过滤掉已取消的订单 orders.removeIf(order -> TradeOrderStatusEnum.isCanceled(order.getStatus())); // 过滤掉已取消的订单
if (CollUtil.isEmpty(orders)) { if (CollUtil.isEmpty(orders)) {
return 0; return 0;

View File

@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.trade.service.order.handler;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.promotion.api.point.PointActivityApi; import cn.iocoder.yudao.module.promotion.api.point.PointActivityApi;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
@ -13,6 +15,9 @@ import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS;
/** /**
* 积分商城活动订单的 {@link TradeOrderHandler} 实现类 * 积分商城活动订单的 {@link TradeOrderHandler} 实现类
* *
@ -23,6 +28,8 @@ public class TradePointOrderHandler implements TradeOrderHandler {
@Resource @Resource
private PointActivityApi pointActivityApi; private PointActivityApi pointActivityApi;
@Resource
private MemberUserApi memberUserApi;
@Override @Override
public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
@ -31,6 +38,11 @@ public class TradePointOrderHandler implements TradeOrderHandler {
} }
// 明确校验一下 // 明确校验一下
Assert.isTrue(orderItems.size() == 1, "积分商城活动兑换商品兑换时,只允许选择一个商品"); Assert.isTrue(orderItems.size() == 1, "积分商城活动兑换商品兑换时,只允许选择一个商品");
// 校验用户剩余积分是否足够兑换商品
MemberUserRespDTO user = memberUserApi.getUser(order.getUserId());
if (user.getPoint() < order.getUsePoint()) {
throw exception(ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS);
}
// 扣减积分商城活动的库存 // 扣减积分商城活动的库存
pointActivityApi.updatePointStockDecr(order.getPointActivityId(), pointActivityApi.updatePointStockDecr(order.getPointActivityId(),

View File

@ -56,36 +56,36 @@ public class TradePointActivityPriceCalculator implements TradePriceCalculator {
Assert.isTrue(param.getItems().size() == 1, "积分商城兑换商品时,只允许选择一个商品"); Assert.isTrue(param.getItems().size() == 1, "积分商城兑换商品时,只允许选择一个商品");
// 2. 校验是否可以参与积分商城活动 // 2. 校验是否可以参与积分商城活动
TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0); TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0);
PointValidateJoinRespDTO activity = validateJoinSeckill( PointValidateJoinRespDTO activity = validateJoinPointActivity(
param.getUserId(), param.getPointActivityId(), param.getUserId(), param.getPointActivityId(),
orderItem.getSkuId(), orderItem.getCount()); orderItem.getSkuId(), orderItem.getCount());
// 3.1 记录优惠明细 // 3.0 积分兑换前置校验
int discountPrice = orderItem.getPayPrice(); // 情况一单使用积分兑换
Assert.isTrue(activity.getPoint() >= 1, "积分商城商品兑换积分必须大于 1"); Assert.isTrue(activity.getPoint() >= 1, "积分商城商品兑换积分必须大于 1");
result.setUsePoint(activity.getPoint() * orderItem.getCount()); // 3.1 记录优惠明细
orderItem.setUsePoint(activity.getPoint() * orderItem.getCount()); int usePoint = activity.getPoint() * orderItem.getCount();
result.setUsePoint(usePoint);
orderItem.setUsePoint(usePoint);
int discountPrice = orderItem.getPayPrice(); // 情况一单使用积分兑换
if (activity.getPrice() != null && activity.getPrice() > 0) { // 情况二积分 + 金额 if (activity.getPrice() != null && activity.getPrice() > 0) { // 情况二积分 + 金额
discountPrice = orderItem.getPayPrice() - activity.getPrice() * orderItem.getCount(); discountPrice = orderItem.getPayPrice() - activity.getPrice() * orderItem.getCount();
} }
// 3.2 记录优惠明细
TradePriceCalculatorHelper.addPromotion(result, orderItem, TradePriceCalculatorHelper.addPromotion(result, orderItem,
param.getPointActivityId(), "积分商城活动", PromotionTypeEnum.POINT.getType(), param.getPointActivityId(), "积分商城活动", PromotionTypeEnum.POINT.getType(),
StrUtil.format("积分商城活动:省 {} 元", TradePriceCalculatorHelper.formatPrice(discountPrice)), StrUtil.format("积分商城活动:省 {} 元", TradePriceCalculatorHelper.formatPrice(discountPrice)),
discountPrice); discountPrice);
// 3.2 更新 SKU 优惠金额
// 3.3 更新 SKU 优惠金额
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + discountPrice); orderItem.setDiscountPrice(orderItem.getDiscountPrice() + discountPrice);
TradePriceCalculatorHelper.recountPayPrice(orderItem); TradePriceCalculatorHelper.recountPayPrice(orderItem);
TradePriceCalculatorHelper.recountAllPrice(result); TradePriceCalculatorHelper.recountAllPrice(result);
} }
private PointValidateJoinRespDTO validateJoinSeckill(Long userId, Long activityId, Long skuId, Integer count) { private PointValidateJoinRespDTO validateJoinPointActivity(Long userId, Long activityId, Long skuId, Integer count) {
// 1. 校验是否可以参与积分商城活动 // 1. 校验是否可以参与积分商城活动
PointValidateJoinRespDTO pointValidateJoinRespDTO = pointActivityApi.validateJoinPointActivity(activityId, skuId, count); PointValidateJoinRespDTO pointValidateJoinRespDTO = pointActivityApi.validateJoinPointActivity(activityId, skuId, count);
// 2. 校验总限购数量目前只有 trade 有具体下单的数据需要交给 trade 价格计算使用 // 2. 校验总限购数量目前只有 trade 有具体下单的数据需要交给 trade 价格计算使用
int activityProductCount = tradeOrderQueryService.getSeckillProductCount(userId, activityId); int pointProductCount = tradeOrderQueryService.getActivityProductCount(userId, activityId, TradeOrderTypeEnum.POINT);
if (activityProductCount + count > pointValidateJoinRespDTO.getCount()) { if (pointProductCount + count > pointValidateJoinRespDTO.getCount()) {
throw exception(PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT); throw exception(PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT);
} }
return pointValidateJoinRespDTO; return pointValidateJoinRespDTO;

View File

@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO; import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
@ -60,7 +61,7 @@ public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator
// 1. 校验是否可以参与秒杀 // 1. 校验是否可以参与秒杀
SeckillValidateJoinRespDTO seckillActivity = seckillActivityApi.validateJoinSeckill(activityId, skuId, count); SeckillValidateJoinRespDTO seckillActivity = seckillActivityApi.validateJoinSeckill(activityId, skuId, count);
// 2. 校验总限购数量目前只有 trade 有具体下单的数据需要交给 trade 价格计算使用 // 2. 校验总限购数量目前只有 trade 有具体下单的数据需要交给 trade 价格计算使用
int seckillProductCount = tradeOrderQueryService.getSeckillProductCount(userId, activityId); int seckillProductCount = tradeOrderQueryService.getActivityProductCount(userId, activityId, TradeOrderTypeEnum.SECKILL);
if (seckillProductCount + count > seckillActivity.getTotalLimitCount()) { if (seckillProductCount + count > seckillActivity.getTotalLimitCount()) {
throw exception(PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT); throw exception(PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT);
} }