diff --git a/bms-back/bms-system/src/main/java/com/bms/price/mapper/BmsProductCountryMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/mapper/BmsProductCountryMapper.java index 84dc0da6..073bfc68 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/mapper/BmsProductCountryMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/mapper/BmsProductCountryMapper.java @@ -116,6 +116,17 @@ public interface BmsProductCountryMapper @Param("weight") BigDecimal weight, @Param("bizDate") Date bizDate); + /** + * Lowest PRODUCT catalog weight band for product/country/zone (ignore weight). + * Used when charge weight is below the minimum band. + */ + public BmsProductCountry selectMinBandByProductCountry( + @Param("productCode") String productCode, + @Param("countryCode") String countryCode, + @Param("countryName") String countryName, + @Param("zoneCode") String zoneCode, + @Param("bizDate") Date bizDate); + /** Count product-country rows that have a zone for this product+country+bizDate */ public int countZonedByProductCountry( @Param("productCode") String productCode, diff --git a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java index 0ff6e2b2..78e0b458 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java @@ -71,6 +71,17 @@ public interface PrcPriceSetDetailMapper @Param("zoneCode") String zoneCode, @Param("weight") BigDecimal weight); + /** + * Lowest FIXED weight band for product/country/zone (ignore weight). + * Used when charge weight is below the minimum band. + */ + public PrcPriceSetDetail selectFixedMinBand( + @Param("psvId") Long psvId, + @Param("productCode") String productCode, + @Param("countryCode") String countryCode, + @Param("countryName") String countryName, + @Param("zoneCode") String zoneCode); + public int countZonedByPsvProductCountry( @Param("psvId") Long psvId, @Param("productCode") String productCode, diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/TmsPriceQuoteServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/TmsPriceQuoteServiceImpl.java index 755fd7f2..c3220204 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/TmsPriceQuoteServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/TmsPriceQuoteServiceImpl.java @@ -520,13 +520,28 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService else if (TYPE_DISCOUNT.equals(setType)) { // DISCOUNT still needs catalog as base rate; do not soft-fail as 产品价未匹配 for now. - if (!hasProductCatalogPrice(catalog)) + BmsProductCountry discCatalog = catalog; + BigDecimal discWeight = weight; + if (!hasProductCatalogPrice(discCatalog)) + { + // Below min catalog band: snap charge weight to lowest band min. + BigDecimal snapped = snapWeightToCatalogMinBand( + productCode, cc, cn, zone.zoneCode, weight, bizDate); + if (snapped != null) + { + discWeight = snapped; + discCatalog = softMatchCatalog( + productCode, cc, cn, zone.zoneCode, discWeight, bizDate, zone.zone); + } + } + if (!hasProductCatalogPrice(discCatalog)) { // catalogMissCode = Math.max(catalogMissCode, // diagnoseCatalogMiss(productCode, cc, cn, zone.zoneCode, bizDate)); continue; } - TmsPriceQuoteResult hit = tryDiscount(bind, set, version, catalog, productCode, productName, weight, bizDate); + TmsPriceQuoteResult hit = tryDiscount(bind, set, version, discCatalog, + productCode, productName, discWeight, bizDate); if (hit != null) { stampRequestMeta(request, hit); @@ -971,6 +986,21 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService PrcPriceSetDetail detail = detailMapper.selectFixedMatch( psvId, productCode, countryCode, countryName, zoneCode, weight); + BigDecimal billWeight = weight; + boolean snappedToMinBand = false; + // Miss: if charge weight is below the lowest band, bill at that band's weight_min. + if (detail == null) + { + PrcPriceSetDetail minBand = detailMapper.selectFixedMinBand( + psvId, productCode, countryCode, countryName, zoneCode); + if (minBand != null && minBand.getWeightMin() != null + && weight.compareTo(minBand.getWeightMin()) < 0) + { + detail = minBand; + billWeight = minBand.getWeightMin().setScale(3, RoundingMode.HALF_UP); + snappedToMinBand = true; + } + } if (detail == null) { return null; @@ -979,16 +1009,55 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService { return null; } - TmsPriceQuoteResult r = buildFromPackageDetail(SRC_FIXED, detail, catalog, resolvedZone, - productCode, productName, weight, detail.getFvValue(), null, null, detail.getFvRegistrationFee(), bizDate); + BmsProductCountry useCatalog = catalog; + if (snappedToMinBand) + { + BmsProductCountry rematched = softMatchCatalog( + productCode, countryCode, countryName, zoneCode, billWeight, bizDate, resolvedZone); + if (hasProductCatalogPrice(rematched)) + { + useCatalog = rematched; + } + } + TmsPriceQuoteResult r = buildFromPackageDetail(SRC_FIXED, detail, useCatalog, resolvedZone, + productCode, productName, billWeight, detail.getFvValue(), null, null, detail.getFvRegistrationFee(), bizDate); fillPackage(r, bind, set); stampVersion(r, version, detail.getPsdId()); - r.setMatchMessage(MessageUtils.message("price.quote.hitCustomerFixedPackageDetail") - + " [" + (version.getVersionNo() == null ? ("psv=" + psvId) : version.getVersionNo()) + "]"); + String verLabel = version.getVersionNo() == null ? ("psv=" + psvId) : version.getVersionNo(); + String msg = MessageUtils.message("price.quote.hitCustomerFixedPackageDetail") + " [" + verLabel + "]"; + if (snappedToMinBand) + { + msg = msg + "; chargeWeight raised to min band " + billWeight.toPlainString(); + } + r.setMatchMessage(msg); r.setCustomerId(bind.getCustomerId()); return r; } + /** + * When weight misses catalog bands but is below the lowest band, return that band's weight_min. + * Otherwise null (caller keeps original miss). + */ + private BigDecimal snapWeightToCatalogMinBand(String productCode, String countryCode, String countryName, + String zoneCode, BigDecimal weight, Date bizDate) + { + if (weight == null || StringUtils.isEmpty(productCode)) + { + return null; + } + BmsProductCountry minBand = productCountryMapper.selectMinBandByProductCountry( + productCode, countryCode, countryName, zoneCode, bizDate); + if (minBand == null || minBand.getWeightMin() == null) + { + return null; + } + if (weight.compareTo(minBand.getWeightMin()) < 0) + { + return minBand.getWeightMin().setScale(3, RoundingMode.HALF_UP); + } + return null; + } + private TmsPriceQuoteResult tryDiscount(PrcCustomerPriceSet bind, PrcPriceSet set, PrcPriceSetVersion version, BmsProductCountry base, String productCode, String productName, BigDecimal weight, Date bizDate) { diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/support/CatalogVersionSupport.java b/bms-back/bms-system/src/main/java/com/bms/price/service/support/CatalogVersionSupport.java index ad65c958..6783cd76 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/support/CatalogVersionSupport.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/support/CatalogVersionSupport.java @@ -446,8 +446,7 @@ public class CatalogVersionSupport } /** - * Catalog version that can accept preview apply / Excel attach / edit. - * Same as sales force-edit: draft, pending, and effect are writable. + * Catalog force-edit: draft, pending, effect, and expired are writable. */ public PrcPriceSetVersion requireEditableCatalogVersion(Long psvId, String priceType) { @@ -467,9 +466,10 @@ public class CatalogVersionSupport } if (!STATUS_DRAFT.equals(ver.getStatus()) && !STATUS_PENDING.equals(ver.getStatus()) - && !STATUS_EFFECT.equals(ver.getStatus())) + && !STATUS_EFFECT.equals(ver.getStatus()) + && !STATUS_EXPIRED.equals(ver.getStatus())) { - throw new ServiceException("仅草稿、待生效或已生效版本可以编辑"); + throw new ServiceException("仅草稿、待生效、已生效或已失效版本可以编辑"); } return ver; } diff --git a/bms-back/bms-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml b/bms-back/bms-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml index 107a6826..38f5880c 100644 --- a/bms-back/bms-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml @@ -357,6 +357,36 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" limit 1 + + + +