套餐启用增加生效时间
This commit is contained in:
+7
-3
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.price.service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.ruoyi.price.domain.PrcCustomerPriceSet;
|
||||
import com.ruoyi.price.domain.PrcPriceSet;
|
||||
@@ -32,8 +33,11 @@ public interface IPrcPriceSetService
|
||||
|
||||
public int disable(Long priceSetId, String updateBy);
|
||||
|
||||
/** Activate a draft version: set effective_time=now, refresh version 0/1/2 */
|
||||
public int activateVersion(Long psvId, String updateBy);
|
||||
/**
|
||||
* Activate a draft version with user-specified effectiveTime.
|
||||
* effectiveTime <= now -> EFFECT; future -> PENDING(3). Then refresh 0/3/1/2.
|
||||
*/
|
||||
public int activateVersion(Long psvId, Date effectiveTime, String updateBy);
|
||||
|
||||
/**
|
||||
* Copy source version into a new draft version under the same package:
|
||||
@@ -65,7 +69,7 @@ public interface IPrcPriceSetService
|
||||
|
||||
public int deleteCustomerByIds(Long[] customerPricesetIds);
|
||||
|
||||
/** chain expire_time = next version effective_time, then refresh 0/1/2 */
|
||||
/** chain expire_time = next version effective_time, then refresh 0/3/1/2 */
|
||||
public int refreshAllVersionStatus();
|
||||
|
||||
/** submit async save, return taskId immediately */
|
||||
|
||||
+14
-3
@@ -128,8 +128,18 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
}
|
||||
bill.setBillKey(billKey);
|
||||
bill.setOrderNo(orderNo);
|
||||
bill.setCustomerId(request.getCustomerId() == null ? Long.valueOf(0L) : request.getCustomerId());
|
||||
bill.setCustomerCode(request.getCustomerCode());
|
||||
Long customerId = request.getCustomerId();
|
||||
if (customerId == null && result != null)
|
||||
{
|
||||
customerId = result.getCustomerId();
|
||||
}
|
||||
bill.setCustomerId(customerId == null ? Long.valueOf(0L) : customerId);
|
||||
String customerCode = request.getCustomerCode();
|
||||
if (StringUtils.isEmpty(customerCode) && result != null)
|
||||
{
|
||||
customerCode = result.getCustomerCode();
|
||||
}
|
||||
bill.setCustomerCode(customerCode);
|
||||
bill.setCustomerName(request.getCustomerName());
|
||||
bill.setTrackingNo(request.getTrackingNo());
|
||||
bill.setPieces(request.getPieces());
|
||||
@@ -178,7 +188,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
bill.setRoundMode(result.getRoundMode());
|
||||
result.setBillId(bill.getBillId());
|
||||
result.setOrderNo(orderNo);
|
||||
result.setCustomerCode(request.getCustomerCode());
|
||||
result.setCustomerId(bill.getCustomerId());
|
||||
result.setCustomerCode(bill.getCustomerCode());
|
||||
result.setIncomeTotal(bill.getIncomeTotal());
|
||||
result.setPayTotal(bill.getPayTotal());
|
||||
result.setPayableTotal(bill.getIncomeTotal());
|
||||
|
||||
+80
-51
@@ -57,6 +57,8 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
private static final String TYPE_DISCOUNT = "DISCOUNT";
|
||||
private static final String VER_DRAFT = "0";
|
||||
private static final String VER_EFFECT = "1";
|
||||
/** Pending: effective_time set but not yet reached */
|
||||
private static final String VER_PENDING = "3";
|
||||
private static final String VER_EXPIRED = "2";
|
||||
|
||||
@Autowired
|
||||
@@ -93,6 +95,8 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
PrcPriceSet set = setMapper.selectPrcPriceSetById(priceSetId);
|
||||
if (set != null)
|
||||
{
|
||||
// Reconcile version status/expire windows so UI always shows at most one EFFECT
|
||||
refreshVersionStatus(priceSetId);
|
||||
fillExpired(set);
|
||||
fillVersions(set);
|
||||
}
|
||||
@@ -268,12 +272,16 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int activateVersion(Long psvId, String updateBy)
|
||||
public int activateVersion(Long psvId, Date effectiveTime, String updateBy)
|
||||
{
|
||||
if (psvId == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.version.notExists"));
|
||||
}
|
||||
if (effectiveTime == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.version.effectiveTime.empty"));
|
||||
}
|
||||
PrcPriceSetVersion version = versionMapper.selectPrcPriceSetVersionById(psvId);
|
||||
if (version == null)
|
||||
{
|
||||
@@ -288,34 +296,11 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.edit.stopped"));
|
||||
}
|
||||
Date now = new Date();
|
||||
// Expire currently effective versions under the same package
|
||||
PrcPriceSetVersion q = new PrcPriceSetVersion();
|
||||
q.setPriceSetId(set.getPriceSetId());
|
||||
List<PrcPriceSetVersion> siblings = versionMapper.selectPrcPriceSetVersionList(q);
|
||||
if (siblings != null)
|
||||
{
|
||||
for (PrcPriceSetVersion other : siblings)
|
||||
{
|
||||
if (other.getPsvId() == null || other.getPsvId().equals(psvId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (VER_EFFECT.equals(other.getStatus()))
|
||||
{
|
||||
other.setStatus(VER_EXPIRED);
|
||||
other.setExpireTime(now);
|
||||
other.setUpdateBy(updateBy);
|
||||
versionMapper.updatePrcPriceSetVersion(other);
|
||||
}
|
||||
}
|
||||
}
|
||||
version.setEffectiveTime(now);
|
||||
// Set schedule; refreshVersionStatus decides PENDING(3) vs EFFECT(1) and chains expire_time
|
||||
version.setEffectiveTime(effectiveTime);
|
||||
version.setExpireTime(null);
|
||||
version.setStatus(VER_EFFECT);
|
||||
version.setUpdateBy(updateBy);
|
||||
versionMapper.updatePrcPriceSetVersion(version);
|
||||
|
||||
refreshVersionStatus(set.getPriceSetId());
|
||||
return 1;
|
||||
}
|
||||
@@ -338,6 +323,10 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.edit.stopped"));
|
||||
}
|
||||
if (hasDraftVersion(set.getPriceSetId()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.version.copy.draftExists"));
|
||||
}
|
||||
|
||||
Integer maxSeq = versionMapper.selectMaxVersionSeq(set.getPriceSetId());
|
||||
int seq = maxSeq == null ? 1 : maxSeq.intValue() + 1;
|
||||
@@ -1925,6 +1914,34 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
version.setSurcharges(saved);
|
||||
}
|
||||
|
||||
/** True when package already has a true draft (status=0). Pending(3) does not block copy. */
|
||||
private boolean hasDraftVersion(Long priceSetId)
|
||||
{
|
||||
if (priceSetId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
PrcPriceSetVersion q = new PrcPriceSetVersion();
|
||||
q.setPriceSetId(priceSetId);
|
||||
List<PrcPriceSetVersion> list = versionMapper.selectPrcPriceSetVersionList(q);
|
||||
if (list == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (PrcPriceSetVersion v : list)
|
||||
{
|
||||
if (v == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (VER_DRAFT.equals(v.getStatus()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void refreshVersionStatus(Long priceSetId)
|
||||
{
|
||||
PrcPriceSetVersion q = new PrcPriceSetVersion();
|
||||
@@ -1958,10 +1975,11 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
return Integer.compare(nullToZero(a.getVersionSeq()), nullToZero(b.getVersionSeq()));
|
||||
});
|
||||
Date now = new Date();
|
||||
// First pass: chain expire_time = next sibling's effective_time; compute window status
|
||||
Long effectPsvId = null;
|
||||
for (int i = 0; i < versions.size(); i++)
|
||||
{
|
||||
PrcPriceSetVersion v = versions.get(i);
|
||||
// Next start only among versions that already have effective_time
|
||||
Date nextStart = null;
|
||||
for (int j = i + 1; j < versions.size(); j++)
|
||||
{
|
||||
@@ -1972,46 +1990,57 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
break;
|
||||
}
|
||||
}
|
||||
String status;
|
||||
v.setExpireTime(nextStart);
|
||||
if (v.getEffectiveTime() == null)
|
||||
{
|
||||
status = VER_DRAFT;
|
||||
v.setStatus(VER_DRAFT);
|
||||
continue;
|
||||
}
|
||||
else if (startedNotAfter(v.getEffectiveTime(), now)
|
||||
&& (nextStart == null || nextStart.after(now)))
|
||||
// Not started yet -> pending
|
||||
if (v.getEffectiveTime().getTime() > now.getTime())
|
||||
{
|
||||
status = VER_EFFECT;
|
||||
v.setStatus(VER_PENDING);
|
||||
continue;
|
||||
}
|
||||
else if (startedNotAfter(v.getEffectiveTime(), now))
|
||||
// Window ended: expire_time <= now (same rule as bill: expire_time > asOf to stay active)
|
||||
if (nextStart != null && nextStart.getTime() <= now.getTime())
|
||||
{
|
||||
status = VER_EXPIRED;
|
||||
v.setStatus(VER_EXPIRED);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
// In window: candidate for the single EFFECT version (latest wins)
|
||||
v.setStatus(VER_EFFECT);
|
||||
effectPsvId = v.getPsvId();
|
||||
}
|
||||
// Second pass: only the latest in-window version stays EFFECT
|
||||
if (effectPsvId != null)
|
||||
{
|
||||
for (PrcPriceSetVersion v : versions)
|
||||
{
|
||||
// future-dated: keep as draft until wall-clock reaches effective_time
|
||||
status = VER_DRAFT;
|
||||
if (VER_EFFECT.equals(v.getStatus())
|
||||
&& v.getPsvId() != null
|
||||
&& !v.getPsvId().equals(effectPsvId))
|
||||
{
|
||||
v.setStatus(VER_EXPIRED);
|
||||
}
|
||||
}
|
||||
boolean statusChanged = !status.equals(v.getStatus());
|
||||
boolean expireChanged = !sameTime(nextStart, v.getExpireTime());
|
||||
}
|
||||
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());
|
||||
if (statusChanged || expireChanged)
|
||||
{
|
||||
v.setStatus(status);
|
||||
v.setExpireTime(nextStart);
|
||||
versionMapper.updatePrcPriceSetVersion(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** effective_time <= now (+1s skew tolerance) */
|
||||
private static boolean startedNotAfter(Date effectiveTime, Date now)
|
||||
{
|
||||
if (effectiveTime == null || now == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return effectiveTime.getTime() <= now.getTime() + 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int refreshAllVersionStatus()
|
||||
{
|
||||
|
||||
+65
-4
@@ -21,6 +21,8 @@ import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.sign.Md5Utils;
|
||||
import com.ruoyi.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.ruoyi.customer.customerinfo.mapper.BmsCustomerMapper;
|
||||
import com.ruoyi.price.domain.BmsProduct;
|
||||
import com.ruoyi.price.domain.BmsProductCountry;
|
||||
import com.ruoyi.price.domain.PrcCustomerPriceSet;
|
||||
@@ -33,6 +35,7 @@ import com.ruoyi.price.domain.PrcQuoteFee;
|
||||
import com.ruoyi.price.domain.PrcSurchargeRel;
|
||||
import com.ruoyi.price.domain.PrcZone;
|
||||
import com.ruoyi.price.mapper.PrcZoneDetailMapper;
|
||||
import com.ruoyi.price.domain.vo.TmsPriceBillRequest;
|
||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteFeeLine;
|
||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteRequest;
|
||||
import com.ruoyi.price.domain.vo.TmsPriceQuoteResult;
|
||||
@@ -106,6 +109,9 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
@Autowired
|
||||
private IBillSearchStore billSearchStore;
|
||||
|
||||
@Autowired
|
||||
private BmsCustomerMapper bmsCustomerMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public TmsPriceQuoteResult quote(TmsPriceQuoteRequest request)
|
||||
@@ -125,6 +131,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
private TmsPriceQuoteResult quoteInternal(TmsPriceQuoteRequest request)
|
||||
{
|
||||
validateRequest(request);
|
||||
resolveCustomer(request);
|
||||
Date bizDate = resolveBizDate(request.getBizDate());
|
||||
BigDecimal weight = request.getWeight().setScale(3, RoundingMode.HALF_UP);
|
||||
String quoteKey = buildQuoteKey(request, weight, bizDate);
|
||||
@@ -156,6 +163,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
public TmsPriceQuoteResult calculate(TmsPriceQuoteRequest request)
|
||||
{
|
||||
validateRequest(request);
|
||||
resolveCustomer(request);
|
||||
Date bizDate = resolveBizDate(request.getBizDate());
|
||||
TmsPriceQuoteResult result = doQuote(request, bizDate);
|
||||
applySurchargesAndFees(result);
|
||||
@@ -312,6 +320,53 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
{
|
||||
result.setDestPostcode(emptyToNull(request.getDestPostcode()));
|
||||
}
|
||||
// Always prefer customer resolved from customerCode (ignore TMS/bind ids)
|
||||
if (request.getCustomerId() != null)
|
||||
{
|
||||
result.setCustomerId(request.getCustomerId());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(request.getCustomerCode()))
|
||||
{
|
||||
result.setCustomerCode(request.getCustomerCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Require customerCode; resolve customer_id from bms_customer.
|
||||
*/
|
||||
private void resolveCustomer(TmsPriceQuoteRequest request)
|
||||
{
|
||||
if (request == null || StringUtils.isEmpty(request.getCustomerCode()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerCodeRequired"));
|
||||
}
|
||||
String code = request.getCustomerCode().trim();
|
||||
if (StringUtils.isEmpty(code))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerCodeRequired"));
|
||||
}
|
||||
request.setCustomerCode(code);
|
||||
BmsCustomer query = new BmsCustomer();
|
||||
query.setCustomerCode(code);
|
||||
List<BmsCustomer> list = bmsCustomerMapper.selectBmsCustomerList(query);
|
||||
if (list == null || list.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerCodeNotFound"));
|
||||
}
|
||||
BmsCustomer hit = list.get(0);
|
||||
request.setCustomerId(hit.getCustomerId());
|
||||
if (StringUtils.isNotEmpty(hit.getCustomerCode()))
|
||||
{
|
||||
request.setCustomerCode(hit.getCustomerCode());
|
||||
}
|
||||
if (request instanceof TmsPriceBillRequest)
|
||||
{
|
||||
TmsPriceBillRequest billReq = (TmsPriceBillRequest) request;
|
||||
if (StringUtils.isEmpty(billReq.getCustomerName()) && StringUtils.isNotEmpty(hit.getCustomerName()))
|
||||
{
|
||||
billReq.setCustomerName(hit.getCustomerName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveCountryIso2(String productCode, String countryCode, String countryName)
|
||||
@@ -684,6 +739,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
quote.setQuoteId(UUID.randomUUID().toString());
|
||||
quote.setQuoteKey(quoteKey);
|
||||
quote.setCustomerId(request.getCustomerId() == null ? Long.valueOf(0L) : request.getCustomerId());
|
||||
quote.setCustomerCode(emptyToNull(request.getCustomerCode()));
|
||||
quote.setProductCode(result.getProductCode());
|
||||
quote.setProductName(result.getProductName());
|
||||
quote.setCountryCode(result.getCountryCode());
|
||||
@@ -810,6 +866,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
r.setMatchSource(quote.getMatchSource());
|
||||
r.setMatchMessage(quote.getMatchMessage());
|
||||
r.setCustomerId(quote.getCustomerId());
|
||||
r.setCustomerCode(quote.getCustomerCode());
|
||||
r.setPriceSetId(quote.getPriceSetId());
|
||||
r.setPriceSetCode(quote.getPriceSetCode());
|
||||
r.setPriceSetName(quote.getPriceSetName());
|
||||
@@ -857,6 +914,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
to.setMatchSource(from.getMatchSource());
|
||||
to.setMatchMessage(from.getMatchMessage());
|
||||
to.setCustomerId(from.getCustomerId());
|
||||
to.setCustomerCode(from.getCustomerCode());
|
||||
to.setPriceSetId(from.getPriceSetId());
|
||||
to.setPriceSetCode(from.getPriceSetCode());
|
||||
to.setPriceSetName(from.getPriceSetName());
|
||||
@@ -892,6 +950,10 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
|
||||
private String buildQuoteKey(TmsPriceQuoteRequest request, BigDecimal weight, Date bizDate)
|
||||
{
|
||||
if (StringUtils.isEmpty(request.getCustomerCode()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerCodeRequired"));
|
||||
}
|
||||
String countryCode = emptyToNull(request.getCountryCode());
|
||||
if (countryCode != null)
|
||||
{
|
||||
@@ -899,8 +961,7 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
}
|
||||
String countryName = emptyToNull(request.getCountryName());
|
||||
String biz = new SimpleDateFormat("yyyy-MM-dd").format(bizDate);
|
||||
String raw = (StringUtils.isNotEmpty(request.getCustomerCode())
|
||||
? request.getCustomerCode() : String.valueOf(request.getCustomerId())) + "|"
|
||||
String raw = request.getCustomerCode().trim() + "|"
|
||||
+ request.getProductCode().trim() + "|"
|
||||
+ nvlStr(countryCode) + "|"
|
||||
+ nvlStr(countryName) + "|"
|
||||
@@ -995,9 +1056,9 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.requestBodyRequired"));
|
||||
}
|
||||
if (StringUtils.isEmpty(request.getCustomerCode()) && request.getCustomerId() == null)
|
||||
if (StringUtils.isEmpty(request.getCustomerCode()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerIdRequired"));
|
||||
throw new ServiceException(MessageUtils.message("price.quote.customerCodeRequired"));
|
||||
}
|
||||
if (StringUtils.isEmpty(request.getProductCode()))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user