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.VoucherInfo;
|
||||
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.IProductConfigService;
|
||||
import com.ycwl.basic.pricing.service.IVoucherService;
|
||||
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||
import com.ycwl.basic.pay.entity.CreateOrderRequest;
|
||||
@@ -63,6 +67,7 @@ public class OrderServiceImpl implements IOrderService {
|
||||
private final MemberMapper memberMapper;
|
||||
private final ICouponService couponService;
|
||||
private final IVoucherService voucherService;
|
||||
private final IProductConfigService productConfigService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -104,15 +109,18 @@ public class OrderServiceImpl implements IOrderService {
|
||||
|
||||
// 3. 保存订单商品明细
|
||||
for (ProductItem product : request.getProducts()) {
|
||||
// 重新计算商品价格信息并获取商品名称
|
||||
ProductPriceAndNameInfo priceInfo = calculateProductItemPriceAndName(product);
|
||||
|
||||
OrderItemV2 orderItem = new OrderItemV2();
|
||||
orderItem.setOrderId(orderId);
|
||||
orderItem.setProductType(product.getProductType().name());
|
||||
orderItem.setProductId(product.getProductId());
|
||||
orderItem.setProductName(getProductName(product)); // 根据商品类型和ID获取商品名称
|
||||
orderItem.setProductName(priceInfo.getProductName()); // 使用配置中的商品名称
|
||||
orderItem.setQuantity(product.getQuantity() != null ? product.getQuantity() : 1);
|
||||
orderItem.setUnitPrice(product.getUnitPrice() != null ? product.getUnitPrice() : BigDecimal.ZERO);
|
||||
orderItem.setOriginalAmount(product.getOriginalPrice() != null ? product.getOriginalPrice() : BigDecimal.ZERO);
|
||||
orderItem.setFinalAmount(product.getSubtotal() != null ? product.getSubtotal() : BigDecimal.ZERO);
|
||||
orderItem.setUnitPrice(product.getUnitPrice());
|
||||
orderItem.setOriginalAmount(product.getOriginalPrice());
|
||||
orderItem.setFinalAmount(product.getSubtotal());
|
||||
orderItem.setCreateTime(now);
|
||||
orderItem.setUpdateTime(now);
|
||||
|
||||
@@ -256,14 +264,6 @@ public class OrderServiceImpl implements IOrderService {
|
||||
return "ORDER" + timestamp + random;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品类型和ID获取商品名称
|
||||
* TODO: 实际应该从商品配置表或其他数据源获取
|
||||
*/
|
||||
private String getProductName(ProductItem product) {
|
||||
return product.getProductType().getDescription() + "-" + product.getProductId();
|
||||
}
|
||||
|
||||
// ====== 新增方法实现 ======
|
||||
|
||||
@Override
|
||||
@@ -769,4 +769,116 @@ public class OrderServiceImpl implements IOrderService {
|
||||
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