Skip to content

feat(billing): margin guard — verified channel costs, save-time margin check, daily margin report - #10

Merged
YunfanGoForIt merged 1 commit into
mainfrom
feat/margin-guard-20261021
Oct 20, 2026
Merged

YunfanGoForIt merged 1 commit into
mainfrom
feat/margin-guard-20261021

Conversation

@YunfanGoForIt

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

Note

本 PR 的代码由 AI 辅助生成(提交者非仓库历史核心开发者),已按仓库约定声明;描述为人工整理,请审计者重点核对下方「审计注意点」。

📝 变更描述 / Description

「管理员后台可操作商品配置」Phase 2:真防亏本三件套。

1. 渠道成本人工核验留痕

  • channels 表新增 cost_verified_at bigint / cost_verified_by int 两列(走 GORM AutoMigrate,与 upstream_costs 列的历史迁移模式一致,三库均为 ADD COLUMN)。
  • 管理员 UpdateChannel 时,若请求中的 upstream_costs 与现值不同,自动写入当前时间戳与操作人 id;同值重存不动 stamp。
  • 两个字段加入 channelReadOnlyFields 并在 clearChannelReadOnlyFields 中清零,客户端无法伪造。

2. 保存时毛利校验 + 下单复检

  • validateV1ContractTx 末尾新增共用校验 validatePlanMarginTx:仅对 enabled plan 且模板 min_margin > 0 生效,逐模型逐分量检查 cost ≤ sale × (1 − min_margin/100)(epsilon 1e-9,恰好等于地板通过),违反时聚合所有分量报错(含模型与分量明细)。
  • 模板分量为 0 的价格行跳过;价格行缺失或未启用时跳过(bootstrap 在价格行插入前即调 ValidateV1Contract,严格报错会破坏初始化;下单路径已有 validateV1ProductPriceCatalogTx 保证价格行存在且启用,因此下单复检天然严格,未在 createSubscriptionOrderTx 重复调用)。
  • 新增 migrateProductTemplateMinMargins() 挂入 MigrateProductTemplates():monthly / pack_ds_glm / pack_qwen / pack_k3 / classroom / bigfish 六个 strict 模板的 min_margin 通过 MigrateLockedProductTemplate 收敛为 10(幂等自愈),wallet 保持 0。已验算全部真实 seed 价格在 10% 地板下通过。

3. 运行时成本超限告警 + 每日毛利报表

  • channel_select 两处过滤点:渠道 enabled 且在分组允许集内、但因成本超限(ChannelSatisfiesPolicy 失败)被排除时,common.SysError 告警,含 product_type / 模型 / 渠道 id 及 cost vs ceiling 分量明细;按 product_type|model|channelId 节流 1 小时。
  • 新增 margin_report SystemTask(仿 billing_refund_task.go):每 24h 流式聚合 consume logs,按 other.product_type 分桶,用渠道当前 upstream_costs 估算成本 vs 收入;任一模板 floor > 0 的 product_type 毛利低于地板时逐条 SysError 并 NotifyUser root。精度边界(历史成本漂移、退款、无成本数据的请求偏向上报漏报而非误报)已在 RunMarginReport 文档注释中说明。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • 关联:商品配置后台化 Phase 2(margin guard 三件套,内部任务,无公开 Issue)

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 Issues 与 PRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

本地验收全部通过(SQLite;postgres 由 CI postgres-accounting 覆盖,新测试模式已加入该 job 三个 package 的正则并集):

GOWORK=off go build ./...                # ok
cd relaykit && GOWORK=off go build ./... # ok
go vet ./model ./service ./controller    # ok
GOWORK=off go test ./model ./service ./controller -count=1
# ok  model       9.3s
# ok  service     1.4s
# ok  controller  1.2s

新增测试:

  • model/margin_guard_test.go — TestMarginGuard*(低于地板拒绝 / 恰等地板通过 / 零地板模板跳过 / disabled plan 跳过 / 下单复检拒薄利 / 模板迁移幂等)、TestChannelCost*(新列存在 / 成本超限告警节流与触发条件)
  • service/margin_report_task_test.go — TestMarginReportAggregatesAndAlertsOnBreach、TestMarginReportHealthyMarginPasses
  • controller/channel_cost_verified_test.go — TestChannelCostVerifiedStampedOnUpstreamCostsUpdate(stamp 写入 / 伪造被忽略 / 同值重存不动 stamp / 真变更动 stamp)

🔍 审计注意点(请审计者重点核对)

  1. 生产迁移行为:上线时 MigrateProductTemplates 会把六个 strict 模板的 min_margin 收敛为 10。若线上既有 enabled 商品的价格行毛利不足 10%,其保存/下单将开始被拒——这是本特性意图,但请先核对线上 pack 类价格行的 selling vs cost。
  2. 渠道新列仅靠 AutoMigrate(与 upstream_costs 历史模式一致),未使用 PRAGMA 特殊路径。
  3. 下单复检 = validateV1ContractTx 内共用函数,createSubscriptionOrderTx 原本即调用该校验,未重复添加调用点。
  4. 极窄窗口:provisionPlanFromOrder(订单完成供货)会带 livePlan.Enabled 重跑校验;价格行不可变故正常不翻转,但若模板地板在下单与支付回调之间被迁移调高,理论上会卡住已支付订单的供货。知悉即可。
  5. 告警节流为 1h / (product_type, model, channel);margin_report 为粗粒度估算,精度边界见 RunMarginReport 注释。
  6. AddChannel(批量创建)不写 verified 字段,仅 update 路径 stamp——管理员批量导入的成本视为未核验。

@YunfanGoForIt

Copy link
Copy Markdown
Author

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

  • 毛利校验逐模型逐分量(cost ≤ sale × (1−floor)),缺失/停用价格行跳过、下单路径由目录校验兜底,设计闭环;
  • 渠道成本核验留痕(verified_at/by + 只读字段防伪造)、超限排除告警(1h 节流)、日终毛利报表(SystemTask)齐备;
  • 上线注意:迁移会把六个 strict 模板 min_margin 收敛为 10,运维需确认线上 enabled 商品价格行毛利达标(已在 PR body 审计注意点记录);
  • CI 6/6 绿(含 PG 16 × 3)。

AI 辅助实现,维护者已核对。

@YunfanGoForIt
YunfanGoForIt marked this pull request as ready for review October 20, 2026 18:29
@YunfanGoForIt
YunfanGoForIt merged commit b443eec into main Oct 20, 2026
6 checks passed
@YunfanGoForIt
YunfanGoForIt deleted the feat/margin-guard-20261021 branch October 20, 2026 18:29
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