## 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` 接口仅支持成本价批量调整；新增独立接口 `PATCH /api/admin/packages/:id/retail-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 分配锁定规则。新增独立接口 `PATCH /api/admin/packages/:id/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` 接口仅支持 `cost_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`（仅成本价批量调价 + 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.go` Handler（新增 `PATCH /packages/:id/retail-price`）、`package_dto.go`（`PackageResponse` 新增 `retail_price` + 新增更新零售价请求 DTO）、`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 值，迁移可在线执行
