## ADDED Requirements

### Requirement: 资产实名策略字段定义

系统 SHALL 在 `IotCard` 和 `Device` 模型上各新增 `realname_policy` 字段（VARCHAR(20)，NOT NULL，DEFAULT 'none'），用于控制该资产的实名认证要求。

**枚举值**：
- `none`：无需实名，充值/购买/实名链接均不受限
- `before_order`：先实名后充值/购买，充值/购买前若未实名则拦截并返回 `CodeNeedRealname`
- `after_order`：先充值/购买后实名，充值/购买放行；实名链接在无有效充值/订单记录前拦截

**常量定义**（`pkg/constants/iot.go` 或 `pkg/constants/realname.go`）：
```go
const (
    RealnmePolicyNone        = "none"         // 无需实名
    RealnmePolicyBeforeOrder = "before_order" // 先实名后充值/购买
    RealnmePolicyAfterOrder  = "after_order"  // 先充值/购买后实名
)
```

#### Scenario: 默认值为 none
- **WHEN** 新建 IotCard 或 Device 时未传入 realname_policy
- **THEN** 系统自动填充 `realname_policy = "none"`

#### Scenario: 存量数据迁移后行为不变
- **WHEN** 数据库迁移执行后，存量 IotCard 和 Device 的 realname_policy 均为 "none"
- **THEN** 充值、购买、实名链接行为与迁移前完全相同（均放行）

---

### Requirement: 生效策略优先级（设备卡 vs 单卡）

系统 SHALL 按以下规则确定一张卡的生效实名策略：

- **单卡**（该卡未绑定任何设备）：使用 `IotCard.realname_policy`
- **设备卡**（该卡已绑定设备）：使用 `Device.realname_policy`，忽略 `IotCard.realname_policy`

此规则 SHALL 封装为 Service 层公共方法 `GetEffectiveRealnamePolicy`，所有需要策略判断的场景均调用该方法，不得在多处重复实现。

#### Scenario: 设备卡使用设备策略
- **WHEN** IotCard.realname_policy="none" 且该卡绑定了 Device.realname_policy="before_order"
- **THEN** 生效策略为 "before_order"（设备策略覆盖卡策略）

#### Scenario: 单卡使用卡策略
- **WHEN** IotCard.realname_policy="before_order" 且该卡未绑定任何设备
- **THEN** 生效策略为 "before_order"

---

### Requirement: C 端充值接口实名策略拦截

系统 SHALL 在 C 端充值预检接口（C3 `GET /api/c/v1/wallet/recharge-check`）和充值下单接口（C4 `POST /api/c/v1/wallet/recharge`）中，按生效实名策略执行以下逻辑：

- `before_order` + `real_name_status=0`（未实名）：MUST 拦截，返回 `CodeNeedRealname`（错误码 1187）
- `before_order` + `real_name_status=1`（已实名）：放行
- `after_order`：放行（不检查实名状态）
- `none`：放行

#### Scenario: before_order 模式未实名时充值被拦截
- **WHEN** 资产 realname_policy="before_order" 且 real_name_status=0，用户调用充值下单接口
- **THEN** 系统返回错误码 1187（CodeNeedRealname）

#### Scenario: before_order 模式已实名时充值放行
- **WHEN** 资产 realname_policy="before_order" 且 real_name_status=1，用户调用充值下单接口
- **THEN** 系统正常创建充值订单

#### Scenario: after_order 模式充值放行
- **WHEN** 资产 realname_policy="after_order" 且 real_name_status=0，用户调用充值下单接口
- **THEN** 系统正常创建充值订单，不检查实名状态

---

### Requirement: C 端购买套餐/订单接口实名策略拦截

系统 SHALL 在 C 端创建订单接口（D1 `POST /api/c/v1/orders/create`）和支付接口（D4 `POST /api/c/v1/orders/:id/pay`）中，按生效实名策略执行与充值相同的拦截规则。D1 中原 `REALNAME-03` 注释代码 SHALL 被删除，由新策略逻辑替代。

#### Scenario: before_order 模式未实名时购买套餐被拦截
- **WHEN** 资产 realname_policy="before_order" 且 real_name_status=0，用户调用创建订单接口
- **THEN** 系统返回错误码 1187（CodeNeedRealname），订单不创建

#### Scenario: none 模式购买套餐放行
- **WHEN** 资产 realname_policy="none"，用户调用创建订单接口
- **THEN** 系统正常创建订单，不检查实名状态

---

### Requirement: C 端实名链接接口策略拦截

系统 SHALL 在 C 端实名链接接口（E1 `GET /api/c/v1/realname/link`）中，按生效实名策略执行以下逻辑：

- `none`：放行，正常返回实名链接（用户可自愿实名）
- `before_order`：放行，正常返回实名链接（引导用户先实名再充值）
- `after_order`：检查该资产当前 generation 内是否存在有效充值（`status=2`）或已支付订单（`payment_status=2`）
  - 有记录 → 放行
  - 无记录 → 拦截，返回错误码（新错误码 `CodeRealnameNotAvailable`），消息为"请先完成充值或购买套餐后再进行实名认证"

#### Scenario: after_order 模式有充值记录时实名链接放行
- **WHEN** 资产 realname_policy="after_order" 且当前 generation 内存在 status=2 的充值记录
- **THEN** 系统正常返回实名链接

#### Scenario: after_order 模式无充值/订单记录时实名链接被拦截
- **WHEN** 资产 realname_policy="after_order" 且当前 generation 内无任何有效充值或已支付订单
- **THEN** 系统返回错误，消息为"请先完成充值或购买套餐后再进行实名认证"

#### Scenario: before_order 模式正常返回实名链接
- **WHEN** 资产 realname_policy="before_order"
- **THEN** 系统正常返回实名链接（引导用户完成实名）

---

### Requirement: 后台管理更新资产实名策略接口

系统 SHALL 提供 `PATCH /api/admin/assets/:identifier/realname-mode`，仅限后台管理端认证用户访问。接口通过 `assetService.Resolve()` 将标识符（ICCID/虚拟号）解析为具体资产，按 asset_type 分别更新 `IotCard.realname_policy` 或 `Device.realname_policy`。

**请求体**：
```json
{ "realname_policy": "none | before_order | after_order" }
```

**响应体**：
```json
{ "asset_type": "card | device", "asset_id": 123, "realname_policy": "before_order" }
```

#### Scenario: 通过 ICCID 更新单卡策略
- **WHEN** 管理员传入 identifier=ICCID，realname_policy="before_order"
- **THEN** 系统更新对应 IotCard 的 realname_policy 为 "before_order"，返回 asset_type="card"

#### Scenario: 通过设备号更新设备策略
- **WHEN** 管理员传入 identifier=设备虚拟号，realname_policy="after_order"
- **THEN** 系统更新对应 Device 的 realname_policy 为 "after_order"，返回 asset_type="device"

#### Scenario: 传入无效枚举值被拒绝
- **WHEN** 管理员传入 realname_policy="invalid_value"
- **THEN** 系统返回参数校验错误，提示实名策略值无效

---

### Requirement: 所有查询接口返回 realname_policy 字段

以下所有 DTO SHALL 新增 `realname_policy` 字段（string）及对应的 description 标签：

**后台管理端 DTO**：
- `StandaloneIotCardResponse`（IoT 卡详情/列表）
- `DeviceResponse`（设备详情/列表）
- `AssetResolveResponse`（统一资产解析）
- `AssetRealtimeStatusResponse`（资产实时状态）
- `DeviceCardBindingResponse`（设备绑卡记录）
- `BoundCardInfo`（asset_dto.go 中的通用子结构）
- `ImportTaskResponse`（iot 卡导入任务）
- `DeviceImportTaskResponse`（设备导入任务）

**C 端 DTO**：
- `AssetInfoResponse`（B1 资产信息）
- `BoundCardInfo`（client_asset_dto.go 中的 C 端子结构）
- `DeviceCardItem`（F1 设备卡列表项）

**description 标签统一格式**：
```go
RealnamePolicy string `json:"realname_policy" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"`
```

#### Scenario: 资产详情接口返回 realname_policy
- **WHEN** 后台管理员查询 IoT 卡详情或资产解析
- **THEN** 响应中包含 realname_policy 字段

#### Scenario: C 端资产信息接口返回 realname_policy
- **WHEN** C 端用户调用 GET /api/c/v1/asset/info
- **THEN** 响应中包含 realname_policy 字段（前端可据此展示提示）
