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:
@@ -89,7 +89,7 @@ type OrderItem struct {
|
||||
|
||||
**理由**:
|
||||
- 简化首期实现,所有终端用户统一售价
|
||||
- 代理的利润 = suggested_retail_price - 成本价
|
||||
- 代理的利润来自返佣(基础返佣 + 一次性佣金)
|
||||
- 后续如需支持代理自定义售价,可扩展 ShopPackageAllocation 增加 retail_price 字段
|
||||
|
||||
**非首期功能**:
|
||||
@@ -98,6 +98,38 @@ type OrderItem struct {
|
||||
|
||||
---
|
||||
|
||||
### 3.1 佣金配置版本快照
|
||||
|
||||
**决策**:订单创建时快照当时的佣金配置版本
|
||||
|
||||
**新增字段**:
|
||||
```go
|
||||
type Order struct {
|
||||
// ... 现有字段
|
||||
|
||||
// 🆕 佣金配置版本快照
|
||||
CommissionConfigVersion int `gorm:"column:commission_config_version;comment:佣金配置版本"`
|
||||
}
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 佣金配置可能随时调整(基础返佣、一次性佣金等)
|
||||
- 订单创建时锁定配置版本,确保历史订单的佣金计算依据可追溯
|
||||
- 使用 ShopSeriesAllocationConfig 表查询特定版本的配置
|
||||
|
||||
**查询示例**:
|
||||
```go
|
||||
// 订单创建时
|
||||
config := allocationConfigStore.GetEffective(allocationID, time.Now())
|
||||
order.CommissionConfigVersion = config.Version
|
||||
|
||||
// 佣金计算时
|
||||
config := allocationConfigStore.GetByVersion(allocationID, order.CommissionConfigVersion)
|
||||
// 使用 config 中的返佣配置计算佣金
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 购买权限验证
|
||||
|
||||
**决策**:多层验证
|
||||
@@ -151,13 +183,14 @@ func ValidatePurchase(card/device, packageID) error {
|
||||
|
||||
### 6. 套餐生效逻辑
|
||||
|
||||
**决策**:创建 PackageUsage 记录
|
||||
**决策**:创建 PackageUsage 记录 + 更新销售统计
|
||||
|
||||
```go
|
||||
func ActivatePackage(order *Order) {
|
||||
for _, item := range order.Items {
|
||||
pkg := GetPackage(item.PackageID)
|
||||
|
||||
// 1. 创建套餐使用记录
|
||||
usage := &PackageUsage{
|
||||
OrderID: order.ID,
|
||||
PackageID: item.PackageID,
|
||||
@@ -170,10 +203,22 @@ func ActivatePackage(order *Order) {
|
||||
Status: 1, // 生效中
|
||||
}
|
||||
CreatePackageUsage(usage)
|
||||
|
||||
// 2. 🆕 更新销售统计(用于一次性佣金的梯度判断)
|
||||
allocationID := GetAllocationIDByPackage(order, item.PackageID)
|
||||
if allocationID > 0 {
|
||||
commissionStatsService.UpdateStats(ctx, allocationID, "all_time", 1, item.Amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**关键说明**:
|
||||
- 套餐生效后,更新 ShopSeriesCommissionStats 表
|
||||
- 统计维度:allocationID(该系列分配的累计销量和销售额)
|
||||
- 统计类型:"all_time" 表示永久累计(不按周期重置)
|
||||
- 一次性佣金的梯度判断依赖此统计数据
|
||||
|
||||
### 7. API 设计
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user