fix: 优惠券使用逻辑修改

This commit is contained in:
张松
2024-11-11 16:21:06 +08:00
parent 64fd381ed4
commit c4fcf08691
5 changed files with 140 additions and 97 deletions

View File

@@ -17,4 +17,5 @@ public class OrderCouponInfoDTO {
private HashMap<Integer, TbUserCouponVo> fullReductionCouponMap = new HashMap<>(); private HashMap<Integer, TbUserCouponVo> fullReductionCouponMap = new HashMap<>();
// 商品优惠券 // 商品优惠券
private HashMap<Integer, TbUserCouponVo> productCouponMap = new HashMap<>(); private HashMap<Integer, TbUserCouponVo> productCouponMap = new HashMap<>();
private HashMap<Integer, List<TbUserCouponVo>> couponMap = new HashMap<>();
} }

View File

@@ -134,7 +134,7 @@ public class MpCashierCartServiceImpl extends ServiceImpl<TbCashierCartMapper, T
@Override @Override
public List<TbCashierCart> selectByOrderIdAndState(Integer orderId, TableConstant.OrderInfo.Status... status) { public List<TbCashierCart> selectByOrderIdAndState(Integer orderId, TableConstant.OrderInfo.Status... status) {
LambdaQueryChainWrapper<TbCashierCart> queryChainWrapper = lambdaQuery().eq(TbCashierCart::getOrderId, orderId); LambdaQueryChainWrapper<TbCashierCart> queryChainWrapper = lambdaQuery().eq(TbCashierCart::getOrderId, orderId);
if (status != null) { if (status != null && status.length > 0) {
queryChainWrapper.in(TbCashierCart::getStatus, CollUtil.newArrayList(status)); queryChainWrapper.in(TbCashierCart::getStatus, CollUtil.newArrayList(status));
} }
return queryChainWrapper.list(); return queryChainWrapper.list();

View File

@@ -74,17 +74,13 @@ public class TbShopCouponServiceImpl extends ServiceImpl<TbShopCouponMapper, TbS
private TbActivateOutRecordMapper outRecordMapper; private TbActivateOutRecordMapper outRecordMapper;
@Autowired @Autowired
private TbShopShareRecordService shareRecordService; private TbShopShareRecordService shareRecordService;
private final TbMShopUserMapper shopUserMapper;
private final MpShopUserService shopUserService; private final MpShopUserService shopUserService;
private final MpOrderInfoService mpOrderInfoService; private final MpOrderInfoService mpOrderInfoService;
private final MpOrderDetailService mpOrderDetailService;
private final MpCashierCartService mpCashierCartService; private final MpCashierCartService mpCashierCartService;
public TbShopCouponServiceImpl(TbMShopUserMapper shopUserMapper, MpShopUserService shopUserService, MpOrderInfoService mpOrderInfoService, MpOrderDetailService mpOrderDetailService, MpCashierCartService mpCashierCartService) { public TbShopCouponServiceImpl(MpShopUserService shopUserService, MpOrderInfoService mpOrderInfoService, MpCashierCartService mpCashierCartService) {
this.shopUserMapper = shopUserMapper;
this.shopUserService = shopUserService; this.shopUserService = shopUserService;
this.mpOrderInfoService = mpOrderInfoService; this.mpOrderInfoService = mpOrderInfoService;
this.mpOrderDetailService = mpOrderDetailService;
this.mpCashierCartService = mpCashierCartService; this.mpCashierCartService = mpCashierCartService;
} }

View File

@@ -1,38 +1,39 @@
/* /*
* Copyright 2019-2020 Zheng Jie * Copyright 2019-2020 Zheng Jie
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.ysk.cashier.pojo.order; package cn.ysk.cashier.pojo.order;
import lombok.Data; import lombok.Data;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import javax.persistence.*; import javax.persistence.*;
import javax.validation.constraints.*; import javax.validation.constraints.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.io.Serializable; import java.io.Serializable;
/** /**
* @website https://eladmin.vip * @author lyf
* @description / * @website https://eladmin.vip
* @author lyf * @description /
* @date 2024-03-02 * @date 2024-03-02
**/ **/
@Entity @Entity
@Data @Data
@Table(name="tb_cashier_cart") @Table(name = "tb_cashier_cart")
public class TbCashierCart implements Serializable { public class TbCashierCart implements Serializable {
@Id @Id
@@ -81,7 +82,7 @@ public class TbCashierCart implements Serializable {
@ApiModelProperty(value = "单价") @ApiModelProperty(value = "单价")
private BigDecimal salePrice; private BigDecimal salePrice;
@Column(name = "`number`",nullable = false) @Column(name = "`number`", nullable = false)
@NotNull @NotNull
@ApiModelProperty(value = "结余数量") @ApiModelProperty(value = "结余数量")
private Integer number; private Integer number;
@@ -168,8 +169,8 @@ public class TbCashierCart implements Serializable {
private BigDecimal memberPrice = BigDecimal.ZERO; private BigDecimal memberPrice = BigDecimal.ZERO;
private Integer isMember; private Integer isMember;
public void copy(TbCashierCart source){ public void copy(TbCashierCart source) {
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
} }
/** /**
@@ -181,12 +182,27 @@ public class TbCashierCart implements Serializable {
} }
if ("true".equals(isGift)) { if ("true".equals(isGift)) {
totalAmount = packFee; totalAmount = packFee;
}else { } else {
if (isMember != null && isMember == 1 && memberPrice != null && memberPrice.compareTo(BigDecimal.ZERO) > 0) { if (isMember != null && isMember == 1 && memberPrice != null && memberPrice.compareTo(BigDecimal.ZERO) > 0) {
totalAmount = BigDecimal.valueOf(totalNumber).multiply(memberPrice).add(packFee); totalAmount = BigDecimal.valueOf(totalNumber).multiply(memberPrice).add(packFee);
}else { } else {
totalAmount = BigDecimal.valueOf(totalNumber).multiply(salePrice).add(packFee); totalAmount = BigDecimal.valueOf(totalNumber).multiply(salePrice).add(packFee);
} }
} }
} }
/**
* 获取总价不包含打包费
*
*/
public BigDecimal getTotalAmountByNum(Integer num) {
if (num == null) {
num = totalNumber;
}
if (isMember != null && isMember == 1 && memberPrice != null && memberPrice.compareTo(BigDecimal.ZERO) > 0) {
return BigDecimal.valueOf(num).multiply(memberPrice);
} else {
return BigDecimal.valueOf(num).multiply(salePrice);
}
}
} }

View File

@@ -1177,77 +1177,107 @@ public class TbShopTableServiceImpl implements TbShopTableService {
} }
private TbUserCouponVo getCanUseCoupon(HashMap<String, List<TbUserCouponVo>> couponMap, String productId) {
List<TbUserCouponVo> tbUserCouponVos = couponMap.get(productId);
if (tbUserCouponVos == null || tbUserCouponVos.isEmpty()) return null;
for (TbUserCouponVo tbUserCouponVo : tbUserCouponVos) {
if (tbUserCouponVo.getCurrentUseNum() > 0) {
return tbUserCouponVo;
}
}
return null;
}
private BigDecimal reduceProCoupon(HashMap<String, List<TbUserCouponVo>> couponMap, TbCashierCart cashierCart, HashMap<Integer,
List<TbUserCouponVo>> usedCouponMap, BigDecimal discountAmount, ArrayList<TbCashierCart> balanceCartList,
ArrayList<TbActivateOutRecord> outRecords, Integer memberId) {
TbUserCouponVo couponVo = getCanUseCoupon(couponMap, cashierCart.getProductId());
if (couponVo != null && couponVo.getCurrentUseNum() > 0) {
BigDecimal currentUseNum;
if (cashierCart.getNumber() < couponVo.getCurrentUseNum()) {
cashierCart.setUserCouponId(couponVo.getId());
discountAmount = discountAmount.add(cashierCart.getTotalAmountByNum(null));
couponVo.setCurrentUseNum(couponVo.getCurrentUseNum() - cashierCart.getNumber());
}
List<TbUserCouponVo> tbUserCouponVos = usedCouponMap.computeIfAbsent(Integer.valueOf(cashierCart.getProductId()), k -> new ArrayList<>());
tbUserCouponVos.add(couponVo);
TbCashierCart balanceCart = null;
// 优惠券数量小于购物车数量,分割购物车数据
if (cashierCart.getNumber() > couponVo.getCurrentUseNum()) {
currentUseNum = BigDecimal.valueOf(couponVo.getCurrentUseNum());
BigDecimal cartNum = BigDecimal.valueOf(cashierCart.getNumber());
int balanceNum = cashierCart.getTotalNumber() - couponVo.getCurrentUseNum();
BigDecimal singlePackFee = cashierCart.getPackFee().divide(cartNum, RoundingMode.HALF_UP);
cashierCart.setPackFee(singlePackFee.multiply(currentUseNum));
BigDecimal totalAmountByNum = cashierCart.getTotalAmountByNum(couponVo.getCurrentUseNum());
cashierCart.setTotalAmount(totalAmountByNum.add(singlePackFee.multiply(currentUseNum)));
cashierCart.setNumber(couponVo.getCurrentUseNum());
cashierCart.setTotalNumber(couponVo.getCurrentUseNum());
cashierCart.setUserCouponId(couponVo.getId());
discountAmount = discountAmount.add(totalAmountByNum);
couponVo.setCurrentUseNum(couponVo.getCurrentUseNum() - cashierCart.getNumber());
// 创建结余购物车
balanceCart = BeanUtil.copyProperties(cashierCart, TbCashierCart.class);
BigDecimal num = BigDecimal.valueOf(balanceNum);
balanceCart.setUserCouponId(null);
balanceCart.setId(null);
balanceCart.setNumber(balanceNum);
balanceCart.setTotalNumber(balanceNum);
balanceCart.setPackFee(singlePackFee.multiply(num));
balanceCart.setTotalAmount(cashierCart.getSalePrice().multiply(num).add(balanceCart.getPackFee()));
balanceCartList.add(balanceCart);
} else {
currentUseNum = BigDecimal.valueOf(cashierCart.getNumber());
discountAmount = discountAmount.add(cashierCart.getTotalAmount().divide(BigDecimal.valueOf(cashierCart.getTotalNumber()), RoundingMode.HALF_UP).multiply(currentUseNum));
cashierCart.setUserCouponId(couponVo.getId());
couponVo.setCurrentUseNum(couponVo.getCurrentUseNum() - cashierCart.getNumber());
}
// 消耗并返还商品优惠券
Integer shopId = Integer.valueOf(cashierCart.getShopId());
TbActivateOutRecord tbActivateOutRecord = new TbActivateOutRecord();
tbActivateOutRecord.setShopId(shopId);
tbActivateOutRecord.setGiveId(couponVo.getId());
tbActivateOutRecord.setVipUserId(memberId);
tbActivateOutRecord.setType(TableConstant.ActivateOutRecord.Type.FULL_REDUCTION.getValue());
tbActivateOutRecord.setUseNum(currentUseNum.toBigInteger().intValue());
tbActivateOutRecord.setStatus(TableConstant.ActivateOutRecord.Status.CLOSED.getValue());
tbActivateOutRecord.setCreateTime(DateUtil.date());
tbActivateOutRecord.setRefNum(0);
outRecords.add(tbActivateOutRecord);
// 优惠券未消耗完毕
if (balanceCart != null && getCanUseCoupon(couponMap, balanceCart.getProductId()) != null) {
discountAmount = reduceProCoupon(couponMap, balanceCart, usedCouponMap, discountAmount, balanceCartList, outRecords, memberId);
}
return discountAmount;
}
return discountAmount;
}
private BigDecimal calcCartPriceWithCoupon(List<TbCashierCart> newCashierCarts, OrderCouponInfoDTO couponInfoDTO, Integer memberId, TbOrderInfo orderInfo) { private BigDecimal calcCartPriceWithCoupon(List<TbCashierCart> newCashierCarts, OrderCouponInfoDTO couponInfoDTO, Integer memberId, TbOrderInfo orderInfo) {
ArrayList<TbCashierCart> balanceCartList = new ArrayList<>(); ArrayList<TbCashierCart> balanceCartList = new ArrayList<>();
BigDecimal discountAmount = BigDecimal.ZERO; BigDecimal discountAmount = BigDecimal.ZERO;
HashMap<String, TbUserCouponVo> couponMap = new HashMap<>(); HashMap<String, List<TbUserCouponVo>> couponMap = new HashMap<>();
couponInfoDTO.getProductCouponMap().values().forEach(item -> { couponInfoDTO.getProductCouponMap().values().forEach(item -> {
couponMap.put(item.getProId().toString(), item); if (item.getCurrentUseNum() <= 0) {
return;
}
List<TbUserCouponVo> tbUserCouponVos = couponMap.get(item.getProId().toString());
if (tbUserCouponVos == null) {
tbUserCouponVos = new ArrayList<>();
tbUserCouponVos.add(item);
couponMap.put(item.getProId().toString(), tbUserCouponVos);
}else {
tbUserCouponVos.add(item);
}
}); });
HashMap<Integer, TbUserCouponVo> usedCouponMap = new HashMap<>(); HashMap<Integer, List<TbUserCouponVo>> usedCouponMap = new HashMap<>();
ArrayList<TbActivateOutRecord> outRecords = new ArrayList<>(); ArrayList<TbActivateOutRecord> outRecords = new ArrayList<>();
for (TbCashierCart cashierCart : newCashierCarts) { for (TbCashierCart cashierCart : newCashierCarts) {
TbUserCouponVo couponVo = couponMap.get(cashierCart.getProductId()); discountAmount = reduceProCoupon(couponMap, cashierCart, usedCouponMap, discountAmount, balanceCartList, outRecords, memberId);
boolean useCoupon;
if (couponVo != null && couponVo.getCurrentUseNum() > 0) {
BigDecimal currentUseNum = BigDecimal.ZERO;
if (cashierCart.getNumber() < couponVo.getCurrentUseNum()) {
currentUseNum = BigDecimal.valueOf(couponVo.getCurrentUseNum());
BigDecimal cartNum = BigDecimal.valueOf(cashierCart.getNumber());
BigDecimal singlePackFee = cashierCart.getPackFee().divide(cartNum, RoundingMode.HALF_UP);
cashierCart.setPackFee(singlePackFee.multiply(currentUseNum));
cashierCart.setTotalAmount(cashierCart.getSalePrice().multiply(currentUseNum).add(singlePackFee.multiply(currentUseNum)));
cashierCart.setNumber(couponVo.getCurrentUseNum());
cashierCart.setTotalNumber(couponVo.getCurrentUseNum());
cashierCart.setUserCouponId(couponVo.getId());
discountAmount = discountAmount.add(cashierCart.getTotalAmount());
couponVo.setCurrentUseNum(couponVo.getCurrentUseNum() - cashierCart.getNumber());
}
usedCouponMap.put(Integer.valueOf(cashierCart.getProductId()), couponVo);
// 优惠券数量小于购物车数量,分割购物车数据
if (cashierCart.getNumber() > couponVo.getCurrentUseNum()) {
currentUseNum = BigDecimal.valueOf(couponVo.getCurrentUseNum());
BigDecimal cartNum = BigDecimal.valueOf(cashierCart.getNumber());
int balanceNum = cashierCart.getTotalNumber() - couponVo.getCurrentUseNum();
BigDecimal singlePackFee = cashierCart.getPackFee().divide(cartNum, RoundingMode.HALF_UP);
cashierCart.setPackFee(singlePackFee.multiply(currentUseNum));
cashierCart.setTotalAmount(cashierCart.getSalePrice().multiply(currentUseNum).add(singlePackFee.multiply(currentUseNum)));
cashierCart.setNumber(couponVo.getCurrentUseNum());
cashierCart.setTotalNumber(couponVo.getCurrentUseNum());
cashierCart.setUserCouponId(couponVo.getId());
discountAmount = discountAmount.add(cashierCart.getTotalAmount());
couponVo.setCurrentUseNum(couponVo.getCurrentUseNum() - cashierCart.getNumber());
// 创建结余购物车
TbCashierCart balanceCart = BeanUtil.copyProperties(cashierCart, TbCashierCart.class);
BigDecimal num = BigDecimal.valueOf(balanceNum);
balanceCart.setUserCouponId(null);
balanceCart.setId(null);
balanceCart.setNumber(balanceNum);
balanceCart.setTotalNumber(balanceNum);
balanceCart.setPackFee(singlePackFee.multiply(num));
balanceCart.setTotalAmount(cashierCart.getSalePrice().multiply(num).add(balanceCart.getPackFee()));
balanceCartList.add(balanceCart);
} else {
currentUseNum = BigDecimal.valueOf(cashierCart.getNumber());
discountAmount = discountAmount.add(cashierCart.getTotalAmount());
cashierCart.setUserCouponId(couponVo.getId());
couponVo.setCurrentUseNum(couponVo.getCurrentUseNum() - cashierCart.getNumber());
}
// 消耗并返还商品优惠券
Integer shopId = Integer.valueOf(cashierCart.getShopId());
TbActivateOutRecord tbActivateOutRecord = new TbActivateOutRecord();
tbActivateOutRecord.setShopId(shopId);
tbActivateOutRecord.setGiveId(couponVo.getId());
tbActivateOutRecord.setVipUserId(memberId);
tbActivateOutRecord.setType(TableConstant.ActivateOutRecord.Type.FULL_REDUCTION.getValue());
tbActivateOutRecord.setUseNum(currentUseNum.toBigInteger().intValue());
tbActivateOutRecord.setStatus(TableConstant.ActivateOutRecord.Status.CLOSED.getValue());
tbActivateOutRecord.setCreateTime(DateUtil.date());
tbActivateOutRecord.setRefNum(0);
outRecords.add(tbActivateOutRecord);
}
} }
if (!balanceCartList.isEmpty()) { if (!balanceCartList.isEmpty()) {
@@ -1258,7 +1288,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
mpCashierCartService.updateBatchById(newCashierCarts); mpCashierCartService.updateBatchById(newCashierCarts);
couponInfoDTO.setOutRecordList(outRecords); couponInfoDTO.setOutRecordList(outRecords);
couponInfoDTO.setProductCouponMap(usedCouponMap); couponInfoDTO.setCouponMap(usedCouponMap);
return discountAmount; return discountAmount;
} }
@@ -1939,7 +1969,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
returnCoupon(orderInfo); returnCoupon(orderInfo);
Set<String> productIdSet = new HashSet<>(); Set<String> productIdSet = new HashSet<>();
List<TbCashierCart> cashierCarts = mpCashierCartService.selectByOrderIdAndState(orderInfo.getId(), null); List<TbCashierCart> cashierCarts = mpCashierCartService.selectByOrderIdAndState(orderInfo.getId());
ArrayList<TbCashierCart> activateCartInfo = new ArrayList<>(); ArrayList<TbCashierCart> activateCartInfo = new ArrayList<>();
for (TbCashierCart cashierCart : cashierCarts) { for (TbCashierCart cashierCart : cashierCarts) {
productIdSet.add(cashierCart.getProductId()); productIdSet.add(cashierCart.getProductId());