修改基础价格版本功能
This commit is contained in:
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.bms.price.domain.BmsProduct;
|
||||
import com.bms.price.domain.BmsProductCountry;
|
||||
import com.bms.price.domain.BmsProductPriceVersion;
|
||||
|
||||
/**
|
||||
* 产品列表 服务层
|
||||
@@ -54,4 +55,7 @@ public interface IBmsProductService
|
||||
* @return HTML result message
|
||||
*/
|
||||
public String importCountryProductExcel(MultipartFile file, String countryCode, String operName) throws Exception;
|
||||
|
||||
/** Distinct base-price version options (by effective_date desc) for package create */
|
||||
public List<BmsProductPriceVersion> selectPriceVersionOptions();
|
||||
}
|
||||
|
||||
+214
-23
@@ -34,9 +34,11 @@ import com.bms.common.utils.MessageUtils;
|
||||
import com.bms.common.utils.StringUtils;
|
||||
import com.bms.price.domain.BmsProduct;
|
||||
import com.bms.price.domain.BmsProductCountry;
|
||||
import com.bms.price.domain.BmsProductPriceVersion;
|
||||
import com.bms.price.domain.PrcZone;
|
||||
import com.bms.price.mapper.BmsProductCountryMapper;
|
||||
import com.bms.price.mapper.BmsProductMapper;
|
||||
import com.bms.price.mapper.BmsProductPriceVersionMapper;
|
||||
import com.bms.price.mapper.PrcZoneMapper;
|
||||
import com.bms.price.service.IBmsProductService;
|
||||
import com.bms.price.service.IPrcSurchargeRelService;
|
||||
@@ -74,6 +76,9 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
@Autowired
|
||||
private BmsProductCountryMapper countryMapper;
|
||||
|
||||
@Autowired
|
||||
private BmsProductPriceVersionMapper priceVersionMapper;
|
||||
|
||||
@Autowired
|
||||
private BmsRegionMapper regionMapper;
|
||||
|
||||
@@ -97,6 +102,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
productMapper.refreshStatusByDates();
|
||||
countryMapper.refreshStatusByDates();
|
||||
priceVersionMapper.refreshStatusByDates();
|
||||
if (product != null)
|
||||
{
|
||||
product.setStatus(normalizeStatusCode(product.getStatus()));
|
||||
@@ -415,6 +421,13 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BmsProductPriceVersion> selectPriceVersionOptions()
|
||||
{
|
||||
List<BmsProductPriceVersion> list = priceVersionMapper.selectVersionOptions();
|
||||
return list == null ? new ArrayList<>() : list;
|
||||
}
|
||||
|
||||
/** @return int[]{added, skipped, countryRows} */
|
||||
private int[] importOneProduct(Workbook workbook, BmsProduct product, String operName,
|
||||
Map<String, BmsRegion> regionByNameCn, List<BmsRegion> euRegions,
|
||||
@@ -476,8 +489,10 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
|
||||
/**
|
||||
* Versioned country save:
|
||||
* - newEff > last open: close old (expire_date = newEff), insert new (keep history)
|
||||
* - newEff equals last open: replace open rows
|
||||
* - require effective_date
|
||||
* - newEff > last open: expire previous version (expire_date = newEff), create new version,
|
||||
* copy previous country rows, then match import (hit=update, miss=insert)
|
||||
* - newEff equals last open: reuse open version, match update/insert (no full replace)
|
||||
* - newEff < last open: reject
|
||||
*/
|
||||
private int saveCountriesVersioned(BmsProduct product, List<BmsProductCountry> countries)
|
||||
@@ -488,40 +503,125 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
String productCode = product.getProductCode();
|
||||
Long productId = product.getProductId();
|
||||
Date newEff = resolveImportEffectiveDate(countries);
|
||||
Date lastOpenEff = countryMapper.selectMaxOpenEffectiveDate(productCode);
|
||||
Date newEff = toDateOnly(resolveImportEffectiveDate(countries));
|
||||
if (newEff == null)
|
||||
{
|
||||
newEff = toDateOnly(product.getEffectiveDate());
|
||||
}
|
||||
if (newEff == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.effEmpty"));
|
||||
}
|
||||
|
||||
if (lastOpenEff != null && newEff != null && newEff.before(lastOpenEff))
|
||||
BmsProductPriceVersion openVer = priceVersionMapper.selectOpenByProductCode(productCode);
|
||||
Date lastOpenEff = openVer != null ? toDateOnly(openVer.getEffectiveDate())
|
||||
: toDateOnly(countryMapper.selectMaxOpenEffectiveDate(productCode));
|
||||
|
||||
if (lastOpenEff != null && newEff.before(lastOpenEff))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.effTooEarly",
|
||||
formatDate(newEff), formatDate(lastOpenEff)));
|
||||
}
|
||||
|
||||
if (lastOpenEff != null && newEff != null && newEff.after(lastOpenEff))
|
||||
BmsProductPriceVersion targetVer;
|
||||
boolean newVersionDay = lastOpenEff == null || newEff.after(lastOpenEff);
|
||||
|
||||
if (newVersionDay)
|
||||
{
|
||||
// Previous open version expire_date = this effective_date; keep old rows
|
||||
countryMapper.expireOpenByProductCode(productCode, newEff);
|
||||
countryMapper.refreshStatusByDates();
|
||||
List<BmsProductCountry> prevSnapshot = null;
|
||||
Long srcPpvId = openVer != null ? openVer.getPpvId() : null;
|
||||
if (lastOpenEff != null)
|
||||
{
|
||||
if (srcPpvId != null)
|
||||
{
|
||||
prevSnapshot = null; // copy via SQL by ppv_id after expire
|
||||
}
|
||||
else
|
||||
{
|
||||
prevSnapshot = countryMapper.selectOpenByProductCode(productCode);
|
||||
}
|
||||
priceVersionMapper.expireOpenByProductCode(productCode, newEff);
|
||||
countryMapper.expireOpenByProductCode(productCode, newEff);
|
||||
}
|
||||
targetVer = createPriceVersion(product, newEff);
|
||||
String newStatus = resolveStoredStatus(newEff, null);
|
||||
if (srcPpvId != null)
|
||||
{
|
||||
countryMapper.copyCountriesFromVersion(srcPpvId, targetVer.getPpvId(), productId,
|
||||
productCode, newEff, newStatus);
|
||||
}
|
||||
else if (prevSnapshot != null && !prevSnapshot.isEmpty())
|
||||
{
|
||||
insertCountryCopies(prevSnapshot, targetVer.getPpvId(), productId, productCode, newEff, newStatus);
|
||||
}
|
||||
}
|
||||
else if (lastOpenEff != null)
|
||||
else
|
||||
{
|
||||
// Same effective day: replace open rows so re-import can fill/fix details
|
||||
countryMapper.deleteOpenByProductCodeAndEffectiveDate(productCode, newEff);
|
||||
targetVer = priceVersionMapper.selectByProductCodeAndEffectiveDate(productCode, newEff);
|
||||
if (targetVer == null)
|
||||
{
|
||||
targetVer = openVer != null ? openVer : createPriceVersion(product, newEff);
|
||||
}
|
||||
else if (targetVer.getProductId() == null && productId != null)
|
||||
{
|
||||
targetVer.setProductId(productId);
|
||||
targetVer.setUpdateBy(product.getUpdateBy());
|
||||
priceVersionMapper.updateBmsProductPriceVersion(targetVer);
|
||||
}
|
||||
assignOpenRowsToVersion(productCode, targetVer.getPpvId());
|
||||
}
|
||||
|
||||
for (BmsProductCountry c : countries)
|
||||
List<BmsProductCountry> baseRows = countryMapper.selectByPpvId(targetVer.getPpvId());
|
||||
if (baseRows == null)
|
||||
{
|
||||
c.setProductId(productId);
|
||||
c.setProductCode(productCode);
|
||||
c.setExpireDate(null);
|
||||
if (c.getEffectiveDate() == null)
|
||||
{
|
||||
c.setEffectiveDate(newEff);
|
||||
}
|
||||
c.setStatus(resolveStoredStatus(c.getEffectiveDate(), c.getExpireDate()));
|
||||
baseRows = new ArrayList<>();
|
||||
}
|
||||
Map<String, BmsProductCountry> byKey = new HashMap<>();
|
||||
for (BmsProductCountry row : baseRows)
|
||||
{
|
||||
byKey.put(countryMatchKey(row), row);
|
||||
}
|
||||
|
||||
int touched = 0;
|
||||
for (BmsProductCountry incoming : countries)
|
||||
{
|
||||
incoming.setProductId(productId);
|
||||
incoming.setProductCode(productCode);
|
||||
incoming.setPpvId(targetVer.getPpvId());
|
||||
incoming.setEffectiveDate(newEff);
|
||||
incoming.setExpireDate(null);
|
||||
incoming.setStatus(resolveStoredStatus(newEff, null));
|
||||
|
||||
String key = countryMatchKey(incoming);
|
||||
BmsProductCountry existing = byKey.get(key);
|
||||
try
|
||||
{
|
||||
countryMapper.insertBmsProductCountry(c);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.setProductId(productId);
|
||||
existing.setPpvId(targetVer.getPpvId());
|
||||
existing.setCountryCode(incoming.getCountryCode());
|
||||
existing.setZoneId(incoming.getZoneId());
|
||||
existing.setZoneCode(incoming.getZoneCode());
|
||||
existing.setZoneName(incoming.getZoneName());
|
||||
existing.setWeightMin(incoming.getWeightMin());
|
||||
existing.setWeightMax(incoming.getWeightMax());
|
||||
existing.setFreightPrice(incoming.getFreightPrice());
|
||||
existing.setRegistrationFee(incoming.getRegistrationFee());
|
||||
existing.setSizeLimit(incoming.getSizeLimit());
|
||||
existing.setLastMile(incoming.getLastMile());
|
||||
existing.setLeadTime(incoming.getLeadTime());
|
||||
existing.setEffectiveDate(newEff);
|
||||
existing.setExpireDate(null);
|
||||
existing.setStatus(resolveStoredStatus(newEff, null));
|
||||
countryMapper.updateBmsProductCountryImport(existing);
|
||||
}
|
||||
else
|
||||
{
|
||||
countryMapper.insertBmsProductCountry(incoming);
|
||||
byKey.put(key, incoming);
|
||||
}
|
||||
touched++;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -530,6 +630,10 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.needFeeAlter"));
|
||||
}
|
||||
if (tip.contains("ppv_id") || tip.contains("bms_product_price_version"))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.product.import.needVersionAlter"));
|
||||
}
|
||||
if (tip.contains("expire_date") || tip.contains("uk_product_country_weight")
|
||||
|| tip.contains("uk_product_country_zone_weight"))
|
||||
{
|
||||
@@ -538,7 +642,94 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return countries.size();
|
||||
countryMapper.refreshStatusByDates();
|
||||
priceVersionMapper.refreshStatusByDates();
|
||||
return touched;
|
||||
}
|
||||
|
||||
private BmsProductPriceVersion createPriceVersion(BmsProduct product, Date effectiveDate)
|
||||
{
|
||||
Integer maxSeq = priceVersionMapper.selectMaxVersionSeq(product.getProductCode());
|
||||
int seq = maxSeq == null ? 1 : maxSeq.intValue() + 1;
|
||||
BmsProductPriceVersion ver = new BmsProductPriceVersion();
|
||||
ver.setProductCode(product.getProductCode());
|
||||
ver.setProductId(product.getProductId());
|
||||
ver.setVersionSeq(Integer.valueOf(seq));
|
||||
ver.setVersionNo("V" + seq);
|
||||
ver.setEffectiveDate(effectiveDate);
|
||||
ver.setExpireDate(null);
|
||||
ver.setStatus(resolveStoredStatus(effectiveDate, null));
|
||||
ver.setCreateBy(product.getCreateBy() != null ? product.getCreateBy() : product.getUpdateBy());
|
||||
priceVersionMapper.insertBmsProductPriceVersion(ver);
|
||||
return ver;
|
||||
}
|
||||
|
||||
/** After expire, insert in-memory previous open rows into the new version */
|
||||
private void insertCountryCopies(List<BmsProductCountry> prevSnapshot, Long newPpvId, Long productId,
|
||||
String productCode, Date newEff, String status)
|
||||
{
|
||||
for (BmsProductCountry src : prevSnapshot)
|
||||
{
|
||||
BmsProductCountry copy = new BmsProductCountry();
|
||||
copy.setProductId(productId);
|
||||
copy.setPpvId(newPpvId);
|
||||
copy.setProductCode(productCode);
|
||||
copy.setCountryName(src.getCountryName());
|
||||
copy.setCountryCode(src.getCountryCode());
|
||||
copy.setZoneId(src.getZoneId());
|
||||
copy.setZoneCode(src.getZoneCode());
|
||||
copy.setZoneName(src.getZoneName());
|
||||
copy.setWeightMin(src.getWeightMin());
|
||||
copy.setWeightMax(src.getWeightMax());
|
||||
copy.setFreightPrice(src.getFreightPrice());
|
||||
copy.setRegistrationFee(src.getRegistrationFee());
|
||||
copy.setSizeLimit(src.getSizeLimit());
|
||||
copy.setLastMile(src.getLastMile());
|
||||
copy.setLeadTime(src.getLeadTime());
|
||||
copy.setEffectiveDate(newEff);
|
||||
copy.setExpireDate(null);
|
||||
copy.setStatus(status);
|
||||
countryMapper.insertBmsProductCountry(copy);
|
||||
}
|
||||
}
|
||||
|
||||
private void assignOpenRowsToVersion(String productCode, Long ppvId)
|
||||
{
|
||||
if (ppvId == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsProductCountry> openRows = countryMapper.selectOpenByProductCode(productCode);
|
||||
if (openRows == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (BmsProductCountry row : openRows)
|
||||
{
|
||||
if (row.getPpvId() == null)
|
||||
{
|
||||
countryMapper.updatePpvId(row.getDetailId(), ppvId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Match key: country + zone + weight band */
|
||||
private String countryMatchKey(BmsProductCountry row)
|
||||
{
|
||||
String country = row.getCountryName() == null ? "" : row.getCountryName().trim();
|
||||
String zone = row.getZoneCode() == null ? "" : row.getZoneCode().trim().toUpperCase(Locale.ROOT);
|
||||
String wMin = normalizeDecimal(row.getWeightMin());
|
||||
String wMax = normalizeDecimal(row.getWeightMax());
|
||||
return country + "|" + zone + "|" + wMin + "|" + wMax;
|
||||
}
|
||||
|
||||
private String normalizeDecimal(BigDecimal v)
|
||||
{
|
||||
if (v == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return v.stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
private Date resolveImportEffectiveDate(List<BmsProductCountry> countries)
|
||||
|
||||
+8
-7
@@ -1830,20 +1830,21 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
detailMapper.deletePrcPriceSetDetailByPsvId(version.getPsvId());
|
||||
// clean legacy rows without psv_id under this set (would look like duplicates in UI)
|
||||
detailMapper.deleteOrphanDetailsByPriceSetId(set.getPriceSetId());
|
||||
String baseVersionNo = set.getBaseVersionNo();
|
||||
if (StringUtils.isEmpty(baseVersionNo))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.baseVersionNo.empty"));
|
||||
}
|
||||
int inserted;
|
||||
if (TYPE_DISCOUNT.equals(set.getSetType()))
|
||||
{
|
||||
inserted = detailMapper.insertDiscountDetailsFromLibrary(set.getPriceSetId(), version.getPsvId());
|
||||
inserted = detailMapper.insertDiscountDetailsFromLibrary(
|
||||
set.getPriceSetId(), version.getPsvId(), baseVersionNo);
|
||||
}
|
||||
else
|
||||
{
|
||||
inserted = detailMapper.insertFixedDetailsFromLibrary(
|
||||
set.getPriceSetId(), version.getPsvId(), version.getEffectiveTime(), false);
|
||||
if (inserted <= 0)
|
||||
{
|
||||
inserted = detailMapper.insertFixedDetailsFromLibrary(
|
||||
set.getPriceSetId(), version.getPsvId(), version.getEffectiveTime(), true);
|
||||
}
|
||||
set.getPriceSetId(), version.getPsvId(), null, false, baseVersionNo);
|
||||
}
|
||||
if (inserted <= 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user