订单 优惠券部分 重写
This commit is contained in:
@@ -21,7 +21,11 @@ import com.czg.enums.ShopUserFlowBizEnum;
|
||||
import com.czg.exception.ApiNotPrintException;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.exception.OrderCancelException;
|
||||
import com.czg.market.entity.MkShopCouponRecord;
|
||||
import com.czg.market.entity.ShopCoupon;
|
||||
import com.czg.market.service.MemberOrderService;
|
||||
import com.czg.market.service.MkShopCouponRecordService;
|
||||
import com.czg.market.service.ShopCouponService;
|
||||
import com.czg.market.service.TbMemberConfigService;
|
||||
import com.czg.order.dto.*;
|
||||
import com.czg.order.entity.*;
|
||||
@@ -56,10 +60,12 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -101,12 +107,14 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
private ShopUserFlowService flowService;
|
||||
@DubboReference
|
||||
private ShopTableService shopTableService;
|
||||
// @DubboReference
|
||||
// @DubboReference
|
||||
// private ShopActivateService activateService;
|
||||
@DubboReference
|
||||
private PointsBasicSettingService pointsBasicService;
|
||||
// @DubboReference
|
||||
// private ShopCouponService couponService;
|
||||
@DubboReference
|
||||
private ShopCouponService couponService;
|
||||
@DubboReference
|
||||
private MkShopCouponRecordService couponRecordService;
|
||||
@DubboReference
|
||||
private TbMemberConfigService memberConfigService;
|
||||
@Resource
|
||||
@@ -339,70 +347,149 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
}
|
||||
orderInfo.setUserId(userInfo.getId());
|
||||
}
|
||||
if (param.getDiscountRatio().compareTo(BigDecimal.ZERO) < 0 || param.getDiscountRatio().compareTo(BigDecimal.ONE) > 0) {
|
||||
throw new ValidateException("生成支付订单失败,折扣比例不正确");
|
||||
}
|
||||
//商品券 <商品id,数量>
|
||||
Map<Long, Integer> prodCouponMap = new HashMap<>();
|
||||
//满减券 满fullCouponAmount 减disCouponAmount
|
||||
BigDecimalDTO fullAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
BigDecimalDTO discountAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//校验优惠券
|
||||
checkCoupon(prodCouponMap, fullAmount, discountAmount, param);
|
||||
|
||||
//获取商品信息 计算金额 需要传入优惠券 减去优惠券
|
||||
List<OrderDetail> orderDetails = orderDetailService.queryChain().eq(OrderDetail::getOrderId, param.getOrderId()).select().list();
|
||||
//商品优惠券金额
|
||||
BigDecimalDTO prodCouponAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//总商品支付金额 不包含打包费 用来计算后续
|
||||
//总商品金额 不包含打包费 不包含临时菜
|
||||
BigDecimalDTO totalAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//最终打包费
|
||||
BigDecimalDTO packAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
processOrderDetails2(orderDetails, prodCouponMap, prodCouponAmount, totalAmount, packAmount, param.isAllPack(), param.getUserAllPack(), param.isVipPrice());
|
||||
//临时菜总费用
|
||||
BigDecimalDTO tempAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//商品兑换券金额
|
||||
BigDecimalDTO prodCouponAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//买一送一券金额
|
||||
BigDecimalDTO oneGiftAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//第二件半价券金额
|
||||
BigDecimalDTO twoHalfAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//折扣金额
|
||||
BigDecimalDTO rateAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//满减金额
|
||||
BigDecimalDTO fullReductionAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
getOrderAmount(orderDetails, totalAmount, packAmount, tempAmount,
|
||||
param.isAllPack(), param.getUserAllPack(), param.isVipPrice());
|
||||
if (totalAmount.getPrice().compareTo(param.getOriginAmount()) != 0) {
|
||||
log.info("订单原价不正确:订单原价:{},传递为:{}", totalAmount.getPrice(), param.getOriginAmount());
|
||||
throw new ValidateException("生成支付订单失败,订单原金额不正确");
|
||||
}
|
||||
//优惠券部分 目前规则 每个券只能用一张
|
||||
if (CollUtil.isNotEmpty(param.getCouponList())) {
|
||||
QueryWrapper couponRecordQuery = new QueryWrapper();
|
||||
couponRecordQuery.in(MkShopCouponRecord::getId, param.getCouponList());
|
||||
couponRecordQuery.eq(MkShopCouponRecord::getShopId, shopId);
|
||||
couponRecordQuery.gt(MkShopCouponRecord::getUseStartTime, LocalDateTime.now());
|
||||
couponRecordQuery.le(MkShopCouponRecord::getUseEndTime, LocalDateTime.now());
|
||||
couponRecordQuery.eq(MkShopCouponRecord::getStatus, 0);
|
||||
couponRecordQuery.ne(MkShopCouponRecord::getIsDel, 1);
|
||||
List<MkShopCouponRecord> list = couponRecordService.list(couponRecordQuery);
|
||||
if (CollUtil.isEmpty(list) || param.getCouponList().size() != list.size()) {
|
||||
throw new ValidateException("生成支付订单失败,优惠券不可用");
|
||||
}
|
||||
Map<Integer, MkShopCouponRecord> couponRecordMap = list.stream().collect(Collectors.toMap(MkShopCouponRecord::getType, t -> t));
|
||||
AtomicBoolean otherCouponShare = new AtomicBoolean(true);
|
||||
couponRecordMap.forEach((type, record) -> {
|
||||
//1-满减券,2-商品兑换券,3-折扣券,4-第二件半价券, 6-买一送一券,
|
||||
// 7-固定价格券,8-免配送费券 暂时没有
|
||||
if (type == 2) {//商品券
|
||||
ShopCoupon coupon = checkCoupon(record, param.isVipPrice());
|
||||
if (coupon.getOtherCouponShare() != 1) {
|
||||
otherCouponShare.set(false);
|
||||
}
|
||||
if (coupon.getFullAmount().compareTo(totalAmount.getPrice()) > 0) {
|
||||
throw new ValidateException("生成支付订单失败,商品券:" + coupon + " 未达到使用门槛" + coupon.getFullAmount() + "元");
|
||||
}
|
||||
boolean isAllFoods = true;
|
||||
List<Long> couponFoodIds = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(coupon.getFoods()) && !",".equals(coupon.getFoods())) {
|
||||
couponFoodIds = Arrays.stream(coupon.getFoods().split(",")).map(Long::parseLong).toList();
|
||||
}
|
||||
foodsCalculate(orderDetails, isAllFoods, couponFoodIds, coupon.getDiscountNum(), "price_asc".equals(coupon.getUseRule()), prodCouponAmount);
|
||||
} else if (type == 4 || type == 6) {//4-第二件半价券, 6-买一送一券
|
||||
if (!otherCouponShare.get()) {
|
||||
throw new ValidateException("生成支付订单失败,商品券与其它券不可共用");
|
||||
}
|
||||
ShopCoupon coupon = checkCoupon(record, param.isVipPrice());
|
||||
boolean isAllFoods = true;
|
||||
List<Long> couponFoodIds = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(coupon.getFoods()) && !",".equals(coupon.getFoods())) {
|
||||
couponFoodIds = Arrays.stream(coupon.getFoods().split(",")).map(Long::parseLong).toList();
|
||||
}
|
||||
if (type == 6) {
|
||||
oneGiftCalculate(orderDetails, isAllFoods, couponFoodIds, "price_asc".equals(coupon.getUseRule()), oneGiftAmount);
|
||||
} else {
|
||||
twoHalfCalculate(orderDetails, isAllFoods, couponFoodIds, "price_asc".equals(coupon.getUseRule()), twoHalfAmount);
|
||||
}
|
||||
} else if (type == 1 || type == 3) {//1-满减券 3-折扣券
|
||||
if (!otherCouponShare.get()) {
|
||||
throw new ValidateException("生成支付订单失败,商品券与其它券不可共用");
|
||||
}
|
||||
ShopCoupon coupon = checkCoupon(record, param.isVipPrice());
|
||||
//计算门槛
|
||||
boolean isAllFoods = true;
|
||||
List<Long> couponFoodIds = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(coupon.getFoods()) && !",".equals(coupon.getFoods())) {
|
||||
couponFoodIds = Arrays.stream(coupon.getFoods().split(",")).map(Long::parseLong).toList();
|
||||
}
|
||||
thresholdCalculate(orderDetails, isAllFoods, couponFoodIds, coupon.getFullAmount());
|
||||
if (type == 3) {
|
||||
BigDecimal rate = new BigDecimal(record.getDiscountRate());
|
||||
rateAmount.setPrice(rate.multiply(totalAmount.getPrice().subtract(tempAmount.getPrice()).subtract(prodCouponAmount.getPrice())).setScale(2, RoundingMode.DOWN));
|
||||
if (rateAmount.getPrice().compareTo(coupon.getMaxDiscountAmount()) > 0) {
|
||||
rateAmount.setPrice(coupon.getMaxDiscountAmount());
|
||||
}
|
||||
} else {
|
||||
fullReductionAmount.setPrice(record.getDiscountAmount());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//总商品支付金额 不包含打包费 用来计算后续
|
||||
if (prodCouponAmount.getPrice().compareTo(param.getProductCouponDiscountAmount()) != 0) {
|
||||
log.info("支付计算金额不正确:商品券抵扣金额为:{},传递为:{}", prodCouponAmount.getPrice(), param.getProductCouponDiscountAmount());
|
||||
throw new ValidateException("生成支付订单失败,商品优惠券优惠金额不正确");
|
||||
}
|
||||
// orderInfo.setOriginAmount(totalAmount.getPrice().add(packAmount.getPrice()).add(orderInfo.getSeatAmount()));
|
||||
orderInfo.setOriginAmount(param.getOriginAmount());
|
||||
BigDecimal newTotalAmount = totalAmount.getPrice();
|
||||
//折扣金额 如 9折 计算 为 订单金额*0.9 向上取整
|
||||
if (param.getDiscountRatio().compareTo(BigDecimal.ZERO) > 0) {
|
||||
newTotalAmount = totalAmount.getPrice().multiply(param.getDiscountRatio()).setScale(2, RoundingMode.UP);
|
||||
|
||||
} else if (param.getDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
//减去商品优惠券
|
||||
newTotalAmount = newTotalAmount.subtract(prodCouponAmount.getPrice());
|
||||
//减去其它优惠券金额
|
||||
newTotalAmount = newTotalAmount.subtract(fullReductionAmount.getPrice());
|
||||
newTotalAmount = newTotalAmount.subtract(rateAmount.getPrice());
|
||||
newTotalAmount = newTotalAmount.subtract(oneGiftAmount.getPrice());
|
||||
newTotalAmount = newTotalAmount.subtract(twoHalfAmount.getPrice());
|
||||
if (param.getOriginAmount().subtract(param.getProductCouponDiscountAmount()).subtract(param.getOtherCouponDiscountAmount()).compareTo(newTotalAmount) != 0) {
|
||||
log.info("其它优惠券金额不正确:满减金额为:{},折扣金额为:{},买一赠一金额为:{},第二件半价券金额为:{} 传递为:{}",
|
||||
fullReductionAmount.getPrice(), rateAmount.getPrice(), oneGiftAmount.getPrice(), twoHalfAmount.getPrice(), param.getOtherCouponDiscountAmount());
|
||||
throw new ValidateException("生成支付订单失败,商品优惠券优惠金额不正确");
|
||||
}
|
||||
//TODO 新客立减
|
||||
//折扣金额
|
||||
if (param.getDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
newTotalAmount = totalAmount.getPrice().subtract(param.getDiscountAmount());
|
||||
}
|
||||
|
||||
//满减券 校验
|
||||
if (newTotalAmount.compareTo(fullAmount.getPrice()) < 0) {
|
||||
throw new ValidateException("生成支付订单失败,满减券不满足条件");
|
||||
}
|
||||
//减去满减优惠券
|
||||
newTotalAmount = newTotalAmount.subtract(discountAmount.getPrice());
|
||||
//积分抵扣 金额范围校验 抵扣金额校验
|
||||
// if (param.getPointsNum() > 0) {
|
||||
// if (pointSetting.getMinPaymentAmount().compareTo(newTotalAmount) > 0) {
|
||||
// throw new ValidateException("生成支付订单失败,未满足积分抵扣最低门槛");
|
||||
// }
|
||||
// if (pointSetting.getMaxDeductionRatio().multiply(newTotalAmount).compareTo(param.getPointsDiscountAmount()) < 0) {
|
||||
// throw new ValidateException("生成支付订单失败,积分抵扣金额已超出最大抵扣金额");
|
||||
// }
|
||||
// BigDecimal pointAmount = new BigDecimal(param.getPointsNum()).divide(new BigDecimal(pointSetting.getEquivalentPoints()), 2, RoundingMode.DOWN);
|
||||
// if (pointAmount.compareTo(param.getPointsDiscountAmount()) != 0) {
|
||||
// throw new ValidateException("生成支付订单失败,积分抵扣金额不正确");
|
||||
// }
|
||||
// }
|
||||
if (param.getPointsNum() > 0) {
|
||||
if (pointSetting.getMinPaymentAmount().compareTo(newTotalAmount) > 0) {
|
||||
throw new ValidateException("生成支付订单失败,未满足积分抵扣最低门槛");
|
||||
}
|
||||
if (pointSetting.getMaxDeductionRatio().multiply(newTotalAmount).compareTo(param.getPointsDiscountAmount()) < 0) {
|
||||
throw new ValidateException("生成支付订单失败,积分抵扣金额已超出最大抵扣金额");
|
||||
}
|
||||
BigDecimal pointAmount = new BigDecimal(param.getPointsNum()).divide(new BigDecimal(pointSetting.getEquivalentPoints()), 2, RoundingMode.DOWN);
|
||||
if (pointAmount.compareTo(param.getPointsDiscountAmount()) != 0) {
|
||||
throw new ValidateException("生成支付订单失败,积分抵扣金额不正确");
|
||||
}
|
||||
}
|
||||
newTotalAmount = newTotalAmount.subtract(param.getPointsDiscountAmount());
|
||||
//抹零
|
||||
newTotalAmount = newTotalAmount.subtract(param.getRoundAmount());
|
||||
//校验最终金额(订单金额 (扣除各类折扣)+打包费 餐位费)
|
||||
newTotalAmount = newTotalAmount.add(packAmount.getPrice()).add(orderInfo.getSeatAmount());
|
||||
if (newTotalAmount.compareTo(param.getOrderAmount()) != 0) {
|
||||
log.info("支付计算金额不正确,订单Id:{},最终计算金额为:{},打包费:{},餐位费:{},商品券金额:{},满减券金额:{},积分抵扣金额:{},抹零金额:{}",
|
||||
orderInfo.getId(), newTotalAmount, packAmount.getPrice(), orderInfo.getSeatAmount(), param.getProductCouponDiscountAmount(),
|
||||
discountAmount.getPrice(), param.getPointsDiscountAmount(), param.getRoundAmount());
|
||||
log.info("支付计算金额不正确,订单Id:{},最终计算金额为:{},打包费:{},餐位费:{},积分抵扣金额:{},抹零金额:{}",
|
||||
orderInfo.getId(), newTotalAmount, packAmount.getPrice(), orderInfo.getSeatAmount(),
|
||||
param.getPointsDiscountAmount(), param.getRoundAmount());
|
||||
throw new ValidateException("生成支付订单失败,订单金额不正确");
|
||||
}
|
||||
orderInfo.setPackFee(packAmount.getPrice());
|
||||
@@ -466,6 +553,218 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 优惠券通用校验规则 不包括门槛校验
|
||||
*
|
||||
* @param isVipPrice 是否使用会员价
|
||||
*/
|
||||
private ShopCoupon checkCoupon(MkShopCouponRecord record, boolean isVipPrice) {
|
||||
ShopCoupon coupon = couponService.getById(record.getCouponId());
|
||||
AssertUtil.isNull(coupon, "生成支付订单失败,券信息不存在");
|
||||
if (isVipPrice && coupon.getVipPriceShare() != 1) {
|
||||
throw new ValidateException("生成支付订单失败,券:" + coupon.getTitle() + "与会员价不共享");
|
||||
}
|
||||
isUseLimit(coupon, record);
|
||||
isUseTime(coupon);
|
||||
return coupon;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断每日使用限量
|
||||
*/
|
||||
private void isUseLimit(ShopCoupon coupon, MkShopCouponRecord record) {
|
||||
if (coupon.getUseLimit() != -10086) {
|
||||
long useNum = couponRecordService.count(new QueryWrapper()
|
||||
.eq(MkShopCouponRecord::getCouponId, coupon.getId())
|
||||
.eq(MkShopCouponRecord::getShopId, record.getShopId())
|
||||
.eq(MkShopCouponRecord::getUserId, record.getUserId())
|
||||
.eq(MkShopCouponRecord::getStatus, 1)
|
||||
.between(MkShopCouponRecord::getUseTime, LocalDateTime.now().with(LocalTime.MIN), LocalDateTime.now().with(LocalTime.MAX))
|
||||
);
|
||||
if (useNum >= coupon.getUseLimit()) {
|
||||
throw new ValidateException("优惠券:" + coupon.getTitle() + " 已达到今日使用限量");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用时段校验
|
||||
*/
|
||||
private void isUseTime(ShopCoupon coupon) {
|
||||
if (!coupon.getUseDays().contains(CzgStrUtils.getStrWeek())) {
|
||||
throw new ValidateException("生成支付订单失败," + coupon.getTitle() + " 今天不可用");
|
||||
}
|
||||
if (!"all".equals(coupon.getUseTimeType())) {
|
||||
// 获取当前时间(仅包含时分秒)
|
||||
LocalTime currentTime = LocalTime.now();
|
||||
LocalTime startTime = coupon.getUseStartTime().toLocalTime();
|
||||
LocalTime endTime = coupon.getUseEndTime().toLocalTime();
|
||||
if (currentTime.isBefore(startTime)) {
|
||||
if (startTime.isBefore(endTime)) {
|
||||
throw new ValidateException("生成支付订单失败,优惠券:" + coupon.getTitle() + " 当前时段不可用");
|
||||
} else if (currentTime.isAfter(endTime)) {
|
||||
throw new ValidateException("生成支付订单失败,优惠券:" + coupon.getTitle() + " 当前时段不可用");
|
||||
}
|
||||
} else if (startTime.isBefore(endTime)) {
|
||||
if (currentTime.isAfter(endTime)) {
|
||||
throw new ValidateException("生成支付订单失败,优惠券:" + coupon.getTitle() + " 当前时段不可用");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品优惠券计算
|
||||
*/
|
||||
private void foodsCalculate(List<OrderDetail> orderDetails, boolean isAllFoods, List<Long> couponFoodIds, int discountNum, boolean isAsc, BigDecimalDTO prodCouponAmount) {
|
||||
orderDetails = getDetailsSort(orderDetails, isAsc);
|
||||
BigDecimal remaining = new BigDecimal(discountNum);
|
||||
for (OrderDetail detail : orderDetails) {
|
||||
if ((isAllFoods || couponFoodIds.contains(detail.getProductId())) && detail.getUnitPrice().compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (remaining.compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (remaining.compareTo(detail.getNum().subtract(detail.getReturnNum())) >= 0) {
|
||||
detail.setCouponNum(detail.getNum().subtract(detail.getReturnNum()).setScale(2, RoundingMode.CEILING));
|
||||
detail.setDiscountAmount(detail.getPayAmount());
|
||||
detail.setPayAmount(BigDecimal.ZERO);
|
||||
remaining = remaining.subtract(detail.getNum().subtract(detail.getReturnNum()).setScale(2, RoundingMode.CEILING));
|
||||
} else {
|
||||
detail.setCouponNum(remaining);
|
||||
detail.setDiscountAmount(remaining.multiply(detail.getUnitPrice()).setScale(2, RoundingMode.DOWN));
|
||||
detail.setPayAmount(detail.getPayAmount().subtract(detail.getDiscountAmount()));
|
||||
remaining = BigDecimal.ZERO;
|
||||
}
|
||||
prodCouponAmount.setPrice(prodCouponAmount.getPrice().add(detail.getDiscountAmount()));
|
||||
}
|
||||
}
|
||||
if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 买一送一优惠券计算
|
||||
*/
|
||||
private void oneGiftCalculate(List<OrderDetail> orderDetails, boolean isAllFoods, List<Long> couponFoodIds, boolean isAsc, BigDecimalDTO oneGiftAmount) {
|
||||
orderDetails = getDetailsSort(orderDetails, isAsc);
|
||||
for (OrderDetail detail : orderDetails) {
|
||||
if ((isAllFoods || couponFoodIds.contains(detail.getProductId())) && couponFoodIds.contains(detail.getProductId())
|
||||
&& detail.getUnitPrice().compareTo(BigDecimal.ZERO) > 0
|
||||
&& detail.getNum().subtract(detail.getReturnNum()).subtract(detail.getCouponNum()).compareTo(BigDecimal.TWO) >= 0) {
|
||||
detail.setCouponNum(detail.getCouponNum().add(BigDecimal.ONE));
|
||||
detail.setDiscountAmount(detail.getDiscountAmount().add(detail.getUnitPrice()));
|
||||
detail.setPayAmount(detail.getPayAmount().subtract(detail.getUnitPrice()));
|
||||
oneGiftAmount.setPrice(detail.getUnitPrice());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 第二件半价优惠券计算
|
||||
*/
|
||||
private void twoHalfCalculate(List<OrderDetail> orderDetails, boolean isAllFoods, List<Long> couponFoodIds, boolean isAsc, BigDecimalDTO oneGiftAmount) {
|
||||
orderDetails = getDetailsSort(orderDetails, isAsc);
|
||||
for (OrderDetail detail : orderDetails) {
|
||||
if ((isAllFoods || couponFoodIds.contains(detail.getProductId())) && couponFoodIds.contains(detail.getProductId())
|
||||
&& detail.getUnitPrice().compareTo(BigDecimal.ZERO) > 0
|
||||
&& detail.getNum().subtract(detail.getReturnNum()).subtract(detail.getCouponNum()).compareTo(BigDecimal.TWO) >= 0) {
|
||||
detail.setHalfPriceCouponNum(BigDecimal.ONE);
|
||||
BigDecimal halfPrice = detail.getUnitPrice().divide(new BigDecimal("2").setScale(2, RoundingMode.FLOOR));
|
||||
detail.setDiscountAmount(detail.getDiscountAmount().add(halfPrice));
|
||||
detail.setPayAmount(detail.getPayAmount().subtract(halfPrice));
|
||||
oneGiftAmount.setPrice(halfPrice);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 满减券/折扣券 门槛计算
|
||||
*
|
||||
* @param couponFoodIds 门槛商品
|
||||
*/
|
||||
private void thresholdCalculate(List<OrderDetail> orderDetails, boolean isAllFoods, List<Long> couponFoodIds, BigDecimal thresholdAmount) {
|
||||
BigDecimal foodsAmount = BigDecimal.ZERO;
|
||||
for (OrderDetail detail : orderDetails) {
|
||||
if ((isAllFoods || couponFoodIds.contains(detail.getProductId())) || couponFoodIds.contains(detail.getProductId())
|
||||
&& detail.getUnitPrice().compareTo(BigDecimal.ZERO) > 0
|
||||
&& detail.getNum().subtract(detail.getReturnNum()).subtract(detail.getCouponNum()).compareTo(BigDecimal.ONE) >= 0) {
|
||||
foodsAmount = foodsAmount.add(detail.getPayAmount());
|
||||
if (foodsAmount.compareTo(thresholdAmount) >= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foodsAmount.compareTo(thresholdAmount) < 0) {
|
||||
throw new ValidateException("优惠券未达到门槛金额");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取价格排序后的orderDetail
|
||||
*
|
||||
* @param isAsc true为升序
|
||||
*/
|
||||
private List<OrderDetail> getDetailsSort(List<OrderDetail> orderDetails, boolean isAsc) {
|
||||
if (isAsc) {
|
||||
return orderDetails.stream()
|
||||
.sorted(Comparator.comparing(OrderDetail::getPrice))
|
||||
.toList();
|
||||
} else {
|
||||
return orderDetails.stream()
|
||||
.sorted(Comparator.comparing(OrderDetail::getPrice).reversed())
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getOrderAmount(List<OrderDetail> orderDetails, BigDecimalDTO totalAmount, BigDecimalDTO packAmount,
|
||||
BigDecimalDTO tempAmount, boolean isAllPack, Integer userAllPack, boolean isVipPrice) {
|
||||
for (OrderDetail orderDetail : orderDetails) {
|
||||
if (orderDetail.getDiscountSaleAmount() != null && orderDetail.getDiscountSaleAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
orderDetail.setUnitPrice(orderDetail.getDiscountSaleAmount());
|
||||
} else {
|
||||
if (isVipPrice) {
|
||||
orderDetail.setUnitPrice(
|
||||
(orderDetail.getMemberPrice() == null || orderDetail.getMemberPrice().compareTo(BigDecimal.ZERO) <= 0)
|
||||
? orderDetail.getPrice() : orderDetail.getMemberPrice());
|
||||
} else {
|
||||
orderDetail.setUnitPrice(orderDetail.getPrice());
|
||||
}
|
||||
}
|
||||
if (userAllPack != null) {
|
||||
if (userAllPack.equals(1)) {
|
||||
orderDetail.setPackNumber(orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
||||
if ("weight".equals(orderDetail.getProductType())) {
|
||||
orderDetail.setPackNumber(BigDecimal.ONE);
|
||||
}
|
||||
} else {
|
||||
orderDetail.setPackNumber(BigDecimal.ZERO);
|
||||
}
|
||||
} else if (isAllPack) {
|
||||
if ("weight".equals(orderDetail.getProductType())) {
|
||||
orderDetail.setPackNumber(BigDecimal.ONE);
|
||||
} else {
|
||||
orderDetail.setPackNumber(orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
||||
}
|
||||
} else {
|
||||
if ("weight".equals(orderDetail.getProductType()) && orderDetail.getPackNumber() != null && orderDetail.getPackNumber().compareTo(BigDecimal.ZERO) > 0) {
|
||||
orderDetail.setPackNumber(BigDecimal.ONE);
|
||||
}
|
||||
}
|
||||
orderDetail.setCouponNum(BigDecimal.ZERO);
|
||||
orderDetail.setPayAmount((orderDetail.getNum().subtract(orderDetail.getReturnNum())).multiply(orderDetail.getUnitPrice()).setScale(2, RoundingMode.DOWN));
|
||||
if (orderDetail.getIsTemporary() == 1) {
|
||||
tempAmount.setPrice(tempAmount.getPrice().add(orderDetail.getPayAmount()));
|
||||
}
|
||||
packAmount.setPrice(packAmount.getPrice().add(orderDetail.getPackAmount().multiply(orderDetail.getPackNumber()).setScale(2, RoundingMode.DOWN)));
|
||||
totalAmount.setPrice(totalAmount.getPrice().add(orderDetail.getPayAmount()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 填充 单价/付款金额
|
||||
*
|
||||
@@ -497,127 +796,6 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充 优惠券使用数量 以及 付款金额
|
||||
*
|
||||
* @param orderDetails 订单详情 需要回填 优惠券抵扣数量
|
||||
* @param prodCouponMap 使用优惠券<商品id,数量>
|
||||
* @param prodCouponAmount 商品券优惠金额 商品单价*优惠数量 的总和
|
||||
* @param totalAmount 最终总金额(没加打包费 餐位费) 去除优惠券金额后的
|
||||
*/
|
||||
@Override
|
||||
public void processOrderDetails2(List<OrderDetail> orderDetails, Map<Long, Integer> prodCouponMap,
|
||||
BigDecimalDTO prodCouponAmount, BigDecimalDTO totalAmount, BigDecimalDTO packAmount,
|
||||
boolean isAllPack, Integer userAllPack, boolean isVipPrice) {
|
||||
Map<Long, List<OrderDetail>> detailMap = new HashMap<>();
|
||||
for (OrderDetail detail : orderDetails) {
|
||||
detailMap.computeIfAbsent(detail.getProductId(), k -> new ArrayList<>()).add(detail);
|
||||
}
|
||||
List<OrderDetail> resultList = new ArrayList<>();
|
||||
for (Map.Entry<Long, List<OrderDetail>> entry : detailMap.entrySet()) {
|
||||
Long key = entry.getKey();
|
||||
List<OrderDetail> value = entry.getValue();
|
||||
BigDecimal couponNum = BigDecimal.ZERO;
|
||||
if (CollUtil.isNotEmpty(prodCouponMap) && prodCouponMap.containsKey(key)) {
|
||||
couponNum = new BigDecimal(prodCouponMap.get(key));
|
||||
if (value.size() > 1) {
|
||||
value.sort(Comparator.comparing(OrderDetail::getPrice));
|
||||
}
|
||||
}
|
||||
for (OrderDetail orderDetail : value) {
|
||||
if (orderDetail.getDiscountSaleAmount() != null && orderDetail.getDiscountSaleAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
orderDetail.setUnitPrice(orderDetail.getDiscountSaleAmount());
|
||||
} else {
|
||||
if (isVipPrice) {
|
||||
orderDetail.setUnitPrice(
|
||||
(orderDetail.getMemberPrice() == null || orderDetail.getMemberPrice().compareTo(BigDecimal.ZERO) <= 0)
|
||||
? orderDetail.getPrice() : orderDetail.getMemberPrice());
|
||||
} else {
|
||||
orderDetail.setUnitPrice(orderDetail.getPrice());
|
||||
}
|
||||
}
|
||||
if (userAllPack != null) {
|
||||
if (userAllPack.equals(1)) {
|
||||
orderDetail.setPackNumber(orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
||||
if ("weight".equals(orderDetail.getProductType())) {
|
||||
orderDetail.setPackNumber(BigDecimal.ONE);
|
||||
}
|
||||
} else {
|
||||
orderDetail.setPackNumber(BigDecimal.ZERO);
|
||||
}
|
||||
} else if (isAllPack) {
|
||||
if ("weight".equals(orderDetail.getProductType())) {
|
||||
orderDetail.setPackNumber(BigDecimal.ONE);
|
||||
} else {
|
||||
orderDetail.setPackNumber(orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
||||
}
|
||||
} else {
|
||||
if ("weight".equals(orderDetail.getProductType()) && orderDetail.getPackNumber() != null && orderDetail.getPackNumber().compareTo(BigDecimal.ZERO) > 0) {
|
||||
orderDetail.setPackNumber(BigDecimal.ONE);
|
||||
}
|
||||
}
|
||||
packAmount.setPrice(packAmount.getPrice().add(orderDetail.getPackAmount().multiply(orderDetail.getPackNumber()).setScale(2, RoundingMode.DOWN)));
|
||||
if (couponNum.compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (couponNum.compareTo(orderDetail.getNum()) >= 0) {
|
||||
orderDetail.setCouponNum(orderDetail.getNum());
|
||||
orderDetail.setPayAmount(BigDecimal.ZERO);
|
||||
couponNum = couponNum.subtract(orderDetail.getNum());
|
||||
} else {
|
||||
orderDetail.setCouponNum(couponNum);
|
||||
orderDetail.setPayAmount((orderDetail.getNum().subtract(orderDetail.getReturnNum()).subtract(couponNum)).multiply(orderDetail.getUnitPrice()).setScale(2, RoundingMode.DOWN));
|
||||
couponNum = BigDecimal.ZERO;
|
||||
}
|
||||
prodCouponAmount.setPrice((prodCouponAmount.getPrice().add(orderDetail.getUnitPrice())).multiply(orderDetail.getCouponNum()).setScale(2, RoundingMode.DOWN));
|
||||
} else {
|
||||
orderDetail.setCouponNum(BigDecimal.ZERO);
|
||||
orderDetail.setPayAmount((orderDetail.getNum().subtract(orderDetail.getReturnNum())).multiply(orderDetail.getUnitPrice()).setScale(2, RoundingMode.DOWN));
|
||||
}
|
||||
totalAmount.setPrice(totalAmount.getPrice().add(orderDetail.getPayAmount()));
|
||||
resultList.add(orderDetail);
|
||||
}
|
||||
// if (couponNum.compareTo(BigDecimal.ZERO) != 0) {
|
||||
// throw new ValidateException("生成支付订单失败,优惠券数量不正确");
|
||||
// }
|
||||
}
|
||||
orderDetails = resultList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验优惠券可用性
|
||||
*/
|
||||
private void checkCoupon(Map<Long, Integer> prodCouponMap, BigDecimalDTO fullAmount, BigDecimalDTO discountAmount, CheckOrderPay param) {
|
||||
if (CollUtil.isNotEmpty(param.getCouponList())) {
|
||||
//TODO 校验优惠券
|
||||
// //校验优惠券
|
||||
// List<ShopActivateCouponRecord> records = couponRecordService.listAs(
|
||||
// QueryWrapper.create()
|
||||
// .where(ShopActivateCouponRecord::getId).in(param.getCouponList())
|
||||
// .and(ShopActivateCouponRecord::getStatus).eq(0), ShopActivateCouponRecord.class);
|
||||
// if (CollUtil.isEmpty(records)) {
|
||||
// throw new ValidateException("生成支付订单失败,优惠券信息不存在");
|
||||
// } else if (records.size() != param.getCouponList().size()) {
|
||||
// throw new ValidateException("生成支付订单失败,优惠券信息不正确");
|
||||
// }
|
||||
// boolean isFullMinus = false;
|
||||
// for (ShopActivateCouponRecord record : records) {
|
||||
// if (record.getType().equals(1)) {
|
||||
// if (isFullMinus) {
|
||||
// throw new ValidateException("生成支付订单失败,满减券仅可使用一张");
|
||||
// }
|
||||
// fullAmount.setPrice(record.getFullAmount());
|
||||
// discountAmount.setPrice(record.getDiscountAmount());
|
||||
// isFullMinus = true;
|
||||
// } else if (record.getType().equals(2)) {
|
||||
// prodCouponMap.compute(record.getProId(), (key, oldValue) -> oldValue == null ? 1 : oldValue + 1);
|
||||
// }
|
||||
// }
|
||||
if (discountAmount.getPrice().compareTo(param.getFullCouponDiscountAmount()) != 0) {
|
||||
throw new ValidateException("生成支付订单失败,满减券减免金额不正确");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void payCallBackOrder(@NotBlank String orderNo, @NotNull JSONObject resultJson, int retryCount) {
|
||||
@@ -695,7 +873,7 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
}
|
||||
|
||||
}
|
||||
}else if ("memberPay".equals(payment.getPayType())) {
|
||||
} else if ("memberPay".equals(payment.getPayType())) {
|
||||
memberConfigService.joinMember(payment.getShopId(), payment.getSourceId(), payment.getRelatedId());
|
||||
}
|
||||
}
|
||||
@@ -784,7 +962,7 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
//券消耗
|
||||
List<Long> coupons = JSON.parseArray(orderInfo.getCouponInfoList(), Long.class);
|
||||
if (CollUtil.isNotEmpty(coupons)) {
|
||||
// couponService.use(coupons, shopUser.getId(), orderInfo.getId());
|
||||
couponService.use(coupons, shopUser.getId(), orderInfo.getId());
|
||||
}
|
||||
}
|
||||
String[] payTypes = {PayEnums.VIP_PAY.getValue(), PayEnums.CREDIT_PAY.getValue()};
|
||||
@@ -937,7 +1115,8 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
orderInfo.setOrderAmount(param.getOrderAmount());
|
||||
orderInfo.setPointsDiscountAmount(param.getPointsDiscountAmount());
|
||||
orderInfo.setProductCouponDiscountAmount(param.getProductCouponDiscountAmount());
|
||||
orderInfo.setFullCouponDiscountAmount(param.getFullCouponDiscountAmount());
|
||||
// orderInfo.setFullCouponDiscountAmount(param.getFullCouponDiscountAmount());
|
||||
orderInfo.setOtherCouponDiscountAmount(param.getOtherCouponDiscountAmount());
|
||||
orderInfo.setDiscountAmount(param.getDiscountAmount());
|
||||
//优惠券
|
||||
orderInfo.setCouponInfoList(CollUtil.isEmpty(param.getCouponList()) ? "" : JSONObject.toJSONString(param.getCouponList()));
|
||||
@@ -971,7 +1150,7 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
//券消耗
|
||||
List<Long> coupons = JSON.parseArray(orderInfo.getCouponInfoList(), Long.class);
|
||||
if (CollUtil.isNotEmpty(coupons)) {
|
||||
// couponService.use(coupons, shopUser.getId(), orderInfo.getId());
|
||||
couponService.use(coupons, shopUser.getId(), orderInfo.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -994,6 +1173,9 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
if (orderInfo.getFullCouponDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
jsonObject.put("满减券抵扣", orderInfo.getFullCouponDiscountAmount());
|
||||
}
|
||||
if(orderInfo.getOtherCouponDiscountAmount().compareTo(BigDecimal.ZERO) > 0){
|
||||
jsonObject.put("其它优惠券折扣", orderInfo.getOtherCouponDiscountAmount());
|
||||
}
|
||||
if (orderInfo.getPointsDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
jsonObject.put("积分抵扣", orderInfo.getPointsDiscountAmount());
|
||||
}
|
||||
|
||||
@@ -75,11 +75,11 @@ public class PayServiceImpl implements PayService {
|
||||
private UserInfoService userInfoService;
|
||||
@DubboReference
|
||||
private ShopInfoService shopInfoService;
|
||||
// @DubboReference
|
||||
// @DubboReference
|
||||
// private ShopActivateService shopActivateService;
|
||||
@DubboReference
|
||||
private ShopUserFlowService userFlowService;
|
||||
// @DubboReference
|
||||
// @DubboReference
|
||||
// private ShopCouponService couponService;
|
||||
@DubboReference
|
||||
private MemberPointsService pointsService;
|
||||
@@ -147,7 +147,8 @@ public class PayServiceImpl implements PayService {
|
||||
BigDecimalDTO totalAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
//最终打包费
|
||||
BigDecimalDTO packAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
orderInfoService.processOrderDetails2(orderDetails, null, null, totalAmount, packAmount, payParam.isAllPack(), payParam.getUserAllPack(), false);
|
||||
BigDecimalDTO tempAmount = new BigDecimalDTO(BigDecimal.ZERO);
|
||||
orderInfoService.getOrderAmount(orderDetails, totalAmount, packAmount, tempAmount, payParam.isAllPack(), payParam.getUserAllPack(), false);
|
||||
BigDecimal total = totalAmount.getPrice().add(packAmount.getPrice());
|
||||
if (total.compareTo(freeConfig.getRechargeThreshold()) < 0) {
|
||||
throw new CzgException("霸王餐满" + freeConfig.getRechargeThreshold() + "可用,当前订单金额为" + total);
|
||||
|
||||
Reference in New Issue
Block a user