购物车价格计算全面优化,优惠券分布到每个订单,满减活动没有对参与商品进行判定问题处理。

This commit is contained in:
Chopper 2021-08-19 17:38:37 +08:00
parent f3e0fd7bf5
commit ab118a8efc
35 changed files with 827 additions and 1711 deletions

View File

@ -52,7 +52,7 @@ public class CartController {
String cartType) {
try {
//读取选中的列表
cartService.add(skuId, num, cartType);
cartService.add(skuId, num, cartType, false);
return ResultUtil.success();
} catch (ServiceException se) {
log.info(se.getMsg(), se);
@ -93,7 +93,7 @@ public class CartController {
@PostMapping(value = "/sku/num/{skuId}")
public ResultMessage<Object> update(@NotNull(message = "产品id不能为空") @PathVariable(name = "skuId") String skuId,
Integer num) {
cartService.updateNum(skuId, num);
cartService.add(skuId, num, CartTypeEnum.CART.name(), true);
return ResultUtil.success();
}

View File

@ -141,7 +141,9 @@ ignored:
- /buyer/article/**
- /buyer/goods/**
- /buyer/category/**
- /buyer/store/**
- /buyer/store
- /buyer/store/get**
- /buyer/store/label/get**
- /buyer/connect/**
- /buyer/members/**
- /buyer/promotion/pintuan/**

View File

@ -6,6 +6,8 @@ import cn.lili.modules.distribution.entity.vos.DistributionGoodsVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 分销商品业务层
@ -39,6 +41,14 @@ public interface DistributionGoodsService extends IService<DistributionGoods> {
*/
DistributionGoods distributionGoodsVOBySkuId(String skuId);
/**
* 批量获取分销商品
*
* @param skuIds sku id集合
* @return 分销商品
*/
List<DistributionGoods> distributionGoods(List<String> skuIds);
/**
* 选择分销商品
*

View File

@ -23,6 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 分销商品接口实现
@ -78,6 +80,11 @@ public class DistributionGoodsServiceImpl extends ServiceImpl<DistributionGoodsM
return this.getOne(new LambdaUpdateWrapper<DistributionGoods>().eq(DistributionGoods::getSkuId, skuId));
}
@Override
public List<DistributionGoods> distributionGoods(List<String> skuIds) {
return this.list(new LambdaUpdateWrapper<DistributionGoods>().in(DistributionGoods::getSkuId, skuIds));
}
@Override
public DistributionGoods checked(String skuId, Double commission) {

View File

@ -64,6 +64,13 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
void update(GoodsSku goodsSku);
/**
* 清除sku缓存
*
* @param skuId skuid
*/
void clearCache(String skuId);
/**
* 从redis缓存中获取商品SKU信息
*

View File

@ -159,6 +159,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
//如果商品状态值不对则es索引移除
if (goods.getIsAuth().equals(GoodsAuthEnum.PASS.name()) && goods.getMarketEnable().equals(GoodsStatusEnum.UPPER.name())) {
goodsIndexService.deleteIndexById(sku.getId());
this.clearCache(sku.getId());
}
}
this.updateBatchById(newSkuList);
@ -179,6 +180,17 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
cache.put(GoodsSkuService.getCacheKeys(goodsSku.getId()), goodsSku);
}
/**
* 清除sku缓存
*
* @param skuId skuID
*/
@Override
public void clearCache(String skuId) {
cache.remove(GoodsSkuService.getCacheKeys(skuId));
}
@Override
public GoodsSku getGoodsSkuByIdFromCache(String id) {
//获取缓存中的sku
@ -195,10 +207,14 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
//获取商品库存
String quantity = stringRedisTemplate.opsForValue().get(GoodsSkuService.getStockCacheKey(id));
//如果sku缓存的库存与库存缓存不符则按照库存缓存进行
//库存不为空
if (StrUtil.isNotEmpty(quantity)) {
goodsSku.setQuantity(Convert.toInt(quantity));
cache.put(GoodsSkuService.getCacheKeys(goodsSku.getId()), goodsSku);
//库存与缓存中不一致
if (!goodsSku.getQuantity().equals(Convert.toInt(quantity))) {
//写入最新的库存信息
goodsSku.setQuantity(Convert.toInt(quantity));
cache.put(GoodsSkuService.getCacheKeys(goodsSku.getId()), goodsSku);
}
}
return goodsSku;
}

View File

@ -19,7 +19,7 @@ public class MemberCouponDTO implements Serializable {
private static final long serialVersionUID = 8276369124551043085L;
/**
* 在整比交易中时 key 为店铺idvalue 为每个店铺跨店优惠 结算金额
* 在购物车中时 key为sku id value为每个商品结算时的金额
* 在购物车中时key为sku id value为每个商品结算时的金额
*/
private Map<String, Double> skuDetail;
@ -28,13 +28,6 @@ public class MemberCouponDTO implements Serializable {
*/
private MemberCoupon memberCoupon;
public MemberCouponDTO() {
}
public MemberCouponDTO(MemberCoupon memberCoupon) {
this.memberCoupon = memberCoupon;
}
public MemberCouponDTO(Map<String, Double> skuDetail, MemberCoupon memberCoupon) {
this.skuDetail = skuDetail;
this.memberCoupon = memberCoupon;

View File

@ -61,14 +61,6 @@ public class TradeDTO implements Serializable {
* 购物车类型
*/
private CartTypeEnum cartTypeEnum;
/**
* key 为商家id
* value 为商家优惠券
* 店铺优惠券
*/
private Map<String, MemberCouponDTO> storeCoupons;
/**
* 店铺备注
*/
@ -89,6 +81,14 @@ public class TradeDTO implements Serializable {
*/
private MemberCouponDTO platformCoupon;
/**
* key 为商家id
* value 为商家优惠券
* 店铺优惠券
*/
private Map<String, MemberCouponDTO> storeCoupons;
/**
* 收货地址
*/

View File

@ -7,14 +7,14 @@ public enum RenderStepEnums {
CHECK_DATA("校验商品"),
CHECKED_FILTER("选择商品过滤"),
CART_SN("交易编号创建"),
COUPON("优惠券价格渲染"),
SKU_FREIGHT("运费计算"),
SKU_PROMOTION("商品促销计算"),
FULL_DISCOUNT("满减计算"),
DISTRIBUTION("分配需要分配的促销金额"),
PLATFORM_COMMISSION("平台佣金"),
CART_PRICE("购物车金额计算"),
DISTRIBUTION("分销人员佣金计算"),
PLATFORM_COMMISSION("平台佣金");
CART_SN("交易编号创建");
private String distribution;

View File

@ -67,9 +67,15 @@ public class CartSkuVO extends CartBase implements Serializable {
private Boolean isShip;
@ApiModelProperty(value = "拼团id 如果是拼团购买 此值为拼团活动id" +
"当pintuanId为空则表示普通购买或者拼团商品单独购买")
"当pintuanId为空则表示普通购买或者拼团商品单独购买")
private String pintuanId;
@ApiModelProperty(value = "砍价ID")
private String kanjiaId;
@ApiModelProperty(value = "积分兑换ID")
private String pointsId;
@ApiModelProperty(value = "可参与的单品活动")
private List<PromotionGoods> promotions;

View File

@ -21,6 +21,9 @@ public class FullDiscountVO extends FullDiscount {
*/
private List<PromotionGoods> promotionGoodsList;
/**
* 参与商品-1则代表所有商品参加
*/
private Integer number;
public String notice() {

View File

@ -69,9 +69,9 @@ public class TradeBuilder {
TradeDTO tradeDTO = cartService.readDTO(checkedWay);
//需要对购物车渲染
if (isSingle(checkedWay)) {
renderCartBySteps(tradeDTO, RenderStepStatement.checkedRender);
} else {
renderCartBySteps(tradeDTO, RenderStepStatement.checkedSingleRender);
} else {
renderCartBySteps(tradeDTO, RenderStepStatement.checkedRender);
}
return tradeDTO;
@ -107,7 +107,9 @@ public class TradeBuilder {
* @return 返回是否单品
*/
private boolean isSingle(CartTypeEnum checkedWay) {
return (checkedWay.equals(CartTypeEnum.CART) || checkedWay.equals(CartTypeEnum.BUY_NOW) || checkedWay.equals(CartTypeEnum.VIRTUAL));
//拼团 积分 砍价商品
return (checkedWay.equals(CartTypeEnum.PINTUAN) || checkedWay.equals(CartTypeEnum.POINTS) || checkedWay.equals(CartTypeEnum.KANJIA));
}
/**

View File

@ -1,26 +1,18 @@
package cn.lili.modules.order.cart.render.impl;
import cn.hutool.core.util.StrUtil;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.promotion.entity.dto.KanjiaActivityGoodsDTO;
import cn.lili.modules.promotion.entity.vos.PointsGoodsVO;
import cn.lili.modules.promotion.service.KanjiaActivityGoodsService;
import cn.lili.modules.promotion.service.PointsGoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 购物车渲染将购物车中的各个商品拆分到每个商家形成购物车VO
@ -52,34 +44,12 @@ public class CartPriceRender implements CartRenderStep {
public RenderStepEnums step() {
return RenderStepEnums.CART_PRICE;
}
@Override
public void render(TradeDTO tradeDTO) {
//构造cartVO
this.buildCart(tradeDTO);
this.buildCartPrice(tradeDTO);
this.buildTradePrice(tradeDTO);
}
/**
* 购物车价格
*
* @param tradeDTO 购物车展示信息
*/
void buildCart(TradeDTO tradeDTO) {
for (CartVO cart : tradeDTO.getCartList()) {
for (CartSkuVO sku : cart.getSkuList()) {
if (Boolean.FALSE.equals(sku.getChecked())) {
continue;
}
cart.addGoodsNum(sku.getNum());
if (cart.getStoreId().equals(sku.getStoreId()) && !cart.getSkuList().contains(sku)) {
cart.getSkuList().add(sku);
}
//写入初始价格
sku.getPriceDetailDTO().setGoodsPrice(CurrencyUtil.mul(sku.getPurchasePrice(), sku.getNum()));
}
}
}
/**
@ -88,64 +58,13 @@ public class CartPriceRender implements CartRenderStep {
* @param tradeDTO 购物车展示信息
*/
void buildCartPrice(TradeDTO tradeDTO) {
List<CartSkuVO> cartSkuVOList = tradeDTO.getSkuList();
//购物车列表
List<CartVO> cartVOS = tradeDTO.getCartList();
//key store id
//value 商品列表
Map<String, List<CartSkuVO>> map = new HashMap<>(2);
for (CartSkuVO cartSkuVO : cartSkuVOList) {
//如果存在商家id
if (map.containsKey(cartSkuVO.getGoodsSku().getStoreId())) {
List<CartSkuVO> list = map.get(cartSkuVO.getGoodsSku().getStoreId());
list.add(cartSkuVO);
} else {
List<CartSkuVO> list = new ArrayList<>();
list.add(cartSkuVO);
map.put(cartSkuVO.getGoodsSku().getStoreId(), list);
}
}
//计算购物车价格
for (CartVO cart : cartVOS) {
List<CartSkuVO> cartSkuVOS = map.get(cart.getStoreId());
//累加价格
List<PriceDetailDTO> priceDetailDTOS = new ArrayList<>();
//购物车选中
if (Boolean.TRUE.equals(cart.getChecked())) {
for (CartSkuVO cartSkuVO : cartSkuVOS) {
//sku选中
if (Boolean.TRUE.equals(cartSkuVO.getChecked())) {
PriceDetailDTO priceDetailDTO = cartSkuVO.getPriceDetailDTO();
//平台佣金根据分类计算
String categoryId = cartSkuVO.getGoodsSku().getCategoryPath()
.substring(cartSkuVO.getGoodsSku().getCategoryPath().lastIndexOf(",") + 1);
if (StrUtil.isNotEmpty(categoryId)) {
Double commissionRate = categoryService.getById(categoryId).getCommissionRate();
priceDetailDTO.setCommission(commissionRate);
}
//如果积分订单 积分订单单独操作订单结算金额和商家结算字段
if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.POINTS)) {
PointsGoodsVO pointsGoodsVO = pointsGoodsService.getPointsGoodsVOByMongo(cartSkuVO.getGoodsSku().getId());
priceDetailDTO.setBillPrice(pointsGoodsVO.getSettlementPrice());
priceDetailDTO.setSettlementPrice(pointsGoodsVO.getSettlementPrice());
}
//如果砍价订单 计算金额单独操作订单结算金额和商家结算字段
else if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) {
KanjiaActivityGoodsDTO kanjiaActivityGoodsDTO = kanjiaActivityGoodsService.getKanJiaGoodsBySku(cartSkuVO.getGoodsSku().getId());
priceDetailDTO.setBillPrice(kanjiaActivityGoodsDTO.getSettlementPrice());
priceDetailDTO.setSettlementPrice(kanjiaActivityGoodsDTO.getSettlementPrice());
}
priceDetailDTOS.add(priceDetailDTO);
}
}
cart.getPriceDetailDTO().accumulationPriceDTO(priceDetailDTOS);
}
}
cartVOS.forEach(cartVO -> {
cartVO.getPriceDetailDTO().accumulationPriceDTO(
cartVO.getSkuList().stream().map(CartSkuVO::getPriceDetailDTO).collect(Collectors.toList()));
});
}
@ -155,14 +74,8 @@ public class CartPriceRender implements CartRenderStep {
* @param tradeDTO 购物车展示信息
*/
void buildTradePrice(TradeDTO tradeDTO) {
//购物车列表
List<CartVO> cartVOS = tradeDTO.getCartList();
List<PriceDetailDTO> priceDetailDTOS = new ArrayList<>();
for (CartVO cart : cartVOS) {
priceDetailDTOS.add(cart.getPriceDetailDTO());
}
tradeDTO.getPriceDetailDTO().accumulationPriceDTO(priceDetailDTOS);
tradeDTO.getPriceDetailDTO().accumulationPriceDTO(
tradeDTO.getCartList().stream().map(CartVO::getPriceDetailDTO).collect(Collectors.toList()));
}
}

View File

@ -18,6 +18,7 @@ import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.promotion.entity.dos.Pintuan;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
@ -25,7 +26,6 @@ import cn.lili.modules.promotion.entity.vos.PointsGoodsVO;
import cn.lili.modules.promotion.service.PintuanService;
import cn.lili.modules.promotion.service.PointsGoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@ -144,7 +144,8 @@ public class CheckDataRender implements CartRenderStep {
/**
* 订单预校验
* 1自己拼团自己创建都拼团判定
* 1自己拼团自己创建都拼团判定拼团限购
* 2积分购买积分足够与否
*
* @param tradeDTO
*/
@ -154,8 +155,8 @@ public class CheckDataRender implements CartRenderStep {
if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.PINTUAN)) {
//拼团判定不能参与自己创建的拼团
if (tradeDTO.getParentOrderSn() != null) {
//订单接
cn.lili.modules.order.order.entity.dos.Order parentOrder = orderService.getBySn(tradeDTO.getParentOrderSn());
//订单接
Order parentOrder = orderService.getBySn(tradeDTO.getParentOrderSn());
//参与活动判定
if (parentOrder.getMemberId().equals(UserContext.getCurrentUser().getId())) {
throw new ServiceException(ResultCode.PINTUAN_JOIN_ERROR);

View File

@ -53,7 +53,6 @@ public class CommissionRender implements CartRenderStep {
@Override
public void render(TradeDTO tradeDTO) {
buildCartPrice(tradeDTO);
buildTradePrice(tradeDTO);
}
/**
@ -77,42 +76,22 @@ public class CommissionRender implements CartRenderStep {
.substring(cartSkuVO.getGoodsSku().getCategoryPath().lastIndexOf(",") + 1);
if (StrUtil.isNotEmpty(categoryId)) {
Double commissionRate = categoryService.getById(categoryId).getCommissionRate();
priceDetailDTO.setCommission(commissionRate);
priceDetailDTO.setPlatFormCommissionPoint(commissionRate);
}
//如果积分订单 积分订单单独操作订单结算金额和商家结算字段
if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.POINTS)) {
PointsGoodsVO pointsGoodsVO = pointsGoodsService.getPointsGoodsVOByMongo(cartSkuVO.getGoodsSku().getId());
priceDetailDTO.setBillPrice(pointsGoodsVO.getSettlementPrice());
priceDetailDTO.setSettlementPrice(pointsGoodsVO.getSettlementPrice());
}
//如果砍价订单 计算金额单独操作订单结算金额和商家结算字段
else if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) {
KanjiaActivityGoodsDTO kanjiaActivityGoodsDTO = kanjiaActivityGoodsService.getKanJiaGoodsBySku(cartSkuVO.getGoodsSku().getId());
priceDetailDTO.setBillPrice(kanjiaActivityGoodsDTO.getSettlementPrice());
priceDetailDTO.setSettlementPrice(kanjiaActivityGoodsDTO.getSettlementPrice());
}
priceDetailDTOS.add(priceDetailDTO);
}
cart.getPriceDetailDTO().accumulationPriceDTO(priceDetailDTOS);
}
}
/**
* 再次总计金额
*
* @param tradeDTO 购物车展示信息
*/
void buildTradePrice(TradeDTO tradeDTO) {
//购物车列表
List<CartVO> cartVOS = tradeDTO.getCartList();
List<PriceDetailDTO> priceDetailDTOS = new ArrayList<>();
for (CartVO cart : cartVOS) {
priceDetailDTOS.add(cart.getPriceDetailDTO());
}
tradeDTO.getPriceDetailDTO().accumulationPriceDTO(priceDetailDTOS);
}
}

View File

@ -1,13 +1,17 @@
package cn.lili.modules.order.cart.render.impl;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.cart.render.util.PromotionPriceUtil;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import org.springframework.core.annotation.Order;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.enums.CouponTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@ -26,13 +30,13 @@ public class CouponRender implements CartRenderStep {
return RenderStepEnums.COUPON;
}
@Autowired
private PromotionPriceUtil promotionPriceUtil;
@Override
public void render(TradeDTO tradeDTO) {
//主要渲染各个优惠的价格
//this.renderCoupon(tradeDTO);
this.renderCoupon(tradeDTO);
}
/**
@ -42,40 +46,85 @@ public class CouponRender implements CartRenderStep {
*/
private void renderCoupon(TradeDTO tradeDTO) {
MemberCouponDTO platformCoupon = tradeDTO.getPlatformCoupon();
//如果有勾选平台优惠券
if (platformCoupon != null) {
//计算平台优惠券
for (CartSkuVO item : tradeDTO.getSkuList()) {
//如果这个sku涉及到平台优惠券价格计算 则操作这个sku的价格
if (platformCoupon.getSkuDetail().containsKey(item.getGoodsSku().getId())) {
PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO();
priceDetailDTO.setSiteCouponPoint(platformCoupon.getMemberCoupon().getStoreCommission());
priceDetailDTO.setSiteCouponPrice(platformCoupon.getSkuDetail().get(item.getGoodsSku().getId()));
priceDetailDTO.setSiteCouponCommission(CurrencyUtil.mul(priceDetailDTO.getSiteCouponPoint(), priceDetailDTO.getSiteCouponPrice()));
}
}
renderSku(tradeDTO, platformCoupon);
}
//计算商家优惠券
Map<String, MemberCouponDTO> map = tradeDTO.getStoreCoupons();
if (map != null && map.size() > 0) {
for (MemberCouponDTO coupon : map.values()) {
for (CartSkuVO item : tradeDTO.getSkuList()) {
if (coupon.getSkuDetail().containsKey(item.getGoodsSku().getId())) {
PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO();
//写入商品折扣金额
priceDetailDTO.setDiscountPrice(
CurrencyUtil.add(
priceDetailDTO.getDiscountPrice(),
coupon.getSkuDetail().get(
item.getGoodsSku().getId()
)
)
);
}
}
for (MemberCouponDTO memberCouponDTO : map.values()) {
renderSku(tradeDTO, memberCouponDTO);
}
}
}
/**
* 渲染sku优惠信息
*
* @param tradeDTO 交易DTO
* @param memberCouponDTO 优惠券DTO
*/
private void renderSku(TradeDTO tradeDTO, MemberCouponDTO memberCouponDTO) {
//计算优惠总金额
Double countPrice = 0D;
Map<String, Double> couponMap = memberCouponDTO.getSkuDetail();
for (Double skuPrice : couponMap.values()) {
countPrice = CurrencyUtil.add(countPrice, skuPrice);
}
//接收具体优惠券信息
MemberCoupon coupon = memberCouponDTO.getMemberCoupon();
//处理一个极端情况如果优惠券满减金额大于订单金额
if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name()) && coupon.getPrice() > countPrice) {
//将符合优惠券的金额写入即最大扣减金额
coupon.setPrice(countPrice);
}
//减免现金则按照商品价格计算 需要通过工具类进行优惠金额的分发分发给每个商品
if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name())) {
//分发优惠券
promotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(), PromotionTypeEnum.COUPON);
//如果是平台券 则需要计算商家承担比例
if (coupon.getIsPlatform() && coupon.getStoreCommission() > 0) {
//循环所有优惠券
for (String skuId : couponMap.keySet()) {
for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
//写入平台优惠券承担比例
if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
cartSkuVO.getPriceDetailDTO().setSiteCouponPrice(cartSkuVO.getPriceDetailDTO().getSiteCouponPrice());
cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission());
}
}
}
}
}
//打折券 直接计算
else {
//循环所有优惠券
for (String skuId : couponMap.keySet()) {
// 循环购物车商品
for (CartSkuVO item : tradeDTO.getSkuList()) {
//如果id相等则渲染商品价格信息
if (item.getGoodsSku().getId().equals(skuId)) {
PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO();
//平台券则写入店铺承担优惠券比例
if (coupon.getIsPlatform()) {
priceDetailDTO.setSiteCouponPrice(CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(), coupon.getDiscount()));
priceDetailDTO.setSiteCouponPoint(coupon.getStoreCommission());
}
priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(),
CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(), coupon.getDiscount())));
}
}
}
}
}
}

View File

@ -3,16 +3,21 @@ package cn.lili.modules.order.cart.render.impl;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.distribution.entity.dos.DistributionGoods;
import cn.lili.modules.distribution.service.DistributionGoodsService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import com.xkcoding.http.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* 购物促销信息渲染实现
* 分销佣金计算
*
* @author Chopper
* @since 2020-07-02 14:47
@ -25,6 +30,9 @@ public class DistributionPriceRender implements CartRenderStep {
@Autowired
private Cache cache;
@Autowired
private DistributionGoodsService distributionGoodsService;
@Override
public RenderStepEnums step() {
return RenderStepEnums.DISTRIBUTION;
@ -32,7 +40,6 @@ public class DistributionPriceRender implements CartRenderStep {
@Override
public void render(TradeDTO tradeDTO) {
//主要渲染各个优惠的价格
this.renderDistribution(tradeDTO);
}
@ -43,13 +50,31 @@ public class DistributionPriceRender implements CartRenderStep {
*/
private void renderDistribution(TradeDTO tradeDTO) {
if(cache.get(CachePrefix.DISTRIBUTION.getPrefix()+"_"+tradeDTO.getMemberId())==null){
//如果存在分销员
String distributionId = (String) cache.get(CachePrefix.DISTRIBUTION.getPrefix() + "_" + tradeDTO.getMemberId());
if (StringUtil.isEmpty(distributionId)) {
return;
}
//循环订单商品列表如果是分销商品则计算商品佣金
tradeDTO.setDistributionId(cache.get(CachePrefix.DISTRIBUTION.getPrefix()+"_"+tradeDTO.getMemberId()).toString());
for (CartSkuVO cartSkuVO: tradeDTO.getSkuList()) {
if(cartSkuVO.getDistributionGoods()!=null){
tradeDTO.setDistributionId(distributionId);
List<String> skuIds = tradeDTO.getSkuList().stream().map(cartSkuVO -> {
return cartSkuVO.getGoodsSku().getId();
}).collect(Collectors.toList());
//是否包含分销商品
List<DistributionGoods> distributionGoods = distributionGoodsService.distributionGoods(skuIds);
if (distributionGoods != null && distributionGoods.size() > 0) {
distributionGoods.forEach(dg -> {
tradeDTO.getSkuList().forEach(cartSkuVO -> {
if (cartSkuVO.getGoodsSku().getId().equals(dg.getSkuId())) {
cartSkuVO.setDistributionGoods(dg);
}
});
});
}
for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
if (cartSkuVO.getDistributionGoods() != null) {
cartSkuVO.getPriceDetailDTO().setDistributionCommission(CurrencyUtil.mul(cartSkuVO.getNum(), cartSkuVO.getDistributionGoods().getCommission()));
}
}

View File

@ -1,20 +1,20 @@
package cn.lili.modules.order.cart.render.impl;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.cart.entity.vo.FullDiscountVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.cart.render.util.PromotionPriceUtil;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.service.FullDiscountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -29,53 +29,60 @@ public class FullDiscountRender implements CartRenderStep {
@Autowired
private FullDiscountService fullDiscountService;
@Autowired
private PromotionPriceUtil promotionPriceUtil;
@Override
public RenderStepEnums step() {
return RenderStepEnums.FULL_DISCOUNT;
}
@Override
public void render(TradeDTO tradeDTO) {
//获取购物车中所有的商品
List<CartSkuVO> cartSkuList = tradeDTO.getSkuList();
//店铺id集合
List<String> storeIds = new ArrayList<>();
//店铺集合
List<CartVO> cartList = tradeDTO.getCartList();
//获取店铺id
Map<String, List<CartSkuVO>> storeCollect = tradeDTO.getSkuList().parallelStream().collect(Collectors.groupingBy(CartSkuVO::getStoreId));
for (Map.Entry<String, List<CartSkuVO>> storeCart : storeCollect.entrySet()) {
if (!storeCart.getValue().isEmpty()) {
storeIds.add(storeCart.getKey());
}
}
//店铺id集合
List<String> storeIds = tradeDTO.getCartList().stream().map(CartVO::getStoreId).collect(Collectors.toList());
//获取当前店铺进行到满减活动
List<FullDiscountVO> fullDiscounts = fullDiscountService.currentPromotion(storeIds);
if (fullDiscounts == null || fullDiscounts.size() == 0) {
return;
}
//循环满减信息
for (FullDiscountVO fullDiscount : fullDiscounts) {
//判定参与活动的商品
if (fullDiscount.getPromotionGoodsList() != null || fullDiscount.getNumber() == -1) {
//判定参与活动的商品 全品类参与或者部分商品参与则进行云散
if (fullDiscount.getNumber() == -1 || fullDiscount.getPromotionGoodsList() != null) {
//循环店铺购物车
for (CartVO cart : cartList) {
//如果购物车中的店铺id与活动店铺id相等则进行促销计算
if (fullDiscount.getStoreId().equals(cart.getStoreId())) {
//写入满减活动
cart.setFullDiscount(fullDiscount);
List<String> skuIds;
Map<String, Double> skuPriceDetail;
//参与活动的sku判定
if (fullDiscount.getNumber() != -1) {
skuIds = initFullDiscountGoods(fullDiscount, cartSkuList);
} else {
skuIds = cart.getSkuList().stream().map(i -> i.getGoodsSku().getId()).collect(Collectors.toList());
}
skuPriceDetail = initFullDiscountGoods(fullDiscount, cartSkuList);
//记录参与满减活动的sku
cart.setFullDiscountSkuIds(skuIds);
cart.setFullDiscountSkuIds(new ArrayList<>(skuPriceDetail.keySet()));
Double countPrice = countPrice(skuPriceDetail);
if (isFull(countPrice, cart)) {
//如果减现金
if (fullDiscount.getIsFullMinus()) {
promotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT);
}
renderFullMinus(cart);
}
}
}
}
}
@ -89,19 +96,87 @@ public class FullDiscountRender implements CartRenderStep {
* @param cartSkuVOS 购物车商品sku信息
* @return 参与满优惠的商品id
*/
public List<String> initFullDiscountGoods(FullDiscountVO fullDiscount, List<CartSkuVO> cartSkuVOS) {
List<String> goodsIds = new ArrayList<>();
//判定参与活动的商品
for (PromotionGoods promotionGoods : fullDiscount.getPromotionGoodsList()) {
//sku 集合判定
public Map<String, Double> initFullDiscountGoods(FullDiscountVO fullDiscount, List<CartSkuVO> cartSkuVOS) {
Map<String, Double> skuPriceDetail = new HashMap<>();
//全品类参与
if (fullDiscount.getNumber() == -1) {
for (CartSkuVO cartSkuVO : cartSkuVOS) {
//如果参加则记录商品sku
if (cartSkuVO.getGoodsSku().getId().equals(promotionGoods.getSkuId())) {
goodsIds.add(promotionGoods.getSkuId());
skuPriceDetail.put(cartSkuVO.getGoodsSku().getId(), cartSkuVO.getPriceDetailDTO().getGoodsPrice());
}
} else {
//判定参与活动的商品
for (PromotionGoods promotionGoods : fullDiscount.getPromotionGoodsList()) {
//sku 集合判定
for (CartSkuVO cartSkuVO : cartSkuVOS) {
//如果参加则记录商品sku
if (cartSkuVO.getGoodsSku().getId().equals(promotionGoods.getSkuId())) {
skuPriceDetail.put(cartSkuVO.getGoodsSku().getId(), cartSkuVO.getPriceDetailDTO().getGoodsPrice());
}
}
}
}
return goodsIds;
return skuPriceDetail;
}
/**
* 渲染满减优惠
*
* @param cartVO 购物车满优惠渲染
*/
private void renderFullMinus(CartVO cartVO) {
//获取参与活动的商品总价
FullDiscountVO fullDiscount = cartVO.getFullDiscount();
if (fullDiscount.getIsCoupon()) {
cartVO.getGiftCouponList().add(fullDiscount.getCouponId());
}
if (fullDiscount.getIsGift()) {
cartVO.setGiftList(Arrays.asList(fullDiscount.getGiftId().split(",")));
}
if (fullDiscount.getIsPoint()) {
cartVO.setGiftPoint(fullDiscount.getPoint());
}
//如果满足判定是否免邮免邮的话需要渲染一边sku
if (fullDiscount.getIsFreeFreight()) {
for (CartSkuVO skuVO : cartVO.getSkuList()) {
skuVO.setIsFreeFreight(true);
}
}
}
/**
* 是否满足满优惠
*
* @param cart 购物车展示信息
* @return 是否满足满优惠
*/
private boolean isFull(Double price, CartVO cart) {
if (cart.getFullDiscount().getFullMoney() <= price) {
cart.setPromotionNotice("正在参与满优惠活动(" + cart.getFullDiscount().getPromotionName() + "" + cart.getFullDiscount().notice());
return true;
} else {
cart.setPromotionNotice("还差" + CurrencyUtil.sub(cart.getFullDiscount().getFullMoney(), price) + " 即可参与活动(" + cart.getFullDiscount().getPromotionName() + "" + cart.getFullDiscount().notice());
return false;
}
}
/**
* 统计参与满减商品价格
*
* @param skuPriceMap sku价格
* @return 总价
*/
private Double countPrice(Map<String, Double> skuPriceMap) {
Double count = 0d;
for (Double price : skuPriceMap.values()) {
count = CurrencyUtil.add(count, price);
}
return count;
}
}

View File

@ -1,33 +1,17 @@
package cn.lili.modules.order.cart.render.impl;
import cn.hutool.core.date.DateUtil;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.cart.entity.vo.FullDiscountVO;
import cn.lili.modules.order.cart.entity.vo.PriceDetailVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.dto.GoodsSkuPromotionPriceDTO;
import cn.lili.modules.promotion.entity.dto.PromotionPriceDTO;
import cn.lili.modules.promotion.entity.dto.PromotionPriceParamDTO;
import cn.lili.modules.promotion.entity.dto.StorePromotionPriceDTO;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import cn.lili.modules.promotion.service.PromotionPriceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 购物促销信息渲染实现
*
@ -38,11 +22,6 @@ import java.util.stream.Collectors;
public class SkuPromotionRender implements CartRenderStep {
/**
* 促销计算
*/
@Autowired
private PromotionPriceService promotionPriceService;
/**
* 促销商品
*/
@ -57,13 +36,30 @@ public class SkuPromotionRender implements CartRenderStep {
@Override
public void render(TradeDTO tradeDTO) {
//渲染促销价格
this.renderPromotionPrice(tradeDTO);
//获取商品促销
//基础价格渲染
renderBasePrice(tradeDTO);
//渲染单品促销
renderSkuPromotion(tradeDTO);
}
/**
* 基础价格渲染
*
* @param tradeDTO
*/
private void renderBasePrice(TradeDTO tradeDTO) {
tradeDTO.getCartList().forEach(
cartVO -> {
cartVO.getSkuList().forEach(cartSkuVO -> {
PriceDetailDTO priceDetailDTO = cartSkuVO.getPriceDetailDTO();
priceDetailDTO.setOriginalPrice(CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum()));
priceDetailDTO.setGoodsPrice(cartSkuVO.getSubTotal());
priceDetailDTO.setDiscountPrice(CurrencyUtil.sub(priceDetailDTO.getOriginalPrice(), cartSkuVO.getSubTotal()));
});
}
);
}
/**
* 渲染单品优惠 积分/拼团/秒杀/砍价
@ -77,223 +73,13 @@ public class SkuPromotionRender implements CartRenderStep {
if (!tradeDTO.getCartTypeEnum().equals(CartTypeEnum.POINTS)
&& !tradeDTO.getCartTypeEnum().equals(CartTypeEnum.PINTUAN)
&& !tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) {
List<CartVO> cartVOS = tradeDTO.getCartList();
for (CartVO cartVO : cartVOS) {
if (isFull(cartVO)) {
this.renderFullMinus(cartVO);
}
for (CartVO cartVO : tradeDTO.getCartList()) {
for (CartSkuVO cartSkuVO : cartVO.getSkuList()) {
promotionGoodsService.getCartSkuPromotion(cartSkuVO);
promotionGoodsService.updatePromotion(cartSkuVO);
}
}
}
}
/**
* 渲染购物车视图的促销价格
* 1.获取购物车商品列表
* 2.获取用户的优惠券
* 3.调用价格计算模块返回价格计算结果
* 4.分配计算后的促销
*
* @param tradeDTO 购物车视图
*/
private void renderPromotionPrice(TradeDTO tradeDTO) {
//获取购物车商品列表
List<PromotionPriceParamDTO> promotionPriceParamList = this.getPromotionPriceParamList(tradeDTO);
//店铺优惠券集合
List<MemberCoupon> memberCoupons = this.getMemberCoupons(tradeDTO);
//调用价格计算模块返回价格计算结果
PromotionPriceDTO promotionPrice = promotionPriceService.calculationPromotionPrice(promotionPriceParamList, memberCoupons, tradeDTO.getCartTypeEnum());
// 分配计算后的促销
this.distributionPromotionPrice(tradeDTO, promotionPrice);
}
/**
* 获取用户优惠券列表
*
* @param tradeDTO 交易DTO
* @return 用户优惠券列表
*/
private List<MemberCoupon> getMemberCoupons(TradeDTO tradeDTO) {
//店铺优惠券集合
List<MemberCoupon> memberCoupons = new ArrayList<>();
if (tradeDTO.getStoreCoupons() != null) {
memberCoupons.addAll(tradeDTO.getStoreCoupons().values().parallelStream().map(MemberCouponDTO::getMemberCoupon).collect(Collectors.toList()));
}
//平台优惠券
if (tradeDTO.getPlatformCoupon() != null && tradeDTO.getPlatformCoupon().getMemberCoupon() != null) {
memberCoupons.add(tradeDTO.getPlatformCoupon().getMemberCoupon());
}
//清除过期优惠券
long now = DateUtil.date().getTime();
memberCoupons.removeIf(memberCoupon -> memberCoupon.getEndTime().getTime() < now);
return memberCoupons;
}
/**
* 获取促销价格DTO列表
*
* @param tradeDTO 交易DTO
* @return 促销价格DTO列表
*/
private List<PromotionPriceParamDTO> getPromotionPriceParamList(TradeDTO tradeDTO) {
List<PromotionPriceParamDTO> promotionPriceParamList = new ArrayList<>();
List<CartVO> cartList = tradeDTO.getCartList();
for (CartVO cartVO : cartList) {
if (Boolean.TRUE.equals(cartVO.getChecked())) {
for (CartSkuVO cartSkuVO : cartVO.getSkuList()) {
//检查当前购物车商品是否有效且为选中
if (Boolean.TRUE.equals(cartSkuVO.getChecked()) && Boolean.FALSE.equals(cartSkuVO.getInvalid())) {
PromotionPriceParamDTO param = new PromotionPriceParamDTO();
param.setSkuId(cartSkuVO.getGoodsSku().getId());
param.setNum(cartSkuVO.getNum());
//是否为拼团商品计算
if (cartSkuVO.getPintuanId() != null) {
param.setPintuanId(cartSkuVO.getPintuanId());
}
promotionPriceParamList.add(param);
}
}
}
}
return promotionPriceParamList;
}
/**
* 分配促销价格到购物车视图
*
* @param tradeDTO 购物车视图
* @param promotionPrice 促销价格计算结果
*/
private void distributionPromotionPrice(TradeDTO tradeDTO, PromotionPriceDTO promotionPrice) {
//根据店铺分配店铺价格计算结果
for (CartVO cartVO : tradeDTO.getCartList()) {
//根据店铺id分组
Optional<StorePromotionPriceDTO> storePromotionPriceDTOOptional =
promotionPrice.getStorePromotionPriceList().parallelStream().filter(i -> i.getStoreId().equals(cartVO.getStoreId())).findAny();
//参数有效 则分发
if (storePromotionPriceDTOOptional.isPresent()) {
StorePromotionPriceDTO storePromotionPriceDTO = storePromotionPriceDTOOptional.get();
//根据商品分配商品结果计算结果
this.distributionSkuPromotionPrice(cartVO.getSkuList(), storePromotionPriceDTO);
PriceDetailDTO priceDetailDTO = new PriceDetailDTO();
PriceDetailVO priceDetailVO = new PriceDetailVO();
priceDetailDTO.setGoodsPrice(storePromotionPriceDTO.getTotalOriginPrice());
priceDetailDTO.setDiscountPrice(storePromotionPriceDTO.getTotalDiscountPrice());
priceDetailDTO.setCouponPrice(storePromotionPriceDTO.getTotalCouponPrice());
priceDetailDTO.setPayPoint(storePromotionPriceDTO.getTotalPoints().intValue());
priceDetailVO.setOriginalPrice(storePromotionPriceDTO.getTotalOriginPrice());
priceDetailVO.setFinalePrice(storePromotionPriceDTO.getTotalFinalePrice());
priceDetailVO.setDiscountPrice(storePromotionPriceDTO.getTotalDiscountPrice());
priceDetailVO.setPayPoint(storePromotionPriceDTO.getTotalPoints().intValue());
cartVO.setPriceDetailDTO(priceDetailDTO);
cartVO.setPriceDetailVO(priceDetailVO);
cartVO.setWeight(storePromotionPriceDTO.getTotalWeight());
}
}
//根据整个购物车分配价格计算结果
PriceDetailDTO priceDetailDTO = new PriceDetailDTO();
priceDetailDTO.setDiscountPrice(promotionPrice.getTotalDiscountPrice());
priceDetailDTO.setGoodsPrice(promotionPrice.getTotalOriginPrice());
priceDetailDTO.setCouponPrice(promotionPrice.getTotalCouponPrice());
priceDetailDTO.setPayPoint(promotionPrice.getTotalPoints().intValue());
tradeDTO.setPriceDetailDTO(priceDetailDTO);
}
/**
* 分配促销价格到购物车视图的每个sku
*
* @param skuList sku列表
* @param storePromotionPriceDTO 店铺促销结果计算结果
*/
private void distributionSkuPromotionPrice(List<CartSkuVO> skuList, StorePromotionPriceDTO storePromotionPriceDTO) {
if (storePromotionPriceDTO != null) {
for (CartSkuVO cartSkuVO : skuList) {
//获取当前购物车商品的商品计算结果
List<GoodsSkuPromotionPriceDTO> collect = storePromotionPriceDTO.getGoodsSkuPromotionPriceList().parallelStream().filter(i -> i.getSkuId().equals(cartSkuVO.getGoodsSku().getId())).collect(Collectors.toList());
if (!collect.isEmpty()) {
GoodsSkuPromotionPriceDTO goodsSkuPromotionPriceDTO = collect.get(0);
PriceDetailDTO spd = new PriceDetailDTO();
spd.setDiscountPrice(goodsSkuPromotionPriceDTO.getTotalDiscountPrice());
spd.setGoodsPrice(goodsSkuPromotionPriceDTO.getTotalOriginalPrice());
spd.setCouponPrice(goodsSkuPromotionPriceDTO.getCouponPrice());
spd.setJoinPromotion(goodsSkuPromotionPriceDTO.getJoinPromotion());
spd.setPayPoint(goodsSkuPromotionPriceDTO.getTotalPoints().intValue());
PriceDetailVO pd = new PriceDetailVO();
pd.setFinalePrice(goodsSkuPromotionPriceDTO.getFinalePrice());
pd.setOriginalPrice(goodsSkuPromotionPriceDTO.getOriginalPrice());
pd.setDiscountPrice(goodsSkuPromotionPriceDTO.getDiscountPrice());
pd.setPayPoint(goodsSkuPromotionPriceDTO.getTotalPoints().intValue());
cartSkuVO.setPriceDetailDTO(spd);
cartSkuVO.setPriceDetailVO(pd);
}
}
}
}
/**
* 渲染满减优惠
*
* @param cartVO 购物车展示信息
*/
private void renderFullMinus(CartVO cartVO) {
//获取参与活动的商品总价
FullDiscountVO fullDiscount = cartVO.getFullDiscount();
if (Boolean.TRUE.equals(fullDiscount.getIsCoupon())) {
cartVO.getGiftCouponList().add(fullDiscount.getCouponId());
}
if (Boolean.TRUE.equals(fullDiscount.getIsGift())) {
cartVO.setGiftList(Arrays.asList(fullDiscount.getGiftId().split(",")));
}
if (Boolean.TRUE.equals(fullDiscount.getIsPoint())) {
cartVO.setGiftPoint(cartVO.getGiftPoint() + fullDiscount.getPoint());
}
}
/**
* 是否满足满优惠
*
* @param cart 购物车展示信息
* @return 是否满足满优惠
*/
private boolean isFull(CartVO cart) {
Double price = cart.getPriceDetailDTO().getGoodsPrice();
if (cart.getFullDiscount() != null) {
if (cart.getFullDiscount().getFullMoney() <= price) {
cart.setPromotionNotice("正在参与满优惠活动(" + cart.getFullDiscount().getPromotionName() + "" + cart.getFullDiscount().notice());
//如果满足判定是否免邮免邮的话需要渲染一边sku
if (Boolean.TRUE.equals(cart.getFullDiscount().getIsFreeFreight())) {
for (CartSkuVO skuVO : cart.getSkuList()) {
skuVO.setIsFreeFreight(true);
}
}
return true;
} else {
cart.setPromotionNotice("还差" + CurrencyUtil.sub(cart.getFullDiscount().getFullMoney(), price) + " 即可参与活动(" + cart.getFullDiscount().getPromotionName() + "" + cart.getFullDiscount().notice());
return false;
}
} else {
cart.setPromotionNotice("");
}
return false;
}
}

View File

@ -0,0 +1,237 @@
package cn.lili.modules.order.cart.render.util;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.promotion.service.KanjiaActivityGoodsService;
import cn.lili.modules.promotion.service.PointsGoodsService;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import cn.lili.modules.promotion.service.SeckillApplyService;
import cn.lili.modules.search.service.EsGoodsSearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 促销价格计算业务层实现
*
* @author paulG
* @since 2020/8/21
**/
@Service
@Slf4j
public class PromotionPriceUtil {
/**
* ES商品
*/
@Autowired
private EsGoodsSearchService goodsSearchService;
/**
* 秒杀活动申请
*/
@Autowired
private SeckillApplyService seckillApplyService;
/**
* 促销商品
*/
@Autowired
private PromotionGoodsService promotionGoodsService;
/**
* 规格商品
*/
@Autowired
private GoodsSkuService goodsSkuService;
/**
* 积分商品
*/
@Autowired
private PointsGoodsService pointsGoodsService;
/**
* 积分商品
*/
@Autowired
private KanjiaActivityGoodsService kanjiaActivityGoodsService;
/**
* 重新计算购物车价格
*
* @param tradeDTO 交易DTO
* @param skuPromotionDetail 参与活动的商品以及商品总金额
* @param discountPrice 需要分发的优惠金额
* @param promotionTypeEnum 促销类型
*/
public void recountPrice(TradeDTO tradeDTO, Map<String, Double> skuPromotionDetail, Double discountPrice, PromotionTypeEnum promotionTypeEnum) {
// sku 促销信息非空判定
if (skuPromotionDetail == null || skuPromotionDetail.size() == 0) {
return;
}
//计算总金额
Double totalPrice = 0D;
for (Double value : skuPromotionDetail.values()) {
totalPrice = CurrencyUtil.add(totalPrice, value);
}
//极端情况如果扣减金额小于需要支付的金额则扣减金额=支付金额不能成为负数
if (discountPrice > totalPrice) {
discountPrice = totalPrice;
for (String skuId : skuPromotionDetail.keySet()) {
//获取对应商品进行计算
for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
//优惠券金额则计入优惠券 其他则计入总的discount price
if (promotionTypeEnum == PromotionTypeEnum.COUPON) {
cartSkuVO.getPriceDetailDTO().setCouponPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice());
} else {
cartSkuVO.getPriceDetailDTO().setDiscountPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice());
}
}
}
}
}
//获取购物车信息
List<CartSkuVO> skuVOList = tradeDTO.getSkuList();
// 获取map分配sku的总数如果是最后一个商品分配金额则将金额从百分比改为总金额扣减避免出现小数除不尽
Integer count = skuPromotionDetail.size();
//已优惠金额
Double deducted = 0D;
for (String skuId : skuPromotionDetail.keySet()) {
//获取对应商品进行计算
for (CartSkuVO cartSkuVO : skuVOList) {
if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
count--;
//sku 优惠金额
Double skuDiscountPrice = 0d;
//非最后一个商品则按照比例计算
if (count > 0) {
//商品金额占比
Double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), totalPrice, 4);
//商品优惠金额
skuDiscountPrice = CurrencyUtil.mul(totalPrice, point);
//累加已优惠金额
deducted = CurrencyUtil.add(deducted, skuDiscountPrice);
}
// 如果是最后一个商品 则减去之前优惠的金额来进行计算
else {
skuDiscountPrice = CurrencyUtil.sub(discountPrice, deducted);
}
//优惠券金额则计入优惠券 其他则计入总的discount price
if (promotionTypeEnum == PromotionTypeEnum.COUPON) {
cartSkuVO.getPriceDetailDTO().setCouponPrice(
CurrencyUtil.add(cartSkuVO.getPriceDetailDTO().getCouponPrice(), skuDiscountPrice));
} else {
cartSkuVO.getPriceDetailDTO().setDiscountPrice(
CurrencyUtil.add(cartSkuVO.getPriceDetailDTO().getDiscountPrice(), skuDiscountPrice));
}
}
}
}
}
// /**
// * 计算积分商品
// * 积分商品的购买金额是0
// * 1.根据SkuId去查询积分商品Mongo
// * 2.计算积分商品的优惠信息
// *
// * @param tradeSkuList 交易商品促销金额列表
// * @return 计算结果
// */
// private List<GoodsSkuPromotionPriceDTO> pointGoodsPromotion(List<PromotionPriceParamDTO> tradeSkuList) {
// List<GoodsSkuPromotionPriceDTO> priceDTOList = new ArrayList<>();
// //获取积分商品SkuId
// String skuId = tradeSkuList.get(0).getSkuId();
// //获取积分商品VO
// PointsGoodsVO pointsGoodsVO = pointsGoodsService.getPointsGoodsVOByMongo(skuId);
// //参与计算的缓存中的商品SKU列表
// GoodsSku goodsSku = pointsGoodsVO.getGoodsSku();
// //获取商品促销金额
// GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice = new GoodsSkuPromotionPriceDTO(goodsSku, tradeSkuList.get(0).getNum());
// //计算商品原价=原价*数量
// goodsSkuPromotionPrice.setTotalOriginalPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getOriginalPrice(), goodsSkuPromotionPrice.getNumber()));
// //计算商品积分数量=兑换积分*数量
// goodsSkuPromotionPrice.setTotalPoints(pointsGoodsVO.getPoints() * Convert.toLong(goodsSkuPromotionPrice.getNumber()));
// //优惠金额=商品原价*数量
// goodsSkuPromotionPrice.setTotalDiscountPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getOriginalPrice(), goodsSkuPromotionPrice.getNumber()));
// //购买价格=积分商品价格为 0
// goodsSkuPromotionPrice.setTotalFinalePrice(0.0);
// priceDTOList.add(goodsSkuPromotionPrice);
// return priceDTOList;
// }
//
// /**
// * 计算砍价商品
// * 砍价商品只能购买一件
// * 1.根据SkuId去查询积分商品Mongo
// * 2.计算积分商品的优惠信息
// *
// * @param tradeSkuList 交易商品促销金额列表
// * @return 计算结果
// */
// private List<GoodsSkuPromotionPriceDTO> kanjiaPromotion(List<PromotionPriceParamDTO> tradeSkuList) {
// List<GoodsSkuPromotionPriceDTO> priceDTOList = new ArrayList<>();
// //获取积分商品SkuId
// String skuId = tradeSkuList.get(0).getSkuId();
// //获取积分商品VO
// KanjiaActivityGoodsDTO kanjiaActivityGoodsDTO = kanjiaActivityGoodsService.getKanJiaGoodsBySku(skuId);
//
// //参与计算的缓存中的商品SKU列表
// GoodsSku goodsSku = kanjiaActivityGoodsDTO.getGoodsSku();
// GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice = new GoodsSkuPromotionPriceDTO(goodsSku, tradeSkuList.get(0).getNum());
// //优惠金额=商品原价-购买价格
// goodsSkuPromotionPrice.setTotalDiscountPrice(CurrencyUtil.sub(goodsSkuPromotionPrice.getOriginalPrice(), kanjiaActivityGoodsDTO.getPurchasePrice()));
// //购买价格=砍价成交金额
// goodsSkuPromotionPrice.setTotalFinalePrice(kanjiaActivityGoodsDTO.getPurchasePrice());
// //原价
// goodsSkuPromotionPrice.setTotalOriginalPrice(goodsSkuPromotionPrice.getOriginalPrice());
// priceDTOList.add(goodsSkuPromotionPrice);
// return priceDTOList;
// }
/**
* 检查活动有效时间
*
* @param startTime 活动开始时间
* @param endTime 活动结束时间
* @param promotionType 活动类型
* @param promotionId 活动ID
* @return 是否有效
*/
private boolean checkPromotionValidTime(Date startTime, Date endTime, String promotionType, String promotionId) {
long now = System.currentTimeMillis();
if (startTime.getTime() > now) {
log.error("商品ID为{}的{}活动开始时间小于当时时间,活动未开始!", promotionId, promotionType);
return false;
}
if (endTime.getTime() < now) {
log.error("活动ID为{}的{}活动结束时间大于当时时间,活动已结束!", promotionId, promotionType);
return false;
}
return true;
}
}

View File

@ -52,16 +52,9 @@ public interface CartService {
* @param skuId 要写入的skuId
* @param num 要加入购物车的数量
* @param cartType 购物车类型
* @param cover 是否覆盖购物车的数量如果为否则累加否则直接覆盖
*/
void add(String skuId, Integer num, String cartType);
/**
* 更新商品数量
*
* @param skuId 要写入的skuId
* @param num 要加入购物车的数量
*/
void updateNum(String skuId, int num);
void add(String skuId, Integer num, String cartType, Boolean cover);
/**

View File

@ -41,10 +41,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -108,26 +105,37 @@ public class CartServiceImpl implements CartService {
private TradeBuilder tradeBuilder;
@Override
public void add(String skuId, Integer num, String cartType) {
public void add(String skuId, Integer num, String cartType, Boolean cover) {
CartTypeEnum cartTypeEnum = getCartType(cartType);
GoodsSku dataSku = checkGoods(skuId, num);
GoodsSku dataSku = checkGoods(skuId);
try {
//购物车方式购买需要保存之前的选择其他方式购买则直接抹除掉之前的记录
TradeDTO tradeDTO;
if (cartTypeEnum.equals(CartTypeEnum.CART)) {
//如果存在则变更数量不做新增否则新增一个商品进入集合
tradeDTO = this.readDTO(cartTypeEnum);
List<CartSkuVO> cartSkuVOS = tradeDTO.getSkuList();
CartSkuVO cartSkuVO = cartSkuVOS.stream().filter(i -> i.getGoodsSku().getId().equals(skuId)).findFirst().orElse(null);
//购物车中已经存在更新数量
if (cartSkuVO != null && dataSku.getUpdateTime().equals(cartSkuVO.getGoodsSku().getUpdateTime())) {
//判断是商品否被修改
int oldNum = cartSkuVO.getNum();
int newNum = oldNum + num;
this.checkSetGoodsQuantity(cartSkuVO, skuId, newNum);
//如果覆盖购物车中商品数量
if (cover) {
cartSkuVO.setNum(num);
this.checkSetGoodsQuantity(cartSkuVO, skuId, num);
} else {
int oldNum = cartSkuVO.getNum();
int newNum = oldNum + num;
this.checkSetGoodsQuantity(cartSkuVO, skuId, newNum);
}
//计算购物车小计
cartSkuVO.setSubTotal(CurrencyUtil.mul(cartSkuVO.getPurchasePrice(), cartSkuVO.getNum()));
} else {
//先清理一下 如果商品无效的话
cartSkuVOS.remove(cartSkuVO);
//购物车中不存在此商品则新建立一个
@ -175,30 +183,6 @@ public class CartServiceImpl implements CartService {
}
}
@Override
public void updateNum(String skuId, int num) {
try {
checkGoods(skuId, num);
TradeDTO tradeDTO = this.readDTO(CartTypeEnum.CART);
CartSkuVO cartSkuVO = null;
for (CartSkuVO skuVO : tradeDTO.getSkuList()) {
if (skuVO.getGoodsSku().getId().equals(skuId)) {
cartSkuVO = skuVO;
}
}
if (cartSkuVO != null) {
this.checkSetGoodsQuantity(cartSkuVO, skuId, num);
}
String originKey = this.getOriginKey(CartTypeEnum.CART);
cache.put(originKey, tradeDTO);
} catch (ServiceException se) {
log.error("购物车渲染异常", se);
} catch (Exception e) {
log.error("购物车渲染异常", e);
throw new ServiceException(errorMessage);
}
}
/**
* 读取当前会员购物原始数据key
*
@ -372,9 +356,8 @@ public class CartServiceImpl implements CartService {
* 校验商品有效性判定失效和库存
*
* @param skuId 商品skuId
* @param num 数量
*/
private GoodsSku checkGoods(String skuId, Integer num) {
private GoodsSku checkGoods(String skuId) {
GoodsSku dataSku = this.goodsSkuService.getGoodsSkuByIdFromCache(skuId);
if (dataSku == null) {
throw new ServiceException(ResultCode.GOODS_NOT_EXIST);
@ -382,13 +365,6 @@ public class CartServiceImpl implements CartService {
if (!GoodsAuthEnum.PASS.name().equals(dataSku.getIsAuth()) || !GoodsStatusEnum.UPPER.name().equals(dataSku.getMarketEnable())) {
throw new ServiceException(ResultCode.GOODS_NOT_EXIST);
}
//读取sku的可用库存
Integer enableQuantity = goodsSkuService.getStock(skuId);
//如果sku的可用库存小于等于0或者小于用户购买的数量则不允许购买
if (enableQuantity <= 0 || enableQuantity < num) {
throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_NOT_ENOUGH);
}
return dataSku;
}
@ -401,13 +377,22 @@ public class CartServiceImpl implements CartService {
*/
private void checkSetGoodsQuantity(CartSkuVO cartSkuVO, String skuId, Integer num) {
Integer enableStock = goodsSkuService.getStock(skuId);
//读取sku的可用库存
Integer enableQuantity = goodsSkuService.getStock(skuId);
//如果sku的可用库存小于等于0或者小于用户购买的数量则不允许购买
if (enableQuantity <= 0 || enableQuantity < num) {
throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_NOT_ENOUGH);
}
if (enableStock <= num) {
cartSkuVO.setNum(enableStock);
} else {
cartSkuVO.setNum(num);
}
if (cartSkuVO.getNum() > 100) {
if (cartSkuVO.getNum() > 99) {
cartSkuVO.setNum(99);
}
}
@ -505,7 +490,7 @@ public class CartServiceImpl implements CartService {
throw new ServiceException(ResultCode.COUPON_EXPIRED);
}
//使用优惠券 与否
if (use && checkCoupon(memberCoupon, tradeDTO)) {
if (use) {
this.useCoupon(tradeDTO, memberCoupon, cartTypeEnum);
} else if (!use) {
if (Boolean.TRUE.equals(memberCoupon.getIsPlatform())) {
@ -567,56 +552,62 @@ public class CartServiceImpl implements CartService {
* @param cartTypeEnum 购物车
*/
private void useCoupon(TradeDTO tradeDTO, MemberCoupon memberCoupon, CartTypeEnum cartTypeEnum) {
//如果是平台优惠券
if (Boolean.TRUE.equals(memberCoupon.getIsPlatform())) {
//购物车价格
Double cartPrice = 0d;
for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
//获取商品的促销信息
Optional<PromotionGoods> promotionOptional =
cartSkuVO.getPromotions().parallelStream().filter(promotionGoods ->
(promotionGoods.getPromotionType().equals(PromotionTypeEnum.PINTUAN.name()) &&
cartTypeEnum.equals(CartTypeEnum.PINTUAN)) ||
promotionGoods.getPromotionType().equals(PromotionTypeEnum.SECKILL.name())).findAny();
//有促销金额则用促销金额否则用商品原价
if (promotionOptional.isPresent()) {
cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(promotionOptional.get().getPrice(), cartSkuVO.getNum()));
} else {
cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum()));
}
//截取符合优惠券的商品
List<CartSkuVO> cartSkuVOS = checkCoupon(memberCoupon, tradeDTO);
//定义使用优惠券的信息商品信息
Map<String, Double> skuPrice = new HashMap<>();
//购物车价格
Double cartPrice = 0d;
//循环符合优惠券的商品
for (CartSkuVO cartSkuVO : cartSkuVOS) {
//获取商品的促销信息
Optional<PromotionGoods> promotionOptional =
cartSkuVO.getPromotions().parallelStream().filter(promotionGoods ->
(promotionGoods.getPromotionType().equals(PromotionTypeEnum.PINTUAN.name()) &&
cartTypeEnum.equals(CartTypeEnum.PINTUAN)) ||
promotionGoods.getPromotionType().equals(PromotionTypeEnum.SECKILL.name())).findAny();
//有促销金额则用促销金额否则用商品原价
if (promotionOptional.isPresent()) {
cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(promotionOptional.get().getPrice(), cartSkuVO.getNum()));
skuPrice.put(cartSkuVO.getGoodsSku().getId(), CurrencyUtil.mul(promotionOptional.get().getPrice(), cartSkuVO.getNum()));
} else {
cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum()));
skuPrice.put(cartSkuVO.getGoodsSku().getId(), CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum()));
}
//如果购物车金额大于消费门槛则使用
if (memberCoupon.getConsumeThreshold() <= cartPrice) {
tradeDTO.setPlatformCoupon(new MemberCouponDTO(memberCoupon));
}
//如果购物车金额大于消费门槛则使用
if (cartPrice >= memberCoupon.getConsumeThreshold()) {
//如果是平台优惠券
if (memberCoupon.getIsPlatform()) {
tradeDTO.setPlatformCoupon(new MemberCouponDTO(skuPrice, memberCoupon));
//选择平台优惠券则将品台优惠券清空
tradeDTO.setStoreCoupons(new HashMap<>(16));
} else {
tradeDTO.getStoreCoupons().put(memberCoupon.getStoreId(), new MemberCouponDTO(skuPrice, memberCoupon));
}
}
//否则为店铺优惠券
else {
//过滤对应店铺购物车
CartSkuVO cartVO = tradeDTO.getSkuList().stream().filter(i -> i.getStoreId().equals(memberCoupon.getStoreId())).findFirst().orElse(null);
//优惠券消费门槛 <= 商品购买时的成交价单品 * 购买数量
if (cartVO != null && memberCoupon.getConsumeThreshold() <= CurrencyUtil.mul(cartVO.getPurchasePrice(), cartVO.getNum())) {
tradeDTO.getStoreCoupons().put(memberCoupon.getStoreId(), new MemberCouponDTO(memberCoupon));
//选择店铺优惠券则将品台优惠券清空
tradeDTO.setPlatformCoupon(null);
}
}
}
/**
* 校验是否可以使用优惠券
* 获取可以使用优惠券的商品信息
*
* @param memberCoupon 用于计算优惠券结算详情
* @param tradeDTO 购物车信息
* @return 是否可以使用优惠券
*/
private boolean checkCoupon(MemberCoupon memberCoupon, TradeDTO tradeDTO) {
private List<CartSkuVO> checkCoupon(MemberCoupon memberCoupon, TradeDTO tradeDTO) {
List<CartSkuVO> cartSkuVOS;
//如果是店铺优惠券判定的内容
if (Boolean.FALSE.equals(memberCoupon.getIsPlatform())) {
if (!memberCoupon.getIsPlatform()) {
cartSkuVOS = tradeDTO.getSkuList().stream().filter(i -> i.getStoreId().equals(memberCoupon.getStoreId())).collect(Collectors.toList());
}
//否则为平台优惠券筛选商品为全部商品
@ -625,17 +616,19 @@ public class CartServiceImpl implements CartService {
}
//当初购物车商品中是否存在符合优惠券条件的商品sku
if (memberCoupon.getScopeType().equals(CouponScopeTypeEnum.PORTION_GOODS_CATEGORY.name())) {
if (memberCoupon.getScopeType().equals(CouponScopeTypeEnum.ALL.name())) {
return cartSkuVOS;
} else if (memberCoupon.getScopeType().equals(CouponScopeTypeEnum.PORTION_GOODS_CATEGORY.name())) {
//分类路径是否包含
return cartSkuVOS.stream().anyMatch(i -> i.getGoodsSku().getCategoryPath().indexOf("," + memberCoupon.getScopeId() + ",") <= 0);
return cartSkuVOS.stream().filter(i -> i.getGoodsSku().getCategoryPath().indexOf("," + memberCoupon.getScopeId() + ",") <= 0).collect(Collectors.toList());
} else if (memberCoupon.getScopeType().equals(CouponScopeTypeEnum.PORTION_GOODS.name())) {
//范围关联ID是否包含
return cartSkuVOS.stream().anyMatch(i -> memberCoupon.getScopeId().indexOf("," + i.getGoodsSku().getId() + ",") <= 0);
return cartSkuVOS.stream().filter(i -> memberCoupon.getScopeId().indexOf("," + i.getGoodsSku().getId() + ",") <= 0).collect(Collectors.toList());
} else if (memberCoupon.getScopeType().equals(CouponScopeTypeEnum.PORTION_SHOP_CATEGORY.name())) {
//分类路径是否包含
return cartSkuVOS.stream().anyMatch(i -> i.getGoodsSku().getStoreCategoryPath().indexOf("," + memberCoupon.getScopeId() + ",") <= 0);
//店铺分类路径是否包含
return cartSkuVOS.stream().filter(i -> i.getGoodsSku().getStoreCategoryPath().indexOf("," + memberCoupon.getScopeId() + ",") <= 0).collect(Collectors.toList());
}
return true;
return new ArrayList<>();
}
/**

View File

@ -54,6 +54,9 @@ public class PriceDetailDTO implements Serializable {
private Double distributionCommission;
@ApiModelProperty(value = "平台收取交易佣金比例")
private Double platFormCommissionPoint;
@ApiModelProperty(value = "平台收取交易佣金")
private Double platFormCommission;
@ -115,6 +118,7 @@ public class PriceDetailDTO implements Serializable {
couponPrice = 0d;
distributionCommission = 0d;
platFormCommissionPoint = 0d;
platFormCommission = 0d;
siteCouponPrice = 0d;
@ -143,132 +147,72 @@ public class PriceDetailDTO implements Serializable {
/**
* 写入佣金比例计算结算金额
*
* @param commission 佣金比例
* 全部重新计算
*/
public void setCommission(Double commission) {
//流水金额(入账 出帐金额) = goodsPrice + freight - discountPrice + couponPrice
public void recount() {
//流水金额(入账 出帐金额) = "流水金额(入账 出帐金额) = goodsPrice + freight - discountPrice - couponPrice + updatePrice"
this.flowPrice = CurrencyUtil.sub(
CurrencyUtil.add(goodsPrice, freightPrice),
CurrencyUtil.add(discountPrice,
couponPrice != null ? couponPrice : 0));
if (updatePrice > 0) {
CurrencyUtil.add(flowPrice, updatePrice);
}
//计算平台佣金 流水金额*平台佣金比例
if (commission != null && commission > 0) {
platFormCommission = CurrencyUtil.div(CurrencyUtil.mul(flowPrice, commission), 100);
if (platFormCommissionPoint != null && getPlatFormCommissionPoint() > 0) {
platFormCommission = CurrencyUtil.div(CurrencyUtil.mul(flowPrice, platFormCommissionPoint), 100);
}
countBill();
}
public void countBill() {
//如果结算信息包含结算金额则最终结算金额直接等于该交易 平台与商户的结算金额
if (settlementPrice > 0) {
billPrice = settlementPrice;
} else {
//如果是普通订单最终结算金额 = flowPrice - platFormCommission - distributionCommission 流水金额-平台佣金-分销佣金
billPrice = CurrencyUtil.sub(CurrencyUtil.sub(flowPrice, platFormCommission), distributionCommission);
}
//如果是普通订单最终结算金额 = flowPrice - platFormCommission - distributionCommission
billPrice = CurrencyUtil.sub(CurrencyUtil.sub(flowPrice, platFormCommission), distributionCommission);
}
/**
* 累加
* 累加金额
*/
public void increase(PriceDetailDTO priceDetailDTO) {
originalPrice = CurrencyUtil.add(originalPrice, priceDetailDTO.getOriginalPrice());
goodsPrice = CurrencyUtil.add(goodsPrice, priceDetailDTO.getGoodsPrice());
freightPrice = CurrencyUtil.add(freightPrice, priceDetailDTO.getFreightPrice());
payPoint = payPoint + priceDetailDTO.getPayPoint();
discountPrice = CurrencyUtil.add(discountPrice, priceDetailDTO.getDiscountPrice());
couponPrice = CurrencyUtil.add(couponPrice, priceDetailDTO.getCouponPrice());
distributionCommission = CurrencyUtil.add(distributionCommission, priceDetailDTO.getDistributionCommission());
platFormCommission = CurrencyUtil.add(platFormCommission, priceDetailDTO.getPlatFormCommission());
siteCouponPrice = CurrencyUtil.add(siteCouponPrice, priceDetailDTO.getSiteCouponPrice());
siteCouponPoint = CurrencyUtil.add(siteCouponPoint, priceDetailDTO.getSiteCouponPoint());
siteCouponCommission = CurrencyUtil.add(siteCouponCommission, priceDetailDTO.getSiteCouponCommission());
updatePrice = CurrencyUtil.add(updatePrice, priceDetailDTO.getUpdatePrice());
flowPrice = CurrencyUtil.add(flowPrice, priceDetailDTO.getFlowPrice());
billPrice = CurrencyUtil.add(billPrice, priceDetailDTO.getBillPrice());
settlementPrice = CurrencyUtil.add(settlementPrice, priceDetailDTO.getSettlementPrice());
}
/**
* 批量累加
*
* @param priceDetailDTOS
* @return
*/
public void accumulationPriceDTO(List<PriceDetailDTO> priceDetailDTOS) {
double originalPrice = 0d;
double goodsPrice = 0d;
double freightPrice = 0d;
int payPoint = 0;
double discountPrice = 0d;
double couponPrice = 0d;
double distributionCommission = 0d;
double platFormCommission = 0d;
double siteCouponPrice = 0d;
double siteCouponPoint = 0d;
double siteCouponCommission = 0d;
double updatePrice = 0d;
double flowPrice = 0d;
double billPrice = 0d;
double settlementPrice = 0d;
for (PriceDetailDTO price : priceDetailDTOS) {
originalPrice = CurrencyUtil.add(originalPrice, price.getOriginalPrice());
goodsPrice = CurrencyUtil.add(goodsPrice, price.getGoodsPrice());
freightPrice = CurrencyUtil.add(freightPrice, price.getFreightPrice());
payPoint = payPoint + price.getPayPoint();
discountPrice = CurrencyUtil.add(discountPrice, price.getDiscountPrice());
couponPrice = CurrencyUtil.add(couponPrice, price.getCouponPrice());
updatePrice = CurrencyUtil.add(updatePrice, price.getUpdatePrice());
distributionCommission = CurrencyUtil.add(distributionCommission, price.getDistributionCommission());
platFormCommission = CurrencyUtil.add(platFormCommission, price.getPlatFormCommission());
siteCouponPrice = CurrencyUtil.add(siteCouponPrice, price.getSiteCouponPrice());
siteCouponPoint = CurrencyUtil.add(siteCouponPoint, price.getSiteCouponPoint());
siteCouponCommission = CurrencyUtil.add(siteCouponCommission, price.getSiteCouponCommission());
flowPrice = CurrencyUtil.add(flowPrice, price.getFlowPrice());
billPrice = CurrencyUtil.add(billPrice, price.getBillPrice());
settlementPrice = CurrencyUtil.add(settlementPrice, price.getSettlementPrice());
this.increase(price);
}
this.setOriginalPrice(originalPrice);
this.setGoodsPrice(goodsPrice);
this.setFreightPrice(freightPrice);
this.setPayPoint(payPoint);
this.setCouponPrice(couponPrice);
this.setDiscountPrice(discountPrice);
this.setUpdatePrice(updatePrice);
this.setDistributionCommission(distributionCommission);
this.setPlatFormCommission(platFormCommission);
this.setSiteCouponPrice(siteCouponPrice);
this.setSiteCouponPoint(siteCouponPoint);
this.setSiteCouponCommission(siteCouponCommission);
this.setFlowPrice(flowPrice);
this.setBillPrice(billPrice);
this.setSettlementPrice(settlementPrice);
}
/**
* 累加
*
* @param priceDetailDTOS
* @return
*/
public static Double sumGoodsPrice(List<PriceDetailDTO> priceDetailDTOS) {
double goodsPrice = 0d;
for (PriceDetailDTO price : priceDetailDTOS) {
goodsPrice = CurrencyUtil.add(goodsPrice, price.getGoodsPrice());
}
return goodsPrice;
}
public Double getGoodsPrice() {
if (goodsPrice == null || goodsPrice <= 0) {
@ -361,4 +305,88 @@ public class PriceDetailDTO implements Serializable {
}
return billPrice;
}
public Double getUpdatePrice() {
if (updatePrice == null || updatePrice <= 0) {
return 0D;
}
return updatePrice;
}
public void setSiteCouponPrice(Double siteCouponPrice) {
this.siteCouponPrice = siteCouponPrice;
if (siteCouponPoint != null && siteCouponPoint != 0) {
this.siteCouponCommission = CurrencyUtil.mul(siteCouponPrice, siteCouponPoint);
}
}
public void setSiteCouponPoint(Double siteCouponPoint) {
this.siteCouponPoint = siteCouponPoint;
if (siteCouponPoint != null && siteCouponPoint != 0) {
this.siteCouponCommission = CurrencyUtil.mul(siteCouponPrice, siteCouponPoint);
}
}
public void setGoodsPrice(Double goodsPrice) {
this.goodsPrice = goodsPrice;
this.recount();
}
public void setFreightPrice(Double freightPrice) {
this.freightPrice = freightPrice;
this.recount();
}
public void setPayPoint(Integer payPoint) {
this.payPoint = payPoint;
}
public void setDiscountPrice(Double discountPrice) {
this.discountPrice = discountPrice;
this.recount();
}
public void setCouponPrice(Double couponPrice) {
this.couponPrice = couponPrice;
this.recount();
}
public void setDistributionCommission(Double distributionCommission) {
this.distributionCommission = distributionCommission;
this.recount();
}
public void setPlatFormCommissionPoint(Double platFormCommissionPoint) {
this.platFormCommissionPoint = platFormCommissionPoint;
this.recount();
}
public void setPlatFormCommission(Double platFormCommission) {
this.platFormCommission = platFormCommission;
this.recount();
}
public void setSiteCouponCommission(Double siteCouponCommission) {
this.siteCouponCommission = siteCouponCommission;
this.recount();
}
public void setFlowPrice(Double flowPrice) {
this.flowPrice = flowPrice;
this.recount();
}
public void setSettlementPrice(Double settlementPrice) {
this.settlementPrice = settlementPrice;
this.recount();
}
public void setBillPrice(Double billPrice) {
this.billPrice = billPrice;
this.recount();
}
}

View File

@ -4,7 +4,6 @@ import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.order.order.aop.OrderLogPoint;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
@ -17,14 +16,12 @@ import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.payment.kit.plugin.bank.BankTransferPlugin;
import cn.lili.modules.system.aspect.annotation.SystemLogPoint;
import cn.lili.modules.system.utils.OperationalJudgment;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* 订单价格业务层实现
@ -56,11 +53,6 @@ public class OrderPriceServiceImpl implements OrderPriceService {
*/
@Autowired
private OrderService orderService;
/**
* 商品分类
*/
@Autowired
private CategoryService categoryService;
@Override
@SystemLogPoint(description = "修改订单价格", customerLog = "'订单编号:'+#orderSn +',价格修改为:'+#orderPrice")
@ -70,9 +62,6 @@ public class OrderPriceServiceImpl implements OrderPriceService {
//修改订单金额
Order order = updateOrderPrice(orderSn, orderPrice);
//修改订单货物金额
//updateOrderItemPrice(order);
//修改交易金额
tradeMapper.updateTradePrice(order.getTradeSn());
return order;
@ -112,28 +101,21 @@ public class OrderPriceServiceImpl implements OrderPriceService {
//获取订单价格信息
PriceDetailDTO orderPriceDetailDTO = order.getPriceDetailDTO();
if (orderPriceDetailDTO.getOriginalPrice() == 0D) {
orderPriceDetailDTO.setOriginalPrice(orderPriceDetailDTO.getFlowPrice());
}
//修改订单价格
order.setFlowPrice(orderPrice);
order.setUpdatePrice(CurrencyUtil.sub(orderPrice, orderPriceDetailDTO.getOriginalPrice()));
//订单修改金额=使用订单原始金额-修改后金额
orderPriceDetailDTO.setUpdatePrice(CurrencyUtil.sub(orderPriceDetailDTO.getOriginalPrice(), orderPrice));
orderPriceDetailDTO.setFlowPrice(orderPrice);
orderPriceDetailDTO.setUpdatePrice(CurrencyUtil.sub(orderPrice, orderPriceDetailDTO.getOriginalPrice()));
order.setFlowPrice(orderPriceDetailDTO.getFlowPrice());
order.setPriceDetail(JSONUtil.toJsonStr(orderPriceDetailDTO));
List<OrderItem> orderItems = updateOrderItemPrice(order);
//这里如果直接赋予订单金额则累加可能会出现小数点最后无法累加回去所以用一个零时变量累加后将平台佣金赋予对象
PriceDetailDTO tempPriceDetail = new PriceDetailDTO();
tempPriceDetail.accumulationPriceDTO(orderItems.stream().map(OrderItem::getPriceDetailDTO).collect(Collectors.toList()));
orderPriceDetailDTO.setPlatFormCommission(tempPriceDetail.getPlatFormCommission());
orderPriceDetailDTO.countBill();
//修改订单
order.setPriceDetail(JSONUtil.toJsonStr(orderPriceDetailDTO));
orderService.updateById(order);
//修改子订单
updateOrderItemPrice(order);
return order;
}
@ -147,41 +129,44 @@ public class OrderPriceServiceImpl implements OrderPriceService {
*
* @param order 订单
*/
private List<OrderItem> updateOrderItemPrice(Order order) {
private void updateOrderItemPrice(Order order) {
List<OrderItem> orderItems = orderItemService.getByOrderSn(order.getSn());
//获取总数入欧最后一个则将其他orderitem的修改金额累加然后进行扣减
Integer index = orderItems.size();
Double countUpdatePrice = 0D;
for (OrderItem orderItem : orderItems) {
//获取订单货物价格信息
PriceDetailDTO priceDetailDTO = orderItem.getPriceDetailDTO();
if (priceDetailDTO.getOriginalPrice() == 0D) {
priceDetailDTO.setOriginalPrice(priceDetailDTO.getFlowPrice());
index--;
//如果是最后一个
if (index == 0) {
//记录修改金额
priceDetailDTO.setUpdatePrice(CurrencyUtil.sub(order.getUpdatePrice(), countUpdatePrice));
//修改订单货物金额
orderItem.setFlowPrice(priceDetailDTO.getFlowPrice());
orderItem.setUnitPrice(CurrencyUtil.div(priceDetailDTO.getFlowPrice(), orderItem.getNum()));
orderItem.setPriceDetail(JSONUtil.toJsonStr(priceDetailDTO));
} else {
//SKU占总订单 金额的百分比
Double priceFluctuationRatio = CurrencyUtil.div(priceDetailDTO.getOriginalPrice(), order.getPriceDetailDTO().getOriginalPrice(), 4);
//记录修改金额
priceDetailDTO.setUpdatePrice(CurrencyUtil.sub(order.getUpdatePrice(), priceFluctuationRatio));
//修改订单货物金额
orderItem.setFlowPrice(priceDetailDTO.getFlowPrice());
orderItem.setUnitPrice(CurrencyUtil.div(priceDetailDTO.getFlowPrice(), orderItem.getNum()));
orderItem.setPriceDetail(JSONUtil.toJsonStr(priceDetailDTO));
countUpdatePrice = CurrencyUtil.add(countUpdatePrice, priceDetailDTO.getUpdatePrice());
}
//SKU占总订单 金额的百分比
Double priceFluctuationRatio = CurrencyUtil.div(priceDetailDTO.getOriginalPrice(), order.getPriceDetailDTO().getOriginalPrice());
//计算修改后的订单货物金额
double flowPrice = CurrencyUtil.mul(order.getFlowPrice(), priceFluctuationRatio);
//记录修改金额
priceDetailDTO.setUpdatePrice(CurrencyUtil.sub(priceDetailDTO.getOriginalPrice(), flowPrice));
priceDetailDTO.setFlowPrice(flowPrice);
//计算平台佣金=交易金额*分类佣金比例/100
Double platFormCommission = CurrencyUtil.div(CurrencyUtil.mul(flowPrice, categoryService.getById(orderItem.getCategoryId()).getCommissionRate()), 100);
priceDetailDTO.setPlatFormCommission(platFormCommission);
//修改订单货物金额
orderItem.setFlowPrice(flowPrice);
orderItem.setUnitPrice(CurrencyUtil.div(flowPrice,orderItem.getNum()));
priceDetailDTO.countBill();
orderItem.setPriceDetail(JSONUtil.toJsonStr(priceDetailDTO));
orderItemService.update(orderItem, new LambdaUpdateWrapper<OrderItem>().eq(OrderItem::getId, orderItem.getId()));
}
return orderItems;
orderItemService.updateBatchById(orderItems);
}
}

View File

@ -87,6 +87,8 @@ public class StoreFlowServiceImpl extends ServiceImpl<StoreFlowMapper, StoreFlow
storeFlow.setMemberName(order.getMemberName());
storeFlow.setGoodsName(item.getGoodsName());
storeFlow.setOrderPromotionType(item.getPromotionType());
//计算平台佣金
storeFlow.setFinalPrice(item.getPriceDetailDTO().getFlowPrice());
storeFlow.setCommissionPrice(item.getPriceDetailDTO().getPlatFormCommission());

View File

@ -1,110 +0,0 @@
package cn.lili.modules.promotion.entity.dto;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 促销活动商品价格数据传输对象
*
* @author paulG
* @since 2020/8/20
**/
@Data
@NoArgsConstructor
public class GoodsSkuPromotionPriceDTO implements Serializable {
private static final long serialVersionUID = 3510264801983456306L;
@ApiModelProperty(value = "商品SkuId")
private String skuId;
@ApiModelProperty(value = "店铺Id")
private String storeId;
@ApiModelProperty(value = "分类path")
private String categoryPath;
@ApiModelProperty(value = "店铺分类id")
private String storeCategoryPath;
@ApiModelProperty(value = "数量")
private Integer number;
@ApiModelProperty(value = "重量")
private Double weight;
@ApiModelProperty(value = "总重量")
private Double totalWeight;
@ApiModelProperty(value = "单个商品原价")
private Double originalPrice;
@ApiModelProperty(value = "商品原价总价 = 商品原价 * 数量")
private Double totalOriginalPrice;
@ApiModelProperty(value = "单个商品积分购买数量")
private Double points;
@ApiModelProperty(value = "商品购买积分总数量 = 单个商品积分购买数量 * 数量")
private Long totalPoints;
@ApiModelProperty(value = "单个优惠的所占总优惠金额比例")
private Double discountPriceRate;
@ApiModelProperty(value = "单个优惠的金额")
private Double discountPrice;
@ApiModelProperty(value = "优惠的总金额 = 单个优惠的金额 * 数量")
private Double totalDiscountPrice;
@ApiModelProperty(value = "单个商品最终成交金额")
private Double finalePrice;
@ApiModelProperty(value = "商品最终成交的总金额 = 单个商品最终成交金额 * 数量")
private Double totalFinalePrice;
@ApiModelProperty(value = "分配到每个商品的优惠券金额")
private Double couponPrice;
@ApiModelProperty(value = "促销活动ID")
private String promotionId;
/**
* @see PromotionTypeEnum
*/
@ApiModelProperty(value = "促销活动类型")
private String promotionType;
/**
* 店铺商品促销信息集合
*/
@ApiModelProperty(value = "参与的促销活动")
private List<BasePromotion> joinPromotion;
public GoodsSkuPromotionPriceDTO(GoodsSku sku, Integer buyNum) {
this.setOriginalPrice(sku.getPrice());
this.setSkuId(sku.getId());
this.setNumber(buyNum);
this.setWeight(sku.getWeight());
this.setTotalWeight(sku.getWeight() != null ? CurrencyUtil.mul(sku.getWeight(), buyNum) : 0);
this.setCategoryPath(sku.getCategoryPath());
this.setStoreCategoryPath(sku.getStoreCategoryPath());
this.setStoreId(sku.getStoreId());
this.setDiscountPrice(0d);
this.setOriginalPrice(sku.getPrice());
this.setCouponPrice(0D);
this.setPoints(0d);
this.setTotalPoints(0L);
this.setFinalePrice(sku.getPrice());
this.setJoinPromotion(new ArrayList<>());
}
}

View File

@ -1,59 +0,0 @@
package cn.lili.modules.promotion.entity.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 促销价格数据传输对象
*
* @author paulG
* @since 2020/11/17
**/
@Data
public class PromotionPriceDTO {
/**
* 实际成交价格合计
*/
@ApiModelProperty(value = "商品原价格合计")
private Double totalOriginPrice;
/**
* 总需支付积分合计
*/
@ApiModelProperty(value = "总需支付积分合计")
private Double totalPoints;
/**
* 总优惠价格合计
*/
@ApiModelProperty(value = "总优惠价格合计")
private Double totalDiscountPrice;
/**
* 优惠券合计
*/
@ApiModelProperty(value = "优惠券合计")
private Double totalCouponPrice;
/**
* 最终结算金额 = totalOriginPrice - totalDiscountPrice - totalCouponPrice
*/
@ApiModelProperty(value = "最终结算金额")
private Double totalFinalePrice;
/**
* 店铺促销计算集合
*/
@ApiModelProperty(value = "店铺促销计算集合")
private List<StorePromotionPriceDTO> storePromotionPriceList;
/**
* 参与的促销活动
*/
@ApiModelProperty(value = "参与的促销活动")
private List<BasePromotion> joinPromotion;
}

View File

@ -1,29 +0,0 @@
package cn.lili.modules.promotion.entity.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 促销价格参数数据传输对象
*
* @author paulG
* @since 2020/11/17
**/
@Data
public class PromotionPriceParamDTO {
@ApiModelProperty(value = "商品SkuId")
private String skuId;
@ApiModelProperty(value = "购买数量")
private Integer num;
@ApiModelProperty(value = "拼团id 如果是拼团购买 此值为拼团活动id当pintuanId为空则表示普通购买或者拼团商品单独购买")
private String pintuanId;
@ApiModelProperty(value = "砍价ID")
private String kanjiaId;
@ApiModelProperty(value = "积分ID")
private String pointsId;
}

View File

@ -1,108 +0,0 @@
package cn.lili.modules.promotion.entity.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 店铺促销计算数据传输对象
*
* @author paulG
* @since 2020/11/17
**/
@Data
public class StorePromotionPriceDTO {
/**
* 店铺ID
*/
@ApiModelProperty(value = "店铺ID")
private String storeId;
/**
* 是否免运费
*/
@ApiModelProperty(value = "是否免运费")
private Boolean isFreeFreight;
/**
* 店铺商品数量合计
*/
@ApiModelProperty(value = "店铺商品数量合计")
private Integer totalNum;
/**
* 店铺商品重量合计
*/
@ApiModelProperty(value = "店铺商品重量合计")
private Double totalWeight;
/**
* 店铺商品原价格合计
*/
@ApiModelProperty(value = "店铺商品原价格合计")
private Double totalOriginPrice;
/**
* 店铺商品需支付积分合计
*/
@ApiModelProperty(value = "店铺商品需支付积分合计")
private Double totalPoints;
/**
* 店铺商品最终成交的总金额
*/
@ApiModelProperty(value = "店铺商品最终成交的总金额")
private Double totalFinalePrice;
/**
* 店铺参与促销商品价格合计
*/
@ApiModelProperty(value = "店铺参与满优惠商品价格合计")
private Double totalJoinDiscountPrice;
/**
* 店铺未参与促销商品价格合计
*/
@ApiModelProperty(value = "店铺未参与满优惠商品价格合计")
private Double totalNotJoinDiscountPrice;
/**
* 店铺商品优惠价格合计
*/
@ApiModelProperty(value = "店铺商品优惠价格合计")
private Double totalDiscountPrice;
/**
* 优惠券合计
*/
@ApiModelProperty(value = "优惠券合计")
private Double totalCouponPrice;
/**
* 店铺商品促销信息集合
*/
@ApiModelProperty(value = "店铺商品促销信息集合")
private List<GoodsSkuPromotionPriceDTO> goodsSkuPromotionPriceList;
/**
* 参与的促销活动
*/
@ApiModelProperty(value = "参与的促销活动")
private List<BasePromotion> joinPromotion;
//=========distribution==========
@ApiModelProperty(value = "1级单品分销返现支出")
private Double distributionCommission1;
@ApiModelProperty(value = "2级单品分销返现支出")
private Double distributionCommission2;
@ApiModelProperty(value = "平台收取交易佣金")
private Double platFormCommission;
//=========end distribution==========
}

View File

@ -1,28 +0,0 @@
package cn.lili.modules.promotion.service;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.dto.PromotionPriceDTO;
import cn.lili.modules.promotion.entity.dto.PromotionPriceParamDTO;
import java.util.List;
/**
* 促销计算
*
* @author paulG
* @since 2020/8/21
**/
public interface PromotionPriceService {
/**
* 计算商品当前所参与的促销活动的价格
*
* @param tradeSkuList 促销计算参数
* @param memberCouponList 使用的优惠券
* @param cartTypeEnum 购物车类型
* @return 促销计算结果
*/
PromotionPriceDTO calculationPromotionPrice(List<PromotionPriceParamDTO> tradeSkuList, List<MemberCoupon> memberCouponList, CartTypeEnum cartTypeEnum);
}

View File

@ -8,8 +8,6 @@ import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.DateUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.distribution.entity.dos.DistributionGoods;
import cn.lili.modules.distribution.service.DistributionGoodsService;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
@ -84,11 +82,6 @@ public class PromotionGoodsServiceImpl extends ServiceImpl<PromotionGoodsMapper,
*/
@Autowired
private PointsGoodsService pointsGoodsService;
/**
* 分销商品
*/
@Autowired
private DistributionGoodsService distributionGoodsService;
@Override
public PromotionGoods findByPromotion(String promotionId, String skuId) {
@ -122,11 +115,6 @@ public class PromotionGoodsServiceImpl extends ServiceImpl<PromotionGoodsMapper,
//下一次更新时间
cartSkuVO.setUpdatePromotionTime(date);
}
//分销商品
DistributionGoods distributionGoods = distributionGoodsService.distributionGoodsVOBySkuId(cartSkuVO.getGoodsSku().getId());
if (distributionGoods != null) {
cartSkuVO.setDistributionGoods(distributionGoods);
}
}
/**
@ -136,7 +124,12 @@ public class PromotionGoodsServiceImpl extends ServiceImpl<PromotionGoodsMapper,
*/
@Override
public void getCartSkuPromotion(CartSkuVO cartSkuVO) {
updatePromotion(cartSkuVO);
Date date = DateUtil.getCurrentDayEndTime();
LambdaQueryWrapper<PromotionGoods> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PromotionGoods::getSkuId, cartSkuVO.getGoodsSku().getId())
.eq(PromotionGoods::getPromotionStatus, PromotionStatusEnum.START.name())
@ -154,7 +147,7 @@ public class PromotionGoodsServiceImpl extends ServiceImpl<PromotionGoodsMapper,
query.addCriteria(Criteria.where("startTime").lte(date));
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
for (FullDiscountVO fullDiscountVO : fullDiscountVOS) {
if (fullDiscountVO.getPromotionGoodsList() == null && fullDiscountVO.getNumber() == -1 &&
if (fullDiscountVO.getPromotionGoodsList() == null &&
cartSkuVO.getStoreId().equals(fullDiscountVO.getStoreId())) {
PromotionGoods p = new PromotionGoods(cartSkuVO.getGoodsSku());
p.setPromotionId(fullDiscountVO.getId());

View File

@ -1,649 +0,0 @@
package cn.lili.modules.promotion.serviceimpl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.promotion.entity.dos.*;
import cn.lili.modules.promotion.entity.dto.*;
import cn.lili.modules.promotion.entity.enums.*;
import cn.lili.modules.promotion.entity.vos.PointsGoodsVO;
import cn.lili.modules.promotion.service.*;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsSearchService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 促销价格计算业务层实现
*
* @author paulG
* @since 2020/8/21
**/
@Service
@Slf4j
public class PromotionPriceServiceImpl implements PromotionPriceService {
/**
* ES商品
*/
@Autowired
private EsGoodsSearchService goodsSearchService;
/**
* 秒杀活动申请
*/
@Autowired
private SeckillApplyService seckillApplyService;
/**
* 促销商品
*/
@Autowired
private PromotionGoodsService promotionGoodsService;
/**
* 规格商品
*/
@Autowired
private GoodsSkuService goodsSkuService;
/**
* 积分商品
*/
@Autowired
private PointsGoodsService pointsGoodsService;
/**
* 积分商品
*/
@Autowired
private KanjiaActivityGoodsService kanjiaActivityGoodsService;
@Override
public PromotionPriceDTO calculationPromotionPrice(List<PromotionPriceParamDTO> tradeSkuList, List<MemberCoupon> memberCouponList, CartTypeEnum cartTypeEnum) {
List<GoodsSkuPromotionPriceDTO> priceDTOList = new ArrayList<>();
//拆分出SkuId列表
List<String> skuIds = tradeSkuList.parallelStream().map(PromotionPriceParamDTO::getSkuId).collect(Collectors.toList());
//参与计算的ES商品SKU及其促销信息列表
List<EsGoodsIndex> esGoodsSkus = goodsSearchService.getEsGoodsBySkuIds(skuIds);
//判断交易类型进行不同的处理
if (cartTypeEnum.equals(CartTypeEnum.POINTS)) {
priceDTOList = this.pointGoodsPromotion(tradeSkuList);
} else if (cartTypeEnum.equals(CartTypeEnum.KANJIA)) {
priceDTOList = this.kanjiaPromotion(tradeSkuList);
} else {
//参与计算的缓存中的商品SKU列表
List<GoodsSku> goodsSkus = goodsSkuService.getGoodsSkuByIdFromCache(skuIds);
//单品商品SKU促销计算结果列表
priceDTOList = this.packageGoodsSkuPromotionPrice(tradeSkuList, esGoodsSkus, goodsSkus);
}
//获取商品促销价格DTO列表
List<StorePromotionPriceDTO> storePromotionPriceList = new ArrayList<>();
//计算优惠券金额
Double couponTotalPrice = 0.0;
//将使用的优惠券根据店铺分类
Map<String, List<MemberCoupon>> couponCollect = memberCouponList.parallelStream().collect(Collectors.groupingBy(MemberCoupon::getStoreId));
//获取店铺优惠券金额
this.getStorePromotionPrice(storePromotionPriceList, priceDTOList, esGoodsSkus, couponCollect, couponTotalPrice);
//获取平台优惠金额
this.getPlatformPromotionPrice(couponCollect, storePromotionPriceList, priceDTOList, couponTotalPrice);
//计算最终结算金额返回数据
return this.getPromotionPriceDTO(storePromotionPriceList, couponTotalPrice);
}
/**
* 获取促销金额DTO
*
* @param storePromotionPriceList 店铺促销列表
* @param couponTotalPrice 优惠券优惠金额
* @return 促销金额DTO
*/
private PromotionPriceDTO getPromotionPriceDTO(List<StorePromotionPriceDTO> storePromotionPriceList, Double couponTotalPrice) {
PromotionPriceDTO promotionPrice = new PromotionPriceDTO();
promotionPrice.setStorePromotionPriceList(storePromotionPriceList);
promotionPrice.setTotalCouponPrice(couponTotalPrice);
promotionPrice.setTotalOriginPrice(storePromotionPriceList.parallelStream().mapToDouble(StorePromotionPriceDTO::getTotalOriginPrice).sum());
promotionPrice.setTotalPoints(storePromotionPriceList.parallelStream().mapToDouble(StorePromotionPriceDTO::getTotalPoints).sum());
promotionPrice.setTotalDiscountPrice(storePromotionPriceList.parallelStream().mapToDouble(StorePromotionPriceDTO::getTotalDiscountPrice).sum());
//最终结算金额 = 商品原价格合计 - 总优惠价格合计 - 优惠券合计
double totalFinalePrice = CurrencyUtil.sub(CurrencyUtil.sub(promotionPrice.getTotalOriginPrice(), promotionPrice.getTotalDiscountPrice()), promotionPrice.getTotalCouponPrice());
promotionPrice.setTotalFinalePrice(totalFinalePrice);
return promotionPrice;
}
/**
* 获取平台优惠券促销金额
*
* @param couponCollect 优惠券列表
* @param storePromotionPriceList 店铺促销列表
* @param priceDTOList 商品促销DTO列表
* @param couponTotalPrice 优惠券金额合计
*/
private void getPlatformPromotionPrice(Map<String, List<MemberCoupon>> couponCollect, List<StorePromotionPriceDTO> storePromotionPriceList, List<GoodsSkuPromotionPriceDTO> priceDTOList, Double couponTotalPrice) {
//获取平台优惠券
List<MemberCoupon> platformCoupons = couponCollect.get("platform");
if (platformCoupons != null && !platformCoupons.isEmpty()) {
//计算平台优惠券活动
couponTotalPrice = CurrencyUtil.add(couponTotalPrice, this.calculationCoupon(platformCoupons, priceDTOList));
for (StorePromotionPriceDTO storePromotionPriceDTO : storePromotionPriceList) {
Double couponPrice = storePromotionPriceDTO.getGoodsSkuPromotionPriceList().parallelStream().mapToDouble(GoodsSkuPromotionPriceDTO::getCouponPrice).sum();
storePromotionPriceDTO.setTotalCouponPrice(couponPrice);
}
}
}
/**
* 获取店铺优惠券促销金额
*
* @param storePromotionPriceList 店铺促销金额列表
* @param priceDTOList 商品促销金额DTO列表
* @param esGoodsSkus 商品索引SKU
* @param couponCollect 会员优惠券列表
* @param couponTotalPrice 优惠券金额合计
*/
private void getStorePromotionPrice(List<StorePromotionPriceDTO> storePromotionPriceList, List<GoodsSkuPromotionPriceDTO> priceDTOList,
List<EsGoodsIndex> esGoodsSkus, Map<String, List<MemberCoupon>> couponCollect, Double couponTotalPrice) {
//根据卖家分组商品信息
Map<String, List<GoodsSkuPromotionPriceDTO>> storeCollect = priceDTOList.parallelStream().collect(Collectors.groupingBy(GoodsSkuPromotionPriceDTO::getStoreId));
for (Map.Entry<String, List<GoodsSkuPromotionPriceDTO>> entry : storeCollect.entrySet()) {
StorePromotionPriceDTO storePromotionPrice = new StorePromotionPriceDTO();
storePromotionPrice.setStoreId(entry.getKey());
storePromotionPrice.setGoodsSkuPromotionPriceList(entry.getValue());
Optional<GoodsSkuPromotionPriceDTO> firstFullDiscount = entry.getValue().parallelStream().filter(i -> i.getPromotionId() != null && i.getPromotionType().equals(PromotionTypeEnum.FULL_DISCOUNT.name())).findFirst();
if (firstFullDiscount.isPresent()) {
String promotionId = firstFullDiscount.get().getPromotionId();
//是否存在满优惠促销活动
String esPromotionFullDiscountKey = PromotionTypeEnum.FULL_DISCOUNT + "-" + promotionId;
if (CharSequenceUtil.isNotEmpty(promotionId)) {
FullDiscount fullDiscount = null;
for (EsGoodsIndex skus : esGoodsSkus) {
//检查是否为正在进行的满优惠活动
if (skus.getPromotionMap() != null && skus.getPromotionMap().containsKey(esPromotionFullDiscountKey)) {
fullDiscount = (FullDiscount) skus.getPromotionMap().get(esPromotionFullDiscountKey);
break;
}
}
if (fullDiscount != null) {
//计算满优惠活动
this.calculationFullDiscount(fullDiscount, storePromotionPrice);
}
}
}
//获取店铺优惠券
List<MemberCoupon> storeCoupons = couponCollect.get(entry.getKey());
if (storeCoupons != null && !storeCoupons.isEmpty()) {
//计算店铺优惠券活动
couponTotalPrice = this.calculationCoupon(storeCoupons, entry.getValue());
storePromotionPrice.setTotalCouponPrice(couponTotalPrice);
storePromotionPrice.setTotalFinalePrice(storePromotionPrice.getGoodsSkuPromotionPriceList().parallelStream().mapToDouble(GoodsSkuPromotionPriceDTO::getTotalFinalePrice).sum());
}
//累加除商品促销信息之外的信息
this.accumulationGoodsSkuPromotionOther(entry.getValue(), storePromotionPrice);
storePromotionPriceList.add(storePromotionPrice);
}
}
/**
* 单品SKU的促销计算
*
* @param tradeSkuList 交易商品信息列表
* @param esGoodsSkus 参与计算的ES商品SKU及其促销信息列表
* @param goodsSkus 参与计算的缓存中的商品SKU列表
* @return 单品SKU促销计算结果列表
*/
private List<GoodsSkuPromotionPriceDTO> packageGoodsSkuPromotionPrice(List<PromotionPriceParamDTO> tradeSkuList, List<EsGoodsIndex> esGoodsSkus, List<GoodsSku> goodsSkus) {
List<GoodsSkuPromotionPriceDTO> priceDTOList = new ArrayList<>();
for (GoodsSku skus : goodsSkus) {
List<EsGoodsIndex> collect = esGoodsSkus.parallelStream().filter(i -> i != null && i.getId().equals(skus.getId())).collect(Collectors.toList());
if (!collect.isEmpty()) {
EsGoodsIndex esGoodsIndex = collect.get(0);
//找出当前商品相应的结算参数
PromotionPriceParamDTO promotionPriceParamDTO = tradeSkuList.parallelStream().filter(i -> i.getSkuId().equals(skus.getId())).findFirst().orElse(new PromotionPriceParamDTO());
GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice = new GoodsSkuPromotionPriceDTO(skus, promotionPriceParamDTO.getNum());
//商品原价总价 = 商品原价 * 数量
goodsSkuPromotionPrice.setTotalOriginalPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getOriginalPrice(), promotionPriceParamDTO.getNum()));
//获取当前商品所有参加的促销活动
Map<String, Object> promotionMap = esGoodsIndex.getPromotionMap();
//如果商品促销列表存在促销活动
this.calculationPromotionMap(promotionMap, goodsSkuPromotionPrice, esGoodsIndex, promotionPriceParamDTO);
goodsSkuPromotionPrice.setTotalOriginalPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getOriginalPrice(), goodsSkuPromotionPrice.getNumber()));
goodsSkuPromotionPrice.setTotalDiscountPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getDiscountPrice(), goodsSkuPromotionPrice.getNumber()));
goodsSkuPromotionPrice.setTotalFinalePrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getFinalePrice(), goodsSkuPromotionPrice.getNumber()));
priceDTOList.add(goodsSkuPromotionPrice);
}
}
return priceDTOList;
}
/**
* 计算积分商品
* 积分商品的购买金额是0
* 1.根据SkuId去查询积分商品Mongo
* 2.计算积分商品的优惠信息
*
* @param tradeSkuList 交易商品促销金额列表
* @return 计算结果
*/
private List<GoodsSkuPromotionPriceDTO> pointGoodsPromotion(List<PromotionPriceParamDTO> tradeSkuList) {
List<GoodsSkuPromotionPriceDTO> priceDTOList = new ArrayList<>();
//获取积分商品SkuId
String skuId = tradeSkuList.get(0).getSkuId();
//获取积分商品VO
PointsGoodsVO pointsGoodsVO = pointsGoodsService.getPointsGoodsVOByMongo(skuId);
//参与计算的缓存中的商品SKU列表
GoodsSku goodsSku = pointsGoodsVO.getGoodsSku();
//获取商品促销金额
GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice = new GoodsSkuPromotionPriceDTO(goodsSku, tradeSkuList.get(0).getNum());
//计算商品原价=原价*数量
goodsSkuPromotionPrice.setTotalOriginalPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getOriginalPrice(), goodsSkuPromotionPrice.getNumber()));
//计算商品积分数量=兑换积分*数量
goodsSkuPromotionPrice.setTotalPoints(pointsGoodsVO.getPoints() * Convert.toLong(goodsSkuPromotionPrice.getNumber()));
//优惠金额=商品原价*数量
goodsSkuPromotionPrice.setTotalDiscountPrice(CurrencyUtil.mul(goodsSkuPromotionPrice.getOriginalPrice(), goodsSkuPromotionPrice.getNumber()));
//购买价格=积分商品价格为 0
goodsSkuPromotionPrice.setTotalFinalePrice(0.0);
priceDTOList.add(goodsSkuPromotionPrice);
return priceDTOList;
}
/**
* 计算砍价商品
* 砍价商品只能购买一件
* 1.根据SkuId去查询积分商品Mongo
* 2.计算积分商品的优惠信息
*
* @param tradeSkuList 交易商品促销金额列表
* @return 计算结果
*/
private List<GoodsSkuPromotionPriceDTO> kanjiaPromotion(List<PromotionPriceParamDTO> tradeSkuList) {
List<GoodsSkuPromotionPriceDTO> priceDTOList = new ArrayList<>();
//获取积分商品SkuId
String skuId = tradeSkuList.get(0).getSkuId();
//获取积分商品VO
KanjiaActivityGoodsDTO kanjiaActivityGoodsDTO = kanjiaActivityGoodsService.getKanJiaGoodsBySku(skuId);
//参与计算的缓存中的商品SKU列表
GoodsSku goodsSku = kanjiaActivityGoodsDTO.getGoodsSku();
GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice = new GoodsSkuPromotionPriceDTO(goodsSku, tradeSkuList.get(0).getNum());
//优惠金额=商品原价-购买价格
goodsSkuPromotionPrice.setTotalDiscountPrice(CurrencyUtil.sub(goodsSkuPromotionPrice.getOriginalPrice(), kanjiaActivityGoodsDTO.getPurchasePrice()));
//购买价格=砍价成交金额
goodsSkuPromotionPrice.setTotalFinalePrice(kanjiaActivityGoodsDTO.getPurchasePrice());
//原价
goodsSkuPromotionPrice.setTotalOriginalPrice(goodsSkuPromotionPrice.getOriginalPrice());
priceDTOList.add(goodsSkuPromotionPrice);
return priceDTOList;
}
/**
* 促销计算(秒杀活动拼团满优惠活动砍价)
*
* @param promotionMap 当前商品所有参加的促销活动
* @param goodsSkuPromotionPrice 商品SKU促销计算信息
* @param esGoodsIndex ES商品信息
* @param promotionPriceParamDTO 拼团id标示是否计算拼团活动
*/
private void calculationPromotionMap(Map<String, Object> promotionMap, GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice, EsGoodsIndex esGoodsIndex, PromotionPriceParamDTO promotionPriceParamDTO) {
//未参加促销则直接返回
if (promotionMap == null || promotionMap.isEmpty()) {
return;
}
//检查当前商品是否存在满优惠活动
Optional<String> existFullDiscount = promotionMap.keySet().parallelStream().filter(i -> i.contains(PromotionTypeEnum.FULL_DISCOUNT.name())).findFirst();
if (existFullDiscount.isPresent()) {
FullDiscount discount = (FullDiscount) promotionMap.get(existFullDiscount.get());
goodsSkuPromotionPrice.setPromotionId(discount.getId());
goodsSkuPromotionPrice.setPromotionType(PromotionTypeEnum.FULL_DISCOUNT.name());
}
//检查当前商品是否存在秒杀活动活动
Optional<String> existSeckill = promotionMap.keySet().parallelStream().filter(i -> i.contains(PromotionTypeEnum.SECKILL.name())).findFirst();
if (existSeckill.isPresent()) {
Seckill seckill = (Seckill) promotionMap.get(existSeckill.get());
//计算秒杀活动促销
this.calculationSeckill(seckill, goodsSkuPromotionPrice);
seckill.setPromotionName(PromotionTypeEnum.SECKILL.name());
goodsSkuPromotionPrice.getJoinPromotion().add(seckill);
}
//检查当前商品是否存在砍价活动
if (promotionPriceParamDTO.getKanjiaId() != null) {
Optional<String> existKanjia = promotionMap.keySet().parallelStream().filter(i -> i.contains(PromotionTypeEnum.KANJIA.name())).findFirst();
if (existKanjia.isPresent()) {
KanjiaActivityGoods kanjiaActivityGoods = (KanjiaActivityGoods) promotionMap.get(existKanjia.get());
//优惠的总价格 = 原商品总价 - 优惠后的商品总价
double discountPrice = CurrencyUtil.sub(kanjiaActivityGoods.getOriginalPrice(), kanjiaActivityGoods.getPurchasePrice());
goodsSkuPromotionPrice.setDiscountPrice(discountPrice);
goodsSkuPromotionPrice.setFinalePrice(kanjiaActivityGoods.getPurchasePrice());
goodsSkuPromotionPrice.getJoinPromotion().add(kanjiaActivityGoods);
}
}
//检查当前商品是否存在拼团活动
else if (promotionPriceParamDTO.getPintuanId() != null) {
Optional<String> existPintuan = promotionMap.keySet().parallelStream().filter(i -> i.contains(PromotionTypeEnum.PINTUAN.name())).findFirst();
if (existPintuan.isPresent()) {
Pintuan pintuan = (Pintuan) promotionMap.get(existPintuan.get());
//优惠的总价格 = 原商品总价 - 优惠后的商品总价
double discountPrice = CurrencyUtil.sub(goodsSkuPromotionPrice.getOriginalPrice(), esGoodsIndex.getPromotionPrice());
goodsSkuPromotionPrice.setDiscountPrice(discountPrice);
goodsSkuPromotionPrice.setFinalePrice(esGoodsIndex.getPromotionPrice());
pintuan.setPromotionName(PromotionTypeEnum.PINTUAN.name());
goodsSkuPromotionPrice.getJoinPromotion().add(pintuan);
}
}
//检查当前商品是否存在积分商品活动
else if (promotionPriceParamDTO.getPointsId() != null) {
Optional<String> existPointsGoods = promotionMap.keySet().parallelStream().filter(i -> i.contains(PromotionTypeEnum.POINTS_GOODS.name())).findFirst();
if (existPointsGoods.isPresent()) {
PointsGoods pointsGoods = (PointsGoods) promotionMap.get(existPointsGoods.get());
goodsSkuPromotionPrice.setPoints(pointsGoods.getPoints().doubleValue());
goodsSkuPromotionPrice.setDiscountPrice(goodsSkuPromotionPrice.getOriginalPrice());
goodsSkuPromotionPrice.setFinalePrice(0.0);
pointsGoods.setPromotionName(pointsGoods.getPromotionName());
goodsSkuPromotionPrice.getJoinPromotion().add(pointsGoods);
}
}
}
/**
* 优惠券计算
*
* @param coupons 使用的优惠券列表
* @param list 商品促销价格信息列表
* @return 优惠券总金额
*/
private double calculationCoupon(List<MemberCoupon> coupons, List<GoodsSkuPromotionPriceDTO> list) {
double couponTotalPrice = 0;
for (MemberCoupon coupon : coupons) {
if (CouponScopeTypeEnum.PORTION_GOODS.name().equals(coupon.getScopeType())) {
String[] scopeSkuIds = coupon.getScopeId().split(",");
List<GoodsSkuPromotionPriceDTO> conformCollect = list.parallelStream().filter(i -> Arrays.asList(scopeSkuIds).contains(i.getSkuId())).collect(Collectors.toList());
//单个优惠券计算
couponTotalPrice = this.calculationSingleCoupon(coupon, conformCollect);
} else if (CouponScopeTypeEnum.ALL.name().equals(coupon.getScopeType())) {
//单个优惠券计算
couponTotalPrice = this.calculationSingleCoupon(coupon, list);
} else if (CouponScopeTypeEnum.PORTION_GOODS_CATEGORY.name().equals(coupon.getScopeType()) || CouponScopeTypeEnum.PORTION_SHOP_CATEGORY.name().equals(coupon.getScopeType())) {
List<GoodsSkuPromotionPriceDTO> collect = this.filterCoupon(coupon, list);
//单个优惠券计算
couponTotalPrice = this.calculationSingleCoupon(coupon, collect);
}
}
return couponTotalPrice;
}
/**
* 过滤优惠券范围内分类 商品sku促销价格信息列表
*
* @param coupon 会员优惠券信息
* @param list 过滤的列表
* @return 过滤后的商品价格信息列表
*/
private List<GoodsSkuPromotionPriceDTO> filterCoupon(MemberCoupon coupon, List<GoodsSkuPromotionPriceDTO> list) {
String[] scopeCategories = coupon.getScopeId().split(",");
//过滤优惠券范围内分类 商品sku促销价格信息列表
return list.parallelStream().filter(i -> {
String[] split;
if (CouponScopeTypeEnum.PORTION_GOODS_CATEGORY.name().equals(coupon.getScopeType())) {
split = i.getCategoryPath().split("\\|");
} else {
split = i.getStoreCategoryPath().split("\\|");
}
for (String s : split) {
if (Arrays.asList(scopeCategories).contains(s)) {
return true;
}
}
return false;
}).collect(Collectors.toList());
}
/**
* 单个优惠券计算
*
* @param coupon 使用的优惠券信息
* @param conformCollect 商品促销价格信息列表
* @return 优惠券总金额
*/
private double calculationSingleCoupon(MemberCoupon coupon, List<GoodsSkuPromotionPriceDTO> conformCollect) {
double couponTotalPrice = 0;
//合计优惠券范围内的所有商品的原价
double totalPrice = conformCollect.parallelStream().mapToDouble(GoodsSkuPromotionPriceDTO::getTotalFinalePrice).sum();
//根据优惠券优惠类型判断是否满足条件
if (CouponTypeEnum.PRICE.name().equals(coupon.getCouponType()) && coupon.getConsumeThreshold() <= totalPrice) {
couponTotalPrice = CurrencyUtil.add(couponTotalPrice, coupon.getPrice());
} else if (CouponTypeEnum.DISCOUNT.name().equals(coupon.getCouponType())) {
double fullRate = coupon.getDiscount() >= 10 ? coupon.getDiscount() / 100 : coupon.getDiscount() / 10;
double discountRatePrice = CurrencyUtil.sub(totalPrice, CurrencyUtil.mul(totalPrice, fullRate));
couponTotalPrice = CurrencyUtil.add(couponTotalPrice, discountRatePrice);
}
//分配到每个商品的优惠券金额
for (GoodsSkuPromotionPriceDTO goodsSkuPromotionPriceDTO : conformCollect) {
double rate = CurrencyUtil.div(goodsSkuPromotionPriceDTO.getTotalFinalePrice(), totalPrice, 5);
double distributeCouponPrice = CurrencyUtil.div(CurrencyUtil.mul(couponTotalPrice, rate), goodsSkuPromotionPriceDTO.getNumber());
if (goodsSkuPromotionPriceDTO.getFinalePrice() != null) {
goodsSkuPromotionPriceDTO.setFinalePrice(CurrencyUtil.sub(goodsSkuPromotionPriceDTO.getFinalePrice(), distributeCouponPrice));
} else {
goodsSkuPromotionPriceDTO.setFinalePrice(CurrencyUtil.sub(goodsSkuPromotionPriceDTO.getOriginalPrice(), distributeCouponPrice));
}
goodsSkuPromotionPriceDTO.setCouponPrice(CurrencyUtil.mul(distributeCouponPrice, goodsSkuPromotionPriceDTO.getNumber()));
goodsSkuPromotionPriceDTO.setTotalFinalePrice(CurrencyUtil.mul(goodsSkuPromotionPriceDTO.getFinalePrice(), goodsSkuPromotionPriceDTO.getNumber()));
BasePromotion basePromotion = new BasePromotion();
basePromotion.setId(coupon.getId());
if (coupon.getIsPlatform() != null && Boolean.TRUE.equals(coupon.getIsPlatform())) {
basePromotion.setPromotionName("platformCoupon");
} else {
basePromotion.setPromotionName("storeCoupon");
}
basePromotion.setStartTime(coupon.getStartTime());
basePromotion.setEndTime(coupon.getEndTime());
goodsSkuPromotionPriceDTO.getJoinPromotion().add(basePromotion);
}
return couponTotalPrice;
}
/**
* 计算秒杀活动
*
* @param seckill 秒杀活动信息
* @param promotionPrice 商品SKU的计算促销信息
*/
private void calculationSeckill(Seckill seckill, GoodsSkuPromotionPriceDTO promotionPrice) {
//检查 活动有效时间 活动有效状态
if (checkPromotionValidTime(seckill.getStartTime(), seckill.getEndTime(), PromotionTypeEnum.SECKILL.name(), seckill.getId()) &&
seckill.getPromotionStatus().equals(PromotionStatusEnum.START.name())) {
LambdaQueryWrapper<SeckillApply> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SeckillApply::getSkuId, promotionPrice.getSkuId()).eq(SeckillApply::getSeckillId, seckill.getId());
SeckillApply seckillApply = seckillApplyService.getOne(queryWrapper);
if (seckillApply.getPromotionApplyStatus().equals(PromotionApplyStatusEnum.PASS.name())) {
Integer quantity = promotionGoodsService.getPromotionGoodsStock(PromotionTypeEnum.SECKILL, seckill.getId(), seckillApply.getSkuId());
int seckillTotalSaleNum = seckillApply.getSalesNum() + promotionPrice.getNumber();
if (quantity >= seckillTotalSaleNum) {
//优惠的价格 = 原商品价 - 优惠后的商品价
double discountPrice = CurrencyUtil.sub(promotionPrice.getOriginalPrice(), seckillApply.getPrice());
promotionPrice.setDiscountPrice(discountPrice);
promotionPrice.setFinalePrice(seckillApply.getPrice());
} else {
log.error("购买数量超出秒杀活动剩余数量");
}
}
}
}
/**
* 计算满优惠促销
*
* @param fullDiscount 满优惠信息
* @param storePromotionPriceDTO 店铺促销计算信息
*/
private void calculationFullDiscount(FullDiscount fullDiscount, StorePromotionPriceDTO storePromotionPriceDTO) {
//检查 活动有效时间 活动有效状态
if (checkPromotionValidTime(fullDiscount.getStartTime(), fullDiscount.getEndTime(), PromotionTypeEnum.FULL_DISCOUNT.name(), fullDiscount.getId()) && fullDiscount.getPromotionStatus().equals(PromotionStatusEnum.START.name())) {
//是否免运费
if (Boolean.TRUE.equals(fullDiscount.getIsFreeFreight())) {
storePromotionPriceDTO.setIsFreeFreight(true);
}
List<GoodsSkuPromotionPriceDTO> goodsSkuPromotionPriceList = storePromotionPriceDTO.getGoodsSkuPromotionPriceList();
//参与活动的商品总数量
this.accumulationGoodsSkuPromotionPrice(goodsSkuPromotionPriceList, storePromotionPriceDTO);
//参与优惠商品的成交金额是否满足满优惠条件
if (fullDiscount.getFullMoney() <= storePromotionPriceDTO.getTotalJoinDiscountPrice()) {
//判断是否为满减反之则为满折扣
if (Boolean.TRUE.equals(fullDiscount.getIsFullMinus())) {
//优惠总金额 = 原优惠总金额 + 满优惠减免的金额
storePromotionPriceDTO.setTotalDiscountPrice(CurrencyUtil.add(storePromotionPriceDTO.getTotalDiscountPrice(), fullDiscount.getFullMinus()));
} else if (Boolean.TRUE.equals(fullDiscount.getIsFullRate())) {
double fullRate = fullDiscount.getFullRate() >= 10 ? fullDiscount.getFullRate() / 100 : fullDiscount.getFullRate() / 10;
//满优惠减免的金额 = 原参与优惠的总金额 * 满优惠折扣百分比
double discountPrice = CurrencyUtil.sub(storePromotionPriceDTO.getTotalJoinDiscountPrice(), CurrencyUtil.mul(storePromotionPriceDTO.getTotalJoinDiscountPrice(), fullRate));
//优惠总金额 = 原优惠总金额 + 满优惠减免的金额
storePromotionPriceDTO.setTotalDiscountPrice(CurrencyUtil.add(storePromotionPriceDTO.getTotalDiscountPrice(), discountPrice));
}
}
//将计算完的促销价格平均分配到参与促销的每个商品上去
this.distributeStoreFullDiscountPromotionPrice(storePromotionPriceDTO, fullDiscount);
}
}
/**
* 计算累加促销活动商品价格
*
* @param goodsSkuPromotionPriceList 商品促销价格信息列表
* @param storePromotionPriceDTO 店铺促销计算信息
*/
private void accumulationGoodsSkuPromotionPrice(List<GoodsSkuPromotionPriceDTO> goodsSkuPromotionPriceList, StorePromotionPriceDTO storePromotionPriceDTO) {
//数据累加
double totalNotJoinDiscountPrice = 0;
double totalJoinDiscountPrice = 0;
double totalDiscountPrice = 0;
for (GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice : goodsSkuPromotionPriceList) {
if (goodsSkuPromotionPrice.getPromotionId() != null && goodsSkuPromotionPrice.getPromotionType().equals(PromotionTypeEnum.FULL_DISCOUNT.name())) {
totalJoinDiscountPrice = CurrencyUtil.add(totalJoinDiscountPrice, goodsSkuPromotionPrice.getTotalFinalePrice());
totalDiscountPrice = CurrencyUtil.add(totalDiscountPrice, goodsSkuPromotionPrice.getDiscountPrice());
} else {
totalNotJoinDiscountPrice = CurrencyUtil.add(totalNotJoinDiscountPrice, goodsSkuPromotionPrice.getFinalePrice());
}
}
storePromotionPriceDTO.setTotalDiscountPrice(totalDiscountPrice);
storePromotionPriceDTO.setTotalJoinDiscountPrice(totalJoinDiscountPrice);
storePromotionPriceDTO.setTotalNotJoinDiscountPrice(totalNotJoinDiscountPrice);
for (GoodsSkuPromotionPriceDTO goodsSkuPromotionPriceDTO : goodsSkuPromotionPriceList) {
double fullDiscountRate = CurrencyUtil.div(goodsSkuPromotionPriceDTO.getTotalFinalePrice(), totalJoinDiscountPrice);
goodsSkuPromotionPriceDTO.setDiscountPriceRate(fullDiscountRate);
}
}
/**
* 计算累加促销活动商品价格其他信息
*
* @param goodsSkuPromotionPriceList 商品促销价格信息列表
* @param storePromotionPriceDTO 店铺促销计算信息
*/
private void accumulationGoodsSkuPromotionOther(List<GoodsSkuPromotionPriceDTO> goodsSkuPromotionPriceList, StorePromotionPriceDTO storePromotionPriceDTO) {
double totalWeight = 0;
double totalNum = 0D;
double totalOriginPrice = 0;
double totalDiscountPrice = 0;
double totalPoints = 0;
for (GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice : goodsSkuPromotionPriceList) {
totalWeight = CurrencyUtil.add(totalWeight, goodsSkuPromotionPrice.getWeight());
totalNum = CurrencyUtil.add(totalNum, goodsSkuPromotionPrice.getNumber());
totalPoints = CurrencyUtil.add(totalPoints, goodsSkuPromotionPrice.getTotalPoints());
totalOriginPrice = CurrencyUtil.add(totalOriginPrice, (goodsSkuPromotionPrice.getOriginalPrice() * goodsSkuPromotionPrice.getNumber()));
if (goodsSkuPromotionPrice.getTotalDiscountPrice() != null && goodsSkuPromotionPrice.getTotalDiscountPrice() > 0) {
totalDiscountPrice = CurrencyUtil.add(totalDiscountPrice, goodsSkuPromotionPrice.getTotalDiscountPrice());
}
}
if (storePromotionPriceDTO.getTotalDiscountPrice() == null && totalDiscountPrice > 0) {
storePromotionPriceDTO.setTotalDiscountPrice(totalDiscountPrice);
} else if (storePromotionPriceDTO.getTotalDiscountPrice() == null) {
storePromotionPriceDTO.setTotalDiscountPrice(0d);
}
storePromotionPriceDTO.setTotalPoints(totalPoints);
storePromotionPriceDTO.setTotalNum((int) totalNum);
storePromotionPriceDTO.setTotalWeight(totalWeight);
storePromotionPriceDTO.setTotalOriginPrice(totalOriginPrice);
}
/**
* 将相应促销活动的店铺促销计算信息中的促销价格和最终成交金额平均分配到每个商品促销信息中去
*
* @param storePromotionPriceDTO 店铺促销计算信息
*/
private void distributeStoreFullDiscountPromotionPrice(StorePromotionPriceDTO storePromotionPriceDTO, FullDiscount fullDiscount) {
//分配的促销总金额 = 促销总金额 / 分配的数量
for (GoodsSkuPromotionPriceDTO goodsSkuPromotionPrice : storePromotionPriceDTO.getGoodsSkuPromotionPriceList()) {
//属于相应的促销活动的商品金额均分
if (goodsSkuPromotionPrice.getDiscountPriceRate() != null
&& goodsSkuPromotionPrice.getPromotionType() != null
&& goodsSkuPromotionPrice.getPromotionType().equals(PromotionTypeEnum.FULL_DISCOUNT.name())) {
double distributeDiscountTotalPrice = CurrencyUtil.mul(storePromotionPriceDTO.getTotalDiscountPrice(), goodsSkuPromotionPrice.getDiscountPriceRate());
goodsSkuPromotionPrice.setDiscountPrice(distributeDiscountTotalPrice);
goodsSkuPromotionPrice.setTotalDiscountPrice(distributeDiscountTotalPrice);
//单品成交价
double finalPrice = CurrencyUtil.sub(goodsSkuPromotionPrice.getTotalOriginalPrice(), distributeDiscountTotalPrice);
goodsSkuPromotionPrice.setFinalePrice(CurrencyUtil.div(finalPrice, goodsSkuPromotionPrice.getNumber()));
goodsSkuPromotionPrice.setTotalFinalePrice(finalPrice);
fullDiscount.setPromotionName(PromotionTypeEnum.FULL_DISCOUNT.name());
goodsSkuPromotionPrice.getJoinPromotion().add(fullDiscount);
}
}
}
/**
* 检查活动有效时间
*
* @param startTime 活动开始时间
* @param endTime 活动结束时间
* @param promotionType 活动类型
* @param promotionId 活动ID
* @return 是否有效
*/
private boolean checkPromotionValidTime(Date startTime, Date endTime, String promotionType, String promotionId) {
long now = System.currentTimeMillis();
if (startTime.getTime() > now) {
log.error("商品ID为{}的{}活动开始时间小于当时时间,活动未开始!", promotionId, promotionType);
return false;
}
if (endTime.getTime() < now) {
log.error("活动ID为{}的{}活动结束时间大于当时时间,活动已结束!", promotionId, promotionType);
return false;
}
return true;
}
}

View File

@ -195,7 +195,7 @@ public class PromotionServiceImpl implements PromotionService {
query.addCriteria(Criteria.where("endTime").gt(new Date()));
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
for (FullDiscountVO fullDiscountVO : fullDiscountVOS) {
if (fullDiscountVO.getPromotionGoodsList() == null && fullDiscountVO.getNumber() == -1) {
if (fullDiscountVO.getPromotionGoodsList() == null) {
if (index.getStoreId().equals(fullDiscountVO.getStoreId())) {
String fullDiscountKey = PromotionTypeEnum.FULL_DISCOUNT.name() + "-" + fullDiscountVO.getId();
promotionMap.put(fullDiscountKey, fullDiscountVO);
@ -288,7 +288,7 @@ public class PromotionServiceImpl implements PromotionService {
//clone一个活动信息用于存放与索引中
FullDiscountVO clone = ObjectUtil.clone(fullDiscountVO);
clone.setPromotionGoodsList(null);
if (fullDiscountVO.getPromotionGoodsList() == null && fullDiscountVO.getNumber() == -1) {
if (fullDiscountVO.getPromotionGoodsList() == null) {
//如果为全品类则更新全部索引
this.goodsIndexService.updateEsGoodsIndexAllByList(clone, esPromotionKey);
} else {

View File

@ -42,7 +42,6 @@ class FullDiscountTest {
FullDiscountVO fullDiscountVO = new FullDiscountVO();
fullDiscountVO.setStoreId("131");
fullDiscountVO.setStoreName("小米自营旗舰店");
fullDiscountVO.setNumber(1);
fullDiscountVO.setDescription("full discount test " + RandomUtil.randomNumber());
fullDiscountVO.setIsFullMinus(true);
fullDiscountVO.setFullMoney(130D);
@ -97,7 +96,6 @@ class FullDiscountTest {
fullDiscountVO.setId("1325981729404248064");
fullDiscountVO.setStoreId("132");
fullDiscountVO.setStoreName("联想自营旗舰店");
fullDiscountVO.setNumber(1);
fullDiscountVO.setDescription("Not worth");
fullDiscountVO.setIsFullMinus(true);
fullDiscountVO.setFullMoney(100D);

View File

@ -1,15 +1,14 @@
package cn.lili.test.promotion;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.promotion.entity.dto.BasePromotion;
import cn.lili.modules.promotion.entity.dto.PromotionGoodsDTO;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.modules.promotion.service.PromotionPriceService;
import cn.lili.modules.promotion.service.PromotionService;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import cn.lili.modules.promotion.service.PromotionService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -28,9 +27,6 @@ import java.util.Map;
@SpringBootTest
class PromotionPriceTest {
@Autowired
private PromotionPriceService promotionPriceService;
@Autowired
private PromotionService promotionService;