This commit is contained in:
@@ -2149,7 +2149,7 @@ components:
|
||||
description: 套餐类型 (formal:正式套餐, addon:加油包)
|
||||
type: string
|
||||
retail_price:
|
||||
description: 零售价(分)
|
||||
description: 生效零售价(分)
|
||||
type: integer
|
||||
validity_days:
|
||||
description: 有效天数
|
||||
@@ -2786,6 +2786,9 @@ components:
|
||||
description: 到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)
|
||||
example: from_activation
|
||||
type: string
|
||||
is_gift:
|
||||
description: 是否赠送套餐
|
||||
type: boolean
|
||||
package_code:
|
||||
description: 套餐编码
|
||||
maxLength: 100
|
||||
@@ -2810,7 +2813,7 @@ components:
|
||||
nullable: true
|
||||
type: integer
|
||||
suggested_retail_price:
|
||||
description: 建议售价(分)
|
||||
description: 建议售价原始值(分,普通可售套餐留空表示未配置,赠送套餐必须显式为0)
|
||||
minimum: 0
|
||||
nullable: true
|
||||
type: integer
|
||||
@@ -5580,6 +5583,10 @@ components:
|
||||
duration_months:
|
||||
description: 套餐时长(月数)
|
||||
type: integer
|
||||
effective_retail_price:
|
||||
description: 生效零售价(分,仅销售链路展示使用)
|
||||
nullable: true
|
||||
type: integer
|
||||
enable_virtual_data:
|
||||
description: 是否启用虚流量
|
||||
type: boolean
|
||||
@@ -5590,6 +5597,9 @@ components:
|
||||
description: 套餐ID
|
||||
minimum: 0
|
||||
type: integer
|
||||
is_gift:
|
||||
description: 是否赠送套餐
|
||||
type: boolean
|
||||
one_time_commission_amount:
|
||||
description: 一次性佣金金额(分,代理视角)
|
||||
nullable: true
|
||||
@@ -5603,6 +5613,12 @@ components:
|
||||
package_type:
|
||||
description: 套餐类型 (formal:正式套餐, addon:附加套餐)
|
||||
type: string
|
||||
price_config_status:
|
||||
description: 价格配置状态 (0:未配置, 1:赠送0价, 2:已配置非0)
|
||||
type: integer
|
||||
price_config_status_name:
|
||||
description: 价格配置状态名称(中文)
|
||||
type: string
|
||||
profit_margin:
|
||||
description: 利润空间(分,仅代理用户可见)
|
||||
nullable: true
|
||||
@@ -5611,7 +5627,11 @@ components:
|
||||
description: 真流量额度(MB)
|
||||
type: integer
|
||||
retail_price:
|
||||
description: 代理零售价(分),仅代理用户可见
|
||||
description: 代理零售价原始值(分,仅代理用户可见,未配置时为空)
|
||||
nullable: true
|
||||
type: integer
|
||||
retail_price_config_status:
|
||||
description: 代理零售价配置状态 (0:未配置, 1:赠送0价, 2:已配置非0)
|
||||
nullable: true
|
||||
type: integer
|
||||
series_id:
|
||||
@@ -5636,7 +5656,8 @@ components:
|
||||
description: 状态名称(中文)
|
||||
type: string
|
||||
suggested_retail_price:
|
||||
description: 建议售价(分)
|
||||
description: 建议售价原始值(分,未配置时为空)
|
||||
nullable: true
|
||||
type: integer
|
||||
tier_info:
|
||||
$ref: '#/components/schemas/DtoCommissionTierInfo'
|
||||
@@ -7704,6 +7725,9 @@ components:
|
||||
description: 套餐周期类型 (natural_month:自然月, by_day:按天)
|
||||
nullable: true
|
||||
type: string
|
||||
clear_suggested_retail_price:
|
||||
description: 是否清空建议售价并恢复为未配置状态
|
||||
type: boolean
|
||||
cost_price:
|
||||
description: 成本价(分)
|
||||
minimum: 0
|
||||
@@ -7733,6 +7757,10 @@ components:
|
||||
description: 到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)
|
||||
nullable: true
|
||||
type: string
|
||||
is_gift:
|
||||
description: 是否赠送套餐
|
||||
nullable: true
|
||||
type: boolean
|
||||
package_name:
|
||||
description: 套餐名称
|
||||
maxLength: 255
|
||||
@@ -7754,7 +7782,7 @@ components:
|
||||
nullable: true
|
||||
type: integer
|
||||
suggested_retail_price:
|
||||
description: 建议售价(分)
|
||||
description: 建议售价原始值(分,普通可售套餐留空表示未配置,赠送套餐必须显式为0)
|
||||
minimum: 0
|
||||
nullable: true
|
||||
type: integer
|
||||
@@ -7960,7 +7988,7 @@ components:
|
||||
DtoUpdateRetailPriceParams:
|
||||
properties:
|
||||
retail_price:
|
||||
description: 零售价(单位:分)
|
||||
description: 零售价原始值(分,普通可售套餐不允许显式0)
|
||||
minimum: 0
|
||||
type: integer
|
||||
required:
|
||||
|
||||
108
docs/package-price-fallback-and-platform-gift-policy/功能总结.md
Normal file
108
docs/package-price-fallback-and-platform-gift-policy/功能总结.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# 套餐价格回退与平台赠送策略功能总结
|
||||
|
||||
## 1. 变更背景
|
||||
|
||||
本次改动解决了套餐价格语义长期混用的问题:
|
||||
|
||||
- 普通可售套餐在建议零售价未配置时,会自动回退到成本价作为生效售价
|
||||
- 赠送套餐不再通过 `0` 价临时猜语义,而是使用独立赠送标记
|
||||
- 赠送套餐仅允许平台后台通过创建订单进行发放,不能进入代理分配、C 端购买或自动购包链路
|
||||
|
||||
## 2. 核心规则
|
||||
|
||||
### 2.1 价格配置状态
|
||||
|
||||
新增统一价格配置状态:
|
||||
|
||||
- `0`:未配置
|
||||
- `1`:赠送 0 价
|
||||
- `2`:已配置非 0
|
||||
|
||||
普通可售套餐:
|
||||
|
||||
- 建议售价留空 → 视为未配置,销售链路按成本价生效
|
||||
- 建议售价填非 0 → 按原值生效
|
||||
- 建议售价显式填 `0` → 拒绝保存
|
||||
|
||||
赠送套餐:
|
||||
|
||||
- 必须显式配置 `0`
|
||||
- 仅平台可创建和维护
|
||||
|
||||
### 2.2 后台套餐管理
|
||||
|
||||
后台创建、编辑、详情、列表现在同时返回:
|
||||
|
||||
- 原始建议售价(未配置时为空)
|
||||
- 价格配置状态
|
||||
- 是否赠送套餐
|
||||
|
||||
同时保留生效价字段,供销售链路或只读展示使用,但不会回写覆盖原始配置值。
|
||||
|
||||
### 2.3 C 端与销售链路
|
||||
|
||||
以下链路统一改为使用生效售价:
|
||||
|
||||
- C 端可购买套餐列表
|
||||
- C 端下单
|
||||
- 后台订单创建
|
||||
- 自动购包
|
||||
|
||||
赠送套餐会被以下链路拦截或隐藏:
|
||||
|
||||
- C 端可购列表
|
||||
- H5/客户端购买
|
||||
- 自动购包
|
||||
- 代理授权与批量分配
|
||||
|
||||
### 2.4 后台发放口径
|
||||
|
||||
“发放”统一解释为**平台后台创建订单**。
|
||||
|
||||
- 赠送套餐只能通过后台创建订单进入资产
|
||||
- 赠送订单仅允许平台侧发起
|
||||
- 赠送订单不要求线下支付凭证
|
||||
- 赠送加油包仍然要求目标资产先存在主套餐
|
||||
|
||||
## 3. 数据库变更
|
||||
|
||||
迁移版本:`000139_add_package_price_status_and_gift_policy`
|
||||
|
||||
主要新增:
|
||||
|
||||
- `tb_package.price_config_status`
|
||||
- `tb_package.is_gift`
|
||||
- `tb_shop_package_allocation.retail_price_config_status`
|
||||
- `tb_order_item.package_price_config_status`
|
||||
- `tb_order_item.package_is_gift`
|
||||
- `tb_package_usage.package_price_config_status`
|
||||
- `tb_package_usage.package_is_gift`
|
||||
- `tb_package_price_review_queue`
|
||||
|
||||
## 4. 历史数据回填策略
|
||||
|
||||
- 历史非 0 建议售价 → 回填为“已配置非 0”
|
||||
- 历史 `0` 且满足“后台创建订单 0 元成交,且未进入代理分配” → 回填为赠送套餐
|
||||
- 其余历史 `0` → 回填为未配置;若无法确认语义,则进入 `tb_package_price_review_queue`
|
||||
|
||||
## 5. 影响范围
|
||||
|
||||
主要涉及:
|
||||
|
||||
- `internal/service/package/service.go`
|
||||
- `internal/service/purchase_validation/service.go`
|
||||
- `internal/service/order/service.go`
|
||||
- `internal/service/client_order/service.go`
|
||||
- `internal/task/auto_purchase.go`
|
||||
- `internal/handler/app/client_asset.go`
|
||||
- `internal/service/shop_series_grant/service.go`
|
||||
- `internal/service/shop_package_batch_allocation/service.go`
|
||||
|
||||
## 6. 验证方式
|
||||
|
||||
本次变更按项目约束使用以下方式验证:
|
||||
|
||||
- `lsp_diagnostics` 静态诊断
|
||||
- `make migrate-up` 迁移执行
|
||||
- PostgreSQL 只读查询验证字段、默认值和回填结果
|
||||
- 后续手工回归按《最终验收清单》执行
|
||||
@@ -0,0 +1,44 @@
|
||||
# 套餐价格回退与平台赠送策略最终验收清单
|
||||
|
||||
## 1. 价格回退
|
||||
|
||||
- [ ] 普通可售套餐未配置建议售价时,后台详情返回 `suggested_retail_price=null` 且 `price_config_status=0`
|
||||
- [ ] 普通可售套餐未配置建议售价时,C 端可购列表展示成本价
|
||||
- [ ] 平台后台创建普通订单时,订单明细使用生效价
|
||||
- [ ] 自动购包命中未配置价格套餐时,订单明细使用生效价
|
||||
|
||||
## 2. 赠送拦截
|
||||
|
||||
- [ ] 普通可售套餐显式填写 `0` 时被拒绝
|
||||
- [ ] 赠送套餐显式填写 `0` 时允许保存
|
||||
- [ ] 赠送套餐不出现在 C 端可购列表
|
||||
- [ ] H5 / 客户端下单赠送套餐被拒绝
|
||||
- [ ] 自动购包命中赠送套餐时被拒绝
|
||||
|
||||
## 3. 平台发放
|
||||
|
||||
- [ ] 平台后台可通过创建订单发放赠送套餐
|
||||
- [ ] 赠送订单不要求线下支付凭证
|
||||
- [ ] 赠送加油包在无主套餐时发放失败
|
||||
- [ ] 赠送订单不会进入代理代购/佣金计算语义
|
||||
|
||||
## 4. 代理授权与分配
|
||||
|
||||
- [ ] 代理系列授权创建时无法加入赠送套餐
|
||||
- [ ] 系列授权详情列表不展示赠送套餐
|
||||
- [ ] 批量分配不会把赠送套餐分配给下级代理
|
||||
- [ ] 代理侧套餐列表不会看到赠送套餐
|
||||
|
||||
## 5. 历史迁移
|
||||
|
||||
- [ ] `tb_package` 已回填 `price_config_status` 与 `is_gift`
|
||||
- [ ] `tb_shop_package_allocation` 已回填 `retail_price_config_status`
|
||||
- [ ] `tb_order_item` / `tb_package_usage` 已回填赠送快照与价格状态快照
|
||||
- [ ] `tb_package_price_review_queue` 中仅保留需要人工复核的记录
|
||||
|
||||
## 6. 最终检查
|
||||
|
||||
- [ ] 相关 Go 文件 `lsp_diagnostics` 无错误
|
||||
- [ ] `make migrate-version` 为 `139`
|
||||
- [ ] `go run cmd/gendocs/main.go` 执行成功
|
||||
- [ ] `go build ./...` 执行成功
|
||||
Reference in New Issue
Block a user