Files
junhong_cmp_fiber/openspec/changes/client-api-data-model-fixes/proposal.md
huang ec86dbf463 feat: 客户端接口数据模型基础准备
- 新增资产状态、订单来源、操作人类型、实名链接类型常量
- 8个模型新增字段(asset_status/generation/source/retail_price等)
- 数据库迁移000082:7张表15+字段,含存量retail_price回填
- BUG-1修复:代理零售价渠道隔离,cost_price分配锁定
- BUG-2修复:一次性佣金仅客户端订单触发
- BUG-4修复:充值回调Store操作纳入事务
- 新增资产手动停用接口(PATCH /iot-cards/:id/deactivate、/devices/:id/deactivate)
- Carrier管理新增实名链接配置
- 后台订单generation写时快照
- BatchUpdatePricing支持retail_price调价目标
- 清理全部H5旧接口和个人客户旧登录方法
2026-03-19 10:56:50 +08:00

68 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Why
系统存在 4 个影响资金安全和业务正确性的 BUG且即将启动客户端C 端)接口体系开发。本提案作为客户端接口系列提案的**前置基础**,解决三类问题:
1. **资金/业务 BUG 修复**代理零售价缺失导致价格计算错误BUG-1、后台订单误触发一次性佣金BUG-2、充值回调事务半提交风险BUG-4
2. **基础字段准备**:为客户端接口和换货系统新增必要的模型字段(`asset_status``generation``source``operator_type``realname_link_type`
3. **旧接口清理**:删除基于 B 端认证体系的旧 H5 接口和旧个人客户登录接口,为新的 `/api/c/v1` 体系腾出空间
## What Changes
### BUG 修复
- **BUG-1 代理零售价修复**`ShopPackageAllocation` 新增 `retail_price` 字段;`GetPurchasePrice()` 改为代理渠道查 `allocation.retail_price`、平台渠道用 `Package.SuggestedRetailPrice``validatePackages()` 内部价格累加同步修正;新增 cost_price 分配锁定规则(存在下级分配时禁止修改 cost_price**扩展现有 `BatchUpdatePricing` 接口支持 `retail_price` 调整**(新增 `pricing_target` 字段区分调 cost_price 还是 retail_price默认 `cost_price` 保持向后兼容);**代理套餐列表(`PackageResponse`)新增 `retail_price` 字段**,代理可查看自己的零售价;**利润计算修正**为 `RetailPrice - CostPrice`(代理实际利润 = 零售价 - 成本价,而非建议售价 - 成本价)
- **BUG-2 一次性佣金触发修复**`Order` 新增 `source` 字段(`admin`/`client`);佣金触发条件从 `!order.IsPurchaseOnBehalf` 改为 `!order.IsPurchaseOnBehalf && order.Source == "client"`,确保只有客户端个人客户购买才触发
- **BUG-4 充值回调事务修复**`HandlePaymentCallback``UpdateStatusWithOptimisticLock``UpdatePaymentInfo``s.db.WithContext(ctx)` 改为事务内 `tx`,确保充值单状态变更和钱包入账原子完成
### 新增模型字段
- **`IotCard`/`Device` 新增 `asset_status`**业务生命周期状态1-在库 2-已销售 3-已换货 4-已停用),与运营商 `network_status` 独立
- **`IotCard`/`Device` 新增 `generation`**:资产世代编号,换货转新时 +1客户端按当前 generation 过滤历史数据
- **`Order`/`PackageUsage`/`AssetRechargeRecord` 新增 `generation`**:创建时快照资产当前 generation客户端查询按此字段过滤
- **`AssetRechargeRecord` 新增 `operator_type`**:区分操作人类型(`admin_user`/`personal_customer`),配合 `user_id` 区分不同 ID 体系
- **`AssetRechargeRecord` 新增强充关联字段**`linked_package_ids``linked_order_type``linked_carrier_type``linked_carrier_id`,支持强充两阶段处理
- **`Carrier` 新增实名链接配置**`realname_link_type`none/template/gateway`realname_link_template`(支持 `{iccid}`/`{msisdn}`/`{virtual_no}` 占位符)。**同步更新 Carrier admin DTO**`CarrierCreateRequest`/`CarrierUpdateRequest`)包含这两个字段,使后台管理员可通过 API 配置运营商实名链接方式
- **`PersonalCustomer` 索引变更**`wx_open_id` 从唯一索引改为普通索引(支持后续多 OpenID 方案)
### 旧接口删除
- **删除全部旧 H5 接口**`internal/handler/h5/` 下所有文件auth、order、recharge、package_usage、enterprise_device`internal/routes/h5*.go` 路由注册
- **删除旧个人客户登录接口**`internal/handler/app/personal_customer.go` 中的 Login、SendCode、WechatOAuthLogin、BindWechat、Profile 方法
- **同步清理**bootstrap 中 H5 Handler 注册、docs.go/gendocs 中引用
## Capabilities
### New Capabilities
- `asset-lifecycle-status`资产业务生命周期状态管理。IotCard/Device 新增 `asset_status` 字段(在库→已销售→已换货→已停用),定义状态流转规则,与运营商 `network_status` 完全独立
- `asset-generation`资产世代机制。IotCard/Device 的 `generation` 字段关联表Order/PackageUsage/AssetRechargeRecord的 generation 写时快照规则,客户端按世代过滤、后台不过滤的查询规则
- `carrier-realname-config`运营商实名链接配置。Carrier 模型新增 `realname_link_type`/`realname_link_template` 字段,支持 none/template/gateway 三种模式URL 模板占位符替换。**Carrier admin DTO 同步更新**,后台可通过现有运营商管理接口配置实名链接
- `agent-retail-price`代理零售价管理。ShopPackageAllocation 新增 `retail_price` 字段,支持代理设定面向终端客户的零售价,约束 `retail_price >= cost_price`cost_price 分配锁定规则。**扩展 `BatchUpdatePricing` 接口**支持 `pricing_target=retail_price` 批量调整零售价;**代理套餐列表展示 retail_price****利润计算修正**为 `RetailPrice - CostPrice`
- `asset-manual-deactivation`:资产手动停用。新增后台接口 `PATCH /api/admin/iot-cards/:id/deactivate``PATCH /api/admin/devices/:id/deactivate`,将 `asset_status` 设为 4已停用`asset_status=1`(在库)或 `asset_status=2`(已销售)时可操作
- `h5-legacy-cleanup`:旧 H5 接口和旧登录接口的完整删除,包括 handler、route、bootstrap 注册、文档生成器引用的清理
### Modified Capabilities
- `package-purchase-validation``GetPurchasePrice()` 价格来源改为按渠道区分代理→retail_price平台→SuggestedRetailPrice`validatePackages()` 价格累加逻辑同步修正
- `package-list`:代理查询套餐列表时,`PackageResponse` 新增 `retail_price` 字段;`ProfitMargin` 计算从 `SuggestedRetailPrice - CostPrice` 改为 `RetailPrice - CostPrice`
- `batch-pricing``BatchUpdatePricing` 接口扩展支持 `pricing_target` 参数(`cost_price`/`retail_price`),默认 `cost_price` 保持向后兼容retail_price 调整时校验 `>= cost_price`
- `one-time-commission-trigger`:触发条件增加 `order.Source == "client"` 判断,确保仅客户端个人客户购买才触发
- `wallet-recharge``HandlePaymentCallback` 事务一致性修复Store 方法支持传入事务 `tx`
- `iot-order`Order 模型新增 `source`(订单来源)和 `generation`(世代)字段;`CreateAdminOrder()` 创建订单时从资产快照当前 `generation` 写入订单(而非依赖默认值 1
- `iot-card`IotCard 模型新增 `asset_status``generation` 字段
- `device`Device 模型新增 `asset_status``generation` 字段
- `personal-customer``wx_open_id` 索引从唯一改为普通索引
- `asset-recharge-adaptation`AssetRechargeRecord 新增 `operator_type``generation`、强充关联字段
## Impact
- **模型文件**`shop_package_allocation.go``carrier.go``order.go``iot_card.go``device.go``package_usage.go``asset_recharge_record.go``personal_customer.go`
- **Service 文件**`purchase_validation/service.go`(价格计算)、`commission_calculation/service.go`(佣金触发)、`recharge/service.go`(回调事务)、`shop_package_batch_pricing/service.go`(扩展支持 retail_price + cost_price 锁定)、`shop_series_grant/service.go`cost_price 锁定)、`order/service.go`source 设置 + generation 快照)、`package/service.go`(利润计算修正 + PackageResponse 新增 retail_price
- **Handler/DTO 文件**`shop_package_batch_pricing.go` Handler扩展`shop_package_batch_pricing_dto.go`(新增 `pricing_target` 字段)、`package_dto.go``PackageResponse` 新增 `retail_price`)、`carrier_dto.go`(新增实名链接字段)
- **Store 文件**`asset_recharge_store.go`(支持事务传入)
- **删除文件**`internal/handler/h5/` 全部5 个文件)、`internal/routes/h5*.go`3 个文件)、`internal/handler/app/personal_customer.go` 中旧方法
- **数据库迁移**7 张表共 15+ 个字段变更1 个索引变更
- **文档生成器**`cmd/api/docs.go``cmd/gendocs/main.go` 移除 H5 Handler 引用
- **Bootstrap**:移除 H5 Handler 注册
- **性能**:所有变更为字段新增/修复,无查询性能影响;新增字段均带 DEFAULT 值,迁移可在线执行