Skip to content

feat(billing): DB-driven product templates replace hardcoded contract constants - #9

Merged
YunfanGoForIt merged 2 commits into
mainfrom
feat/product-templates-20261021
Oct 20, 2026
Merged

YunfanGoForIt merged 2 commits into
mainfrom
feat/product-templates-20261021

Conversation

@YunfanGoForIt

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

本 PR 为 AI 辅助生成(Kimi Code),已经过人工要求的设计评审点核对;请审计者重点复核 model/cilai_contract.go 校验规则与模板 seed 数值的等价性。

📝 变更描述 / Description

把 ValidateV1Contract 里的硬编码"冻结契约"下沉为数据库驱动的 product_templates 表,这是"管理员后台可操作商品配置"改造的第一阶段(模板编辑 UI 与毛利校验在后续阶段)。

  • 新增 product_templates 表(三库兼容:SQLite/MySQL/PostgreSQL,注册进 migrateDB/migrateDBFast 两个 AutoMigrate 清单):product_type 唯一索引、时长、plan 级倍率、模型集合、渠道绑定、成本上限快照、限购、支付/兑换/课程开关、price_rules 定价项列表(月付 tier→价格、bigfish code→价格、classroom 固定价)、family/price_version 默认值、min_margin_percent(Phase 2 预留)、display_metadata(Phase 4 预留)、locked 标记。
  • SeedProductTemplates() 把 7 个核心模板(wallet/monthly/pack_ds_glm/pack_qwen/pack_k3/classroom/bigfish)按现有常量原样落库:只在模板不存在时 INSERT,绝不覆盖运营期修改;在 MigrateCilaiV1Contracts() 之后随主迁移执行。bigfish 模板从 validateBigfishPlan 规则反推。硬编码常量(frozenV1BillingMultipliers、月付 tier 价格、bigfish code→价格等)全部保留为 seed 定义来源。
  • ValidateV1Contract 保持函数签名与规则语义不变,数值来源改为模板行:空/legacy product_type 放行不变;模板缺失报"未知产品类型"错误;价格从等值比较改为必须命中模板 price_rules 对应 code/tier 条目(严格度不变);classroom/bigfish 的模型集合与渠道精确绑定、bigfish 的限购/禁兑换/禁余额支付/禁分组变更均从模板字段校验。
  • subscription_plans 新增 template_id bigint 列(SQLite 走 PRAGMA+ADD COLUMN 模式,MySQL/PG 走 AutoMigrate);plan 校验时自动钉住并校验与 product_type 一致;迁移按 product_type 回填存量 plan。
  • 模板查询按 plan 缓存同款模式加了进程内(+Redis)缓存,模板写操作即时失效;locked=true 的核心模板行走独立的 MigrateLockedProductTemplate 高权限路径,普通运营写路径 UpdateProductTemplate 拒绝修改 locked 模板(管理端 API 与 UI 属 Phase 3,本阶段只保证模型层完整)。
  • 事务内调用点(下单主事务、权益发放、不可变快照重建、bigfish BeforeCreate hook)改用 validateV1ContractTx(tx),模板查询复用事务连接,避免 SQLite 单连接下的池死锁。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix)
  • ✨ 新功能 (New feature)
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • 第一阶段:数据库驱动商品模板。后续阶段:模板管理 UI(Phase 3)、毛利校验 min_margin_percent(Phase 2)、前台展示元数据 display_metadata(Phase 4)。

✅ 提交前检查项 / Checklist

  • 人工确认: 本描述按模板结构整理;代码为 AI 辅助生成,需审计者复核后方可合并。
  • 非重复提交: 已搜索现有 Issues 与 PRs,无重复。
  • Bug fix 说明: 不适用(非 bug fix)。
  • 变更理解: 已理解改动的工作原理及影响面。
  • 范围聚焦: 本 PR 未包含与商品模板无关的改动;未触碰 relaykit、上游品牌署名与支付验签逻辑。
  • 本地验证: 本地构建、vet、模型层与控制层测试全部通过(见下)。
  • 安全合规: 无敏感凭据,遵循项目代码规范。

📸 运行证明 / Proof of Work

GOWORK=off go build ./...                       # OK
cd relaykit && GOWORK=off go build ./...        # OK(relaykit 未改动,独立构建验证)
go vet ./model ./controller                     # OK
go test ./model -count=1                        # ok  github.com/QuantumNous/new-api/model  10.161s
go test ./controller -run "TestSubscription|TestBigfish|TestIFLinkPay" -count=1
                                                # ok  github.com/QuantumNous/new-api/controller
go test ./controller -count=1                   # ok(全量控制层回归)
CILAI_TEST_FULL_MIGRATION=1 go test ./model -run "TestSeededTemplates|TestSeedProductTemplates|TestSubscriptionPlanTemplateId" -count=1
                                                # ok(完整 migrateDB 路径:迁移→种子→回填)

新增测试覆盖:seed 幂等且不覆盖手改(TestSeedProductTemplatesIsIdempotentAndPreservesOperatorEdits)、seed 定义与冻结常量一致性(TestProductTemplateSeedDefinitionsMatchFrozenContractConstants)、既有商品(月付三档/classroom/bigfish 三档)全部通过新校验、模板缺失/价格不在 price_rules/倍率漂移均拒绝、template_id 钉住/不一致拒绝/回填、locked 模板仅迁移路径可改。存量 TestValidateV1ContractRejectsFrozenRuleDrift 语义保持不变并继续通过。

Replace the hardcoded frozen contract numbers inside ValidateV1Contract
with the new product_templates table: seven seeded core templates
(wallet, monthly, ds_glm/qwen/k3 packs, classroom, bigfish) now carry
duration, multiplier, model/channel scope, purchase limits and price
rules. Seed is insert-only and idempotent so operational edits survive
restarts; locked templates can only change through the migration-only
write path. subscription_plans gains template_id, pinned during
validation and backfilled for existing plans.
The service package TestMain builds its own schema; add ProductTemplate
to its AutoMigrate list and seed the core templates so V1 plan
validation (billing_pool_isolation e2e) resolves its template row.
@YunfanGoForIt

Copy link
Copy Markdown
Author

维护者评审通过(2026-10-21):

  • 模板 seed 与原冻结契约逐条等价(倍率引用同一常量来源;时长 30/10/15、限购、渠道绑定、成本上限、bigfish code→价格、classroom ¥5、兑换/课程资格开关全部核对);
  • 事务内模板查询走 tx 连接,修复了 SQLite 单连接死锁;
  • pack_ds_glm/pack_qwen/pack_k3 模板为推断超集已知晓,生产无存量 product_type 计划,风险可控,Phase 2 复核;
  • CI 5/5 绿(含 PostgreSQL 16 accounting × 3)。

AI 辅助实现,维护者已核对。合并后触发生产发布管线(平台侧需 repin 子模块,另起 PR)。

@YunfanGoForIt
YunfanGoForIt marked this pull request as ready for review October 20, 2026 17:59
@YunfanGoForIt
YunfanGoForIt merged commit 11c998f into main Oct 20, 2026
5 checks passed
@YunfanGoForIt
YunfanGoForIt deleted the feat/product-templates-20261021 branch October 20, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant