You've already forked FrameTour-BE
feat(voucher): 增加券码适用商品类型功能
- 在 VoucherBatchCreateReq、VoucherBatchResp 和 VoucherInfo 中添加适用商品类型列表字段 - 在 PriceVoucherBatchConfig 中添加适用商品类型列表字段,并使用 ProductTypeListTypeHandler 进行 JSON 序列化和反序列化 - 实现 ProductTypeListTypeHandler 以处理商品类型列表的 JSON 序列化和反序列化 - 更新 VoucherBatchServiceImpl 和 VoucherServiceImpl 以支持适用商品类型的筛选和计算
This commit is contained in:
@@ -190,6 +190,7 @@ public class VoucherBatchServiceImpl implements VoucherBatchService {
|
||||
|
||||
resp.setStatusName(batch.getStatus() == 1 ? "启用" : "禁用");
|
||||
resp.setAvailableCount(batch.getTotalCount() - batch.getClaimedCount());
|
||||
resp.setApplicableProducts(batch.getApplicableProducts());
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ycwl.basic.pricing.service.impl;
|
||||
import com.ycwl.basic.pricing.dto.DiscountDetectionContext;
|
||||
import com.ycwl.basic.pricing.dto.ProductItem;
|
||||
import com.ycwl.basic.pricing.dto.VoucherInfo;
|
||||
import com.ycwl.basic.pricing.enums.ProductType;
|
||||
import com.ycwl.basic.pricing.entity.PriceVoucherBatchConfig;
|
||||
import com.ycwl.basic.pricing.entity.PriceVoucherCode;
|
||||
import com.ycwl.basic.pricing.enums.VoucherCodeStatus;
|
||||
@@ -197,32 +198,40 @@ public class VoucherServiceImpl implements IVoucherService {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 筛选适用的商品
|
||||
List<ProductItem> applicableItems = filterApplicableProducts(context.getProducts(), voucherInfo.getApplicableProducts());
|
||||
if (applicableItems.isEmpty()) {
|
||||
log.debug("券码 {} 没有适用的商品", voucherInfo.getVoucherCode());
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
return switch (discountType) {
|
||||
case FREE_ALL -> {
|
||||
// 全场免费,返回当前总金额
|
||||
yield context.getCurrentAmount() != null ? context.getCurrentAmount() : BigDecimal.ZERO;
|
||||
// 全场免费,计算适用商品的总金额
|
||||
BigDecimal applicableAmount = calculateApplicableAmount(applicableItems, context);
|
||||
yield applicableAmount;
|
||||
}
|
||||
case REDUCE_PRICE -> {
|
||||
// 商品降价,每个商品减免固定金额
|
||||
// 商品降价,每个适用商品减免固定金额
|
||||
if (discountValue == null || discountValue.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
yield BigDecimal.ZERO;
|
||||
}
|
||||
BigDecimal totalDiscount = BigDecimal.ZERO;
|
||||
for (ProductItem product : context.getProducts()) {
|
||||
for (ProductItem product : applicableItems) {
|
||||
BigDecimal productDiscount = discountValue.multiply(BigDecimal.valueOf(product.getQuantity()));
|
||||
totalDiscount = totalDiscount.add(productDiscount);
|
||||
}
|
||||
yield totalDiscount;
|
||||
}
|
||||
case DISCOUNT -> {
|
||||
// 商品打折,按百分比计算
|
||||
// 商品打折,按适用商品的金额比例计算
|
||||
if (discountValue == null || discountValue.compareTo(BigDecimal.ZERO) <= 0 ||
|
||||
discountValue.compareTo(BigDecimal.valueOf(100)) >= 0) {
|
||||
yield BigDecimal.ZERO;
|
||||
}
|
||||
BigDecimal currentAmount = context.getCurrentAmount() != null ? context.getCurrentAmount() : BigDecimal.ZERO;
|
||||
BigDecimal applicableAmount = calculateApplicableAmount(applicableItems, context);
|
||||
BigDecimal discountRate = discountValue.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
|
||||
yield currentAmount.multiply(discountRate).setScale(2, RoundingMode.HALF_UP);
|
||||
yield applicableAmount.multiply(discountRate).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -267,7 +276,44 @@ public class VoucherServiceImpl implements IVoucherService {
|
||||
voucherInfo.setStatus(voucherCode.getStatus());
|
||||
voucherInfo.setClaimedTime(voucherCode.getClaimedTime());
|
||||
voucherInfo.setUsedTime(voucherCode.getUsedTime());
|
||||
voucherInfo.setApplicableProducts(batchConfig.getApplicableProducts());
|
||||
|
||||
return voucherInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选适用的商品
|
||||
*/
|
||||
private List<ProductItem> filterApplicableProducts(List<ProductItem> products, List<ProductType> applicableProducts) {
|
||||
if (applicableProducts == null || applicableProducts.isEmpty()) {
|
||||
// null或空列表表示适用所有商品类型
|
||||
return products;
|
||||
}
|
||||
|
||||
return products.stream()
|
||||
.filter(product -> {
|
||||
try {
|
||||
ProductType productType = ProductType.fromCode(product.getProductType());
|
||||
return applicableProducts.contains(productType);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("未知的商品类型: {}", product.getProductType());
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算适用商品的总金额
|
||||
*/
|
||||
private BigDecimal calculateApplicableAmount(List<ProductItem> applicableItems, DiscountDetectionContext context) {
|
||||
// 简单计算:基于商品数量和单价
|
||||
// 在实际应用中可能需要更复杂的计算逻辑
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
for (ProductItem item : applicableItems) {
|
||||
BigDecimal itemAmount = item.getUnitPrice().multiply(BigDecimal.valueOf(item.getQuantity()));
|
||||
totalAmount = totalAmount.add(itemAmount);
|
||||
}
|
||||
return totalAmount;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user