修改产品价和红线价功能
This commit is contained in:
@@ -29,11 +29,10 @@ public class PrcPriceSetVersion extends BaseEntity
|
||||
/** 0 draft / 3 pending / 1 active / 2 expired */
|
||||
private String status;
|
||||
/**
|
||||
* Create-price mode for this version:
|
||||
* PULL = from product library,
|
||||
* IMPORT = Excel with prior version preload,
|
||||
* IMPORT_FRESH = Excel without prior version data.
|
||||
* Column: price_build_mode
|
||||
* Create-price mode for this version (column: price_build_mode).
|
||||
* SALES: PULL = product library; IMPORT = Excel + prior version; IMPORT_FRESH = Excel blank.
|
||||
* PRODUCT/REDLINE: IMPORT = copy from effect version; IMPORT_FRESH = rebuild (Excel).
|
||||
* Legacy catalog: COPY → IMPORT, old IMPORT → IMPORT_FRESH (see migrate SQL).
|
||||
*/
|
||||
private String priceBuildMode;
|
||||
/** 0 normal / 1 soft-deleted */
|
||||
|
||||
+163
-30
@@ -102,7 +102,8 @@ public class CatalogVersionSupport
|
||||
nv.setVersionNo("V" + next);
|
||||
nv.setEffectiveTime(effectiveTime);
|
||||
nv.setStatus(STATUS_DRAFT);
|
||||
nv.setPriceBuildMode("IMPORT");
|
||||
// IMPORT = inherit effect version; IMPORT_FRESH = empty rebuild (Excel)
|
||||
nv.setPriceBuildMode(copyFromLatest ? "IMPORT" : "IMPORT_FRESH");
|
||||
nv.setCreateBy("system");
|
||||
versionMapper.insertPrcPriceSetVersion(nv);
|
||||
|
||||
@@ -122,7 +123,11 @@ public class CatalogVersionSupport
|
||||
return nv;
|
||||
}
|
||||
|
||||
/** Activate draft: set EFFECT, chain expire on previous EFFECT versions of same type. */
|
||||
/**
|
||||
* Activate draft/pending catalog version.
|
||||
* IMPORT_FRESH (align sales): may start inside a prior window; forbid equal to any other
|
||||
* version's effective/expire of the same price_type; then chain expire times and sync children.
|
||||
*/
|
||||
public void activateVersion(Long psvId, Date effectiveTime)
|
||||
{
|
||||
PrcPriceSetVersion ver = versionMapper.selectPrcPriceSetVersionById(psvId);
|
||||
@@ -140,39 +145,165 @@ public class CatalogVersionSupport
|
||||
{
|
||||
throw new ServiceException("请选择生效时间");
|
||||
}
|
||||
Date prevEff = findPrevEffectiveTime(ver);
|
||||
if (prevEff != null && eff.before(prevEff))
|
||||
boolean importFresh = "IMPORT_FRESH".equalsIgnoreCase(StringUtils.trim(ver.getPriceBuildMode()));
|
||||
if (importFresh)
|
||||
{
|
||||
throw new ServiceException("生效时间不能早于上一版本");
|
||||
validateImportFreshActivateTime(ver, eff);
|
||||
}
|
||||
|
||||
boolean future = eff.after(new Date());
|
||||
if (!future)
|
||||
else
|
||||
{
|
||||
PrcPriceSetVersion q = new PrcPriceSetVersion();
|
||||
q.setPriceType(ver.getPriceType());
|
||||
q.setStatus(STATUS_EFFECT);
|
||||
List<PrcPriceSetVersion> prevList = versionMapper.selectPrcPriceSetVersionList(q);
|
||||
if (prevList != null)
|
||||
Date prevEff = findPrevEffectiveTime(ver);
|
||||
if (prevEff != null && eff.before(prevEff))
|
||||
{
|
||||
for (PrcPriceSetVersion prev : prevList)
|
||||
{
|
||||
if (prev.getPsvId().equals(psvId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
prev.setExpireTime(eff);
|
||||
prev.setStatus(STATUS_EXPIRED);
|
||||
versionMapper.updatePrcPriceSetVersion(prev);
|
||||
}
|
||||
throw new ServiceException("生效时间不能早于上一版本");
|
||||
}
|
||||
}
|
||||
|
||||
ver.setEffectiveTime(eff);
|
||||
ver.setExpireTime(null);
|
||||
ver.setStatus(future ? STATUS_PENDING : STATUS_EFFECT);
|
||||
versionMapper.updatePrcPriceSetVersion(ver);
|
||||
refreshCatalogStatuses(ver.getPriceType());
|
||||
// Chain B.expire=A.eff, A.expire=next/B.oldExpire; refresh status + product/detail effect
|
||||
chainAndRefreshCatalogStatuses(ver.getPriceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORT_FRESH: may be earlier than prev-by-seq; must not equal any other version's eff/exp
|
||||
* within the same PRODUCT/REDLINE type.
|
||||
*/
|
||||
private void validateImportFreshActivateTime(PrcPriceSetVersion version, Date effectiveTime)
|
||||
{
|
||||
if (version == null || effectiveTime == null || StringUtils.isEmpty(version.getPriceType()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
PrcPriceSetVersion q = new PrcPriceSetVersion();
|
||||
q.setPriceType(version.getPriceType());
|
||||
List<PrcPriceSetVersion> list = versionMapper.selectPrcPriceSetVersionList(q);
|
||||
if (list == null || list.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (PrcPriceSetVersion v : list)
|
||||
{
|
||||
if (v == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (version.getPsvId() != null && version.getPsvId().equals(v.getPsvId()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sameTime(v.getEffectiveTime(), effectiveTime) || sameTime(v.getExpireTime(), effectiveTime))
|
||||
{
|
||||
throw new ServiceException("生效时间不能与已有版本的生效时间或失效时间相同");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort timed versions by effective_time, chain expire_time = next start, then set status
|
||||
* and sync product/detail effect fields (same idea as sales refreshVersionStatus).
|
||||
*/
|
||||
private void chainAndRefreshCatalogStatuses(String priceType)
|
||||
{
|
||||
assertCatalogType(priceType);
|
||||
PrcPriceSetVersion q = new PrcPriceSetVersion();
|
||||
q.setPriceType(priceType);
|
||||
List<PrcPriceSetVersion> versions = versionMapper.selectPrcPriceSetVersionList(q);
|
||||
if (versions == null || versions.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
versions.sort((a, b) -> {
|
||||
Date ta = a.getEffectiveTime();
|
||||
Date tb = b.getEffectiveTime();
|
||||
if (ta == null && tb == null)
|
||||
{
|
||||
return Integer.compare(nullToZero(a.getVersionSeq()), nullToZero(b.getVersionSeq()));
|
||||
}
|
||||
if (ta == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (tb == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int c = ta.compareTo(tb);
|
||||
if (c != 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return Integer.compare(nullToZero(a.getVersionSeq()), nullToZero(b.getVersionSeq()));
|
||||
});
|
||||
Date now = new Date();
|
||||
Long effectPsvId = null;
|
||||
for (int i = 0; i < versions.size(); i++)
|
||||
{
|
||||
PrcPriceSetVersion v = versions.get(i);
|
||||
Date nextStart = null;
|
||||
for (int j = i + 1; j < versions.size(); j++)
|
||||
{
|
||||
Date t = versions.get(j).getEffectiveTime();
|
||||
if (t != null)
|
||||
{
|
||||
nextStart = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
v.setExpireTime(nextStart);
|
||||
if (v.getEffectiveTime() == null)
|
||||
{
|
||||
v.setStatus(STATUS_DRAFT);
|
||||
continue;
|
||||
}
|
||||
if (v.getEffectiveTime().getTime() > now.getTime())
|
||||
{
|
||||
v.setStatus(STATUS_PENDING);
|
||||
continue;
|
||||
}
|
||||
if (nextStart != null && nextStart.getTime() <= now.getTime())
|
||||
{
|
||||
v.setStatus(STATUS_EXPIRED);
|
||||
continue;
|
||||
}
|
||||
v.setStatus(STATUS_EFFECT);
|
||||
effectPsvId = v.getPsvId();
|
||||
}
|
||||
if (effectPsvId != null)
|
||||
{
|
||||
for (PrcPriceSetVersion v : versions)
|
||||
{
|
||||
if (STATUS_EFFECT.equals(v.getStatus())
|
||||
&& v.getPsvId() != null
|
||||
&& !v.getPsvId().equals(effectPsvId))
|
||||
{
|
||||
v.setStatus(STATUS_EXPIRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PrcPriceSetVersion v : versions)
|
||||
{
|
||||
PrcPriceSetVersion db = versionMapper.selectPrcPriceSetVersionById(v.getPsvId());
|
||||
if (db == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
boolean statusChanged = !String.valueOf(v.getStatus()).equals(String.valueOf(db.getStatus()));
|
||||
boolean expireChanged = !sameTime(v.getExpireTime(), db.getExpireTime());
|
||||
boolean effChanged = !sameTime(v.getEffectiveTime(), db.getEffectiveTime());
|
||||
if (statusChanged || expireChanged || effChanged)
|
||||
{
|
||||
versionMapper.updatePrcPriceSetVersion(v);
|
||||
}
|
||||
}
|
||||
productMapper.syncEffectByPriceType(priceType);
|
||||
detailMapper.syncEffectByPriceType(priceType);
|
||||
}
|
||||
|
||||
private static int nullToZero(Integer v)
|
||||
{
|
||||
return v == null ? 0 : v.intValue();
|
||||
}
|
||||
|
||||
public List<PrcPriceSetVersion> listVersions(String priceType, String status)
|
||||
@@ -345,14 +476,16 @@ public class CatalogVersionSupport
|
||||
|
||||
/**
|
||||
* Prepare draft for catalog price create page.
|
||||
* copyFromLatest=true: copy from current EFFECT version when draft is empty.
|
||||
* copyFromLatest=false: empty draft (Excel import / rebuild).
|
||||
* copyFromLatest=true → priceBuildMode=IMPORT: copy from current EFFECT version when draft is empty.
|
||||
* copyFromLatest=false → priceBuildMode=IMPORT_FRESH: empty draft (Excel import / rebuild).
|
||||
* Legacy values COPY/IMPORT are migrated by SQL to IMPORT/IMPORT_FRESH.
|
||||
*/
|
||||
public PrcPriceSetVersion prepareDraftVersion(String priceType, boolean copyFromLatest)
|
||||
{
|
||||
assertCatalogType(priceType);
|
||||
List<PrcPriceSetVersion> drafts = listVersions(priceType, STATUS_DRAFT);
|
||||
PrcPriceSetVersion draft;
|
||||
String mode = copyFromLatest ? "IMPORT" : "IMPORT_FRESH";
|
||||
if (drafts.isEmpty())
|
||||
{
|
||||
if (copyFromLatest)
|
||||
@@ -364,7 +497,7 @@ public class CatalogVersionSupport
|
||||
}
|
||||
}
|
||||
draft = ensureDraftVersion(priceType, null, copyFromLatest);
|
||||
draft.setPriceBuildMode(copyFromLatest ? "COPY" : "IMPORT");
|
||||
draft.setPriceBuildMode(mode);
|
||||
versionMapper.updatePrcPriceSetVersion(draft);
|
||||
return reloadCatalogVersion(draft.getPsvId(), priceType);
|
||||
}
|
||||
@@ -386,12 +519,12 @@ public class CatalogVersionSupport
|
||||
productMapper.updatePriceTypeByPsvId(draft.getPsvId(), priceType);
|
||||
detailMapper.updatePriceTypeByPsvId(draft.getPsvId(), priceType);
|
||||
}
|
||||
draft.setPriceBuildMode("COPY");
|
||||
draft.setPriceBuildMode(mode);
|
||||
versionMapper.updatePrcPriceSetVersion(draft);
|
||||
}
|
||||
else if (count == 0)
|
||||
{
|
||||
draft.setPriceBuildMode("IMPORT");
|
||||
draft.setPriceBuildMode(mode);
|
||||
versionMapper.updatePrcPriceSetVersion(draft);
|
||||
}
|
||||
return reloadCatalogVersion(draft.getPsvId(), priceType);
|
||||
|
||||
Reference in New Issue
Block a user