套餐加分区功能
This commit is contained in:
@@ -18,6 +18,12 @@ public class BmsProductCountry implements Serializable
|
||||
private String productCode;
|
||||
private String countryName;
|
||||
private String countryCode;
|
||||
/** prc_zone.zone_id; null when product country has no zone */
|
||||
private Long zoneId;
|
||||
/** e.g. Z1; null when no zone */
|
||||
private String zoneCode;
|
||||
/** e.g. Australia(Z1); null when no zone */
|
||||
private String zoneName;
|
||||
private BigDecimal weightMin;
|
||||
private BigDecimal weightMax;
|
||||
private BigDecimal freightPrice;
|
||||
|
||||
@@ -18,6 +18,12 @@ public class PrcPriceSetDetail implements Serializable
|
||||
private String productName;
|
||||
private String countryCode;
|
||||
private String countryName;
|
||||
/** prc_zone.zone_id; null when country has no zone */
|
||||
private Long zoneId;
|
||||
/** e.g. Z1; null when no zone */
|
||||
private String zoneCode;
|
||||
/** zone display name; null when no zone */
|
||||
private String zoneName;
|
||||
private Long zdId;
|
||||
private Long wsdId;
|
||||
private String weightLabel;
|
||||
|
||||
+2
-1
@@ -27,12 +27,13 @@ public interface PrcPriceSetDetailMapper
|
||||
|
||||
public int countByPriceSetId(Long priceSetId);
|
||||
|
||||
/** FIXED:按产品+国家+关联产品国家明细/重量段命中 */
|
||||
/** FIXED: product + country + zone + productCountryId / weight */
|
||||
public PrcPriceSetDetail selectFixedMatch(
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
@Param("productCode") String productCode,
|
||||
@Param("countryCode") String countryCode,
|
||||
@Param("countryName") String countryName,
|
||||
@Param("zoneCode") String zoneCode,
|
||||
@Param("productCountryId") Long productCountryId,
|
||||
@Param("weightLabel") String weightLabel);
|
||||
|
||||
|
||||
+97
-38
@@ -34,10 +34,13 @@ import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.price.domain.BmsProduct;
|
||||
import com.ruoyi.price.domain.BmsProductCountry;
|
||||
import com.ruoyi.price.domain.PrcZone;
|
||||
import com.ruoyi.price.mapper.BmsProductCountryMapper;
|
||||
import com.ruoyi.price.mapper.BmsProductMapper;
|
||||
import com.ruoyi.price.mapper.PrcZoneMapper;
|
||||
import com.ruoyi.price.service.IBmsProductService;
|
||||
import com.ruoyi.price.service.IPrcSurchargeRelService;
|
||||
import com.ruoyi.price.util.ZoneCodeAbbrevs;
|
||||
import com.ruoyi.system.domain.BmsRegion;
|
||||
import com.ruoyi.system.mapper.BmsRegionMapper;
|
||||
|
||||
@@ -74,6 +77,9 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
@Autowired
|
||||
private BmsRegionMapper regionMapper;
|
||||
|
||||
@Autowired
|
||||
private PrcZoneMapper zoneMapper;
|
||||
|
||||
@Autowired
|
||||
private IPrcSurchargeRelService surchargeRelService;
|
||||
|
||||
@@ -248,6 +254,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.regionEmpty"));
|
||||
}
|
||||
List<BmsRegion> euRegions = loadEuRegions(regionByNameCn);
|
||||
Map<String, PrcZone> zoneByCountryAndCode = loadZoneByCountryAndCode();
|
||||
|
||||
int successNum = 0;
|
||||
int skipNum = 0;
|
||||
@@ -263,7 +270,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
try
|
||||
{
|
||||
int[] nums = importOneProduct(workbook, product, operName, regionByNameCn, euRegions,
|
||||
unmatchedCountries);
|
||||
zoneByCountryAndCode, unmatchedCountries);
|
||||
transactionManager.commit(tx);
|
||||
successNum += nums[0];
|
||||
skipNum += nums[1];
|
||||
@@ -300,7 +307,8 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
|
||||
/** @return int[]{added, skipped, countryRows} */
|
||||
private int[] importOneProduct(Workbook workbook, BmsProduct product, String operName,
|
||||
Map<String, BmsRegion> regionByNameCn, List<BmsRegion> euRegions, Set<String> unmatchedCountries)
|
||||
Map<String, BmsRegion> regionByNameCn, List<BmsRegion> euRegions,
|
||||
Map<String, PrcZone> zoneByCountryAndCode, Set<String> unmatchedCountries)
|
||||
{
|
||||
product.setSourceSheet(product.getProductName());
|
||||
product.setCreateBy(operName);
|
||||
@@ -314,7 +322,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
product.setSourceSheet(productSheet.getSheetName());
|
||||
List<BmsProductCountry> countries = parseProductSheet(productSheet, product,
|
||||
regionByNameCn, euRegions, unmatchedCountries);
|
||||
regionByNameCn, euRegions, zoneByCountryAndCode, unmatchedCountries);
|
||||
if (countries == null || countries.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.noCountry",
|
||||
@@ -412,7 +420,8 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.needFeeAlter"));
|
||||
}
|
||||
if (tip.contains("expire_date") || tip.contains("uk_product_country_weight"))
|
||||
if (tip.contains("expire_date") || tip.contains("uk_product_country_weight")
|
||||
|| tip.contains("uk_product_country_zone_weight"))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.needExpireAlter"));
|
||||
}
|
||||
@@ -716,7 +725,8 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
|
||||
private List<BmsProductCountry> parseProductSheet(Sheet sheet, BmsProduct product,
|
||||
Map<String, BmsRegion> regionByNameCn, List<BmsRegion> euRegions, Set<String> unmatchedCountries)
|
||||
Map<String, BmsRegion> regionByNameCn, List<BmsRegion> euRegions,
|
||||
Map<String, PrcZone> zoneByCountryAndCode, Set<String> unmatchedCountries)
|
||||
{
|
||||
if (sheet == null)
|
||||
{
|
||||
@@ -739,7 +749,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
int colSize = findColByHeader(headerRow, "\u5c3a\u5bf8", colCountry + 1);
|
||||
int colLastMile = findColByHeader(headerRow, "\u5c3e\u7a0b", colCountry + 1);
|
||||
int colLeadTime = findColByHeader(headerRow, "\u65f6\u6548", colCountry + 1);
|
||||
// Fallback offsets when header text missing (Weishi layout: B=country ... H=lead time)
|
||||
if (colWeight < 0)
|
||||
{
|
||||
colWeight = colCountry + 1;
|
||||
@@ -765,7 +774,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
colLeadTime = colCountry + 6;
|
||||
}
|
||||
|
||||
String currentCountry = null;
|
||||
String currentCountryRaw = null;
|
||||
String currentSize = null;
|
||||
String currentLastMile = null;
|
||||
String currentLeadTime = null;
|
||||
@@ -785,12 +794,12 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
if (StringUtils.isNotEmpty(countryCell))
|
||||
{
|
||||
currentCountry = normalizeCountryName(countryCell);
|
||||
currentCountryRaw = countryCell;
|
||||
currentSize = emptyToNull(cellString(row.getCell(colSize)));
|
||||
currentLastMile = emptyToNull(cellString(row.getCell(colLastMile)));
|
||||
currentLeadTime = emptyToNull(cellString(row.getCell(colLeadTime)));
|
||||
}
|
||||
if (StringUtils.isEmpty(currentCountry))
|
||||
if (StringUtils.isEmpty(currentCountryRaw))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -803,14 +812,23 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
BigDecimal registration = cellDecimal(row.getCell(colRegister));
|
||||
Date eff = sheetEffective != null ? sheetEffective : product.getEffectiveDate();
|
||||
|
||||
BmsRegion region = resolveRegion(currentCountry, regionByNameCn);
|
||||
ZoneCodeAbbrevs.CountryZoneParts parts = ZoneCodeAbbrevs.splitCountryZone(currentCountryRaw);
|
||||
if (parts == null || StringUtils.isEmpty(parts.countryName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String baseCountry = parts.countryName;
|
||||
String zoneLabel = parts.zoneLabel;
|
||||
|
||||
BmsRegion region = resolveRegion(baseCountry, regionByNameCn);
|
||||
if (region != null)
|
||||
{
|
||||
list.add(buildCountryRow(region.getCountryNameCn(), region.getCountryCode2(),
|
||||
zoneLabel, zoneByCountryAndCode,
|
||||
range, freight, registration, currentSize, currentLastMile, currentLeadTime, eff));
|
||||
continue;
|
||||
}
|
||||
if (isEuZoneName(currentCountry))
|
||||
if (isEuZoneName(baseCountry) && StringUtils.isEmpty(zoneLabel))
|
||||
{
|
||||
if (euRegions == null || euRegions.isEmpty())
|
||||
{
|
||||
@@ -819,23 +837,26 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
for (BmsRegion eu : euRegions)
|
||||
{
|
||||
list.add(buildCountryRow(eu.getCountryNameCn(), eu.getCountryCode2(),
|
||||
null, zoneByCountryAndCode,
|
||||
range, freight, registration, currentSize, currentLastMile, currentLeadTime, eff));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
unmatchedCountries.add(currentCountry);
|
||||
list.add(buildCountryRow(currentCountry, null,
|
||||
unmatchedCountries.add(currentCountryRaw.trim().replace("\n", " ").replace("\r", " "));
|
||||
list.add(buildCountryRow(baseCountry, null, zoneLabel, zoneByCountryAndCode,
|
||||
range, freight, registration, currentSize, currentLastMile, currentLeadTime, eff));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private BmsProductCountry buildCountryRow(String countryName, String countryCode, BigDecimal[] range,
|
||||
private BmsProductCountry buildCountryRow(String countryName, String countryCode, String zoneLabel,
|
||||
Map<String, PrcZone> zoneByCountryAndCode, BigDecimal[] range,
|
||||
BigDecimal freight, BigDecimal registration, String sizeLimit, String lastMile, String leadTime, Date eff)
|
||||
{
|
||||
BmsProductCountry c = new BmsProductCountry();
|
||||
c.setCountryName(countryName);
|
||||
c.setCountryCode(countryCode);
|
||||
applyZoneFields(c, countryCode, zoneLabel, zoneByCountryAndCode);
|
||||
c.setWeightMin(range[0]);
|
||||
c.setWeightMax(range[1]);
|
||||
c.setFreightPrice(freight);
|
||||
@@ -847,6 +868,68 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
return c;
|
||||
}
|
||||
|
||||
private void applyZoneFields(BmsProductCountry c, String countryCode, String zoneLabel,
|
||||
Map<String, PrcZone> zoneByCountryAndCode)
|
||||
{
|
||||
if (StringUtils.isEmpty(zoneLabel))
|
||||
{
|
||||
c.setZoneId(null);
|
||||
c.setZoneCode(null);
|
||||
c.setZoneName(null);
|
||||
return;
|
||||
}
|
||||
String zoneCode = ZoneCodeAbbrevs.toAbbrev(zoneLabel);
|
||||
c.setZoneCode(zoneCode);
|
||||
PrcZone zone = null;
|
||||
if (StringUtils.isNotEmpty(countryCode) && zoneByCountryAndCode != null)
|
||||
{
|
||||
zone = zoneByCountryAndCode.get(zoneKey(countryCode, zoneCode));
|
||||
}
|
||||
if (zone != null)
|
||||
{
|
||||
c.setZoneId(zone.getZoneId());
|
||||
c.setZoneCode(zone.getZoneCode());
|
||||
c.setZoneName(zone.getZoneName());
|
||||
}
|
||||
else
|
||||
{
|
||||
c.setZoneId(null);
|
||||
c.setZoneName(StringUtils.isNotEmpty(c.getCountryName())
|
||||
? c.getCountryName() + "(" + zoneCode + ")"
|
||||
: zoneCode);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, PrcZone> loadZoneByCountryAndCode()
|
||||
{
|
||||
Map<String, PrcZone> map = new HashMap<>();
|
||||
List<PrcZone> list = zoneMapper.selectPrcZoneList(new PrcZone());
|
||||
if (list == null)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
for (PrcZone zone : list)
|
||||
{
|
||||
if (zone == null || StringUtils.isEmpty(zone.getZoneCode()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String code2 = zone.getCountryCode();
|
||||
if (StringUtils.isEmpty(code2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
map.put(zoneKey(code2, zone.getZoneCode()), zone);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static String zoneKey(String countryCode, String zoneCode)
|
||||
{
|
||||
return String.valueOf(countryCode).trim().toUpperCase(Locale.ROOT)
|
||||
+ "|" + String.valueOf(zoneCode).trim().toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load bms_region map: country_name_cn -> region (for country_code_2).
|
||||
*/
|
||||
@@ -907,7 +990,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
return candidates.get(0);
|
||||
}
|
||||
// Prefer longest Chinese name match (e.g. 捷克共和国 over 捷克)
|
||||
BmsRegion best = candidates.get(0);
|
||||
for (int i = 1; i < candidates.size(); i++)
|
||||
{
|
||||
@@ -920,29 +1002,6 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
return best;
|
||||
}
|
||||
|
||||
/** Strip Excel footnotes like "澳大利亚(1区)\\n分区点击" */
|
||||
private static String normalizeCountryName(String name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String n = name.trim();
|
||||
int cut = n.length();
|
||||
int nl = n.indexOf('\n');
|
||||
if (nl >= 0 && nl < cut)
|
||||
{
|
||||
cut = nl;
|
||||
}
|
||||
int cr = n.indexOf('\r');
|
||||
if (cr >= 0 && cr < cut)
|
||||
{
|
||||
cut = cr;
|
||||
}
|
||||
n = n.substring(0, cut).trim();
|
||||
return n.isEmpty() ? null : n;
|
||||
}
|
||||
|
||||
private BigDecimal[] parseWeightRange(String label)
|
||||
{
|
||||
if (StringUtils.isEmpty(label))
|
||||
|
||||
+130
-12
@@ -248,6 +248,9 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
nd.setProductName(d.getProductName());
|
||||
nd.setCountryCode(d.getCountryCode());
|
||||
nd.setCountryName(d.getCountryName());
|
||||
nd.setZoneId(d.getZoneId());
|
||||
nd.setZoneCode(d.getZoneCode());
|
||||
nd.setZoneName(d.getZoneName());
|
||||
nd.setZdId(d.getZdId());
|
||||
nd.setWsdId(d.getWsdId());
|
||||
nd.setWeightLabel(d.getWeightLabel());
|
||||
@@ -659,6 +662,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.detail.country.empty"));
|
||||
}
|
||||
requireZoneIfNeeded(detail);
|
||||
if (detail.getWsdId() == null && StringUtils.isEmpty(detail.getWeightLabel()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.detail.weight.empty"));
|
||||
@@ -692,6 +696,29 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When product country rows for this country have zones, zone is required.
|
||||
*/
|
||||
private void requireZoneIfNeeded(PrcPriceSetDetail detail)
|
||||
{
|
||||
if (detail.getZoneId() != null || StringUtils.isNotEmpty(detail.getZoneCode()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsProductCountry> rows = listOpenProductCountries(detail.getProductCode());
|
||||
for (BmsProductCountry row : rows)
|
||||
{
|
||||
if (!matchDetailCountryOnly(detail, row))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (row.getZoneId() != null || StringUtils.isNotEmpty(row.getZoneCode()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.detail.zone.empty"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve / verify product_country_id from bms_product_country when missing.
|
||||
*/
|
||||
@@ -699,25 +726,16 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
if (detail.getProductCountryId() != null)
|
||||
{
|
||||
syncZoneFromProductCountry(detail);
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(detail.getProductCode()) || StringUtils.isEmpty(detail.getWeightLabel()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
BmsProductCountry query = new BmsProductCountry();
|
||||
query.setProductCode(detail.getProductCode());
|
||||
List<BmsProductCountry> rows = productCountryMapper.selectBmsProductCountryList(query);
|
||||
if (rows == null || rows.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsProductCountry> rows = listOpenProductCountries(detail.getProductCode());
|
||||
for (BmsProductCountry row : rows)
|
||||
{
|
||||
if (row.getExpireDate() != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!matchDetailCountry(detail, row))
|
||||
{
|
||||
continue;
|
||||
@@ -730,12 +748,80 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
&& detail.getWeightLabel().contains(stripTrailingZeros(row.getWeightMax()))))
|
||||
{
|
||||
detail.setProductCountryId(row.getDetailId());
|
||||
applyZoneFromRow(detail, row);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matchDetailCountry(PrcPriceSetDetail detail, BmsProductCountry row)
|
||||
private void syncZoneFromProductCountry(PrcPriceSetDetail detail)
|
||||
{
|
||||
if (detail.getProductCountryId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (detail.getZoneId() != null || StringUtils.isNotEmpty(detail.getZoneCode()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
BmsProductCountry query = new BmsProductCountry();
|
||||
query.setProductCode(detail.getProductCode());
|
||||
List<BmsProductCountry> rows = productCountryMapper.selectBmsProductCountryList(query);
|
||||
if (rows == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (BmsProductCountry row : rows)
|
||||
{
|
||||
if (detail.getProductCountryId().equals(row.getDetailId()))
|
||||
{
|
||||
applyZoneFromRow(detail, row);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<BmsProductCountry> listOpenProductCountries(String productCode)
|
||||
{
|
||||
if (StringUtils.isEmpty(productCode))
|
||||
{
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
BmsProductCountry query = new BmsProductCountry();
|
||||
query.setProductCode(productCode);
|
||||
List<BmsProductCountry> rows = productCountryMapper.selectBmsProductCountryList(query);
|
||||
if (rows == null || rows.isEmpty())
|
||||
{
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
List<BmsProductCountry> open = new ArrayList<BmsProductCountry>();
|
||||
for (BmsProductCountry row : rows)
|
||||
{
|
||||
if (row.getExpireDate() == null)
|
||||
{
|
||||
open.add(row);
|
||||
}
|
||||
}
|
||||
return open;
|
||||
}
|
||||
|
||||
private static void applyZoneFromRow(PrcPriceSetDetail detail, BmsProductCountry row)
|
||||
{
|
||||
if (detail.getZoneId() == null)
|
||||
{
|
||||
detail.setZoneId(row.getZoneId());
|
||||
}
|
||||
if (StringUtils.isEmpty(detail.getZoneCode()))
|
||||
{
|
||||
detail.setZoneCode(row.getZoneCode());
|
||||
}
|
||||
if (StringUtils.isEmpty(detail.getZoneName()))
|
||||
{
|
||||
detail.setZoneName(row.getZoneName());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matchDetailCountryOnly(PrcPriceSetDetail detail, BmsProductCountry row)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(detail.getCountryCode()) && StringUtils.isNotEmpty(row.getCountryCode()))
|
||||
{
|
||||
@@ -745,6 +831,38 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
&& detail.getCountryName().equals(row.getCountryName());
|
||||
}
|
||||
|
||||
private static boolean matchDetailCountry(PrcPriceSetDetail detail, BmsProductCountry row)
|
||||
{
|
||||
if (!matchDetailCountryOnly(detail, row))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return matchDetailZone(detail, row);
|
||||
}
|
||||
|
||||
private static boolean matchDetailZone(PrcPriceSetDetail detail, BmsProductCountry row)
|
||||
{
|
||||
boolean detailHas = detail.getZoneId() != null || StringUtils.isNotEmpty(detail.getZoneCode());
|
||||
boolean rowHas = row.getZoneId() != null || StringUtils.isNotEmpty(row.getZoneCode());
|
||||
if (!detailHas && !rowHas)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (detailHas != rowHas)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (detail.getZoneId() != null && row.getZoneId() != null)
|
||||
{
|
||||
return detail.getZoneId().equals(row.getZoneId());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(detail.getZoneCode()) && StringUtils.isNotEmpty(row.getZoneCode()))
|
||||
{
|
||||
return detail.getZoneCode().equalsIgnoreCase(row.getZoneCode());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String formatWeightLabel(BigDecimal min, BigDecimal max)
|
||||
{
|
||||
return stripTrailingZeros(min) + "<W\u2264" + stripTrailingZeros(max);
|
||||
|
||||
+4
-75
@@ -31,6 +31,7 @@ import com.ruoyi.price.domain.PrcZoneRegion;
|
||||
import com.ruoyi.price.mapper.PrcZoneDetailMapper;
|
||||
import com.ruoyi.price.mapper.PrcZoneMapper;
|
||||
import com.ruoyi.price.service.IPrcZoneService;
|
||||
import com.ruoyi.price.util.ZoneCodeAbbrevs;
|
||||
import com.ruoyi.system.domain.BmsRegion;
|
||||
import com.ruoyi.system.mapper.BmsRegionMapper;
|
||||
|
||||
@@ -130,7 +131,7 @@ public class PrcZoneServiceImpl implements IPrcZoneService
|
||||
}
|
||||
if (StringUtils.isNotEmpty(zone.getZoneCode()))
|
||||
{
|
||||
zone.setZoneCode(toZoneCodeAbbrev(zone.getZoneCode()));
|
||||
zone.setZoneCode(ZoneCodeAbbrevs.toAbbrev(zone.getZoneCode()));
|
||||
}
|
||||
if (StringUtils.isEmpty(zone.getZoneName()))
|
||||
{
|
||||
@@ -156,7 +157,7 @@ public class PrcZoneServiceImpl implements IPrcZoneService
|
||||
}
|
||||
if (StringUtils.isNotEmpty(zone.getZoneCode()))
|
||||
{
|
||||
zone.setZoneCode(toZoneCodeAbbrev(zone.getZoneCode()));
|
||||
zone.setZoneCode(ZoneCodeAbbrevs.toAbbrev(zone.getZoneCode()));
|
||||
}
|
||||
if (zone.getZoneSort() == null && StringUtils.isNotEmpty(zone.getZoneCode()))
|
||||
{
|
||||
@@ -293,7 +294,7 @@ public class PrcZoneServiceImpl implements IPrcZoneService
|
||||
String countryName = region.getCountryNameCn();
|
||||
for (Map.Entry<String, List<String>> entry : entries)
|
||||
{
|
||||
String zoneCode = toZoneCodeAbbrev(entry.getKey());
|
||||
String zoneCode = ZoneCodeAbbrevs.toAbbrev(entry.getKey());
|
||||
PrcZone zone = new PrcZone();
|
||||
zone.setRegionId(regionId);
|
||||
zone.setCountryCode(region.getCountryCode2());
|
||||
@@ -868,78 +869,6 @@ public class PrcZoneServiceImpl implements IPrcZoneService
|
||||
return (countryName == null ? "" : countryName) + "(" + zoneCode + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Excel/local zone labels to English abbreviations for zone_code.
|
||||
*/
|
||||
private static String toZoneCodeAbbrev(String raw)
|
||||
{
|
||||
if (StringUtils.isEmpty(raw))
|
||||
{
|
||||
return raw;
|
||||
}
|
||||
String key = raw.replace('\r', ' ').replace('\n', ' ').replaceAll("\\s+", " ").trim();
|
||||
switch (key)
|
||||
{
|
||||
case "1\u533a":
|
||||
return "Z1";
|
||||
case "2\u533a":
|
||||
return "Z2";
|
||||
case "3\u533a":
|
||||
return "Z3";
|
||||
case "4\u533a":
|
||||
return "Z4";
|
||||
case "5\u533a":
|
||||
return "Z5";
|
||||
case "Mondial Relay":
|
||||
return "MR";
|
||||
case "\u6c96\u7e04\u770c":
|
||||
return "OKN";
|
||||
case "\u5317\u7231\u5c14\u5170":
|
||||
return "NI";
|
||||
case "\u9ad8\u5730\u548c\u5c9b\u5c7f":
|
||||
return "HI";
|
||||
case "\u6d77\u5ce1\u7fa4\u5c9b(\u542b\u9521\u5229\u5c9b)":
|
||||
return "CI";
|
||||
case "\u9a6c\u6069\u5c9b":
|
||||
return "IM";
|
||||
case "Beckton":
|
||||
return "BEC";
|
||||
case "Bristol":
|
||||
return "BRS";
|
||||
case "Cambridge":
|
||||
return "CAM";
|
||||
case "Collier Wood":
|
||||
return "CW";
|
||||
case "Guernsey":
|
||||
return "GG";
|
||||
case "Isle of Man Bailiwick of Guernsey States of Jersey":
|
||||
return "IM_GG_JE";
|
||||
case "Lakeside":
|
||||
return "LKS";
|
||||
case "London Congestion Zone":
|
||||
return "LCZ";
|
||||
case "London Congestion Zone - Gemini":
|
||||
return "LCZ_GEM";
|
||||
case "London ULEZ - Wimbledon":
|
||||
return "ULEZ_WIM";
|
||||
case "Northern Ireland Isles of Scilly":
|
||||
return "NI_SCILLY";
|
||||
case "Old Kent Road Cargo Bikes":
|
||||
return "OKR_CB";
|
||||
case "Oxford":
|
||||
return "OXF";
|
||||
case "The Highlands Islands of Scotland":
|
||||
return "HIGHLANDS";
|
||||
default:
|
||||
// already abbrev or unknown: keep trimmed original (spaces -> underscore)
|
||||
if (key.matches(".*[\\u4e00-\\u9fff].*"))
|
||||
{
|
||||
return key;
|
||||
}
|
||||
return key.replace(' ', '_').toUpperCase(Locale.ROOT).replaceAll("_+", "_");
|
||||
}
|
||||
}
|
||||
|
||||
private static int extractZoneSort(String zoneCode)
|
||||
{
|
||||
if (StringUtils.isEmpty(zoneCode))
|
||||
|
||||
+2
-1
@@ -248,7 +248,8 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
|
||||
PrcPriceSetDetail detail = detailMapper.selectFixedMatch(
|
||||
set.getPriceSetId(), productCode,
|
||||
base.getCountryCode(), base.getCountryName(), base.getDetailId(),
|
||||
base.getCountryCode(), base.getCountryName(), base.getZoneCode(),
|
||||
base.getDetailId(),
|
||||
formatWeightLabel(base.getWeightMin(), base.getWeightMax()));
|
||||
if (detail == null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.ruoyi.price.util;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Parse Excel country cell with optional zone suffix, map labels to English abbreviations.
|
||||
*/
|
||||
public final class ZoneCodeAbbrevs
|
||||
{
|
||||
// fullwidth () and ASCII ()
|
||||
private static final Pattern ZONE_SUFFIX = Pattern.compile(
|
||||
"^(.+?)[\\(\\uFF08]([^\\)\\uFF09]+)[\\)\\uFF09]\\s*$");
|
||||
|
||||
private ZoneCodeAbbrevs()
|
||||
{
|
||||
}
|
||||
|
||||
public static final class CountryZoneParts
|
||||
{
|
||||
public final String countryName;
|
||||
public final String zoneLabel;
|
||||
|
||||
public CountryZoneParts(String countryName, String zoneLabel)
|
||||
{
|
||||
this.countryName = countryName;
|
||||
this.zoneLabel = zoneLabel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split country cell like Country(zoneLabel); no parenthesis -> zoneLabel null.
|
||||
*/
|
||||
public static CountryZoneParts splitCountryZone(String raw)
|
||||
{
|
||||
if (StringUtils.isEmpty(raw))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String n = raw.trim();
|
||||
int cut = n.length();
|
||||
int nl = n.indexOf('\n');
|
||||
if (nl >= 0 && nl < cut)
|
||||
{
|
||||
cut = nl;
|
||||
}
|
||||
int cr = n.indexOf('\r');
|
||||
if (cr >= 0 && cr < cut)
|
||||
{
|
||||
cut = cr;
|
||||
}
|
||||
n = n.substring(0, cut).trim();
|
||||
if (n.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Matcher m = ZONE_SUFFIX.matcher(n);
|
||||
if (m.matches())
|
||||
{
|
||||
String country = m.group(1).trim();
|
||||
String zone = m.group(2).trim();
|
||||
if (StringUtils.isEmpty(country))
|
||||
{
|
||||
return new CountryZoneParts(n, null);
|
||||
}
|
||||
return new CountryZoneParts(country, StringUtils.isEmpty(zone) ? null : zone);
|
||||
}
|
||||
return new CountryZoneParts(n, null);
|
||||
}
|
||||
|
||||
public static String toAbbrev(String raw)
|
||||
{
|
||||
if (StringUtils.isEmpty(raw))
|
||||
{
|
||||
return raw;
|
||||
}
|
||||
String key = raw.replace('\r', ' ').replace('\n', ' ').replaceAll("\\s+", " ").trim();
|
||||
switch (key)
|
||||
{
|
||||
case "1\u533a":
|
||||
return "Z1";
|
||||
case "2\u533a":
|
||||
return "Z2";
|
||||
case "3\u533a":
|
||||
return "Z3";
|
||||
case "4\u533a":
|
||||
return "Z4";
|
||||
case "5\u533a":
|
||||
return "Z5";
|
||||
case "Mondial Relay":
|
||||
return "MR";
|
||||
case "\u6c96\u7e04\u770c":
|
||||
return "OKN";
|
||||
case "\u5317\u7231\u5c14\u5170":
|
||||
return "NI";
|
||||
case "\u9ad8\u5730\u548c\u5c9b\u5c7f":
|
||||
return "HI";
|
||||
case "\u6d77\u5ce1\u7fa4\u5c9b(\u542b\u9521\u5229\u5c9b)":
|
||||
return "CI";
|
||||
case "\u9a6c\u6069\u5c9b":
|
||||
return "IM";
|
||||
case "Beckton":
|
||||
return "BEC";
|
||||
case "Bristol":
|
||||
return "BRS";
|
||||
case "Cambridge":
|
||||
return "CAM";
|
||||
case "Collier Wood":
|
||||
return "CW";
|
||||
case "Guernsey":
|
||||
return "GG";
|
||||
case "Isle of Man Bailiwick of Guernsey States of Jersey":
|
||||
return "IM_GG_JE";
|
||||
case "Lakeside":
|
||||
return "LKS";
|
||||
case "London Congestion Zone":
|
||||
return "LCZ";
|
||||
case "London Congestion Zone - Gemini":
|
||||
return "LCZ_GEM";
|
||||
case "London ULEZ - Wimbledon":
|
||||
return "ULEZ_WIM";
|
||||
case "Northern Ireland Isles of Scilly":
|
||||
return "NI_SCILLY";
|
||||
case "Old Kent Road Cargo Bikes":
|
||||
return "OKR_CB";
|
||||
case "Oxford":
|
||||
return "OXF";
|
||||
case "The Highlands Islands of Scotland":
|
||||
return "HIGHLANDS";
|
||||
default:
|
||||
if (key.matches("(?i)Z[1-9]\\d*"))
|
||||
{
|
||||
return key.toUpperCase(Locale.ROOT);
|
||||
}
|
||||
if (key.matches(".*[\\u4e00-\\u9fff].*"))
|
||||
{
|
||||
return key;
|
||||
}
|
||||
return key.replace(' ', '_').toUpperCase(Locale.ROOT).replaceAll("_+", "_");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user