feat: 实现卡和设备的套餐系列绑定功能
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m37s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m37s
- 添加 Device 和 IotCard 模型的 SeriesID 字段 - 实现 DeviceService 和 IotCardService 的套餐系列绑定逻辑 - 添加 DeviceStore 和 IotCardStore 的数据库操作方法 - 更新 API 接口和路由支持套餐系列绑定 - 创建数据库迁移脚本(000027_add_series_binding_fields) - 添加完整的单元测试和集成测试 - 更新 OpenAPI 文档 - 归档 OpenSpec 变更文档 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
70
openspec/specs/card-series-bindng/spec.md
Normal file
70
openspec/specs/card-series-bindng/spec.md
Normal file
@@ -0,0 +1,70 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 批量设置卡的套餐系列
|
||||
|
||||
系统 SHALL 允许代理批量为 IoT 卡设置套餐系列分配。只能设置当前店铺被分配且启用的套餐系列。
|
||||
|
||||
#### Scenario: 成功批量设置
|
||||
- **WHEN** 代理提交多个 ICCID 和一个有效的 series_allocation_id
|
||||
- **THEN** 系统更新这些卡的 series_allocation_id 字段
|
||||
|
||||
#### Scenario: 系列未分配给店铺
|
||||
- **WHEN** 代理尝试设置一个未分配给卡所属店铺的系列
|
||||
- **THEN** 系统返回错误 "该套餐系列未分配给此店铺"
|
||||
|
||||
#### Scenario: 系列分配已禁用
|
||||
- **WHEN** 代理尝试设置一个已禁用的系列分配
|
||||
- **THEN** 系统返回错误 "该套餐系列分配已禁用"
|
||||
|
||||
#### Scenario: ICCID 不存在
|
||||
- **WHEN** 提交的 ICCID 中有不存在的卡
|
||||
- **THEN** 系统返回错误,列出不存在的 ICCID
|
||||
|
||||
#### Scenario: 卡不属于当前店铺
|
||||
- **WHEN** 代理尝试设置不属于自己店铺的卡
|
||||
- **THEN** 系统返回错误 "部分卡不属于您的店铺"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 清除卡的套餐系列关联
|
||||
|
||||
系统 SHALL 允许代理清除卡的套餐系列关联(将 series_allocation_id 设为 0)。
|
||||
|
||||
#### Scenario: 清除单卡关联
|
||||
- **WHEN** 代理将卡的 series_allocation_id 设为 0
|
||||
- **THEN** 系统清除该卡的套餐系列关联
|
||||
|
||||
#### Scenario: 批量清除关联
|
||||
- **WHEN** 代理批量提交 ICCID 列表,series_allocation_id 为 0
|
||||
- **THEN** 系统清除这些卡的套餐系列关联
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 查询卡的套餐系列信息
|
||||
|
||||
系统 SHALL 在卡详情和列表中返回套餐系列关联信息。
|
||||
|
||||
#### Scenario: 卡详情包含系列信息
|
||||
- **WHEN** 查询卡详情
|
||||
- **THEN** 响应包含 series_allocation_id、关联的系列名称、佣金状态
|
||||
|
||||
#### Scenario: 卡列表支持按系列筛选
|
||||
- **WHEN** 代理按 series_allocation_id 筛选卡列表
|
||||
- **THEN** 系统只返回关联该系列的卡
|
||||
|
||||
---
|
||||
|
||||
### Requirement: IotCard 模型新增字段
|
||||
|
||||
系统 MUST 在 IotCard 模型中新增以下字段:
|
||||
- `series_allocation_id`:套餐系列分配 ID
|
||||
- `first_commission_paid`:一次性佣金是否已发放(默认 false)
|
||||
- `accumulated_recharge`:累计充值金额(默认 0)
|
||||
|
||||
#### Scenario: 新卡默认值
|
||||
- **WHEN** 创建新的 IoT 卡
|
||||
- **THEN** series_allocation_id 为空,first_commission_paid 为 false,accumulated_recharge 为 0
|
||||
|
||||
#### Scenario: 字段在响应中可见
|
||||
- **WHEN** 查询卡信息
|
||||
- **THEN** 响应包含这三个新字段
|
||||
84
openspec/specs/device-series-bindng/spec.md
Normal file
84
openspec/specs/device-series-bindng/spec.md
Normal file
@@ -0,0 +1,84 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 批量设置设备的套餐系列
|
||||
|
||||
系统 SHALL 允许代理批量为设备设置套餐系列分配。只能设置当前店铺被分配且启用的套餐系列。
|
||||
|
||||
#### Scenario: 成功批量设置
|
||||
- **WHEN** 代理提交多个设备 ID 和一个有效的 series_allocation_id
|
||||
- **THEN** 系统更新这些设备的 series_allocation_id 字段
|
||||
|
||||
#### Scenario: 系列未分配给店铺
|
||||
- **WHEN** 代理尝试设置一个未分配给设备所属店铺的系列
|
||||
- **THEN** 系统返回错误 "该套餐系列未分配给此店铺"
|
||||
|
||||
#### Scenario: 系列分配已禁用
|
||||
- **WHEN** 代理尝试设置一个已禁用的系列分配
|
||||
- **THEN** 系统返回错误 "该套餐系列分配已禁用"
|
||||
|
||||
#### Scenario: 设备不存在
|
||||
- **WHEN** 提交的设备 ID 中有不存在的设备
|
||||
- **THEN** 系统返回错误,列出不存在的设备 ID
|
||||
|
||||
#### Scenario: 设备不属于当前店铺
|
||||
- **WHEN** 代理尝试设置不属于自己店铺的设备
|
||||
- **THEN** 系统返回错误 "部分设备不属于您的店铺"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 清除设备的套餐系列关联
|
||||
|
||||
系统 SHALL 允许代理清除设备的套餐系列关联。
|
||||
|
||||
#### Scenario: 清除单设备关联
|
||||
- **WHEN** 代理将设备的 series_allocation_id 设为 0
|
||||
- **THEN** 系统清除该设备的套餐系列关联
|
||||
|
||||
#### Scenario: 批量清除关联
|
||||
- **WHEN** 代理批量提交设备 ID 列表,series_allocation_id 为 0
|
||||
- **THEN** 系统清除这些设备的套餐系列关联
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 查询设备的套餐系列信息
|
||||
|
||||
系统 SHALL 在设备详情和列表中返回套餐系列关联信息。
|
||||
|
||||
#### Scenario: 设备详情包含系列信息
|
||||
- **WHEN** 查询设备详情
|
||||
- **THEN** 响应包含 series_allocation_id、关联的系列名称、佣金状态
|
||||
|
||||
#### Scenario: 设备列表支持按系列筛选
|
||||
- **WHEN** 代理按 series_allocation_id 筛选设备列表
|
||||
- **THEN** 系统只返回关联该系列的设备
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Device 模型新增字段
|
||||
|
||||
系统 MUST 在 Device 模型中新增以下字段:
|
||||
- `series_allocation_id`:套餐系列分配 ID
|
||||
- `first_commission_paid`:一次性佣金是否已发放(默认 false)
|
||||
- `accumulated_recharge`:累计充值金额(默认 0)
|
||||
|
||||
#### Scenario: 新设备默认值
|
||||
- **WHEN** 创建新设备
|
||||
- **THEN** series_allocation_id 为空,first_commission_paid 为 false,accumulated_recharge 为 0
|
||||
|
||||
#### Scenario: 字段在响应中可见
|
||||
- **WHEN** 查询设备信息
|
||||
- **THEN** 响应包含这三个新字段
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 设备级套餐购买优先级
|
||||
|
||||
设备购买套餐时 MUST 使用 Device.series_allocation_id 确定可购买的套餐系列,而非设备下单卡的 series_allocation_id。
|
||||
|
||||
#### Scenario: 设备有系列关联
|
||||
- **WHEN** 设备有 series_allocation_id,且其下的卡也有各自的 series_allocation_id
|
||||
- **THEN** 设备级套餐购买使用设备的 series_allocation_id
|
||||
|
||||
#### Scenario: 设备无系列关联
|
||||
- **WHEN** 设备的 series_allocation_id 为空
|
||||
- **THEN** 该设备无法购买设备级套餐
|
||||
Reference in New Issue
Block a user