|
|
|
|
@@ -33,6 +33,9 @@ import java.util.Set;
|
|
|
|
|
public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
|
|
|
|
|
private static final String CAPABILITY_METADATA_ATTRIBUTE_KEYS = "pricingAttributeKeys";
|
|
|
|
|
private static final int AMOUNT_SCALE = 2;
|
|
|
|
|
private static final String UPGRADE_TYPE_ONE_PRICE = "ONE_PRICE";
|
|
|
|
|
private static final String UPGRADE_TYPE_BUNDLE_DISCOUNT = "BUNDLE_DISCOUNT";
|
|
|
|
|
|
|
|
|
|
private final IProductConfigService productConfigService;
|
|
|
|
|
private final ICouponService couponService;
|
|
|
|
|
@@ -166,7 +169,7 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
if (request == null) {
|
|
|
|
|
throw new PriceCalculationException("升单检测请求不能为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ProductItem> purchasedProducts = cloneProducts(request.getPurchasedProducts());
|
|
|
|
|
List<ProductItem> intendingProducts = cloneProducts(request.getIntendingProducts());
|
|
|
|
|
|
|
|
|
|
@@ -176,29 +179,34 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
|
|
|
|
|
normalizeProducts(purchasedProducts);
|
|
|
|
|
normalizeProducts(intendingProducts);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Long scenicId = request.getScenicId();
|
|
|
|
|
PriceDetails purchasedDetails = purchasedProducts.isEmpty()
|
|
|
|
|
? new PriceDetails(BigDecimal.ZERO, BigDecimal.ZERO)
|
|
|
|
|
: calculateProductsPriceWithOriginal(purchasedProducts);
|
|
|
|
|
: calculateProductsPriceWithOriginal(purchasedProducts, scenicId);
|
|
|
|
|
PriceDetails intendingDetails = intendingProducts.isEmpty()
|
|
|
|
|
? new PriceDetails(BigDecimal.ZERO, BigDecimal.ZERO)
|
|
|
|
|
: calculateProductsPriceWithOriginal(intendingProducts);
|
|
|
|
|
|
|
|
|
|
: calculateProductsPriceWithOriginal(intendingProducts, scenicId);
|
|
|
|
|
|
|
|
|
|
List<ProductItem> combinedProducts = new ArrayList<>();
|
|
|
|
|
combinedProducts.addAll(purchasedProducts);
|
|
|
|
|
combinedProducts.addAll(intendingProducts);
|
|
|
|
|
PriceDetails combinedDetails = calculateProductsPriceWithOriginal(combinedProducts);
|
|
|
|
|
|
|
|
|
|
UpgradePriceSummary priceSummary = buildPriceSummary(purchasedDetails, intendingDetails, combinedDetails);
|
|
|
|
|
UpgradeOnePriceResult onePriceResult = evaluateOnePrice(request.getScenicId(), combinedProducts, combinedDetails);
|
|
|
|
|
UpgradeBundleDiscountResult bundleDiscountResult = evaluateBundleDiscount(request.getScenicId(), combinedProducts, combinedDetails);
|
|
|
|
|
|
|
|
|
|
PriceDetails combinedDetails = calculateProductsPriceWithOriginal(combinedProducts, scenicId);
|
|
|
|
|
|
|
|
|
|
BigDecimal paidAmount = resolvePaidAmount(request, purchasedDetails);
|
|
|
|
|
BigDecimal currentTotalAmount = calculateCurrentTotalAmount(paidAmount, intendingDetails);
|
|
|
|
|
|
|
|
|
|
UpgradePriceSummary priceSummary = buildPriceSummary(purchasedDetails, intendingDetails, combinedDetails, paidAmount);
|
|
|
|
|
UpgradeOnePriceResult onePriceResult = evaluateOnePrice(scenicId, combinedProducts, combinedDetails, paidAmount, currentTotalAmount);
|
|
|
|
|
UpgradeBundleDiscountResult bundleDiscountResult = evaluateBundleDiscount(scenicId, combinedProducts, combinedDetails, paidAmount, currentTotalAmount);
|
|
|
|
|
|
|
|
|
|
UpgradeCheckResult result = new UpgradeCheckResult();
|
|
|
|
|
result.setScenicId(request.getScenicId());
|
|
|
|
|
result.setScenicId(scenicId);
|
|
|
|
|
result.setFaceId(request.getFaceId());
|
|
|
|
|
result.setPriceSummary(priceSummary);
|
|
|
|
|
result.setOnePriceResult(onePriceResult);
|
|
|
|
|
result.setBundleDiscountResult(bundleDiscountResult);
|
|
|
|
|
fillBestUpgrade(result, onePriceResult, bundleDiscountResult);
|
|
|
|
|
result.setPurchasedProducts(purchasedProducts);
|
|
|
|
|
result.setIntendingProducts(intendingProducts);
|
|
|
|
|
return result;
|
|
|
|
|
@@ -435,7 +443,7 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
return new ProductPriceInfo(actualPrice, originalPrice);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private UpgradePriceSummary buildPriceSummary(PriceDetails purchased, PriceDetails intending, PriceDetails combined) {
|
|
|
|
|
private UpgradePriceSummary buildPriceSummary(PriceDetails purchased, PriceDetails intending, PriceDetails combined, BigDecimal paidAmount) {
|
|
|
|
|
UpgradePriceSummary summary = new UpgradePriceSummary();
|
|
|
|
|
summary.setPurchasedOriginalAmount(purchased.getOriginalTotalAmount());
|
|
|
|
|
summary.setPurchasedSubtotalAmount(purchased.getTotalAmount());
|
|
|
|
|
@@ -443,10 +451,15 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
summary.setIntendingSubtotalAmount(intending.getTotalAmount());
|
|
|
|
|
summary.setCombinedOriginalAmount(combined.getOriginalTotalAmount());
|
|
|
|
|
summary.setCombinedSubtotalAmount(combined.getTotalAmount());
|
|
|
|
|
summary.setPaidAmount(paidAmount);
|
|
|
|
|
return summary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private UpgradeOnePriceResult evaluateOnePrice(Long scenicId, List<ProductItem> combinedProducts, PriceDetails combinedDetails) {
|
|
|
|
|
private UpgradeOnePriceResult evaluateOnePrice(Long scenicId,
|
|
|
|
|
List<ProductItem> combinedProducts,
|
|
|
|
|
PriceDetails combinedDetails,
|
|
|
|
|
BigDecimal paidAmount,
|
|
|
|
|
BigDecimal currentTotalAmount) {
|
|
|
|
|
UpgradeOnePriceResult result = new UpgradeOnePriceResult();
|
|
|
|
|
result.setApplicable(false);
|
|
|
|
|
|
|
|
|
|
@@ -458,23 +471,32 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
BigDecimal bundlePrice = bundleConfig.getBundlePrice() != null
|
|
|
|
|
? bundleConfig.getBundlePrice()
|
|
|
|
|
: combinedDetails.getTotalAmount();
|
|
|
|
|
BigDecimal discountAmount = combinedDetails.getTotalAmount().subtract(bundlePrice);
|
|
|
|
|
if (discountAmount.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
|
|
discountAmount = BigDecimal.ZERO;
|
|
|
|
|
BigDecimal normalizedBundlePrice = normalizeAmount(bundlePrice);
|
|
|
|
|
BigDecimal normalizedCurrentTotal = normalizeAmount(currentTotalAmount);
|
|
|
|
|
BigDecimal normalizedPaidAmount = normalizeAmount(paidAmount);
|
|
|
|
|
|
|
|
|
|
if (!isUpgradeBeneficial(normalizedCurrentTotal, normalizedBundlePrice)) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BigDecimal discountAmount = normalizedCurrentTotal.subtract(normalizedBundlePrice);
|
|
|
|
|
|
|
|
|
|
result.setApplicable(true);
|
|
|
|
|
result.setBundleConfigId(bundleConfig.getId());
|
|
|
|
|
result.setBundleName(bundleConfig.getBundleName());
|
|
|
|
|
result.setDescription(bundleConfig.getDescription());
|
|
|
|
|
result.setScenicId(bundleConfig.getScenicId());
|
|
|
|
|
result.setBundlePrice(bundlePrice);
|
|
|
|
|
result.setBundlePrice(normalizedBundlePrice);
|
|
|
|
|
result.setDiscountAmount(discountAmount);
|
|
|
|
|
result.setEstimatedFinalAmount(bundlePrice);
|
|
|
|
|
result.setEstimatedFinalAmount(calculateSupplementAmount(normalizedBundlePrice, normalizedPaidAmount));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private UpgradeBundleDiscountResult evaluateBundleDiscount(Long scenicId, List<ProductItem> combinedProducts, PriceDetails combinedDetails) {
|
|
|
|
|
private UpgradeBundleDiscountResult evaluateBundleDiscount(Long scenicId,
|
|
|
|
|
List<ProductItem> combinedProducts,
|
|
|
|
|
PriceDetails combinedDetails,
|
|
|
|
|
BigDecimal paidAmount,
|
|
|
|
|
BigDecimal currentTotalAmount) {
|
|
|
|
|
UpgradeBundleDiscountResult result = new UpgradeBundleDiscountResult();
|
|
|
|
|
result.setApplicable(false);
|
|
|
|
|
|
|
|
|
|
@@ -491,21 +513,28 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BigDecimal normalizedPaidAmount = normalizeAmount(paidAmount);
|
|
|
|
|
BigDecimal normalizedCurrentTotal = normalizeAmount(currentTotalAmount);
|
|
|
|
|
BigDecimal normalizedDiscount = normalizeAmount(discountAmount);
|
|
|
|
|
BigDecimal targetTotal = combinedDetails.getTotalAmount().subtract(normalizedDiscount);
|
|
|
|
|
if (targetTotal.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
|
|
targetTotal = BigDecimal.ZERO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isUpgradeBeneficial(normalizedCurrentTotal, targetTotal)) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.setApplicable(true);
|
|
|
|
|
result.setBundleConfigId(bestDiscount.getBundleConfigId());
|
|
|
|
|
result.setBundleName(bestDiscount.getBundleName());
|
|
|
|
|
result.setBundleDescription(bestDiscount.getBundleDescription());
|
|
|
|
|
result.setDiscountType(bestDiscount.getDiscountType());
|
|
|
|
|
result.setDiscountValue(bestDiscount.getDiscountValue());
|
|
|
|
|
result.setDiscountAmount(discountAmount);
|
|
|
|
|
result.setDiscountAmount(normalizedDiscount);
|
|
|
|
|
result.setMinQuantity(bestDiscount.getMinQuantity());
|
|
|
|
|
result.setMinAmount(bestDiscount.getMinAmount());
|
|
|
|
|
|
|
|
|
|
BigDecimal finalAmount = combinedDetails.getTotalAmount().subtract(discountAmount);
|
|
|
|
|
if (finalAmount.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
|
|
finalAmount = BigDecimal.ZERO;
|
|
|
|
|
}
|
|
|
|
|
result.setEstimatedFinalAmount(finalAmount);
|
|
|
|
|
result.setEstimatedFinalAmount(calculateSupplementAmount(targetTotal, normalizedPaidAmount));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -562,6 +591,71 @@ public class PriceCalculationServiceImpl implements IPriceCalculationService {
|
|
|
|
|
}
|
|
|
|
|
return configScenicId.equals(String.valueOf(scenicId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BigDecimal resolvePaidAmount(UpgradeCheckRequest request, PriceDetails purchasedDetails) {
|
|
|
|
|
BigDecimal paidAmount = request != null ? request.getPaidAmount() : null;
|
|
|
|
|
if (paidAmount == null && purchasedDetails != null) {
|
|
|
|
|
paidAmount = purchasedDetails.getTotalAmount();
|
|
|
|
|
}
|
|
|
|
|
return normalizeAmount(paidAmount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BigDecimal calculateCurrentTotalAmount(BigDecimal paidAmount, PriceDetails intendingDetails) {
|
|
|
|
|
BigDecimal intendingAmount = intendingDetails != null ? intendingDetails.getTotalAmount() : BigDecimal.ZERO;
|
|
|
|
|
BigDecimal normalizedPaidAmount = normalizeAmount(paidAmount);
|
|
|
|
|
BigDecimal normalizedIntendingAmount = normalizeAmount(intendingAmount);
|
|
|
|
|
return normalizedPaidAmount.add(normalizedIntendingAmount).setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BigDecimal calculateSupplementAmount(BigDecimal targetTotalAmount, BigDecimal paidAmount) {
|
|
|
|
|
BigDecimal normalizedTarget = normalizeAmount(targetTotalAmount);
|
|
|
|
|
BigDecimal normalizedPaid = normalizeAmount(paidAmount);
|
|
|
|
|
BigDecimal supplementAmount = normalizedTarget.subtract(normalizedPaid);
|
|
|
|
|
if (supplementAmount.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
|
|
supplementAmount = BigDecimal.ZERO;
|
|
|
|
|
}
|
|
|
|
|
return supplementAmount.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean isUpgradeBeneficial(BigDecimal currentTotalAmount, BigDecimal targetTotalAmount) {
|
|
|
|
|
BigDecimal normalizedCurrent = normalizeAmount(currentTotalAmount);
|
|
|
|
|
BigDecimal normalizedTarget = normalizeAmount(targetTotalAmount);
|
|
|
|
|
return normalizedCurrent.compareTo(normalizedTarget) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BigDecimal normalizeAmount(BigDecimal amount) {
|
|
|
|
|
if (amount == null) {
|
|
|
|
|
return BigDecimal.ZERO.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
}
|
|
|
|
|
BigDecimal normalized = amount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : amount;
|
|
|
|
|
return normalized.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void fillBestUpgrade(UpgradeCheckResult result,
|
|
|
|
|
UpgradeOnePriceResult onePriceResult,
|
|
|
|
|
UpgradeBundleDiscountResult bundleDiscountResult) {
|
|
|
|
|
if (result == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
BigDecimal bestPayableAmount = null;
|
|
|
|
|
String bestUpgradeType = null;
|
|
|
|
|
|
|
|
|
|
if (onePriceResult != null && onePriceResult.isApplicable()) {
|
|
|
|
|
bestPayableAmount = onePriceResult.getEstimatedFinalAmount();
|
|
|
|
|
bestUpgradeType = UPGRADE_TYPE_ONE_PRICE;
|
|
|
|
|
}
|
|
|
|
|
if (bundleDiscountResult != null && bundleDiscountResult.isApplicable()) {
|
|
|
|
|
BigDecimal bundlePayableAmount = bundleDiscountResult.getEstimatedFinalAmount();
|
|
|
|
|
if (bestPayableAmount == null || (bundlePayableAmount != null
|
|
|
|
|
&& bundlePayableAmount.compareTo(bestPayableAmount) < 0)) {
|
|
|
|
|
bestPayableAmount = bundlePayableAmount;
|
|
|
|
|
bestUpgradeType = UPGRADE_TYPE_BUNDLE_DISCOUNT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.setBestPayableAmount(bestPayableAmount);
|
|
|
|
|
result.setBestUpgradeType(bestUpgradeType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 计算优惠(券码 + 优惠券)
|
|
|
|
|
|