修改套餐价格
This commit is contained in:
@@ -37,6 +37,15 @@ public class PrcPriceSet extends BaseEntity
|
||||
private Boolean expired;
|
||||
private String keyword;
|
||||
private String submitFlag;
|
||||
/** current version on create/edit save */
|
||||
private PrcPriceSetVersion version;
|
||||
private List<PrcPriceSetDetail> details;
|
||||
private List<PrcPriceSetVersion> versions;
|
||||
private List<PrcCustomerPriceSet> customers;
|
||||
/** async save task id (not persisted) */
|
||||
private String saveTaskId;
|
||||
/** Y: backend joins product library into details (skip front pull) */
|
||||
private String pullFromLibrary;
|
||||
/** Y: even if version already has details, delete+re-pull from library */
|
||||
private String forcePullLibrary;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ruoyi.price.domain;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -14,6 +15,8 @@ public class PrcPriceSetDetail implements Serializable
|
||||
|
||||
private Long psdId;
|
||||
private Long priceSetId;
|
||||
/** prc_price_set_version.psv_id */
|
||||
private Long psvId;
|
||||
private String productCode;
|
||||
private String productName;
|
||||
private String countryCode;
|
||||
@@ -27,6 +30,9 @@ public class PrcPriceSetDetail implements Serializable
|
||||
private Long zdId;
|
||||
private Long wsdId;
|
||||
private String weightLabel;
|
||||
/** KG inclusive, same as bms_product_country */
|
||||
private BigDecimal weightMin;
|
||||
private BigDecimal weightMax;
|
||||
/** bms_product_country.detail_id */
|
||||
private Long productCountryId;
|
||||
private BigDecimal fvValue;
|
||||
@@ -35,8 +41,16 @@ public class PrcPriceSetDetail implements Serializable
|
||||
/** UP / DOWN / HALF_UP */
|
||||
private String roundMode;
|
||||
private Integer prId;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date effectiveDate;
|
||||
/** null = open */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date expireDate;
|
||||
private List<PrcPriceSetVersionSurcharge> surcharges;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
/** query only: product/country/zone/weight keyword */
|
||||
private String keyword;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.ruoyi.price.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Async save progress for price set (Redis).
|
||||
*/
|
||||
public class PrcPriceSetSaveTask implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String STATUS_PENDING = "PENDING";
|
||||
public static final String STATUS_RUNNING = "RUNNING";
|
||||
public static final String STATUS_SUCCESS = "SUCCESS";
|
||||
public static final String STATUS_FAIL = "FAIL";
|
||||
|
||||
private String taskId;
|
||||
private String status;
|
||||
private int percent;
|
||||
private String message;
|
||||
private Long priceSetId;
|
||||
private String error;
|
||||
|
||||
public String getTaskId()
|
||||
{
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(String taskId)
|
||||
{
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getPercent()
|
||||
{
|
||||
return percent;
|
||||
}
|
||||
|
||||
public void setPercent(int percent)
|
||||
{
|
||||
this.percent = percent;
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Long getPriceSetId()
|
||||
{
|
||||
return priceSetId;
|
||||
}
|
||||
|
||||
public void setPriceSetId(Long priceSetId)
|
||||
{
|
||||
this.priceSetId = priceSetId;
|
||||
}
|
||||
|
||||
public String getError()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error)
|
||||
{
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.price.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/** Price set version prc_price_set_version */
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PrcPriceSetVersion extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long psvId;
|
||||
private Long priceSetId;
|
||||
/** V1 / V2 */
|
||||
private String versionNo;
|
||||
private Integer versionSeq;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date effectiveTime;
|
||||
/** null = open; set to next version effective_time when that version starts */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date expireTime;
|
||||
/** 0 draft / 1 active / 2 expired */
|
||||
private String status;
|
||||
|
||||
private List<PrcPriceSetDetail> details;
|
||||
private List<PrcPriceSetVersionSurcharge> surcharges;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.price.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/** Price set version surcharge snapshot prc_price_set_version_surcharge */
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PrcPriceSetVersionSurcharge extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long psvsId;
|
||||
private Long psvId;
|
||||
/** source prc_surcharge.sc_id */
|
||||
private Long scId;
|
||||
/** prc_price_set_detail.psd_id */
|
||||
private Long psdId;
|
||||
/** copied from detail */
|
||||
private String productCode;
|
||||
private String scName;
|
||||
private String feeType;
|
||||
/** FIXED / WEIGHT / RATE */
|
||||
private String chargeType;
|
||||
private BigDecimal chargeValue;
|
||||
private String currency;
|
||||
private String roundMode;
|
||||
private String countryCode;
|
||||
private String scNote;
|
||||
}
|
||||
+26
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.price.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.ruoyi.price.domain.PrcPriceSetDetail;
|
||||
@@ -23,10 +24,35 @@ public interface PrcPriceSetDetailMapper
|
||||
|
||||
public int deletePrcPriceSetDetailByPriceSetId(Long priceSetId);
|
||||
|
||||
public int deletePrcPriceSetDetailByPsvId(Long psvId);
|
||||
|
||||
/** legacy rows: price_set_id match but psv_id is null */
|
||||
public int deleteOrphanDetailsByPriceSetId(Long priceSetId);
|
||||
|
||||
public int countProductByPriceSetId(Long priceSetId);
|
||||
|
||||
public int countByPriceSetId(Long priceSetId);
|
||||
|
||||
public int countByPsvId(Long psvId);
|
||||
|
||||
/** Copy all details from src version into new version (new psd_id, same price_set_id) */
|
||||
public int copyDetailsFromVersion(@Param("srcPsvId") Long srcPsvId, @Param("newPsvId") Long newPsvId);
|
||||
|
||||
/**
|
||||
* FIXED: insert details from active product + country library (asOf window or openOnly fallback).
|
||||
* @return inserted row count
|
||||
*/
|
||||
public int insertFixedDetailsFromLibrary(
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
@Param("psvId") Long psvId,
|
||||
@Param("asOf") Date asOf,
|
||||
@Param("openOnly") boolean openOnly);
|
||||
|
||||
/** DISCOUNT: one detail row per active product */
|
||||
public int insertDiscountDetailsFromLibrary(
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
@Param("psvId") Long psvId);
|
||||
|
||||
/** FIXED: product + country + zone + productCountryId / weight */
|
||||
public PrcPriceSetDetail selectFixedMatch(
|
||||
@Param("priceSetId") Long priceSetId,
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.price.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.ruoyi.price.domain.PrcPriceSetVersion;
|
||||
|
||||
/**
|
||||
* Price set version
|
||||
*/
|
||||
public interface PrcPriceSetVersionMapper
|
||||
{
|
||||
public PrcPriceSetVersion selectPrcPriceSetVersionById(Long psvId);
|
||||
|
||||
public List<PrcPriceSetVersion> selectPrcPriceSetVersionList(PrcPriceSetVersion version);
|
||||
|
||||
public Integer selectMaxVersionSeq(@Param("priceSetId") Long priceSetId);
|
||||
|
||||
public int insertPrcPriceSetVersion(PrcPriceSetVersion version);
|
||||
|
||||
public int updatePrcPriceSetVersion(PrcPriceSetVersion version);
|
||||
|
||||
public int deletePrcPriceSetVersionByIds(Long[] psvIds);
|
||||
|
||||
public int deletePrcPriceSetVersionByPriceSetId(Long priceSetId);
|
||||
|
||||
public List<Long> selectPriceSetIds();
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.ruoyi.price.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.ruoyi.price.domain.PrcPriceSetVersionSurcharge;
|
||||
|
||||
/**
|
||||
* Price set version surcharge snapshot
|
||||
*/
|
||||
public interface PrcPriceSetVersionSurchargeMapper
|
||||
{
|
||||
public PrcPriceSetVersionSurcharge selectPrcPriceSetVersionSurchargeById(Long psvsId);
|
||||
|
||||
public List<PrcPriceSetVersionSurcharge> selectPrcPriceSetVersionSurchargeList(PrcPriceSetVersionSurcharge surcharge);
|
||||
|
||||
public int insertPrcPriceSetVersionSurcharge(PrcPriceSetVersionSurcharge surcharge);
|
||||
|
||||
public int updatePrcPriceSetVersionSurcharge(PrcPriceSetVersionSurcharge surcharge);
|
||||
|
||||
public int deletePrcPriceSetVersionSurchargeByIds(Long[] psvsIds);
|
||||
|
||||
public int deleteByPsvId(Long psvId);
|
||||
|
||||
public int deleteByPsdId(Long psdId);
|
||||
|
||||
public List<PrcPriceSetVersionSurcharge> selectByPsdIds(@Param("psdIds") List<Long> psdIds);
|
||||
|
||||
/** Snapshot all applicable product-rel surcharges for details under psvId (library create). */
|
||||
public int insertFromLibraryRels(@Param("psvId") Long psvId, @Param("createBy") String createBy);
|
||||
|
||||
/** Copy surcharge snapshots from src version onto new version details (match by detail keys). */
|
||||
public int copySurchargesFromVersion(
|
||||
@Param("srcPsvId") Long srcPsvId,
|
||||
@Param("newPsvId") Long newPsvId,
|
||||
@Param("createBy") String createBy);
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.ruoyi.price.domain.PrcCustomerPriceSet;
|
||||
import com.ruoyi.price.domain.PrcPriceSet;
|
||||
import com.ruoyi.price.domain.PrcPriceSetCheckItem;
|
||||
import com.ruoyi.price.domain.PrcPriceSetDetail;
|
||||
import com.ruoyi.price.domain.PrcPriceSetSaveTask;
|
||||
|
||||
/**
|
||||
* 价格套餐 服务层
|
||||
@@ -31,6 +32,19 @@ 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);
|
||||
|
||||
/**
|
||||
* Copy source version into a new draft version under the same package:
|
||||
* insert prc_price_set_version + copy prc_price_set_detail (+ surcharge snapshots).
|
||||
* @return new psvId
|
||||
*/
|
||||
public Long copyVersion(Long sourcePsvId, String createBy);
|
||||
|
||||
/** Delete a draft version and its details / surcharge snapshots */
|
||||
public int deleteVersion(Long psvId, String updateBy);
|
||||
|
||||
public Long copy(Long priceSetId, String createBy);
|
||||
|
||||
public List<PrcPriceSetCheckItem> validate(PrcPriceSet set);
|
||||
@@ -50,4 +64,13 @@ public interface IPrcPriceSetService
|
||||
public int updateCustomer(PrcCustomerPriceSet customer);
|
||||
|
||||
public int deleteCustomerByIds(Long[] customerPricesetIds);
|
||||
|
||||
/** chain expire_time = next version effective_time, then refresh 0/1/2 */
|
||||
public int refreshAllVersionStatus();
|
||||
|
||||
/** submit async save, return taskId immediately */
|
||||
public String submitSaveAsync(PrcPriceSet set);
|
||||
|
||||
/** poll async save progress */
|
||||
public PrcPriceSetSaveTask getSaveTask(String taskId);
|
||||
}
|
||||
|
||||
+1003
-68
File diff suppressed because it is too large
Load Diff
@@ -3,10 +3,13 @@ package com.ruoyi.price.task;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.price.mapper.BmsProductCountryMapper;
|
||||
import com.ruoyi.price.mapper.BmsProductMapper;
|
||||
import com.ruoyi.price.service.IPrcPriceSetService;
|
||||
|
||||
/**
|
||||
* bms_product / bms_product_country 状态自动刷新
|
||||
@@ -26,7 +29,7 @@ import com.ruoyi.price.mapper.BmsProductMapper;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class BmsStatusRefreshTask
|
||||
public class BmsStatusRefreshTask implements ApplicationRunner
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(BmsStatusRefreshTask.class);
|
||||
|
||||
@@ -36,6 +39,9 @@ public class BmsStatusRefreshTask
|
||||
@Autowired
|
||||
private BmsProductCountryMapper productCountryMapper;
|
||||
|
||||
@Autowired
|
||||
private IPrcPriceSetService priceSetService;
|
||||
|
||||
/** 每天 02:00 跑(cron: sec min hour DOM month DOW) */
|
||||
@Scheduled(cron = "0 0 2 * * ?")
|
||||
public void scheduled()
|
||||
@@ -43,16 +49,31 @@ public class BmsStatusRefreshTask
|
||||
refreshNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args)
|
||||
{
|
||||
try
|
||||
{
|
||||
int n = priceSetService.refreshAllVersionStatus();
|
||||
log.info("startup prc_price_set_version expire/status refreshed, sets={}", n);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("startup prc_price_set_version refresh failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即刷新两表状态。返回 [product 影响行数, country 影响行数]。
|
||||
* 异常时打印 ERROR 并原样抛出,便于调用方(手动触发接口)回滚事务。
|
||||
* Refresh product/country status and chain version expire_time.
|
||||
* Returns [product rows, country rows, price-set count].
|
||||
*/
|
||||
public int[] refreshNow()
|
||||
{
|
||||
int productCount = productMapper.refreshStatusByDates();
|
||||
int countryCount = productCountryMapper.refreshStatusByDates();
|
||||
log.info("BmsStatusRefreshTask done: bms_product={}, bms_product_country={}",
|
||||
productCount, countryCount);
|
||||
return new int[] { productCount, countryCount };
|
||||
int versionSets = priceSetService.refreshAllVersionStatus();
|
||||
log.info("BmsStatusRefreshTask done: bms_product={}, bms_product_country={}, price_set_version_sets={}",
|
||||
productCount, countryCount, versionSets);
|
||||
return new int[] { productCount, countryCount, versionSets };
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.ruoyi.price.task;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.price.domain.PrcPriceSet;
|
||||
import com.ruoyi.price.domain.PrcPriceSetSaveTask;
|
||||
import com.ruoyi.price.service.IPrcPriceSetService;
|
||||
|
||||
/**
|
||||
* Async runner for price-set save (avoids HTTP timeout on large detail snapshots).
|
||||
*/
|
||||
@Component
|
||||
public class PrcPriceSetSaveAsyncRunner
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PrcPriceSetSaveAsyncRunner.class);
|
||||
|
||||
public static final String CACHE_KEY_PREFIX = "price:set:save:task:";
|
||||
public static final int TTL_MINUTES = 60;
|
||||
|
||||
@Autowired
|
||||
private IPrcPriceSetService priceSetService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Async("threadPoolTaskExecutor")
|
||||
public void run(String taskId, PrcPriceSet set)
|
||||
{
|
||||
try
|
||||
{
|
||||
put(taskId, PrcPriceSetSaveTask.STATUS_RUNNING, 8, "saving basic", null, null);
|
||||
set.setSaveTaskId(taskId);
|
||||
Long id = priceSetService.savePrcPriceSet(set);
|
||||
put(taskId, PrcPriceSetSaveTask.STATUS_SUCCESS, 100, "done", id, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("async save price set failed, taskId={}", taskId, e);
|
||||
String msg = e.getMessage();
|
||||
if (StringUtils.isEmpty(msg))
|
||||
{
|
||||
msg = e.getClass().getSimpleName();
|
||||
}
|
||||
put(taskId, PrcPriceSetSaveTask.STATUS_FAIL, 100, "failed", null, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void put(String taskId, String status, int percent, String message, Long priceSetId, String error)
|
||||
{
|
||||
PrcPriceSetSaveTask task = new PrcPriceSetSaveTask();
|
||||
task.setTaskId(taskId);
|
||||
task.setStatus(status);
|
||||
task.setPercent(percent);
|
||||
task.setMessage(message);
|
||||
task.setPriceSetId(priceSetId);
|
||||
task.setError(error);
|
||||
redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public PrcPriceSetSaveTask get(String taskId)
|
||||
{
|
||||
return redisCache.getCacheObject(CACHE_KEY_PREFIX + taskId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user