增加一个打单功能套餐
This commit is contained in:
@@ -20,9 +20,6 @@ public class ChannelProductMap
|
||||
|
||||
private Long productId;
|
||||
|
||||
/** 应收套餐 prc_price_set.price_set_id */
|
||||
private Long priceSetId;
|
||||
|
||||
/** AR 应收,AP 应付 */
|
||||
private String payType;
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.bms.price.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 打单套餐价卡版本(按 pay_product_term.version_no 聚合,不走价格套餐 prc_price_set_version)。
|
||||
*/
|
||||
@Data
|
||||
public class LabelPackageVersion
|
||||
{
|
||||
private Long priceSetId;
|
||||
|
||||
private Integer versionNo;
|
||||
|
||||
/** 展示用,如 V1 */
|
||||
private String versionLabel;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date effectiveTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date expireTime;
|
||||
|
||||
/** 与 pay_product_term.status 一致:0待生效 1生效 2已失效 */
|
||||
private String status;
|
||||
|
||||
private Integer productCount;
|
||||
|
||||
/** status=1 生效条数 */
|
||||
private Integer activeCount;
|
||||
|
||||
/** status=0 待生效条数 */
|
||||
private Integer pendingCount;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -12,6 +12,9 @@ public class PayExtraLine
|
||||
|
||||
private Long productId;
|
||||
|
||||
/** 价卡周期,对应 pay_product_term.term_id;与 productId 组成明细维度 */
|
||||
private Long termId;
|
||||
|
||||
/** 邮编 或 配置 */
|
||||
private String lineType;
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ public class PayProductTerm extends BaseEntity
|
||||
|
||||
private Long productId;
|
||||
|
||||
/** 打单套餐ID;应付公共模板为空 */
|
||||
private Long priceSetId;
|
||||
|
||||
private Integer versionNo;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@@ -30,7 +33,7 @@ public class PayProductTerm extends BaseEntity
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date effectiveEnd;
|
||||
|
||||
/** 0 生效,1 失效 */
|
||||
/** 0待生效 1生效 2已失效 */
|
||||
private String status;
|
||||
|
||||
private String productName;
|
||||
|
||||
@@ -13,5 +13,17 @@ public class PaySaveCommand
|
||||
/** 为 true 时,同文件同表同名的旧产品先删后插 */
|
||||
private boolean overwrite;
|
||||
|
||||
/** 打单套餐ID;有值时走 LABEL 导入(稳定 product_id + term.price_set_id) */
|
||||
private Long priceSetId;
|
||||
|
||||
/** 打单套餐名称;priceSetId 为空时新建套餐壳 */
|
||||
private String priceSetName;
|
||||
|
||||
/** 打单套餐备注 */
|
||||
private String priceSetNote;
|
||||
|
||||
/** 编辑待生效版本时传入,覆盖该 version_no,不新建版本号 */
|
||||
private Integer versionNo;
|
||||
|
||||
private List<PayProduct> products = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ public class PaySurcharge
|
||||
|
||||
private Long productId;
|
||||
|
||||
/** 所属价卡版本,跟产品版本一起变 */
|
||||
/** 价卡周期,对应 pay_product_term.term_id;与 productId 组成明细维度 */
|
||||
private Long termId;
|
||||
|
||||
/** 所属价卡版本,跟产品版本一起变(展示兼容) */
|
||||
private Integer versionNo;
|
||||
|
||||
private String sectionName;
|
||||
|
||||
@@ -13,7 +13,10 @@ public class PayWeightBand
|
||||
|
||||
private Long productId;
|
||||
|
||||
/** 所属价卡版本,跟产品版本一起变 */
|
||||
/** 价卡周期,对应 pay_product_term.term_id;与 productId 组成明细维度 */
|
||||
private Long termId;
|
||||
|
||||
/** 所属价卡版本,跟产品版本一起变(展示兼容) */
|
||||
private Integer versionNo;
|
||||
|
||||
/** 报价区块,例如派送费、偏远附加费 */
|
||||
|
||||
@@ -19,6 +19,8 @@ public class PrcPriceSet extends BaseEntity
|
||||
public static final String CATEGORY_PACKAGE = "PACKAGE";
|
||||
/** Boss exclusive quote. */
|
||||
public static final String CATEGORY_EXCLUSIVE = "EXCLUSIVE";
|
||||
/** Label / 打单套餐(应收价卡套餐). */
|
||||
public static final String CATEGORY_LABEL = "LABEL";
|
||||
|
||||
private Long priceSetId;
|
||||
private String priceSetCode;
|
||||
@@ -26,7 +28,7 @@ public class PrcPriceSet extends BaseEntity
|
||||
private String priceSetNote;
|
||||
/** FIXED / DISCOUNT */
|
||||
private String setType;
|
||||
/** PACKAGE=ordinary set / EXCLUSIVE=boss exclusive quote */
|
||||
/** PACKAGE=ordinary set / EXCLUSIVE=boss exclusive quote / LABEL=打单套餐 */
|
||||
private String setCategory;
|
||||
private BigDecimal defaultDiscount;
|
||||
private String defaultType;
|
||||
|
||||
@@ -38,16 +38,33 @@ public interface PayProductMapper
|
||||
|
||||
List<PayWeightBand> selectWeightBands(@Param("productIds") List<Long> productIds);
|
||||
|
||||
List<PayWeightBand> selectWeightBandsByTerm(@Param("termIds") List<Long> termIds);
|
||||
|
||||
List<PaySurcharge> selectSurcharges(@Param("productIds") List<Long> productIds);
|
||||
|
||||
List<PaySurcharge> selectSurchargesByTerm(@Param("termIds") List<Long> termIds);
|
||||
|
||||
List<PayExtraLine> selectExtraLines(@Param("productIds") List<Long> productIds);
|
||||
|
||||
List<PayExtraLine> selectExtraLinesByTerm(@Param("termIds") List<Long> termIds);
|
||||
|
||||
int deleteWeightBands(@Param("productIds") List<Long> productIds);
|
||||
|
||||
int deleteSurcharges(@Param("productIds") List<Long> productIds);
|
||||
|
||||
int deleteExtraLines(@Param("productIds") List<Long> productIds);
|
||||
|
||||
int deleteWeightBandsByTerm(@Param("termIds") List<Long> termIds);
|
||||
|
||||
int deleteSurchargesByTerm(@Param("termIds") List<Long> termIds);
|
||||
|
||||
int deleteExtraLinesByTerm(@Param("termIds") List<Long> termIds);
|
||||
|
||||
Long selectTemplateIdByType(@Param("dictValue") String dictValue, @Param("productType") String productType);
|
||||
|
||||
/** 打单专用:命中仅属于打单套餐的 AR 产品,不命中应付公共模板 */
|
||||
Long selectLabelProductIdByDict(@Param("dictValue") String dictValue);
|
||||
|
||||
int deletePayProducts(@Param("productIds") List<Long> productIds);
|
||||
|
||||
List<Long> selectFamilyIds(@Param("rootId") Long rootId);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bms.price.mapper;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.bms.price.domain.LabelPackageVersion;
|
||||
import com.bms.price.domain.PayProductTerm;
|
||||
|
||||
/**
|
||||
@@ -16,6 +17,24 @@ public interface PayProductTermMapper
|
||||
|
||||
PayProductTerm selectByProductId(Long productId);
|
||||
|
||||
List<PayProductTerm> selectByPriceSetId(@Param("priceSetId") Long priceSetId);
|
||||
|
||||
List<PayProductTerm> selectByPriceSetIdAndVersion(@Param("priceSetId") Long priceSetId,
|
||||
@Param("versionNo") Integer versionNo);
|
||||
|
||||
/** 打单套餐:按 version_no 聚合版本(含已失效) */
|
||||
List<LabelPackageVersion> selectLabelVersionGroups(@Param("priceSetId") Long priceSetId);
|
||||
|
||||
/** 打单套餐:批量改某一版的生效起止与状态 */
|
||||
int updateLabelVersionPeriod(@Param("priceSetId") Long priceSetId, @Param("versionNo") Integer versionNo,
|
||||
@Param("effectiveStart") Date effectiveStart, @Param("effectiveEnd") Date effectiveEnd,
|
||||
@Param("status") String status, @Param("updateBy") String updateBy);
|
||||
|
||||
Integer selectMaxVersionByProduct(@Param("productId") Long productId, @Param("priceSetId") Long priceSetId);
|
||||
|
||||
/** 打单套餐下最大 version_no */
|
||||
Integer selectMaxVersionByPriceSet(@Param("priceSetId") Long priceSetId);
|
||||
|
||||
int insertTerm(PayProductTerm term);
|
||||
|
||||
int updatePeriod(PayProductTerm term);
|
||||
@@ -25,7 +44,29 @@ public interface PayProductTermMapper
|
||||
/** 新版本生效时,把同一产品仍生效的旧版本关掉,结束日收到新版本开始的前一天 */
|
||||
int closeOpenTerms(@Param("dictValue") String dictValue, @Param("endDate") Date endDate, @Param("updateBy") String updateBy);
|
||||
|
||||
/** 打单套餐:按套餐+产品关闭仍生效的旧周期 */
|
||||
int closeOpenTermsBySetProduct(@Param("priceSetId") Long priceSetId, @Param("productId") Long productId,
|
||||
@Param("endDate") Date endDate, @Param("updateBy") String updateBy);
|
||||
|
||||
/** 打单:只关掉某产品本套餐待生效 term */
|
||||
int closePendingBySetProduct(@Param("priceSetId") Long priceSetId, @Param("productId") Long productId,
|
||||
@Param("endDate") Date endDate, @Param("updateBy") String updateBy);
|
||||
|
||||
/** 打单:启动某版本时,关掉本套餐其它版本的生效 term */
|
||||
int closeEffectExceptVersion(@Param("priceSetId") Long priceSetId, @Param("versionNo") Integer versionNo,
|
||||
@Param("endDate") Date endDate, @Param("updateBy") String updateBy);
|
||||
|
||||
/** 打单:预约未来生效时,只写旧版失效日,仍保持生效;并恢复被提前关掉但未到期的旧版 */
|
||||
int scheduleEndExceptVersion(@Param("priceSetId") Long priceSetId, @Param("versionNo") Integer versionNo,
|
||||
@Param("endDate") Date endDate, @Param("today") Date today, @Param("updateBy") String updateBy);
|
||||
|
||||
/** 打单:恢复「失效日未到却被标成已失效」的 term */
|
||||
int restorePrematureClosed(@Param("priceSetId") Long priceSetId, @Param("today") Date today,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
int deleteByProductIds(@Param("productIds") List<Long> productIds);
|
||||
|
||||
int deleteByTermIds(@Param("termIds") List<Long> termIds);
|
||||
|
||||
int updateProductEffectiveDate(@Param("productId") Long productId, @Param("effectiveDate") Date effectiveDate);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bms.price.service;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.bms.price.domain.LabelPackageVersion;
|
||||
import com.bms.price.domain.PayParseProgress;
|
||||
import com.bms.price.domain.PayPreview;
|
||||
import com.bms.price.domain.PayPriceCompare;
|
||||
@@ -54,7 +55,34 @@ public interface IPayProductService
|
||||
PayProduct selectChannelPrice(String channelId, String payType);
|
||||
|
||||
/** 只绑定产品编号,不产生新版本;同时落 channel_code。payType 为空时按应付 AP */
|
||||
void bindChannel(String channelId, Long productId, Long priceSetId, String payType);
|
||||
void bindChannel(String channelId, Long productId, String payType);
|
||||
|
||||
/**
|
||||
* 打单套餐预览:解析复用应付解析器,但「已存在」只按本套餐 price_set_id 判断,
|
||||
* 不与应付公共模板互相挡导入。
|
||||
*/
|
||||
PayPreview previewLabel(byte[] bytes, String filename, String dictValue, String progressId, Long priceSetId);
|
||||
|
||||
/** 打单套餐导入:稳定 product_id,明细挂 term_id,term 写 price_set_id;跳过仅限本套餐已有生效版 */
|
||||
String saveLabel(PaySaveCommand command);
|
||||
|
||||
/** 打单套餐价卡版本列表(按 term.version_no 聚合) */
|
||||
List<LabelPackageVersion> selectLabelVersions(Long priceSetId);
|
||||
|
||||
/** 启动/修改打单套餐某一版生效时间,并视情况启用套餐 */
|
||||
String activateLabelVersion(Long priceSetId, Integer versionNo, Date effectiveTime);
|
||||
|
||||
/** 打单套餐内当前生效/待生效产品列表 */
|
||||
List<PayProduct> selectLabelProducts(Long priceSetId);
|
||||
|
||||
/** 打单套餐某一版本的产品列表 */
|
||||
List<PayProduct> selectLabelProductsByVersion(Long priceSetId, Integer versionNo);
|
||||
|
||||
/** 按 term 加载明细 */
|
||||
PayProduct selectPayProductDetailByTerm(Long termId);
|
||||
|
||||
/** 从打单套餐移除产品(失效/清理对应 term 明细) */
|
||||
int removeLabelProducts(Long priceSetId, Long[] productIds);
|
||||
|
||||
/** 取消渠道上指定收付类型的产品。payType 为空时按应付 AP */
|
||||
void unbindChannel(String channelId, String payType);
|
||||
|
||||
+580
-32
@@ -25,6 +25,7 @@ import com.bms.common.utils.SecurityUtils;
|
||||
import com.bms.common.utils.file.OssStorage;
|
||||
import com.bms.common.utils.uuid.IdUtils;
|
||||
import com.bms.price.domain.ChannelProductMap;
|
||||
import com.bms.price.domain.LabelPackageVersion;
|
||||
import com.bms.price.domain.PayExtraLine;
|
||||
import com.bms.price.domain.PayParseProgress;
|
||||
import com.bms.price.domain.PayPreview;
|
||||
@@ -35,11 +36,13 @@ import com.bms.price.domain.PayProductTerm;
|
||||
import com.bms.price.domain.PaySaveCommand;
|
||||
import com.bms.price.domain.PaySurcharge;
|
||||
import com.bms.price.domain.PayWeightBand;
|
||||
import com.bms.price.domain.PrcPriceSet;
|
||||
import com.bms.masterdata.domain.ServiceChannel;
|
||||
import com.bms.masterdata.mapper.ServiceChannelMapper;
|
||||
import com.bms.price.mapper.ChannelProductMapMapper;
|
||||
import com.bms.price.mapper.PayProductMapper;
|
||||
import com.bms.price.mapper.PayProductTermMapper;
|
||||
import com.bms.price.mapper.PrcPriceSetMapper;
|
||||
import com.bms.price.pay.PayParseProgressListener;
|
||||
import com.bms.price.pay.PayWorkbookParser;
|
||||
import com.bms.price.service.IPayProductService;
|
||||
@@ -59,6 +62,13 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
|
||||
private static final String PAY_TYPE_AR = "AR";
|
||||
|
||||
/** pay_product_term.status:0待生效 1生效 2已失效 */
|
||||
private static final String TERM_PENDING = "0";
|
||||
|
||||
private static final String TERM_EFFECT = "1";
|
||||
|
||||
private static final String TERM_EXPIRED = "2";
|
||||
|
||||
@Autowired
|
||||
private PayProductMapper payProductMapper;
|
||||
|
||||
@@ -71,6 +81,9 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
@Autowired
|
||||
private PayProductTermMapper payProductTermMapper;
|
||||
|
||||
@Autowired
|
||||
private PrcPriceSetMapper priceSetMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysDictTypeService dictTypeService;
|
||||
|
||||
@@ -97,6 +110,21 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
|
||||
@Override
|
||||
public PayPreview preview(byte[] bytes, String filename, String dictValue, String progressId)
|
||||
{
|
||||
return doPreview(bytes, filename, dictValue, progressId, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayPreview previewLabel(byte[] bytes, String filename, String dictValue, String progressId, Long priceSetId)
|
||||
{
|
||||
return doPreview(bytes, filename, dictValue, progressId, true, priceSetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param labelMode true=打单套餐:已存在仅看本套餐;false=应付:看公共模板
|
||||
*/
|
||||
private PayPreview doPreview(byte[] bytes, String filename, String dictValue, String progressId,
|
||||
boolean labelMode, Long priceSetId)
|
||||
{
|
||||
String progressKey = progressKey(progressId);
|
||||
PayParseProgressListener listener = progressKey == null ? null : (percent, message) ->
|
||||
@@ -115,9 +143,24 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
for (PayProduct product : preview.getProducts())
|
||||
{
|
||||
product.setFilePath(stored);
|
||||
Long existsId = isBlank(product.getDictValue()) ? null : payProductMapper.selectTemplateId(product.getDictValue());
|
||||
product.setDuplicated(existsId != null);
|
||||
product.setExistsId(existsId);
|
||||
if (labelMode)
|
||||
{
|
||||
product.setProductType(PAY_TYPE_AR);
|
||||
// 只认「打单侧」产品,绝不把应付公共模板标成已存在
|
||||
Long existsId = isBlank(product.getDictValue()) ? null
|
||||
: payProductMapper.selectLabelProductIdByDict(product.getDictValue());
|
||||
product.setExistsId(existsId);
|
||||
// 仅待生效占用标「已存在」;已生效可继续建新版本
|
||||
boolean pendingInSet = priceSetId != null && existsId != null
|
||||
&& hasLabelTermStatus(priceSetId, existsId, TERM_PENDING);
|
||||
product.setDuplicated(pendingInSet);
|
||||
}
|
||||
else
|
||||
{
|
||||
Long existsId = isBlank(product.getDictValue()) ? null : payProductMapper.selectTemplateId(product.getDictValue());
|
||||
product.setDuplicated(existsId != null);
|
||||
product.setExistsId(existsId);
|
||||
}
|
||||
}
|
||||
writeProgress(progressKey, 100, "解析完成", PayParseProgress.SUCCESS);
|
||||
return preview;
|
||||
@@ -220,7 +263,6 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
product.setFilePath(resolveSource(product));
|
||||
prepareCounts(product);
|
||||
fitColumns(product);
|
||||
product.setProductId(null);
|
||||
product.setChannelId(null);
|
||||
product.setCreateBy(operator);
|
||||
product.setCreateTime(new Date());
|
||||
@@ -231,13 +273,14 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
}
|
||||
else
|
||||
{
|
||||
product.setProductId(null);
|
||||
product.setOriginId(null);
|
||||
product.setVersionNo(1);
|
||||
payProductMapper.insertPayProduct(product);
|
||||
openTerm(product, false, null);
|
||||
insertBands(product);
|
||||
insertSurcharges(product);
|
||||
insertExtras(product);
|
||||
openTerm(product, false);
|
||||
}
|
||||
saved++;
|
||||
}
|
||||
@@ -426,11 +469,29 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
|
||||
private void replaceChildren(Long productId, PayProduct product)
|
||||
{
|
||||
List<Long> ids = Collections.singletonList(productId);
|
||||
payProductMapper.deleteWeightBands(ids);
|
||||
payProductMapper.deleteSurcharges(ids);
|
||||
payProductMapper.deleteExtraLines(ids);
|
||||
product.setProductId(productId);
|
||||
if (product.getTermId() == null)
|
||||
{
|
||||
PayProductTerm term = payProductTermMapper.selectByProductId(productId);
|
||||
if (term != null)
|
||||
{
|
||||
product.setTermId(term.getTermId());
|
||||
}
|
||||
}
|
||||
if (product.getTermId() != null)
|
||||
{
|
||||
List<Long> termIds = Collections.singletonList(product.getTermId());
|
||||
payProductMapper.deleteWeightBandsByTerm(termIds);
|
||||
payProductMapper.deleteSurchargesByTerm(termIds);
|
||||
payProductMapper.deleteExtraLinesByTerm(termIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Long> ids = Collections.singletonList(productId);
|
||||
payProductMapper.deleteWeightBands(ids);
|
||||
payProductMapper.deleteSurcharges(ids);
|
||||
payProductMapper.deleteExtraLines(ids);
|
||||
}
|
||||
insertBands(product);
|
||||
insertSurcharges(product);
|
||||
insertExtras(product);
|
||||
@@ -511,7 +572,7 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
{
|
||||
term.setDictValue(termKey(product));
|
||||
term.setVersionNo(product.getVersionNo() == null ? 1 : product.getVersionNo());
|
||||
term.setStatus("0");
|
||||
term.setStatus(TERM_EFFECT);
|
||||
term.setCreateBy(operator);
|
||||
payProductTermMapper.insertTerm(term);
|
||||
}
|
||||
@@ -535,9 +596,10 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
@Override
|
||||
public int changeTermStatus(PayProductTerm term)
|
||||
{
|
||||
if (term == null || (!"0".equals(term.getStatus()) && !"1".equals(term.getStatus())))
|
||||
if (term == null || (!TERM_PENDING.equals(term.getStatus()) && !TERM_EFFECT.equals(term.getStatus())
|
||||
&& !TERM_EXPIRED.equals(term.getStatus())))
|
||||
{
|
||||
throw new ServiceException("请选择生效或失效");
|
||||
throw new ServiceException("状态只能是待生效、生效或已失效");
|
||||
}
|
||||
if (term.getTermId() == null && term.getProductId() != null)
|
||||
{
|
||||
@@ -556,27 +618,48 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
}
|
||||
|
||||
/** 给刚保存的这一版记一条生效记录。新版本从生效日开始,旧版本收到生效日前一天。 */
|
||||
private void openTerm(PayProduct product, boolean replacePrevious)
|
||||
private PayProductTerm openTerm(PayProduct product, boolean replacePrevious, Long priceSetId)
|
||||
{
|
||||
String key = termKey(product);
|
||||
if (product.getEffectiveDate() == null)
|
||||
boolean labelMode = priceSetId != null;
|
||||
// 应付:无生效日则默认今天;打单:创建不写默认生效日,由详情「启动」设置
|
||||
if (!labelMode && product.getEffectiveDate() == null)
|
||||
{
|
||||
product.setEffectiveDate(today());
|
||||
}
|
||||
if (replacePrevious)
|
||||
{
|
||||
java.time.LocalDate start = toLocalDate(product.getEffectiveDate());
|
||||
payProductTermMapper.closeOpenTerms(key, toDate(start.minusDays(1)), product.getCreateBy());
|
||||
Date endDate;
|
||||
if (product.getEffectiveDate() != null)
|
||||
{
|
||||
endDate = toDate(toLocalDate(product.getEffectiveDate()).minusDays(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
endDate = toDate(toLocalDate(today()).minusDays(1));
|
||||
}
|
||||
if (labelMode)
|
||||
{
|
||||
payProductTermMapper.closeOpenTermsBySetProduct(priceSetId, product.getProductId(), endDate, product.getCreateBy());
|
||||
}
|
||||
else
|
||||
{
|
||||
payProductTermMapper.closeOpenTerms(key, endDate, product.getCreateBy());
|
||||
}
|
||||
}
|
||||
PayProductTerm term = new PayProductTerm();
|
||||
term.setDictValue(key);
|
||||
term.setProductId(product.getProductId());
|
||||
term.setPriceSetId(priceSetId);
|
||||
term.setVersionNo(product.getVersionNo() == null ? 1 : product.getVersionNo());
|
||||
term.setEffectiveStart(product.getEffectiveDate());
|
||||
term.setEffectiveStart(labelMode ? null : product.getEffectiveDate());
|
||||
term.setFilePath(sourcePath(product.getFilePath()));
|
||||
term.setStatus("0");
|
||||
// 打单套餐新建为待生效,详情启动后再变生效;应付公共模板直接生效
|
||||
term.setStatus(labelMode ? TERM_PENDING : TERM_EFFECT);
|
||||
term.setCreateBy(product.getCreateBy());
|
||||
payProductTermMapper.insertTerm(term);
|
||||
product.setTermId(term.getTermId());
|
||||
return term;
|
||||
}
|
||||
|
||||
private String termKey(PayProduct product)
|
||||
@@ -730,6 +813,20 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
{
|
||||
return null;
|
||||
}
|
||||
PayProductTerm term = payProductTermMapper.selectByProductId(productId);
|
||||
if (term != null)
|
||||
{
|
||||
product.setTermId(term.getTermId());
|
||||
product.setTermStatus(term.getStatus());
|
||||
product.setTermStart(term.getEffectiveStart());
|
||||
product.setTermEnd(term.getEffectiveEnd());
|
||||
product.setVersionNo(term.getVersionNo() == null ? product.getVersionNo() : term.getVersionNo());
|
||||
List<Long> termIds = Collections.singletonList(term.getTermId());
|
||||
product.setWeightBands(payProductMapper.selectWeightBandsByTerm(termIds));
|
||||
product.setSurcharges(payProductMapper.selectSurchargesByTerm(termIds));
|
||||
product.setExtraLines(payProductMapper.selectExtraLinesByTerm(termIds));
|
||||
return product;
|
||||
}
|
||||
List<Long> ids = Collections.singletonList(productId);
|
||||
product.setWeightBands(payProductMapper.selectWeightBands(ids));
|
||||
product.setSurcharges(payProductMapper.selectSurcharges(ids));
|
||||
@@ -737,6 +834,450 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
return product;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayProduct selectPayProductDetailByTerm(Long termId)
|
||||
{
|
||||
if (termId == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
PayProductTerm term = payProductTermMapper.selectById(termId);
|
||||
if (term == null || term.getProductId() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
PayProduct product = payProductMapper.selectPayProductById(term.getProductId());
|
||||
if (product == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
product.setTermId(term.getTermId());
|
||||
product.setTermStatus(term.getStatus());
|
||||
product.setTermStart(term.getEffectiveStart());
|
||||
product.setTermEnd(term.getEffectiveEnd());
|
||||
product.setVersionNo(term.getVersionNo() == null ? product.getVersionNo() : term.getVersionNo());
|
||||
if (!isBlank(term.getFilePath()))
|
||||
{
|
||||
product.setFilePath(term.getFilePath());
|
||||
}
|
||||
List<Long> termIds = Collections.singletonList(termId);
|
||||
product.setWeightBands(payProductMapper.selectWeightBandsByTerm(termIds));
|
||||
product.setSurcharges(payProductMapper.selectSurchargesByTerm(termIds));
|
||||
product.setExtraLines(payProductMapper.selectExtraLinesByTerm(termIds));
|
||||
return product;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String saveLabel(PaySaveCommand command)
|
||||
{
|
||||
if (command == null || command.getProducts() == null || command.getProducts().isEmpty())
|
||||
{
|
||||
throw new ServiceException("请先勾选要保存的产品");
|
||||
}
|
||||
Long priceSetId = ensureLabelPriceSet(command);
|
||||
String operator = SecurityUtils.getUsername();
|
||||
Date keepStart = null;
|
||||
String keepStatus = TERM_PENDING;
|
||||
int nextVersionNo;
|
||||
boolean editPendingVersion = command.getVersionNo() != null;
|
||||
if (editPendingVersion)
|
||||
{
|
||||
// 编辑待生效版:清掉该 version 后按原号重写,保留原生效日
|
||||
LabelVersionKeep keep = clearPendingLabelVersion(priceSetId, command.getVersionNo(), operator);
|
||||
keepStart = keep.effectiveStart;
|
||||
keepStatus = keep.status == null ? TERM_PENDING : keep.status;
|
||||
nextVersionNo = command.getVersionNo();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 整批统一套餐级 version_no:新建套餐从 1,新建版本 = max+1
|
||||
Integer maxSetVer = payProductTermMapper.selectMaxVersionByPriceSet(priceSetId);
|
||||
nextVersionNo = (maxSetVer == null ? 0 : maxSetVer) + 1;
|
||||
}
|
||||
int saved = 0;
|
||||
int replaced = 0;
|
||||
int skipped = 0;
|
||||
for (PayProduct product : command.getProducts())
|
||||
{
|
||||
if (product == null || isBlank(product.getProductName()) || isBlank(product.getSheetName()) || isBlank(product.getFileMd5()))
|
||||
{
|
||||
throw new ServiceException("产品名称、工作表和文件摘要不能为空");
|
||||
}
|
||||
product.setProductType(PAY_TYPE_AR);
|
||||
String dict = blankTo(product.getDictValue(), product.getProductName());
|
||||
product.setDictValue(dict);
|
||||
// 独立产品族:只复用打单侧 AR,绝不复用/改写应付公共模板
|
||||
Long existsId = isBlank(dict) ? null : payProductMapper.selectLabelProductIdByDict(dict);
|
||||
// 编辑待生效版时强制覆盖;新建版本仅「待生效」占用时跳过
|
||||
boolean hasPending = !editPendingVersion && existsId != null
|
||||
&& hasLabelTermStatus(priceSetId, existsId, TERM_PENDING);
|
||||
if (hasPending && !command.isOverwrite())
|
||||
{
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
product.setFilePath(resolveSource(product));
|
||||
prepareCounts(product);
|
||||
fitColumns(product);
|
||||
product.setChannelId(null);
|
||||
product.setCreateBy(operator);
|
||||
product.setUpdateBy(operator);
|
||||
product.setCreateTime(new Date());
|
||||
product.setVersionNo(nextVersionNo);
|
||||
// 打单不写默认生效日,由详情设置;编辑时下面统一回写 keepStart
|
||||
product.setEffectiveDate(null);
|
||||
if (existsId != null)
|
||||
{
|
||||
appendLabelVersion(existsId, product, operator, priceSetId, nextVersionNo,
|
||||
editPendingVersion || command.isOverwrite());
|
||||
replaced++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 新建打单专用产品行,与应付同名字典产品并存互不影响
|
||||
product.setProductId(null);
|
||||
product.setOriginId(null);
|
||||
payProductMapper.insertPayProduct(product);
|
||||
openTerm(product, false, priceSetId);
|
||||
insertBands(product);
|
||||
insertSurcharges(product);
|
||||
insertExtras(product);
|
||||
}
|
||||
saved++;
|
||||
}
|
||||
if (editPendingVersion && keepStart != null)
|
||||
{
|
||||
payProductTermMapper.updateLabelVersionPeriod(priceSetId, nextVersionNo, keepStart, null, keepStatus, operator);
|
||||
}
|
||||
return editPendingVersion
|
||||
? ("套餐" + priceSetId + "版本V" + nextVersionNo + "已更新" + saved + "个产品")
|
||||
: ("套餐" + priceSetId + "已保存" + saved + "个产品,新版本" + replaced + "个,跳过" + skipped + "个");
|
||||
}
|
||||
|
||||
private static final class LabelVersionKeep
|
||||
{
|
||||
private Date effectiveStart;
|
||||
private String status;
|
||||
}
|
||||
|
||||
/** 仅允许清待生效版;返回原生效日便于编辑后回写 */
|
||||
private LabelVersionKeep clearPendingLabelVersion(Long priceSetId, Integer versionNo, String operator)
|
||||
{
|
||||
if (priceSetId == null || versionNo == null)
|
||||
{
|
||||
throw new ServiceException("请指定要编辑的版本");
|
||||
}
|
||||
List<PayProductTerm> terms = payProductTermMapper.selectByPriceSetIdAndVersion(priceSetId, versionNo);
|
||||
if (terms == null || terms.isEmpty())
|
||||
{
|
||||
throw new ServiceException("该版本不存在或没有产品");
|
||||
}
|
||||
LabelVersionKeep keep = new LabelVersionKeep();
|
||||
List<Long> termIds = new ArrayList<>();
|
||||
for (PayProductTerm term : terms)
|
||||
{
|
||||
if (!TERM_PENDING.equals(term.getStatus()))
|
||||
{
|
||||
// 兼容:生效日未到但 status 误为 1,仍允许编辑
|
||||
boolean futureStart = term.getEffectiveStart() != null
|
||||
&& toLocalDate(term.getEffectiveStart()).isAfter(toLocalDate(today()));
|
||||
if (!futureStart)
|
||||
{
|
||||
throw new ServiceException("只能编辑待生效版本");
|
||||
}
|
||||
}
|
||||
if (keep.effectiveStart == null && term.getEffectiveStart() != null)
|
||||
{
|
||||
keep.effectiveStart = term.getEffectiveStart();
|
||||
}
|
||||
if (keep.status == null)
|
||||
{
|
||||
keep.status = TERM_PENDING;
|
||||
}
|
||||
termIds.add(term.getTermId());
|
||||
}
|
||||
payProductMapper.deleteWeightBandsByTerm(termIds);
|
||||
payProductMapper.deleteSurchargesByTerm(termIds);
|
||||
payProductMapper.deleteExtraLinesByTerm(termIds);
|
||||
payProductTermMapper.deleteByTermIds(termIds);
|
||||
return keep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayProduct> selectLabelProducts(Long priceSetId)
|
||||
{
|
||||
return toLabelProducts(payProductTermMapper.selectByPriceSetId(priceSetId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayProduct> selectLabelProductsByVersion(Long priceSetId, Integer versionNo)
|
||||
{
|
||||
if (priceSetId == null || versionNo == null)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return toLabelProducts(payProductTermMapper.selectByPriceSetIdAndVersion(priceSetId, versionNo));
|
||||
}
|
||||
|
||||
private List<PayProduct> toLabelProducts(List<PayProductTerm> terms)
|
||||
{
|
||||
if (terms == null || terms.isEmpty())
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<PayProduct> list = new ArrayList<>();
|
||||
for (PayProductTerm term : terms)
|
||||
{
|
||||
PayProduct product = payProductMapper.selectPayProductById(term.getProductId());
|
||||
if (product == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
product.setTermId(term.getTermId());
|
||||
product.setTermStatus(term.getStatus());
|
||||
product.setTermStart(term.getEffectiveStart());
|
||||
product.setTermEnd(term.getEffectiveEnd());
|
||||
product.setVersionNo(term.getVersionNo() == null ? product.getVersionNo() : term.getVersionNo());
|
||||
product.setSourceFile(blankTo(term.getSourceFile(), product.getSourceFile()));
|
||||
if (!isBlank(term.getFilePath()))
|
||||
{
|
||||
product.setFilePath(term.getFilePath());
|
||||
}
|
||||
product.setWeightCount(term.getWeightCount() == null ? product.getWeightCount() : term.getWeightCount());
|
||||
product.setSurchargeCount(term.getSurchargeCount() == null ? product.getSurchargeCount() : term.getSurchargeCount());
|
||||
list.add(product);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int removeLabelProducts(Long priceSetId, Long[] productIds)
|
||||
{
|
||||
if (priceSetId == null || productIds == null || productIds.length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int n = 0;
|
||||
List<PayProductTerm> allTerms = payProductTermMapper.selectByPriceSetId(priceSetId);
|
||||
if (allTerms == null || allTerms.isEmpty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Set<Long> removeIds = new LinkedHashSet<>(Arrays.asList(productIds));
|
||||
List<Long> termIds = new ArrayList<>();
|
||||
for (PayProductTerm term : allTerms)
|
||||
{
|
||||
if (term.getProductId() != null && removeIds.contains(term.getProductId()))
|
||||
{
|
||||
termIds.add(term.getTermId());
|
||||
}
|
||||
}
|
||||
if (termIds.isEmpty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
payProductMapper.deleteWeightBandsByTerm(termIds);
|
||||
payProductMapper.deleteSurchargesByTerm(termIds);
|
||||
payProductMapper.deleteExtraLinesByTerm(termIds);
|
||||
payProductTermMapper.deleteByTermIds(termIds);
|
||||
return termIds.size();
|
||||
}
|
||||
|
||||
private boolean hasActiveLabelTerm(Long priceSetId, Long productId)
|
||||
{
|
||||
return hasLabelTermStatus(priceSetId, productId, TERM_PENDING)
|
||||
|| hasLabelTermStatus(priceSetId, productId, TERM_EFFECT);
|
||||
}
|
||||
|
||||
private boolean hasLabelTermStatus(Long priceSetId, Long productId, String status)
|
||||
{
|
||||
List<PayProductTerm> terms = payProductTermMapper.selectByPriceSetId(priceSetId);
|
||||
if (terms == null || productId == null || status == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (PayProductTerm term : terms)
|
||||
{
|
||||
if (productId.equals(term.getProductId()) && status.equals(term.getStatus()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打单追加版本:不关闭已生效 term,只在覆盖时关掉待生效;version_no 用套餐级批次号。
|
||||
*/
|
||||
private PayProduct appendLabelVersion(Long rootId, PayProduct incoming, String operator, Long priceSetId,
|
||||
int versionNo, boolean overwritePending)
|
||||
{
|
||||
Long root = resolveRoot(rootId);
|
||||
PayProduct base = payProductMapper.selectPayProductById(root);
|
||||
PayProduct copy = copyHeader(base, incoming == null ? base : incoming);
|
||||
copy.setProductId(root);
|
||||
copy.setOriginId(null);
|
||||
copy.setChannelId(null);
|
||||
copy.setDictValue(blankTo(copy.getDictValue(), base.getDictValue()));
|
||||
copy.setVersionNo(versionNo);
|
||||
copy.setEffectiveDate(null);
|
||||
copy.setCreateBy(operator);
|
||||
copy.setUpdateBy(operator);
|
||||
copy.setCreateTime(new Date());
|
||||
prepareCounts(copy);
|
||||
fitColumns(copy);
|
||||
payProductMapper.updatePayProduct(copy);
|
||||
if (overwritePending)
|
||||
{
|
||||
Date endDate = toDate(toLocalDate(today()).minusDays(1));
|
||||
payProductTermMapper.closePendingBySetProduct(priceSetId, root, endDate, operator);
|
||||
}
|
||||
openTerm(copy, false, priceSetId);
|
||||
insertBands(copy);
|
||||
insertSurcharges(copy);
|
||||
insertExtras(copy);
|
||||
return selectPayProductDetailByTerm(copy.getTermId());
|
||||
}
|
||||
|
||||
private Long ensureLabelPriceSet(PaySaveCommand command)
|
||||
{
|
||||
if (command.getPriceSetId() != null)
|
||||
{
|
||||
PrcPriceSet db = priceSetMapper.selectPrcPriceSetById(command.getPriceSetId());
|
||||
if (db == null)
|
||||
{
|
||||
throw new ServiceException("打单套餐不存在");
|
||||
}
|
||||
if (!PrcPriceSet.CATEGORY_LABEL.equalsIgnoreCase(String.valueOf(db.getSetCategory())))
|
||||
{
|
||||
throw new ServiceException("只能向打单套餐导入价卡");
|
||||
}
|
||||
return db.getPriceSetId();
|
||||
}
|
||||
if (isBlank(command.getPriceSetName()))
|
||||
{
|
||||
throw new ServiceException("请填写打单套餐名称");
|
||||
}
|
||||
String operator = SecurityUtils.getUsername();
|
||||
PrcPriceSet set = new PrcPriceSet();
|
||||
set.setPriceSetName(command.getPriceSetName().trim());
|
||||
set.setPriceSetNote(command.getPriceSetNote());
|
||||
set.setSetType("FIXED");
|
||||
set.setSetCategory(PrcPriceSet.CATEGORY_LABEL);
|
||||
// 新建为待启用,详情页设启动时间后再生效(对齐价格套餐)
|
||||
set.setStatus("D");
|
||||
set.setCreateBy(operator);
|
||||
set.setUpdateBy(operator);
|
||||
priceSetMapper.insertPrcPriceSet(set);
|
||||
set.setPriceSetCode(String.format("LBL%04d", set.getPriceSetId()));
|
||||
priceSetMapper.updatePrcPriceSet(set);
|
||||
command.setPriceSetId(set.getPriceSetId());
|
||||
return set.getPriceSetId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LabelPackageVersion> selectLabelVersions(Long priceSetId)
|
||||
{
|
||||
if (priceSetId == null)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
PrcPriceSet set = priceSetMapper.selectPrcPriceSetById(priceSetId);
|
||||
if (set == null)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Date now = today();
|
||||
// 纠正历史:未来生效版启动时把旧版提前标成已失效
|
||||
payProductTermMapper.restorePrematureClosed(priceSetId, now, "system");
|
||||
List<LabelPackageVersion> groups = payProductTermMapper.selectLabelVersionGroups(priceSetId);
|
||||
if (groups == null || groups.isEmpty())
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
for (LabelPackageVersion ver : groups)
|
||||
{
|
||||
ver.setPriceSetId(priceSetId);
|
||||
ver.setVersionLabel("V" + (ver.getVersionNo() == null ? 1 : ver.getVersionNo()));
|
||||
int active = ver.getActiveCount() == null ? 0 : ver.getActiveCount();
|
||||
int pending = ver.getPendingCount() == null ? 0 : ver.getPendingCount();
|
||||
Date start = ver.getEffectiveTime();
|
||||
Date end = ver.getExpireTime();
|
||||
// 按日期判定:未到生效日=待生效;已过失效日=已失效;中间段=生效
|
||||
if (start == null)
|
||||
{
|
||||
ver.setStatus(pending > 0 ? TERM_PENDING : (active > 0 ? TERM_EFFECT : TERM_EXPIRED));
|
||||
}
|
||||
else if (toLocalDate(start).isAfter(toLocalDate(now)))
|
||||
{
|
||||
ver.setStatus(TERM_PENDING);
|
||||
}
|
||||
else if (end != null && toLocalDate(end).isBefore(toLocalDate(now)))
|
||||
{
|
||||
ver.setStatus(TERM_EXPIRED);
|
||||
}
|
||||
else
|
||||
{
|
||||
ver.setStatus(TERM_EFFECT);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String activateLabelVersion(Long priceSetId, Integer versionNo, Date effectiveTime)
|
||||
{
|
||||
if (priceSetId == null || versionNo == null)
|
||||
{
|
||||
throw new ServiceException("请选择要启动的版本");
|
||||
}
|
||||
if (effectiveTime == null)
|
||||
{
|
||||
throw new ServiceException("请选择生效时间");
|
||||
}
|
||||
PrcPriceSet set = priceSetMapper.selectPrcPriceSetById(priceSetId);
|
||||
if (set == null)
|
||||
{
|
||||
throw new ServiceException("打单套餐不存在");
|
||||
}
|
||||
if (!PrcPriceSet.CATEGORY_LABEL.equalsIgnoreCase(String.valueOf(set.getSetCategory())))
|
||||
{
|
||||
throw new ServiceException("只能启动打单套餐版本");
|
||||
}
|
||||
String operator = SecurityUtils.getUsername();
|
||||
boolean future = toLocalDate(effectiveTime).isAfter(toLocalDate(today()));
|
||||
Date endDate = toDate(toLocalDate(effectiveTime).minusDays(1));
|
||||
if (future)
|
||||
{
|
||||
// 未到生效日:本版保持待生效;旧版只预约失效日,当前仍生效
|
||||
payProductTermMapper.scheduleEndExceptVersion(priceSetId, versionNo, endDate, today(), operator);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 当天或已过:本版立刻生效,旧版关掉
|
||||
payProductTermMapper.closeEffectExceptVersion(priceSetId, versionNo, endDate, operator);
|
||||
}
|
||||
String termStatus = future ? TERM_PENDING : TERM_EFFECT;
|
||||
int n = payProductTermMapper.updateLabelVersionPeriod(priceSetId, versionNo, effectiveTime, null, termStatus, operator);
|
||||
if (n <= 0)
|
||||
{
|
||||
throw new ServiceException("该版本没有可启动的产品价卡");
|
||||
}
|
||||
// 真正生效时才把套餐壳置为生效
|
||||
if (!future && !"E".equalsIgnoreCase(String.valueOf(set.getStatus())))
|
||||
{
|
||||
PrcPriceSet upd = new PrcPriceSet();
|
||||
upd.setPriceSetId(priceSetId);
|
||||
upd.setStatus("E");
|
||||
upd.setUpdateBy(operator);
|
||||
priceSetMapper.updatePrcPriceSetStatus(upd);
|
||||
}
|
||||
return future ? "已设为待生效" : "版本已启动";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int deletePayProducts(Long[] productIds)
|
||||
@@ -826,6 +1367,7 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
for (PayWeightBand row : rows)
|
||||
{
|
||||
row.setProductId(product.getProductId());
|
||||
row.setTermId(product.getTermId());
|
||||
row.setVersionNo(product.getVersionNo() == null ? 1 : product.getVersionNo());
|
||||
}
|
||||
for (int i = 0; i < rows.size(); i += BATCH)
|
||||
@@ -844,6 +1386,7 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
for (PaySurcharge row : rows)
|
||||
{
|
||||
row.setProductId(product.getProductId());
|
||||
row.setTermId(product.getTermId());
|
||||
row.setVersionNo(product.getVersionNo() == null ? 1 : product.getVersionNo());
|
||||
}
|
||||
for (int i = 0; i < rows.size(); i += BATCH)
|
||||
@@ -868,6 +1411,7 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
for (PayExtraLine row : rows)
|
||||
{
|
||||
row.setProductId(product.getProductId());
|
||||
row.setTermId(product.getTermId());
|
||||
}
|
||||
for (int i = 0; i < rows.size(); i += BATCH)
|
||||
{
|
||||
@@ -938,7 +1482,7 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindChannel(String channelId, Long productId, Long priceSetId, String payType)
|
||||
public void bindChannel(String channelId, Long productId, String payType)
|
||||
{
|
||||
if (isBlank(channelId) || productId == null)
|
||||
{
|
||||
@@ -955,7 +1499,6 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
row.setChannelId(channelId);
|
||||
row.setChannelCode(channel.getChannelCode());
|
||||
row.setProductId(storedId);
|
||||
row.setPriceSetId(priceSetId);
|
||||
row.setPayType(type);
|
||||
String operator = SecurityUtils.getUsername();
|
||||
row.setCreateBy(operator);
|
||||
@@ -1015,37 +1558,42 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
return compared;
|
||||
}
|
||||
|
||||
/** 在同一个产品编号下追加一版价格,不新开产品编号。 */
|
||||
/** 在同一个产品编号下追加一版价格:复用稳定 product_id,明细挂新 term_id。 */
|
||||
private PayProduct appendVersion(Long rootId, PayProduct incoming, String operator)
|
||||
{
|
||||
return appendVersion(rootId, incoming, operator, null);
|
||||
}
|
||||
|
||||
private PayProduct appendVersion(Long rootId, PayProduct incoming, String operator, Long priceSetId)
|
||||
{
|
||||
Long root = resolveRoot(rootId);
|
||||
PayProduct base = payProductMapper.selectPayProductById(root);
|
||||
PayProduct copy = copyHeader(base, incoming == null ? base : incoming);
|
||||
copy.setProductId(null);
|
||||
copy.setOriginId(root);
|
||||
copy.setProductId(root);
|
||||
copy.setOriginId(null);
|
||||
copy.setChannelId(null);
|
||||
copy.setDictValue(blankTo(copy.getDictValue(), base.getDictValue()));
|
||||
Integer maxVersion = payProductMapper.selectMaxVersion(root);
|
||||
Integer maxVersion = payProductTermMapper.selectMaxVersionByProduct(root, priceSetId);
|
||||
if (maxVersion == null || maxVersion < 1)
|
||||
{
|
||||
maxVersion = payProductMapper.selectMaxVersion(root);
|
||||
}
|
||||
copy.setVersionNo((maxVersion == null ? 1 : maxVersion) + 1);
|
||||
if (copy.getEffectiveDate() == null)
|
||||
{
|
||||
copy.setEffectiveDate(today());
|
||||
}
|
||||
copy.setCreateBy(operator);
|
||||
copy.setUpdateBy(operator);
|
||||
copy.setCreateTime(new Date());
|
||||
prepareCounts(copy);
|
||||
fitColumns(copy);
|
||||
payProductMapper.insertPayProduct(copy);
|
||||
payProductMapper.updatePayProduct(copy);
|
||||
openTerm(copy, true, priceSetId);
|
||||
insertBands(copy);
|
||||
insertSurcharges(copy);
|
||||
insertExtras(copy);
|
||||
openTerm(copy, true);
|
||||
PayProduct saved = selectPayProductDetail(copy.getProductId());
|
||||
if (saved != null)
|
||||
{
|
||||
saved.setOriginId(root);
|
||||
}
|
||||
return saved;
|
||||
return selectPayProductDetailByTerm(copy.getTermId());
|
||||
}
|
||||
|
||||
/** 渠道产品绑定记在映射表,产品编号是不变的根产品。 */
|
||||
|
||||
+10
-2
@@ -77,6 +77,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
private static final String TYPE_FIXED = "FIXED";
|
||||
private static final String CATEGORY_PACKAGE = PrcPriceSet.CATEGORY_PACKAGE;
|
||||
private static final String CATEGORY_EXCLUSIVE = PrcPriceSet.CATEGORY_EXCLUSIVE;
|
||||
private static final String CATEGORY_LABEL = PrcPriceSet.CATEGORY_LABEL;
|
||||
private static final String TYPE_DISCOUNT = "DISCOUNT";
|
||||
private static final String VER_DRAFT = "0";
|
||||
private static final String VER_EFFECT = "1";
|
||||
@@ -2979,16 +2980,23 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
/** PACKAGE (default) or EXCLUSIVE. */
|
||||
public static String normalizeSetCategory(String setCategory)
|
||||
{
|
||||
if (CATEGORY_EXCLUSIVE.equalsIgnoreCase(StringUtils.trim(setCategory)))
|
||||
String raw = StringUtils.trim(setCategory);
|
||||
if (CATEGORY_EXCLUSIVE.equalsIgnoreCase(raw))
|
||||
{
|
||||
return CATEGORY_EXCLUSIVE;
|
||||
}
|
||||
if (CATEGORY_LABEL.equalsIgnoreCase(raw))
|
||||
{
|
||||
return CATEGORY_LABEL;
|
||||
}
|
||||
return CATEGORY_PACKAGE;
|
||||
}
|
||||
|
||||
private static String buildPriceSetCode(String setCategory, Long priceSetId)
|
||||
{
|
||||
String prefix = CATEGORY_EXCLUSIVE.equals(normalizeSetCategory(setCategory)) ? "EXC" : "SET";
|
||||
String category = normalizeSetCategory(setCategory);
|
||||
String prefix = CATEGORY_EXCLUSIVE.equals(category) ? "EXC"
|
||||
: (CATEGORY_LABEL.equals(category) ? "LBL" : "SET");
|
||||
return String.format("%s%04d", prefix, priceSetId);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="selectByChannelAndType" resultType="com.bms.price.domain.ChannelProductMap">
|
||||
select id, channel_id as channelId, channel_code as channelCode, product_id as productId,
|
||||
price_set_id as priceSetId, pay_type as payType, create_by as createBy, create_time as createTime,
|
||||
pay_type as payType, create_by as createBy, create_time as createTime,
|
||||
update_by as updateBy, update_time as updateTime
|
||||
from srv_channel_product_map
|
||||
where channel_id = #{channelId} and pay_type = #{payType}
|
||||
@@ -15,14 +15,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<insert id="upsert">
|
||||
insert into srv_channel_product_map (
|
||||
channel_id, channel_code, product_id, price_set_id, pay_type, create_by, create_time, update_by, update_time
|
||||
channel_id, channel_code, product_id, pay_type, create_by, create_time, update_by, update_time
|
||||
) values (
|
||||
#{channelId}, #{channelCode}, #{productId}, #{priceSetId}, #{payType}, #{createBy}, sysdate(), #{updateBy}, sysdate()
|
||||
#{channelId}, #{channelCode}, #{productId}, #{payType}, #{createBy}, sysdate(), #{updateBy}, sysdate()
|
||||
)
|
||||
on duplicate key update
|
||||
channel_code = values(channel_code),
|
||||
product_id = values(product_id),
|
||||
price_set_id = values(price_set_id),
|
||||
update_by = values(update_by),
|
||||
update_time = sysdate()
|
||||
</insert>
|
||||
|
||||
@@ -49,6 +49,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<where>
|
||||
<if test="templateOnly != null and templateOnly">
|
||||
and (pay_product.channel_id is null or pay_product.channel_id = '')
|
||||
and not (
|
||||
exists (
|
||||
select 1 from pay_product_term t_label
|
||||
where t_label.product_id = pay_product.product_id
|
||||
and t_label.price_set_id is not null
|
||||
)
|
||||
and not exists (
|
||||
select 1 from pay_product_term t_pay
|
||||
where t_pay.product_id = pay_product.product_id
|
||||
and t_pay.price_set_id is null
|
||||
)
|
||||
)
|
||||
</if>
|
||||
<if test="currentOnly != null and currentOnly">
|
||||
and pay_product.origin_id is null
|
||||
@@ -129,7 +141,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
inner join pay_product v on v.product_id = t2.product_id
|
||||
where (v.channel_id is null or v.channel_id = '')
|
||||
and (v.product_id = pay_product.product_id or v.origin_id = pay_product.product_id)
|
||||
order by case when t2.status = '0' then 0 else 1 end, ifnull(v.version_no, 1) desc, t2.term_id desc
|
||||
and t2.price_set_id is null
|
||||
order by case when t2.status = '1' then 0 when t2.status = '0' then 1 else 2 end, ifnull(v.version_no, 1) desc, t2.term_id desc
|
||||
limit 1
|
||||
)
|
||||
left join pay_product cur on cur.product_id = t.product_id
|
||||
@@ -202,15 +215,65 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where product_id = #{productId}
|
||||
</update>
|
||||
|
||||
<!-- 应付公共模板:排除「仅打单套餐」产品(有 label term、无公共 term) -->
|
||||
<sql id="payPublicTemplateOnly">
|
||||
and not (
|
||||
exists (
|
||||
select 1 from pay_product_term t_label
|
||||
where t_label.product_id = pay_product.product_id
|
||||
and t_label.price_set_id is not null
|
||||
)
|
||||
and not exists (
|
||||
select 1 from pay_product_term t_pay
|
||||
where t_pay.product_id = pay_product.product_id
|
||||
and t_pay.price_set_id is null
|
||||
)
|
||||
)
|
||||
</sql>
|
||||
|
||||
<select id="selectTemplateId" resultType="long">
|
||||
select product_id from pay_product
|
||||
where dict_value = #{dictValue}
|
||||
and (channel_id is null or channel_id = '')
|
||||
and origin_id is null
|
||||
<include refid="payPublicTemplateOnly"/>
|
||||
order by product_id
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectTemplateIdByType" resultType="long">
|
||||
select product_id from pay_product
|
||||
where dict_value = #{dictValue}
|
||||
and ifnull(product_type, 'AP') = #{productType}
|
||||
and (channel_id is null or channel_id = '')
|
||||
and origin_id is null
|
||||
<include refid="payPublicTemplateOnly"/>
|
||||
order by product_id
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<!-- 打单套餐专用:只命中已有 label term 的 AR 产品,绝不碰应付公共模板 -->
|
||||
<select id="selectLabelProductIdByDict" resultType="long">
|
||||
select p.product_id
|
||||
from pay_product p
|
||||
where p.dict_value = #{dictValue}
|
||||
and ifnull(p.product_type, 'AP') = 'AR'
|
||||
and (p.channel_id is null or p.channel_id = '')
|
||||
and p.origin_id is null
|
||||
and exists (
|
||||
select 1 from pay_product_term t
|
||||
where t.product_id = p.product_id
|
||||
and t.price_set_id is not null
|
||||
)
|
||||
and not exists (
|
||||
select 1 from pay_product_term t2
|
||||
where t2.product_id = p.product_id
|
||||
and t2.price_set_id is null
|
||||
)
|
||||
order by p.product_id
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectTemplateOptions" resultMap="PayProductResult">
|
||||
select p.product_id, p.product_name, p.product_type, p.dict_value, p.sheet_name, p.supplier_name, p.effective_date,
|
||||
p.currency, ifnull(cur.version_no, p.version_no) as version_no
|
||||
@@ -221,13 +284,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
inner join pay_product v on v.product_id = t2.product_id
|
||||
where (v.channel_id is null or v.channel_id = '')
|
||||
and (v.product_id = p.product_id or v.origin_id = p.product_id)
|
||||
order by case when t2.status = '0' then 0 else 1 end, ifnull(v.version_no, 1) desc, t2.term_id desc
|
||||
and t2.price_set_id is null
|
||||
order by case when t2.status = '1' then 0 when t2.status = '0' then 1 else 2 end, ifnull(v.version_no, 1) desc, t2.term_id desc
|
||||
limit 1
|
||||
)
|
||||
left join pay_product cur on cur.product_id = t.product_id
|
||||
where (p.channel_id is null or p.channel_id = '')
|
||||
and p.origin_id is null
|
||||
and ifnull(p.product_type, 'AP') = #{payType}
|
||||
and not (
|
||||
exists (
|
||||
select 1 from pay_product_term t_label
|
||||
where t_label.product_id = p.product_id
|
||||
and t_label.price_set_id is not null
|
||||
)
|
||||
and not exists (
|
||||
select 1 from pay_product_term t_pay
|
||||
where t_pay.product_id = p.product_id
|
||||
and t_pay.price_set_id is null
|
||||
)
|
||||
)
|
||||
order by p.product_name
|
||||
</select>
|
||||
|
||||
@@ -238,11 +314,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<insert id="insertWeightBands">
|
||||
insert into pay_weight_band (
|
||||
product_id, version_no, section_name, country_name, country_code, zone_name, weight_label, weight_min, weight_max,
|
||||
product_id, term_id, version_no, section_name, country_name, country_code, zone_name, weight_label, weight_min, weight_max,
|
||||
volume_text, charge_name, price, price_unit, sort_no
|
||||
) values
|
||||
<foreach collection="list" item="row" separator=",">
|
||||
(#{row.productId}, ifnull(#{row.versionNo}, 1), #{row.sectionName}, #{row.countryName}, #{row.countryCode}, #{row.zoneName},
|
||||
(#{row.productId}, #{row.termId}, ifnull(#{row.versionNo}, 1), #{row.sectionName}, #{row.countryName}, #{row.countryCode}, #{row.zoneName},
|
||||
#{row.weightLabel}, #{row.weightMin}, #{row.weightMax}, #{row.volumeText}, #{row.chargeName}, #{row.price},
|
||||
#{row.priceUnit}, #{row.sortNo})
|
||||
</foreach>
|
||||
@@ -250,11 +326,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<insert id="insertSurcharges">
|
||||
insert into pay_surcharge (
|
||||
product_id, version_no, section_name, fee_name, zone_name, charge_text, amount, currency, price_unit, fee_desc, period_text,
|
||||
product_id, term_id, version_no, section_name, fee_name, zone_name, charge_text, amount, currency, price_unit, fee_desc, period_text,
|
||||
effective_start, effective_end, charge_timing, calc_rule, calc_param, weight_min, weight_max, postcode_param, sort_no
|
||||
) values
|
||||
<foreach collection="list" item="row" separator=",">
|
||||
(#{row.productId}, ifnull(#{row.versionNo}, 1), #{row.sectionName}, #{row.feeName}, #{row.zoneName}, #{row.chargeText}, #{row.amount},
|
||||
(#{row.productId}, #{row.termId}, ifnull(#{row.versionNo}, 1), #{row.sectionName}, #{row.feeName}, #{row.zoneName}, #{row.chargeText}, #{row.amount},
|
||||
#{row.currency}, #{row.priceUnit}, #{row.feeDesc}, #{row.periodText}, #{row.effectiveStart}, #{row.effectiveEnd},
|
||||
#{row.chargeTiming}, ifnull(#{row.calcRule}, 'MANUAL'), #{row.calcParam}, #{row.weightMin}, #{row.weightMax},
|
||||
#{row.postcodeParam}, #{row.sortNo})
|
||||
@@ -262,14 +338,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</insert>
|
||||
|
||||
<insert id="insertExtraLines">
|
||||
insert into pay_extra_line (product_id, line_type, line_text, sort_no) values
|
||||
insert into pay_extra_line (product_id, term_id, line_type, line_text, sort_no) values
|
||||
<foreach collection="list" item="row" separator=",">
|
||||
(#{row.productId}, #{row.lineType}, #{row.lineText}, #{row.sortNo})
|
||||
(#{row.productId}, #{row.termId}, #{row.lineType}, #{row.lineText}, #{row.sortNo})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="selectWeightBands" resultType="com.bms.price.domain.PayWeightBand">
|
||||
select band_id as bandId, product_id as productId, version_no as versionNo, section_name as sectionName, country_name as countryName,
|
||||
select band_id as bandId, product_id as productId, term_id as termId, version_no as versionNo, section_name as sectionName, country_name as countryName,
|
||||
country_code as countryCode, zone_name as zoneName, weight_label as weightLabel, weight_min as weightMin,
|
||||
weight_max as weightMax, volume_text as volumeText, charge_name as chargeName, price, price_unit as priceUnit, sort_no as sortNo
|
||||
from pay_weight_band
|
||||
@@ -278,8 +354,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
order by product_id, sort_no, band_id
|
||||
</select>
|
||||
|
||||
<select id="selectWeightBandsByTerm" resultType="com.bms.price.domain.PayWeightBand">
|
||||
select band_id as bandId, product_id as productId, term_id as termId, version_no as versionNo, section_name as sectionName, country_name as countryName,
|
||||
country_code as countryCode, zone_name as zoneName, weight_label as weightLabel, weight_min as weightMin,
|
||||
weight_max as weightMax, volume_text as volumeText, charge_name as chargeName, price, price_unit as priceUnit, sort_no as sortNo
|
||||
from pay_weight_band
|
||||
where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
order by product_id, sort_no, band_id
|
||||
</select>
|
||||
|
||||
<select id="selectSurcharges" resultType="com.bms.price.domain.PaySurcharge">
|
||||
select surcharge_id as surchargeId, product_id as productId, version_no as versionNo, section_name as sectionName, fee_name as feeName,
|
||||
select surcharge_id as surchargeId, product_id as productId, term_id as termId, version_no as versionNo, section_name as sectionName, fee_name as feeName,
|
||||
zone_name as zoneName, charge_text as chargeText, amount, currency, price_unit as priceUnit, fee_desc as feeDesc,
|
||||
period_text as periodText, effective_start as effectiveStart, effective_end as effectiveEnd,
|
||||
charge_timing as chargeTiming, calc_rule as calcRule, calc_param as calcParam,
|
||||
@@ -290,14 +376,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
order by product_id, sort_no, surcharge_id
|
||||
</select>
|
||||
|
||||
<select id="selectSurchargesByTerm" resultType="com.bms.price.domain.PaySurcharge">
|
||||
select surcharge_id as surchargeId, product_id as productId, term_id as termId, version_no as versionNo, section_name as sectionName, fee_name as feeName,
|
||||
zone_name as zoneName, charge_text as chargeText, amount, currency, price_unit as priceUnit, fee_desc as feeDesc,
|
||||
period_text as periodText, effective_start as effectiveStart, effective_end as effectiveEnd,
|
||||
charge_timing as chargeTiming, calc_rule as calcRule, calc_param as calcParam,
|
||||
weight_min as weightMin, weight_max as weightMax, postcode_param as postcodeParam, sort_no as sortNo
|
||||
from pay_surcharge
|
||||
where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
order by product_id, sort_no, surcharge_id
|
||||
</select>
|
||||
|
||||
<select id="selectExtraLines" resultType="com.bms.price.domain.PayExtraLine">
|
||||
select line_id as lineId, product_id as productId, line_type as lineType, line_text as lineText, sort_no as sortNo
|
||||
select line_id as lineId, product_id as productId, term_id as termId, line_type as lineType, line_text as lineText, sort_no as sortNo
|
||||
from pay_extra_line
|
||||
where product_id in
|
||||
<foreach collection="productIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
order by product_id, sort_no, line_id
|
||||
</select>
|
||||
|
||||
<select id="selectExtraLinesByTerm" resultType="com.bms.price.domain.PayExtraLine">
|
||||
select line_id as lineId, product_id as productId, term_id as termId, line_type as lineType, line_text as lineText, sort_no as sortNo
|
||||
from pay_extra_line
|
||||
where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
order by product_id, sort_no, line_id
|
||||
</select>
|
||||
|
||||
<delete id="deleteWeightBandsByTerm">
|
||||
delete from pay_weight_band where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
<delete id="deleteSurchargesByTerm">
|
||||
delete from pay_surcharge where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
<delete id="deleteExtraLinesByTerm">
|
||||
delete from pay_extra_line where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="deleteWeightBands">
|
||||
delete from pay_weight_band where product_id in
|
||||
<foreach collection="productIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
@@ -323,13 +442,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where product_id = #{rootId} or origin_id = #{rootId}
|
||||
</select>
|
||||
|
||||
<!-- 取价只看有效期。生效/失效开关不参与,和历史页说明一致。 -->
|
||||
<!-- 取价只看有效期。生效/失效开关不参与,和历史页说明一致。仅应付公共 term。 -->
|
||||
<select id="selectEffectiveVersionId" resultType="long">
|
||||
select v.product_id
|
||||
from pay_product v
|
||||
inner join pay_product_term t on t.product_id = v.product_id
|
||||
where (v.channel_id is null or v.channel_id = '')
|
||||
and (v.product_id = #{stableId} or v.origin_id = #{stableId})
|
||||
and t.price_set_id is null
|
||||
and t.status = '1'
|
||||
and (t.effective_start is null or t.effective_start <= date(#{bizDate}))
|
||||
and (t.effective_end is null or t.effective_end >= date(#{bizDate}))
|
||||
order by ifnull(v.version_no, 1) desc, v.product_id desc
|
||||
|
||||
@@ -5,7 +5,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<mapper namespace="com.bms.price.mapper.PayProductTermMapper">
|
||||
|
||||
<select id="selectByDict" resultType="com.bms.price.domain.PayProductTerm">
|
||||
select t.term_id as termId, t.dict_value as dictValue, t.product_id as productId, t.version_no as versionNo,
|
||||
select t.term_id as termId, t.dict_value as dictValue, t.product_id as productId, t.price_set_id as priceSetId,
|
||||
t.version_no as versionNo,
|
||||
t.effective_start as effectiveStart, t.effective_end as effectiveEnd, t.status,
|
||||
t.created_by as createBy, t.create_time as createTime, t.remark,
|
||||
p.product_name as productName, p.source_file as sourceFile,
|
||||
@@ -15,29 +16,107 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
join pay_product p on p.product_id = t.product_id
|
||||
where t.dict_value = #{dictValue}
|
||||
and (p.channel_id is null or p.channel_id = '')
|
||||
and t.price_set_id is null
|
||||
order by t.version_no desc, t.term_id desc
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultType="com.bms.price.domain.PayProductTerm">
|
||||
select term_id as termId, dict_value as dictValue, product_id as productId, version_no as versionNo,
|
||||
select term_id as termId, dict_value as dictValue, product_id as productId, price_set_id as priceSetId,
|
||||
version_no as versionNo,
|
||||
effective_start as effectiveStart, effective_end as effectiveEnd, status
|
||||
from pay_product_term
|
||||
where term_id = #{termId}
|
||||
</select>
|
||||
|
||||
<!-- 应付侧当前版:只取公共 term;优先生效(1),其次待生效(0) -->
|
||||
<select id="selectByProductId" resultType="com.bms.price.domain.PayProductTerm">
|
||||
select term_id as termId, dict_value as dictValue, product_id as productId, version_no as versionNo,
|
||||
select term_id as termId, dict_value as dictValue, product_id as productId, price_set_id as priceSetId,
|
||||
version_no as versionNo,
|
||||
effective_start as effectiveStart, effective_end as effectiveEnd, status
|
||||
from pay_product_term
|
||||
where product_id = #{productId}
|
||||
and price_set_id is null
|
||||
and status in ('0', '1')
|
||||
order by case when status = '1' then 0 when status = '0' then 1 else 2 end, version_no desc, term_id desc
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<!-- 打单套餐产品列表:待生效+生效 -->
|
||||
<select id="selectByPriceSetId" resultType="com.bms.price.domain.PayProductTerm">
|
||||
select t.term_id as termId, t.dict_value as dictValue, t.product_id as productId, t.price_set_id as priceSetId,
|
||||
t.version_no as versionNo,
|
||||
t.effective_start as effectiveStart, t.effective_end as effectiveEnd, t.status,
|
||||
p.product_name as productName, p.source_file as sourceFile,
|
||||
ifnull(t.file_path, p.file_path) as filePath, p.weight_count as weightCount,
|
||||
p.surcharge_count as surchargeCount, p.currency
|
||||
from pay_product_term t
|
||||
join pay_product p on p.product_id = t.product_id
|
||||
where t.price_set_id = #{priceSetId}
|
||||
and t.status in ('0', '1')
|
||||
order by p.product_name, t.term_id desc
|
||||
</select>
|
||||
|
||||
<select id="selectByPriceSetIdAndVersion" resultType="com.bms.price.domain.PayProductTerm">
|
||||
select t.term_id as termId, t.dict_value as dictValue, t.product_id as productId, t.price_set_id as priceSetId,
|
||||
t.version_no as versionNo,
|
||||
t.effective_start as effectiveStart, t.effective_end as effectiveEnd, t.status,
|
||||
p.product_name as productName, p.source_file as sourceFile,
|
||||
ifnull(t.file_path, p.file_path) as filePath, p.weight_count as weightCount,
|
||||
p.surcharge_count as surchargeCount, p.currency
|
||||
from pay_product_term t
|
||||
join pay_product p on p.product_id = t.product_id
|
||||
where t.price_set_id = #{priceSetId}
|
||||
and t.version_no = #{versionNo}
|
||||
order by case when t.status = '1' then 0 when t.status = '0' then 1 else 2 end, p.product_name, t.term_id desc
|
||||
</select>
|
||||
|
||||
<select id="selectLabelVersionGroups" resultType="com.bms.price.domain.LabelPackageVersion">
|
||||
select #{priceSetId} as priceSetId,
|
||||
t.version_no as versionNo,
|
||||
min(t.effective_start) as effectiveTime,
|
||||
max(t.effective_end) as expireTime,
|
||||
count(distinct t.product_id) as productCount,
|
||||
sum(case when t.status = '1' then 1 else 0 end) as activeCount,
|
||||
sum(case when t.status = '0' then 1 else 0 end) as pendingCount,
|
||||
min(t.create_time) as createTime
|
||||
from pay_product_term t
|
||||
where t.price_set_id = #{priceSetId}
|
||||
group by t.version_no
|
||||
order by t.version_no desc
|
||||
</select>
|
||||
|
||||
<!-- 启动:写入生效日;未到日 status=0,已到/当天 status=1 -->
|
||||
<update id="updateLabelVersionPeriod">
|
||||
update pay_product_term
|
||||
set effective_start = #{effectiveStart},
|
||||
effective_end = #{effectiveEnd},
|
||||
status = #{status},
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where price_set_id = #{priceSetId}
|
||||
and version_no = #{versionNo}
|
||||
and status in ('0', '1')
|
||||
</update>
|
||||
|
||||
<select id="selectMaxVersionByProduct" resultType="int">
|
||||
select ifnull(max(version_no), 0) from pay_product_term where product_id = #{productId}
|
||||
<if test="priceSetId != null">
|
||||
and price_set_id = #{priceSetId}
|
||||
</if>
|
||||
<if test="priceSetId == null">
|
||||
and price_set_id is null
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectMaxVersionByPriceSet" resultType="int">
|
||||
select ifnull(max(version_no), 0) from pay_product_term where price_set_id = #{priceSetId}
|
||||
</select>
|
||||
|
||||
<insert id="insertTerm" parameterType="com.bms.price.domain.PayProductTerm" useGeneratedKeys="true" keyProperty="termId">
|
||||
insert into pay_product_term (
|
||||
dict_value, product_id, version_no, effective_start, effective_end, file_path, status, created_by, create_time, remark
|
||||
dict_value, product_id, price_set_id, version_no, effective_start, effective_end, file_path, status, created_by, create_time, remark
|
||||
) values (
|
||||
#{dictValue}, #{productId}, ifnull(#{versionNo}, 1), #{effectiveStart}, #{effectiveEnd}, #{filePath},
|
||||
#{dictValue}, #{productId}, #{priceSetId}, ifnull(#{versionNo}, 1), #{effectiveStart}, #{effectiveEnd}, #{filePath},
|
||||
ifnull(#{status}, '0'), #{createBy}, sysdate(), #{remark}
|
||||
)
|
||||
</insert>
|
||||
@@ -59,9 +138,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where term_id = #{termId}
|
||||
</update>
|
||||
|
||||
<!-- 截断旧版:生效/待生效 → 已失效(2) -->
|
||||
<update id="closeOpenTerms">
|
||||
update pay_product_term
|
||||
set status = '1',
|
||||
set status = '2',
|
||||
effective_end = case
|
||||
when effective_end is not null and effective_end < #{endDate} then effective_end
|
||||
when effective_start is not null and effective_start > #{endDate} then effective_start
|
||||
@@ -70,14 +150,90 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where dict_value = #{dictValue}
|
||||
and status in ('0', '1')
|
||||
and price_set_id is null
|
||||
</update>
|
||||
|
||||
<update id="closeOpenTermsBySetProduct">
|
||||
update pay_product_term
|
||||
set status = '2',
|
||||
effective_end = case
|
||||
when effective_end is not null and effective_end < #{endDate} then effective_end
|
||||
when effective_start is not null and effective_start > #{endDate} then effective_start
|
||||
else #{endDate}
|
||||
end,
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where product_id = #{productId}
|
||||
and price_set_id = #{priceSetId}
|
||||
and status in ('0', '1')
|
||||
</update>
|
||||
|
||||
<update id="closePendingBySetProduct">
|
||||
update pay_product_term
|
||||
set status = '2',
|
||||
effective_end = case
|
||||
when effective_end is not null and effective_end < #{endDate} then effective_end
|
||||
when effective_start is not null and effective_start > #{endDate} then effective_start
|
||||
else #{endDate}
|
||||
end,
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where product_id = #{productId}
|
||||
and price_set_id = #{priceSetId}
|
||||
and status = '0'
|
||||
</update>
|
||||
|
||||
<update id="closeEffectExceptVersion">
|
||||
update pay_product_term
|
||||
set status = '2',
|
||||
effective_end = case
|
||||
when effective_end is not null and effective_end < #{endDate} then effective_end
|
||||
when effective_start is not null and effective_start > #{endDate} then effective_start
|
||||
else #{endDate}
|
||||
end,
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where price_set_id = #{priceSetId}
|
||||
and status = '1'
|
||||
and version_no <> #{versionNo}
|
||||
</update>
|
||||
|
||||
<update id="scheduleEndExceptVersion">
|
||||
update pay_product_term
|
||||
set status = '1',
|
||||
effective_end = #{endDate},
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where price_set_id = #{priceSetId}
|
||||
and version_no <> #{versionNo}
|
||||
and (
|
||||
status = '1'
|
||||
or (status = '2' and effective_end is not null and effective_end >= #{today})
|
||||
)
|
||||
</update>
|
||||
|
||||
<update id="restorePrematureClosed">
|
||||
update pay_product_term
|
||||
set status = '1',
|
||||
updated_by = #{updateBy},
|
||||
update_time = sysdate()
|
||||
where price_set_id = #{priceSetId}
|
||||
and status = '2'
|
||||
and effective_end is not null
|
||||
and effective_end >= #{today}
|
||||
</update>
|
||||
|
||||
<delete id="deleteByProductIds">
|
||||
delete from pay_product_term where product_id in
|
||||
<foreach collection="productIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByTermIds">
|
||||
delete from pay_product_term where term_id in
|
||||
<foreach collection="termIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
|
||||
<update id="updateProductEffectiveDate">
|
||||
update pay_product
|
||||
set effective_date = #{effectiveDate},
|
||||
|
||||
@@ -31,11 +31,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
s.default_discount, s.default_type, s.calculate_sign,
|
||||
s.status, s.tms_id,
|
||||
s.created_by, s.create_time, s.updated_by, s.update_time,
|
||||
(select count(distinct p.product_code)
|
||||
from prc_price_set_product p
|
||||
inner join prc_price_set_version v on v.psv_id = p.psv_id
|
||||
where v.price_set_id = s.price_set_id
|
||||
and ifnull(p.is_del, '0') = '0') as product_count,
|
||||
case
|
||||
when ifnull(s.set_category, 'PACKAGE') = 'LABEL' then
|
||||
(select count(distinct t.product_id)
|
||||
from pay_product_term t
|
||||
where t.price_set_id = s.price_set_id
|
||||
and t.status = '0')
|
||||
else
|
||||
(select count(distinct p.product_code)
|
||||
from prc_price_set_product p
|
||||
inner join prc_price_set_version v on v.psv_id = p.psv_id
|
||||
where v.price_set_id = s.price_set_id
|
||||
and ifnull(p.is_del, '0') = '0')
|
||||
end as product_count,
|
||||
(select count(1) from prc_customer_price_set c where c.price_set_id = s.price_set_id) as customer_count,
|
||||
(select group_concat(
|
||||
concat(ifnull(c.customer_code, ''),
|
||||
|
||||
Reference in New Issue
Block a user