mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
【功能完善】商城: APP 完善积分商城活动订单价格计算
This commit is contained in:
parent
f72dd272a2
commit
f01c600492
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.api.point;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.point.dto.PointValidateJoinRespDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 积分商城活动 API 接口
|
||||||
|
*
|
||||||
|
* @author HUIHUI
|
||||||
|
*/
|
||||||
|
public interface PointActivityApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【下单前】校验是否参与积分商城活动
|
||||||
|
*
|
||||||
|
* 如果校验失败,则抛出业务异常
|
||||||
|
*
|
||||||
|
* @param activityId 活动编号
|
||||||
|
* @param skuId SKU 编号
|
||||||
|
* @param count 数量
|
||||||
|
* @return 积分商城商品信息
|
||||||
|
*/
|
||||||
|
PointValidateJoinRespDTO validateJoinPointActivity(Long activityId, Long skuId, Integer count);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.api.point.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验参与积分商城 Response DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PointValidateJoinRespDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可兑换次数
|
||||||
|
*/
|
||||||
|
private Integer count;
|
||||||
|
/**
|
||||||
|
* 所需兑换积分
|
||||||
|
*/
|
||||||
|
private Integer point;
|
||||||
|
/**
|
||||||
|
* 所需兑换金额,单位:分
|
||||||
|
*/
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
}
|
@ -50,6 +50,10 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode POINT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_007_002, "积分商城活动已关闭,不能修改");
|
ErrorCode POINT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_007_002, "积分商城活动已关闭,不能修改");
|
||||||
ErrorCode POINT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_007_003, "积分商城活动未关闭或未结束,不能删除");
|
ErrorCode POINT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_007_003, "积分商城活动未关闭或未结束,不能删除");
|
||||||
ErrorCode POINT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_007_004, "积分商城活动已关闭,不能重复关闭");
|
ErrorCode POINT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_007_004, "积分商城活动已关闭,不能重复关闭");
|
||||||
|
ErrorCode POINT_ACTIVITY_JOIN_ACTIVITY_STATUS_CLOSED = new ErrorCode(1_013_007_005, "积分商品兑换失败,原因:积分商城活动已关闭");
|
||||||
|
ErrorCode POINT_ACTIVITY_JOIN_ACTIVITY_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_007_006, "积分商品兑换失败,原因:单次限购超出");
|
||||||
|
ErrorCode POINT_ACTIVITY_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS = new ErrorCode(1_013_007_007, "积分商品兑换失败,原因:商品不存在");
|
||||||
|
ErrorCode POINT_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_007_008, "积分商品兑换失败,原因:积分商品库存不足");
|
||||||
|
|
||||||
// ========== 秒杀活动 1-013-008-000 ==========
|
// ========== 秒杀活动 1-013-008-000 ==========
|
||||||
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_008_000, "秒杀活动不存在");
|
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_008_000, "秒杀活动不存在");
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.api.point;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.point.dto.PointValidateJoinRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.point.PointActivityService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 积分商城活动 Api 接口实现类
|
||||||
|
*
|
||||||
|
* @author HUIHUI
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class PointActivityApiImpl implements PointActivityApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PointActivityService pointActivityService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PointValidateJoinRespDTO validateJoinPointActivity(Long activityId, Long skuId, Integer count) {
|
||||||
|
return pointActivityService.validateJoinPointActivity(activityId, skuId, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,4 +29,9 @@ public interface PointProductMapper extends BaseMapperX<PointProductDO> {
|
|||||||
.eq(PointProductDO::getActivityId, pointProductDO.getActivityId()));
|
.eq(PointProductDO::getActivityId, pointProductDO.getActivityId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default PointProductDO selectListByActivityIdAndSkuId(Long activityId, Long skuId) {
|
||||||
|
return selectOne(PointProductDO::getActivityId, activityId,
|
||||||
|
PointProductDO::getSkuId, skuId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.promotion.service.point;
|
package cn.iocoder.yudao.module.promotion.service.point;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.point.dto.PointValidateJoinRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivityPageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivityPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivitySaveReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivitySaveReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.point.PointActivityDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.point.PointActivityDO;
|
||||||
@ -78,4 +79,16 @@ public interface PointActivityService {
|
|||||||
*/
|
*/
|
||||||
List<PointProductDO> getPointProductListByActivityIds(Collection<Long> activityIds);
|
List<PointProductDO> getPointProductListByActivityIds(Collection<Long> activityIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【下单前】校验是否参与积分商城活动
|
||||||
|
*
|
||||||
|
* 如果校验失败,则抛出业务异常
|
||||||
|
*
|
||||||
|
* @param activityId 活动编号
|
||||||
|
* @param skuId SKU 编号
|
||||||
|
* @param count 数量
|
||||||
|
* @return 积分商城商品信息
|
||||||
|
*/
|
||||||
|
PointValidateJoinRespDTO validateJoinPointActivity(Long activityId, Long skuId, Integer count);
|
||||||
|
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
|||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.point.dto.PointValidateJoinRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivityPageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivityPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivitySaveReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivitySaveReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.product.PointProductSaveReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.product.PointProductSaveReqVO;
|
||||||
@ -244,4 +245,28 @@ public class PointActivityServiceImpl implements PointActivityService {
|
|||||||
return pointProductMapper.selectListByActivityId(activityIds);
|
return pointProductMapper.selectListByActivityId(activityIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PointValidateJoinRespDTO validateJoinPointActivity(Long activityId, Long skuId, Integer count) {
|
||||||
|
// 1. 校验积分商城活动是否存在
|
||||||
|
PointActivityDO activity = validatePointActivityExists(activityId);
|
||||||
|
if (CommonStatusEnum.isDisable(activity.getStatus())) {
|
||||||
|
throw exception(POINT_ACTIVITY_JOIN_ACTIVITY_STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.1 校验积分商城商品是否存在
|
||||||
|
PointProductDO product = pointProductMapper.selectListByActivityIdAndSkuId(activityId, skuId);
|
||||||
|
if (product == null) {
|
||||||
|
throw exception(POINT_ACTIVITY_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 2.2 超过单次购买限制
|
||||||
|
if (count > product.getCount()) {
|
||||||
|
throw exception(POINT_ACTIVITY_JOIN_ACTIVITY_SINGLE_LIMIT_COUNT_EXCEED);
|
||||||
|
}
|
||||||
|
// 2.2 校验库存是否充足
|
||||||
|
if (count > product.getStock()) {
|
||||||
|
throw exception(POINT_ACTIVITY_UPDATE_STOCK_FAIL);
|
||||||
|
}
|
||||||
|
return BeanUtils.toBean(product, PointValidateJoinRespDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -58,11 +58,12 @@ public interface ErrorCodeConstants {
|
|||||||
|
|
||||||
// ========== Price 相关 1-011-003-000 ============
|
// ========== Price 相关 1-011-003-000 ============
|
||||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1_011_003_000, "支付价格计算异常,原因:价格小于等于 0");
|
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1_011_003_000, "支付价格计算异常,原因:价格小于等于 0");
|
||||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_002, "计算快递运费异常,找不到对应的运费模板");
|
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_001, "计算快递运费异常,找不到对应的运费模板");
|
||||||
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_002, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
||||||
ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量");
|
ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_003, "参与秒杀的商品,超过了秒杀总限购数量");
|
||||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_006, "计算快递运费异常,配送方式不匹配");
|
ErrorCode PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_004, "参与积分活动的商品,超过了积分活动商品总限购数量");
|
||||||
ErrorCode PRICE_CALCULATE_COUPON_CAN_NOT_USE = new ErrorCode(1_011_003_007, "该优惠劵无法使用,原因:{}」");
|
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_005, "计算快递运费异常,配送方式不匹配");
|
||||||
|
ErrorCode PRICE_CALCULATE_COUPON_CAN_NOT_USE = new ErrorCode(1_011_003_006, "该优惠劵无法使用,原因:{}」");
|
||||||
|
|
||||||
// ========== 物流 Express 模块 1-011-004-000 ==========
|
// ========== 物流 Express 模块 1-011-004-000 ==========
|
||||||
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
|
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
|
||||||
|
@ -20,6 +20,7 @@ public enum TradeOrderTypeEnum implements IntArrayValuable {
|
|||||||
SECKILL(1, "秒杀订单"),
|
SECKILL(1, "秒杀订单"),
|
||||||
BARGAIN(2, "砍价订单"),
|
BARGAIN(2, "砍价订单"),
|
||||||
COMBINATION(3, "拼团订单"),
|
COMBINATION(3, "拼团订单"),
|
||||||
|
POINT(4, "积分商城"),
|
||||||
;
|
;
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderTypeEnum::getType).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderTypeEnum::getType).toArray();
|
||||||
|
@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.common.validation.Mobile;
|
|||||||
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.AssertTrue;
|
import jakarta.validation.constraints.AssertTrue;
|
||||||
import jakarta.validation.constraints.Min;
|
import jakarta.validation.constraints.Min;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Schema(description = "用户 App - 交易订单结算 Request VO")
|
@Schema(description = "用户 App - 交易订单结算 Request VO")
|
||||||
@ -62,6 +62,10 @@ public class AppTradeOrderSettlementReqVO {
|
|||||||
@Schema(description = "砍价记录编号", example = "123")
|
@Schema(description = "砍价记录编号", example = "123")
|
||||||
private Long bargainRecordId;
|
private Long bargainRecordId;
|
||||||
|
|
||||||
|
// ========== 积分商城活动相关字段 ==========
|
||||||
|
@Schema(description = "积分商城活动编号", example = "123")
|
||||||
|
private Long pointActivityId;
|
||||||
|
|
||||||
@AssertTrue(message = "活动商品每次只能购买一种规格")
|
@AssertTrue(message = "活动商品每次只能购买一种规格")
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public boolean isValidActivityItems() {
|
public boolean isValidActivityItems() {
|
||||||
|
@ -219,7 +219,8 @@ public interface TradeOrderConvert {
|
|||||||
.setSeckillActivityId(settlementReqVO.getSeckillActivityId())
|
.setSeckillActivityId(settlementReqVO.getSeckillActivityId())
|
||||||
.setBargainRecordId(settlementReqVO.getBargainRecordId())
|
.setBargainRecordId(settlementReqVO.getBargainRecordId())
|
||||||
.setCombinationActivityId(settlementReqVO.getCombinationActivityId())
|
.setCombinationActivityId(settlementReqVO.getCombinationActivityId())
|
||||||
.setCombinationHeadId(settlementReqVO.getCombinationHeadId());
|
.setCombinationHeadId(settlementReqVO.getCombinationHeadId())
|
||||||
|
.setPointActivityId(settlementReqVO.getPointActivityId());
|
||||||
// 商品项的构建
|
// 商品项的构建
|
||||||
Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId);
|
Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId);
|
||||||
for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) {
|
for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) {
|
||||||
|
@ -116,7 +116,7 @@ public interface TradeOrderQueryService {
|
|||||||
* @param activityId 活动编号
|
* @param activityId 活动编号
|
||||||
* @return 秒杀商品数量
|
* @return 秒杀商品数量
|
||||||
*/
|
*/
|
||||||
int getSeckillProductCount(Long userId, Long activityId);
|
int getActivityProductCount(Long userId, Long activityId);
|
||||||
|
|
||||||
// =================== Order Item ===================
|
// =================== Order Item ===================
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClien
|
|||||||
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;
|
||||||
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
@ -174,7 +174,7 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSeckillProductCount(Long userId, Long activityId) {
|
public int getActivityProductCount(Long userId, Long activityId) {
|
||||||
// 获得订单列表
|
// 获得订单列表
|
||||||
List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndSeckillActivityId(userId, activityId);
|
List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndSeckillActivityId(userId, activityId);
|
||||||
orders.removeIf(order -> TradeOrderStatusEnum.isCanceled(order.getStatus())); // 过滤掉【已取消】的订单
|
orders.removeIf(order -> TradeOrderStatusEnum.isCanceled(order.getStatus())); // 过滤掉【已取消】的订单
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package cn.iocoder.yudao.module.trade.service.price.bo;
|
package cn.iocoder.yudao.module.trade.service.price.bo;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.Min;
|
import jakarta.validation.constraints.Min;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +84,12 @@ public class TradePriceCalculateReqBO {
|
|||||||
*/
|
*/
|
||||||
private Long bargainRecordId;
|
private Long bargainRecordId;
|
||||||
|
|
||||||
|
// ========== 积分商城活动相关字段 ==========
|
||||||
|
/**
|
||||||
|
* 积分商城活动编号
|
||||||
|
*/
|
||||||
|
private Long pointActivityId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品 SKU
|
* 商品 SKU
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package cn.iocoder.yudao.module.trade.service.price.calculator;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.point.PointActivityApi;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.point.dto.PointValidateJoinRespDTO;
|
||||||
|
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.price.bo.TradePriceCalculateReqBO;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 积分商城的 {@link TradePriceCalculator} 实现类
|
||||||
|
*
|
||||||
|
* @author owen
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Order(TradePriceCalculator.ORDER_POINT_ACTIVITY)
|
||||||
|
@Slf4j
|
||||||
|
public class TradePointActivityPriceCalculator implements TradePriceCalculator {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PointActivityApi pointActivityApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TradeOrderQueryService tradeOrderQueryService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
|
||||||
|
// 1. 判断订单类型是否为积分商城活动
|
||||||
|
if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.POINT.getType())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.isTrue(param.getItems().size() == 1, "积分商城兑换商品时,只允许选择一个商品");
|
||||||
|
// 2. 校验是否可以参与积分商城活动
|
||||||
|
TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0);
|
||||||
|
PointValidateJoinRespDTO activity = validateJoinSeckill(
|
||||||
|
param.getUserId(), param.getPointActivityId(),
|
||||||
|
orderItem.getSkuId(), orderItem.getCount());
|
||||||
|
|
||||||
|
// 3.1 记录优惠明细
|
||||||
|
int discountPrice = 0;
|
||||||
|
Assert.isTrue(activity.getPoint() >= 1, "积分商城商品兑换积分必须大于 1");
|
||||||
|
// 情况一:单使用积分兑换
|
||||||
|
if (activity.getPrice() == null || activity.getPrice() == 0) {
|
||||||
|
discountPrice = orderItem.getPayPrice();
|
||||||
|
} else { // 情况二:积分 + 金额
|
||||||
|
discountPrice = orderItem.getPayPrice() - activity.getPrice() * orderItem.getCount();
|
||||||
|
}
|
||||||
|
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||||
|
param.getPointActivityId(), "积分商城活动", PromotionTypeEnum.POINT.getType(),
|
||||||
|
StrUtil.format("积分商城活动:省 {} 元", TradePriceCalculatorHelper.formatPrice(discountPrice)),
|
||||||
|
discountPrice);
|
||||||
|
// 3.2 更新 SKU 优惠金额
|
||||||
|
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + discountPrice);
|
||||||
|
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||||
|
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PointValidateJoinRespDTO validateJoinSeckill(Long userId, Long activityId, Long skuId, Integer count) {
|
||||||
|
// 1. 校验是否可以参与积分商城活动
|
||||||
|
PointValidateJoinRespDTO pointValidateJoinRespDTO = pointActivityApi.validateJoinPointActivity(activityId, skuId, count);
|
||||||
|
// 2. 校验总限购数量,目前只有 trade 有具体下单的数据,需要交给 trade 价格计算使用
|
||||||
|
int activityProductCount = tradeOrderQueryService.getActivityProductCount(userId, activityId);
|
||||||
|
if (activityProductCount + count > pointValidateJoinRespDTO.getCount()) {
|
||||||
|
throw exception(PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT);
|
||||||
|
}
|
||||||
|
return pointValidateJoinRespDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,6 +16,7 @@ public interface TradePriceCalculator {
|
|||||||
int ORDER_SECKILL_ACTIVITY = 8;
|
int ORDER_SECKILL_ACTIVITY = 8;
|
||||||
int ORDER_BARGAIN_ACTIVITY = 8;
|
int ORDER_BARGAIN_ACTIVITY = 8;
|
||||||
int ORDER_COMBINATION_ACTIVITY = 8;
|
int ORDER_COMBINATION_ACTIVITY = 8;
|
||||||
|
int ORDER_POINT_ACTIVITY = 8;
|
||||||
|
|
||||||
int ORDER_DISCOUNT_ACTIVITY = 10;
|
int ORDER_DISCOUNT_ACTIVITY = 10;
|
||||||
int ORDER_REWARD_ACTIVITY = 20;
|
int ORDER_REWARD_ACTIVITY = 20;
|
||||||
|
@ -90,6 +90,9 @@ public class TradePriceCalculatorHelper {
|
|||||||
if (param.getBargainRecordId() != null) {
|
if (param.getBargainRecordId() != null) {
|
||||||
return TradeOrderTypeEnum.BARGAIN.getType();
|
return TradeOrderTypeEnum.BARGAIN.getType();
|
||||||
}
|
}
|
||||||
|
if (param.getPointActivityId() != null) {
|
||||||
|
return TradeOrderTypeEnum.POINT.getType();
|
||||||
|
}
|
||||||
return TradeOrderTypeEnum.NORMAL.getType();
|
return TradeOrderTypeEnum.NORMAL.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,10 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
|
|||||||
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;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT;
|
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT;
|
||||||
|
|
||||||
@ -61,7 +60,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);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user