You've already forked FrameTour-BE
feat(order): 优化订单创建逻辑,增加商品价格和名称计算
- 新增 calculateProductItemPriceAndName 方法,用于重新计算商品价格信息并获取商品名称 - 更新订单创建流程,使用计算后的商品价格和名称信息 - 引入 IProductConfigService 接口,用于获取商品配置信息 - 优化异常处理,确保在价格计算失败时有兜底方案
This commit is contained in:
@@ -25,7 +25,11 @@ import com.ycwl.basic.pricing.dto.PriceCalculationResult;
|
|||||||
import com.ycwl.basic.pricing.dto.ProductItem;
|
import com.ycwl.basic.pricing.dto.ProductItem;
|
||||||
import com.ycwl.basic.pricing.dto.VoucherInfo;
|
import com.ycwl.basic.pricing.dto.VoucherInfo;
|
||||||
import com.ycwl.basic.pricing.dto.CouponUseRequest;
|
import com.ycwl.basic.pricing.dto.CouponUseRequest;
|
||||||
|
import com.ycwl.basic.pricing.entity.PriceProductConfig;
|
||||||
|
import com.ycwl.basic.pricing.entity.PriceTierConfig;
|
||||||
|
import com.ycwl.basic.pricing.exception.PriceCalculationException;
|
||||||
import com.ycwl.basic.pricing.service.ICouponService;
|
import com.ycwl.basic.pricing.service.ICouponService;
|
||||||
|
import com.ycwl.basic.pricing.service.IProductConfigService;
|
||||||
import com.ycwl.basic.pricing.service.IVoucherService;
|
import com.ycwl.basic.pricing.service.IVoucherService;
|
||||||
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||||
import com.ycwl.basic.pay.entity.CreateOrderRequest;
|
import com.ycwl.basic.pay.entity.CreateOrderRequest;
|
||||||
@@ -63,6 +67,7 @@ public class OrderServiceImpl implements IOrderService {
|
|||||||
private final MemberMapper memberMapper;
|
private final MemberMapper memberMapper;
|
||||||
private final ICouponService couponService;
|
private final ICouponService couponService;
|
||||||
private final IVoucherService voucherService;
|
private final IVoucherService voucherService;
|
||||||
|
private final IProductConfigService productConfigService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@@ -104,15 +109,18 @@ public class OrderServiceImpl implements IOrderService {
|
|||||||
|
|
||||||
// 3. 保存订单商品明细
|
// 3. 保存订单商品明细
|
||||||
for (ProductItem product : request.getProducts()) {
|
for (ProductItem product : request.getProducts()) {
|
||||||
|
// 重新计算商品价格信息并获取商品名称
|
||||||
|
ProductPriceAndNameInfo priceInfo = calculateProductItemPriceAndName(product);
|
||||||
|
|
||||||
OrderItemV2 orderItem = new OrderItemV2();
|
OrderItemV2 orderItem = new OrderItemV2();
|
||||||
orderItem.setOrderId(orderId);
|
orderItem.setOrderId(orderId);
|
||||||
orderItem.setProductType(product.getProductType().name());
|
orderItem.setProductType(product.getProductType().name());
|
||||||
orderItem.setProductId(product.getProductId());
|
orderItem.setProductId(product.getProductId());
|
||||||
orderItem.setProductName(getProductName(product)); // 根据商品类型和ID获取商品名称
|
orderItem.setProductName(priceInfo.getProductName()); // 使用配置中的商品名称
|
||||||
orderItem.setQuantity(product.getQuantity() != null ? product.getQuantity() : 1);
|
orderItem.setQuantity(product.getQuantity() != null ? product.getQuantity() : 1);
|
||||||
orderItem.setUnitPrice(product.getUnitPrice() != null ? product.getUnitPrice() : BigDecimal.ZERO);
|
orderItem.setUnitPrice(product.getUnitPrice());
|
||||||
orderItem.setOriginalAmount(product.getOriginalPrice() != null ? product.getOriginalPrice() : BigDecimal.ZERO);
|
orderItem.setOriginalAmount(product.getOriginalPrice());
|
||||||
orderItem.setFinalAmount(product.getSubtotal() != null ? product.getSubtotal() : BigDecimal.ZERO);
|
orderItem.setFinalAmount(product.getSubtotal());
|
||||||
orderItem.setCreateTime(now);
|
orderItem.setCreateTime(now);
|
||||||
orderItem.setUpdateTime(now);
|
orderItem.setUpdateTime(now);
|
||||||
|
|
||||||
@@ -256,14 +264,6 @@ public class OrderServiceImpl implements IOrderService {
|
|||||||
return "ORDER" + timestamp + random;
|
return "ORDER" + timestamp + random;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据商品类型和ID获取商品名称
|
|
||||||
* TODO: 实际应该从商品配置表或其他数据源获取
|
|
||||||
*/
|
|
||||||
private String getProductName(ProductItem product) {
|
|
||||||
return product.getProductType().getDescription() + "-" + product.getProductId();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====== 新增方法实现 ======
|
// ====== 新增方法实现 ======
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -769,4 +769,116 @@ public class OrderServiceImpl implements IOrderService {
|
|||||||
default -> "景区商品";
|
default -> "景区商品";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品价格和名称信息内部DTO
|
||||||
|
*/
|
||||||
|
private static class ProductPriceAndNameInfo {
|
||||||
|
private BigDecimal unitPrice;
|
||||||
|
private BigDecimal originalPrice;
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
public ProductPriceAndNameInfo(BigDecimal unitPrice, BigDecimal originalPrice, String productName) {
|
||||||
|
this.unitPrice = unitPrice;
|
||||||
|
this.originalPrice = originalPrice;
|
||||||
|
this.productName = productName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getUnitPrice() { return unitPrice; }
|
||||||
|
public BigDecimal getOriginalPrice() { return originalPrice; }
|
||||||
|
public String getProductName() { return productName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新计算商品价格信息并获取商品名称
|
||||||
|
* 基于定价配置重新计算商品的单价、原价和商品名称
|
||||||
|
*/
|
||||||
|
private ProductPriceAndNameInfo calculateProductItemPriceAndName(ProductItem product) {
|
||||||
|
String productTypeCode = product.getProductType().getCode();
|
||||||
|
String productId = product.getProductId() != null ? product.getProductId() : "default";
|
||||||
|
|
||||||
|
BigDecimal unitPrice;
|
||||||
|
BigDecimal originalPrice;
|
||||||
|
String productName;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 优先使用基于product_id的阶梯定价
|
||||||
|
PriceTierConfig tierConfig = productConfigService.getTierConfig(
|
||||||
|
productTypeCode, productId, product.getQuantity());
|
||||||
|
|
||||||
|
if (tierConfig != null) {
|
||||||
|
unitPrice = tierConfig.getPrice();
|
||||||
|
originalPrice = tierConfig.getOriginalPrice();
|
||||||
|
|
||||||
|
// 阶梯定价没有商品名称,需要从基础配置获取
|
||||||
|
PriceProductConfig baseConfig = productConfigService.getProductConfig(productTypeCode, productId);
|
||||||
|
productName = (baseConfig != null && baseConfig.getProductName() != null)
|
||||||
|
? baseConfig.getProductName()
|
||||||
|
: getProductTypeName(product.getProductType().name());
|
||||||
|
|
||||||
|
log.debug("使用阶梯定价: productType={}, productId={}, quantity={}, price={}, originalPrice={}, productName={}",
|
||||||
|
productTypeCode, productId, product.getQuantity(), unitPrice, originalPrice, productName);
|
||||||
|
} else {
|
||||||
|
// 2. 使用基于product_id的基础配置
|
||||||
|
PriceProductConfig baseConfig;
|
||||||
|
try {
|
||||||
|
baseConfig = productConfigService.getProductConfig(productTypeCode, productId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("未找到具体商品配置: productType={}, productId={}, 使用default配置",
|
||||||
|
productTypeCode, productId);
|
||||||
|
baseConfig = productConfigService.getProductConfig(productTypeCode, "default");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseConfig == null) {
|
||||||
|
throw new PriceCalculationException(
|
||||||
|
String.format("未找到商品价格配置: productType=%s, productId=%s", productTypeCode, productId));
|
||||||
|
}
|
||||||
|
|
||||||
|
unitPrice = baseConfig.getBasePrice();
|
||||||
|
originalPrice = baseConfig.getOriginalPrice();
|
||||||
|
productName = (baseConfig.getProductName() != null)
|
||||||
|
? baseConfig.getProductName()
|
||||||
|
: getProductTypeName(product.getProductType().name());
|
||||||
|
|
||||||
|
// 3. 处理按数量计价的商品类型
|
||||||
|
if (product.getProductType() == com.ycwl.basic.pricing.enums.ProductType.PHOTO_PRINT ||
|
||||||
|
product.getProductType() == com.ycwl.basic.pricing.enums.ProductType.MACHINE_PRINT) {
|
||||||
|
if (product.getQuantity() != null && product.getQuantity() > 0) {
|
||||||
|
unitPrice = unitPrice.multiply(BigDecimal.valueOf(product.getQuantity()));
|
||||||
|
if (originalPrice != null) {
|
||||||
|
originalPrice = originalPrice.multiply(BigDecimal.valueOf(product.getQuantity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 设置计算后的价格到ProductItem
|
||||||
|
product.setUnitPrice(unitPrice);
|
||||||
|
product.setOriginalPrice(originalPrice != null ? originalPrice : unitPrice);
|
||||||
|
|
||||||
|
// 5. 计算小计(单价 × 购买数量)
|
||||||
|
int purchaseCount = product.getPurchaseCount() != null ? product.getPurchaseCount() : 1;
|
||||||
|
BigDecimal subtotal = unitPrice.multiply(BigDecimal.valueOf(purchaseCount));
|
||||||
|
product.setSubtotal(subtotal);
|
||||||
|
|
||||||
|
log.debug("商品价格和名称计算完成: productType={}, productId={}, unitPrice={}, originalPrice={}, subtotal={}, productName={}",
|
||||||
|
productTypeCode, productId, unitPrice, originalPrice, subtotal, productName);
|
||||||
|
|
||||||
|
return new ProductPriceAndNameInfo(unitPrice, originalPrice != null ? originalPrice : unitPrice, productName);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("计算商品价格失败: productType={}, productId={}, error={}",
|
||||||
|
productTypeCode, productId, e.getMessage(), e);
|
||||||
|
|
||||||
|
// 兜底处理:使用默认价格和类型名称
|
||||||
|
BigDecimal defaultPrice = BigDecimal.ZERO;
|
||||||
|
String fallbackName = getProductTypeName(product.getProductType().name());
|
||||||
|
|
||||||
|
product.setUnitPrice(defaultPrice);
|
||||||
|
product.setOriginalPrice(defaultPrice);
|
||||||
|
product.setSubtotal(defaultPrice);
|
||||||
|
|
||||||
|
return new ProductPriceAndNameInfo(defaultPrice, defaultPrice, fallbackName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user