From 93a424058ac1e6987763d09cfaea4121f1c5cc81 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 29 Aug 2025 17:39:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(order):=20=E4=BC=98=E5=8C=96=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E5=88=9B=E5=BB=BA=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=95=86=E5=93=81=E4=BB=B7=E6=A0=BC=E5=92=8C=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 calculateProductItemPriceAndName 方法,用于重新计算商品价格信息并获取商品名称 - 更新订单创建流程,使用计算后的商品价格和名称信息 - 引入 IProductConfigService 接口,用于获取商品配置信息 - 优化异常处理,确保在价格计算失败时有兜底方案 --- .../order/service/impl/OrderServiceImpl.java | 136 ++++++++++++++++-- 1 file changed, 124 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ycwl/basic/order/service/impl/OrderServiceImpl.java b/src/main/java/com/ycwl/basic/order/service/impl/OrderServiceImpl.java index 471bc9b..1c78eb0 100644 --- a/src/main/java/com/ycwl/basic/order/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/ycwl/basic/order/service/impl/OrderServiceImpl.java @@ -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); + } + } } \ No newline at end of file