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
+
+
+
+