修改套餐规则

This commit is contained in:
wuweihua
2026-10-28 18:10:10 +08:00
parent 2bd417b84e
commit 8ed7b3146b
21 changed files with 536 additions and 411 deletions
@@ -139,8 +139,8 @@ public class ProductController extends BaseController
return success();
}
/** Persist create-page preview details into draft/pending version. */
@PreAuthorize("@ss.hasPermi('price:product:add')")
/** Persist create-page preview details into draft/pending/effect version. */
@PreAuthorize("@ss.hasPermi('price:product:add') or @ss.hasPermi('price:product:edit')")
@Log(title = "product preview apply", businessType = BusinessType.UPDATE)
@PostMapping("/version/applyPreview")
public AjaxResult applyPreview(@RequestBody CatalogPreviewApplyRequest body)
@@ -149,7 +149,7 @@ public class ProductController extends BaseController
}
/** Async parallel save of create-page preview. Returns taskId; poll /import/task/{taskId}. */
@PreAuthorize("@ss.hasPermi('price:product:add')")
@PreAuthorize("@ss.hasPermi('price:product:add') or @ss.hasPermi('price:product:edit')")
@Log(title = "product preview apply", businessType = BusinessType.UPDATE)
@PostMapping("/version/applyPreviewAsync")
public AjaxResult applyPreviewAsync(@RequestBody CatalogPreviewApplyRequest body)
@@ -160,7 +160,7 @@ public class ProductController extends BaseController
return success(payload);
}
/** Save import Excel attachment onto a draft/pending version (prc_price_excel_file). */
/** Save import Excel attachment onto a draft/pending/effect version (prc_price_excel_file). */
@PreAuthorize("@ss.hasPermi('price:product:import')")
@Log(title = "product version excel", businessType = BusinessType.IMPORT)
@PostMapping("/version/{psvId}/excel")
@@ -139,8 +139,8 @@ public class RedlineProductController extends BaseController
return success();
}
/** Persist create-page preview details into draft/pending version. */
@PreAuthorize("@ss.hasPermi('price:redline:add')")
/** Persist create-page preview details into draft/pending/effect version. */
@PreAuthorize("@ss.hasPermi('price:redline:add') or @ss.hasPermi('price:redline:edit')")
@Log(title = "redline preview apply", businessType = BusinessType.UPDATE)
@PostMapping("/version/applyPreview")
public AjaxResult applyPreview(@RequestBody RedlineCatalogPreviewApplyRequest body)
@@ -149,7 +149,7 @@ public class RedlineProductController extends BaseController
}
/** Async parallel save of create-page preview. Returns taskId; poll /import/task/{taskId}. */
@PreAuthorize("@ss.hasPermi('price:redline:add')")
@PreAuthorize("@ss.hasPermi('price:redline:add') or @ss.hasPermi('price:redline:edit')")
@Log(title = "redline preview apply", businessType = BusinessType.UPDATE)
@PostMapping("/version/applyPreviewAsync")
public AjaxResult applyPreviewAsync(@RequestBody RedlineCatalogPreviewApplyRequest body)
@@ -160,7 +160,7 @@ public class RedlineProductController extends BaseController
return success(payload);
}
/** Save import Excel attachment onto a draft/pending version (prc_price_excel_file). */
/** Save import Excel attachment onto a draft/pending/effect version (prc_price_excel_file). */
@PreAuthorize("@ss.hasPermi('price:redline:import')")
@Log(title = "redline version excel", businessType = BusinessType.IMPORT)
@PostMapping("/version/{psvId}/excel")
@@ -207,7 +207,7 @@ price.set.version.effectiveTime.empty=版本生效时间不能为空
price.set.version.effectiveTime.beforePrev=生效时间不能早于上一版本的生效时间
price.set.version.notExists=套餐版本不存在
price.set.version.activate.statusNotAllowed=仅草稿或待生效版本可设置生效时间
price.set.version.delete.statusNotAllowed=仅草稿或待生效版本可删除
price.set.version.delete.statusNotAllowed=仅草稿、待生效或已生效版本可删除
price.set.version.copy.draftExists=已有草稿版本,请先启动或删除后再复制
price.set.version.create.draftExists=已有草稿版本,请先启动或删除后再新建
price.set.save.task.notExists=保存任务不存在或已过期
@@ -33,6 +33,8 @@ public class PrcPriceSetVersion extends BaseEntity
* Column: price_build_mode
*/
private String priceBuildMode;
/** 0 normal / 1 soft-deleted */
private String isDel;
private List<PrcPriceSetDetail> details;
private List<PrcPriceSetProduct> products;
@@ -30,6 +30,9 @@ public interface PrcPriceSetVersionMapper
public int deletePrcPriceSetVersionByIds(Long[] psvIds);
/** Soft-delete catalog/sales version row (is_del=1). */
public int softDeleteById(@Param("psvId") Long psvId, @Param("updateBy") String updateBy);
public int deletePrcPriceSetVersionByPriceSetId(Long priceSetId);
public List<Long> selectPriceSetIds();
@@ -48,6 +48,9 @@ public interface PrcSurchargeRelMapper
/** Hard delete surcharge rows linked to products/details under a version. */
public int physicalDeleteByPsvId(@Param("psvId") Long psvId);
/** Soft-delete surcharge rows linked to products/details under a version. */
public int softDeleteByPsvId(@Param("psvId") Long psvId);
/** 附加费版本化编辑后,把产品关联从旧记录重指向新记录 */
public int rebindRelScId(@Param("oldScId") Long oldScId, @Param("newScId") Long newScId, @Param("operator") String operator);
}
@@ -546,16 +546,29 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
{
throw new ServiceException(MessageUtils.message("price.set.version.notExists"));
}
// Draft and pending versions may be deleted; effect/expired cannot.
if (!VER_DRAFT.equals(version.getStatus()) && !VER_PENDING.equals(version.getStatus()))
if ("1".equals(version.getIsDel()))
{
throw new ServiceException(MessageUtils.message("price.set.version.notExists"));
}
// Draft / pending: hard delete; EFFECT: soft delete then reopen previous via refreshVersionStatus
if (!VER_DRAFT.equals(version.getStatus())
&& !VER_PENDING.equals(version.getStatus())
&& !VER_EFFECT.equals(version.getStatus()))
{
throw new ServiceException(MessageUtils.message("price.set.version.delete.statusNotAllowed"));
}
requireSet(version.getPriceSetId());
// Draft / pending only reach here: hard-delete children with the version row
wipeVersionChildren(psvId, version.getStatus());
int rows = versionMapper.deletePrcPriceSetVersionByIds(new Long[] { psvId });
// Rechain expire_time / status for remaining versions (e.g. reopen previous effect window)
int rows;
if (VER_EFFECT.equals(version.getStatus()))
{
rows = versionMapper.softDeleteById(psvId, updateBy);
}
else
{
rows = versionMapper.deletePrcPriceSetVersionByIds(new Long[] { psvId });
}
// Rechain expire_time / status for remaining versions (reopen previous effect window)
refreshVersionStatus(version.getPriceSetId());
return rows;
}
@@ -193,8 +193,9 @@ public class CatalogVersionSupport
}
/**
* Hard-delete draft/pending catalog version with products, details,
* surcharge links and excel attachments.
* Delete catalog version:
* - draft / pending: hard-delete version + children + excel
* - effect: soft-delete version + products + details (+ surcharge rel)
*/
public int deleteDraftVersion(Long psvId)
{
@@ -204,9 +205,17 @@ public class CatalogVersionSupport
throw new ServiceException("版本不存在");
}
assertCatalogType(ver.getPriceType());
if ("1".equals(ver.getIsDel()))
{
throw new ServiceException("版本已删除");
}
if (STATUS_EFFECT.equals(ver.getStatus()))
{
return softDeleteEffectVersion(ver);
}
if (!STATUS_DRAFT.equals(ver.getStatus()) && !STATUS_PENDING.equals(ver.getStatus()))
{
throw new ServiceException("仅草稿或待生效版本可以删除");
throw new ServiceException("仅草稿、待生效或已生效版本可以删除");
}
surchargeRelMapper.physicalDeleteByPsvId(psvId);
detailMapper.physicalDeleteByPsvId(psvId);
@@ -215,6 +224,89 @@ public class CatalogVersionSupport
return versionMapper.deletePrcPriceSetVersionByIds(new Long[] { psvId });
}
/**
* Soft-delete EFFECT version with products and details,
* then reopen the previous version as EFFECT (clear expire_time;
* product/detail expire cleared via syncEffect).
*/
private int softDeleteEffectVersion(PrcPriceSetVersion ver)
{
Long psvId = ver.getPsvId();
String priceType = ver.getPriceType();
surchargeRelMapper.softDeleteByPsvId(psvId);
detailMapper.deletePrcPriceSetDetailByPsvId(psvId);
productMapper.deleteByPsvId(psvId);
int rows = versionMapper.softDeleteById(psvId, null);
PrcPriceSetVersion prev = findPreviousVersionToRestore(ver);
if (prev != null)
{
prev.setExpireTime(null);
prev.setStatus(STATUS_EFFECT);
versionMapper.updatePrcPriceSetVersion(prev);
}
refreshCatalogStatuses(priceType);
return rows;
}
/**
* Previous catalog version (highest version_seq below deleted) that can become EFFECT again.
* Prefers expired/effect rows that already had an effective_time.
*/
private PrcPriceSetVersion findPreviousVersionToRestore(PrcPriceSetVersion deleted)
{
if (deleted == null || deleted.getPriceType() == null)
{
return null;
}
PrcPriceSetVersion q = new PrcPriceSetVersion();
q.setPriceType(deleted.getPriceType());
List<PrcPriceSetVersion> list = versionMapper.selectPrcPriceSetVersionList(q);
if (list == null || list.isEmpty())
{
return null;
}
int curSeq = deleted.getVersionSeq() == null ? 0 : deleted.getVersionSeq().intValue();
PrcPriceSetVersion best = null;
int bestSeq = Integer.MIN_VALUE;
Date now = new Date();
for (PrcPriceSetVersion v : list)
{
if (v == null || v.getPsvId() == null)
{
continue;
}
if (deleted.getPsvId() != null && deleted.getPsvId().equals(v.getPsvId()))
{
continue;
}
if (v.getEffectiveTime() == null)
{
continue;
}
// Skip future pending drafts: they are not "previous" effective windows
if (STATUS_PENDING.equals(v.getStatus()) && v.getEffectiveTime().after(now))
{
continue;
}
if (STATUS_DRAFT.equals(v.getStatus()))
{
continue;
}
int seq = v.getVersionSeq() == null ? 0 : v.getVersionSeq().intValue();
if (seq >= curSeq)
{
continue;
}
if (seq > bestSeq)
{
bestSeq = seq;
best = v;
}
}
return best;
}
/** Current draft version (status=0), or null. */
public PrcPriceSetVersion currentDraft(String priceType)
{
@@ -222,7 +314,10 @@ public class CatalogVersionSupport
return drafts.isEmpty() ? null : drafts.get(0);
}
/** Draft/pending catalog version that can accept preview apply / edit. */
/**
* Catalog version that can accept preview apply / Excel attach / edit.
* Same as sales force-edit: draft, pending, and effect are writable.
*/
public PrcPriceSetVersion requireEditableCatalogVersion(Long psvId, String priceType)
{
PrcPriceSetVersion ver = versionMapper.selectPrcPriceSetVersionById(psvId);
@@ -235,9 +330,15 @@ public class CatalogVersionSupport
{
throw new ServiceException("版本类型不匹配");
}
if (!STATUS_DRAFT.equals(ver.getStatus()) && !STATUS_PENDING.equals(ver.getStatus()))
if ("1".equals(ver.getIsDel()))
{
throw new ServiceException("仅草稿或待生效版本可以编辑");
throw new ServiceException("版本已删除");
}
if (!STATUS_DRAFT.equals(ver.getStatus())
&& !STATUS_PENDING.equals(ver.getStatus())
&& !STATUS_EFFECT.equals(ver.getStatus()))
{
throw new ServiceException("仅草稿、待生效或已生效版本可以编辑");
}
return ver;
}
@@ -14,6 +14,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="expireTime" column="expire_time" />
<result property="status" column="status" />
<result property="priceBuildMode" column="price_build_mode"/>
<result property="isDel" column="is_del" />
<result property="createBy" column="created_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="updated_by" />
@@ -24,7 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectPrcPriceSetVersionVo">
select psv_id, price_set_id, price_type, version_no, version_seq, effective_time, expire_time, status,
price_build_mode, created_by, create_time, updated_by, update_time
price_build_mode, is_del, created_by, create_time, updated_by, update_time
from prc_price_set_version
</sql>
@@ -36,6 +37,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectPrcPriceSetVersionList" parameterType="PrcPriceSetVersion" resultMap="PrcPriceSetVersionResult">
<include refid="selectPrcPriceSetVersionVo"/>
<where>
and ifnull(is_del, '0') = '0'
<if test="priceSetId != null">
AND price_set_id = #{priceSetId}
</if>
@@ -57,7 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectCatalogVersionList" parameterType="PrcPriceSetVersion" resultMap="PrcPriceSetVersionResult">
select v.psv_id, v.price_set_id, v.price_type, v.version_no, v.version_seq,
v.effective_time, v.expire_time, v.status, v.price_build_mode,
v.effective_time, v.expire_time, v.status, v.price_build_mode, v.is_del,
v.created_by, v.create_time, v.updated_by, v.update_time,
(select count(1) from prc_price_set_product p
where p.psv_id = v.psv_id and ifnull(p.is_del, '0') = '0') as product_count,
@@ -66,6 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
from prc_price_set_version v
where v.price_set_id is null
and v.price_type = #{priceType}
and ifnull(v.is_del, '0') = '0'
<choose>
<when test="statusGroup != null and statusGroup == 'pending'">
and v.status in ('0', '3')
@@ -162,6 +165,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectPrcPriceSetVersionVo"/>
where price_type = 'SALES'
and price_set_id = #{priceSetId}
and ifnull(is_del, '0') = '0'
and effective_time is not null
and effective_time &lt;= #{asOf}
and (expire_time is null or expire_time &gt; #{asOf})
@@ -173,6 +177,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectPrcPriceSetVersionVo"/>
where price_type = #{priceType}
and price_set_id is null
and ifnull(is_del, '0') = '0'
and effective_time is not null
and effective_time &lt;= #{asOf}
and (expire_time is null or expire_time &gt; #{asOf})
@@ -180,6 +185,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
limit 1
</select>
<update id="softDeleteById">
update prc_price_set_version
set is_del = '1',
<if test="updateBy != null and updateBy != ''">updated_by = #{updateBy},</if>
update_time = sysdate()
where psv_id = #{psvId}
and ifnull(is_del, '0') = '0'
</update>
<update id="refreshCatalogStatusByDates">
update prc_price_set_version
set status = case
@@ -191,6 +205,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update_time = sysdate()
where price_type = #{priceType}
and price_set_id is null
and ifnull(is_del, '0') = '0'
and status in ('0','1','2','3')
</update>
@@ -166,6 +166,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
)
</delete>
<update id="softDeleteByPsvId">
update prc_surcharge_rel r
set r.is_del = '1', r.update_time = sysdate()
where ifnull(r.is_del, '0') = '0'
and (
exists (
select 1 from prc_price_set_product p
where p.psp_id = r.product_id and p.psv_id = #{psvId}
)
or exists (
select 1 from prc_price_set_detail d
where d.psd_id = r.detail_id and d.psv_id = #{psvId}
)
)
</update>
<!-- 附加费版本化编辑后,产品关联重指向新记录 -->
<update id="rebindRelScId">
update prc_surcharge_rel
+3 -1
View File
@@ -1315,6 +1315,7 @@ CREATE TABLE `prc_price_set_version` (
`expire_time` datetime DEFAULT NULL COMMENT '失效时间(空=长期;下一版本启动时写入该启动时间)',
`status` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '0 draft 3 pending 1 effect 2 expired',
`price_build_mode` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建价格方式 PULL=拉取产品库 IMPORT=Excel导入',
`is_del` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '是否删除 0未删除 1已删除',
`created_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`updated_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新人',
@@ -1324,7 +1325,8 @@ CREATE TABLE `prc_price_set_version` (
UNIQUE KEY `uk_psv_type_set_seq` (`price_type`,`price_set_id_key`,`version_seq`),
KEY `idx_psv_set_eff` (`price_set_id`,`effective_time`),
KEY `idx_psv_type_eff` (`price_type`,`status`,`effective_time`),
KEY `idx_psv_status` (`status`)
KEY `idx_psv_status` (`status`),
KEY `idx_psv_is_del` (`is_del`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='价格版本(三价统一;与套餐弱关联)';
@@ -0,0 +1,13 @@
-- Soft-delete flag for price versions (catalog EFFECT soft-delete)
SET @db := DATABASE();
SET @sql := (
SELECT IF(COUNT(*) = 0,
'ALTER TABLE prc_price_set_version ADD COLUMN is_del char(1) NOT NULL DEFAULT ''0'' COMMENT ''是否删除 0未删除 1已删除'' AFTER price_build_mode, ADD KEY idx_psv_is_del (is_del)',
'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'prc_price_set_version' AND COLUMN_NAME = 'is_del'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
UPDATE prc_price_set_version SET is_del = '0' WHERE is_del IS NULL OR is_del = '';