Compare commits
6 Commits
e945a672ed
...
246ae5e123
| Author | SHA1 | Date | |
|---|---|---|---|
| 246ae5e123 | |||
| 7e613a0d2b | |||
| 510a5bfb21 | |||
| decb7a10ec | |||
| 5588c7c762 | |||
| eebc7194d8 |
@@ -20,7 +20,7 @@ type MyPackageResponse struct {
|
||||
SuggestedRetailPrice int64 `json:"suggested_retail_price" description:"建议售价(分)"`
|
||||
ProfitMargin int64 `json:"profit_margin" description:"利润空间(分)= 建议售价 - 成本价"`
|
||||
PriceSource string `json:"price_source" description:"价格来源 (series_pricing:系列加价, package_override:单套餐覆盖)"`
|
||||
Status int `json:"status" description:"套餐状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" description:"套餐状态 (0:禁用, 1:启用)"`
|
||||
ShelfStatus int `json:"shelf_status" description:"上架状态 (1:上架, 2:下架)"`
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ type MyPackageDetailResponse struct {
|
||||
SuggestedRetailPrice int64 `json:"suggested_retail_price" description:"建议售价(分)"`
|
||||
ProfitMargin int64 `json:"profit_margin" description:"利润空间(分)"`
|
||||
PriceSource string `json:"price_source" description:"价格来源 (series_pricing:系列加价, package_override:单套餐覆盖)"`
|
||||
Status int `json:"status" description:"套餐状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" description:"套餐状态 (0:禁用, 1:启用)"`
|
||||
ShelfStatus int `json:"shelf_status" description:"上架状态 (1:上架, 2:下架)"`
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ type MySeriesAllocationResponse struct {
|
||||
BaseCommissionValue int64 `json:"base_commission_value" description:"基础佣金值"`
|
||||
AvailablePackageCount int `json:"available_package_count" description:"可售套餐数量"`
|
||||
AllocatorShopName string `json:"allocator_shop_name" description:"分配者店铺名称"`
|
||||
Status int `json:"status" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" description:"状态 (0:禁用, 1:启用)"`
|
||||
}
|
||||
|
||||
// MySeriesAllocationPageResult 我的套餐系列分配分页结果
|
||||
|
||||
@@ -41,14 +41,14 @@ type PackageListRequest struct {
|
||||
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"`
|
||||
PackageName *string `json:"package_name" query:"package_name" validate:"omitempty,max=255" maxLength:"255" description:"套餐名称(模糊搜索)"`
|
||||
SeriesID *uint `json:"series_id" query:"series_id" validate:"omitempty" description:"套餐系列ID"`
|
||||
Status *int `json:"status" query:"status" validate:"omitempty,oneof=1 2" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1" description:"状态 (0:禁用, 1:启用)"`
|
||||
ShelfStatus *int `json:"shelf_status" query:"shelf_status" validate:"omitempty,oneof=1 2" description:"上架状态 (1:上架, 2:下架)"`
|
||||
PackageType *string `json:"package_type" query:"package_type" validate:"omitempty,oneof=formal addon" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"`
|
||||
}
|
||||
|
||||
// UpdatePackageStatusRequest 更新套餐状态请求
|
||||
type UpdatePackageStatusRequest struct {
|
||||
Status int `json:"status" validate:"required,oneof=1 2" required:"true" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" validate:"required,oneof=0 1" required:"true" description:"状态 (0:禁用, 1:启用)"`
|
||||
}
|
||||
|
||||
// UpdatePackageShelfStatusRequest 更新套餐上架状态请求
|
||||
@@ -84,7 +84,7 @@ type PackageResponse struct {
|
||||
SuggestedRetailPrice int64 `json:"suggested_retail_price" description:"建议售价(分)"`
|
||||
CostPrice int64 `json:"cost_price" description:"成本价(分)"`
|
||||
OneTimeCommissionAmount *int64 `json:"one_time_commission_amount,omitempty" description:"一次性佣金金额(分,代理视角)"`
|
||||
Status int `json:"status" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" description:"状态 (0:禁用, 1:启用)"`
|
||||
ShelfStatus int `json:"shelf_status" description:"上架状态 (1:上架, 2:下架)"`
|
||||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||||
UpdatedAt string `json:"updated_at" description:"更新时间"`
|
||||
|
||||
@@ -46,13 +46,13 @@ type PackageSeriesListRequest struct {
|
||||
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"`
|
||||
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"`
|
||||
SeriesName *string `json:"series_name" query:"series_name" validate:"omitempty,max=255" maxLength:"255" description:"系列名称(模糊搜索)"`
|
||||
Status *int `json:"status" query:"status" validate:"omitempty,oneof=1 2" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1" description:"状态 (0:禁用, 1:启用)"`
|
||||
EnableOneTimeCommission *bool `json:"enable_one_time_commission" query:"enable_one_time_commission" description:"是否启用一次性佣金"`
|
||||
}
|
||||
|
||||
// UpdatePackageSeriesStatusRequest 更新套餐系列状态请求
|
||||
type UpdatePackageSeriesStatusRequest struct {
|
||||
Status int `json:"status" validate:"required,oneof=1 2" required:"true" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" validate:"required,oneof=0 1" required:"true" description:"状态 (0:禁用, 1:启用)"`
|
||||
}
|
||||
|
||||
// PackageSeriesResponse 套餐系列响应
|
||||
@@ -63,7 +63,7 @@ type PackageSeriesResponse struct {
|
||||
Description string `json:"description" description:"描述"`
|
||||
EnableOneTimeCommission bool `json:"enable_one_time_commission" description:"是否启用一次性佣金"`
|
||||
OneTimeCommissionConfig *SeriesOneTimeCommissionConfigDTO `json:"one_time_commission_config,omitempty" description:"一次性佣金规则配置"`
|
||||
Status int `json:"status" description:"状态 (1:启用, 2:禁用)"`
|
||||
Status int `json:"status" description:"状态 (0:禁用, 1:启用)"`
|
||||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||||
UpdatedAt string `json:"updated_at" description:"更新时间"`
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ type ShopSeriesGrantPackageItem struct {
|
||||
PackageCode string `json:"package_code" description:"套餐编码"`
|
||||
CostPrice int64 `json:"cost_price" description:"成本价(分)"`
|
||||
ShelfStatus int `json:"shelf_status" description:"上架状态 1-上架 2-下架"`
|
||||
Status int `json:"status" description:"分配状态 1-启用 2-禁用"`
|
||||
Status int `json:"status" description:"分配状态 0=禁用 1=启用"`
|
||||
}
|
||||
|
||||
// GrantCommissionTierItem 梯度佣金档位(operator/dimension/stat_scope 仅出现在响应中,来自 PackageSeries 全局配置)
|
||||
@@ -42,7 +42,7 @@ type ShopSeriesGrantResponse struct {
|
||||
ForceRechargeAmount int64 `json:"force_recharge_amount" description:"强充金额(分)"`
|
||||
AllocatorShopID uint `json:"allocator_shop_id" description:"分配者店铺ID,0 表示平台"`
|
||||
AllocatorShopName string `json:"allocator_shop_name" description:"分配者店铺名称"`
|
||||
Status int `json:"status" description:"状态 1-启用 2-禁用"`
|
||||
Status int `json:"status" description:"状态 0=禁用 1=启用"`
|
||||
Packages []ShopSeriesGrantPackageItem `json:"packages" description:"已授权套餐列表"`
|
||||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||||
UpdatedAt string `json:"updated_at" description:"更新时间"`
|
||||
@@ -79,7 +79,7 @@ type ShopSeriesGrantListRequest struct {
|
||||
ShopID *uint `json:"shop_id" query:"shop_id" validate:"omitempty" description:"过滤被授权店铺ID"`
|
||||
SeriesID *uint `json:"series_id" query:"series_id" validate:"omitempty" description:"过滤套餐系列ID"`
|
||||
AllocatorShopID *uint `json:"allocator_shop_id" query:"allocator_shop_id" validate:"omitempty" description:"过滤分配者店铺ID"`
|
||||
Status *int `json:"status" query:"status" validate:"omitempty" description:"过滤状态 1-启用 2-禁用"`
|
||||
Status *int `json:"status" query:"status" validate:"omitempty" description:"过滤状态 0=禁用 1=启用"`
|
||||
}
|
||||
|
||||
// ShopSeriesGrantListItem 系列授权列表项
|
||||
@@ -97,7 +97,7 @@ type ShopSeriesGrantListItem struct {
|
||||
AllocatorShopID uint `json:"allocator_shop_id" description:"分配者店铺ID"`
|
||||
AllocatorShopName string `json:"allocator_shop_name" description:"分配者店铺名称"`
|
||||
PackageCount int `json:"package_count" description:"已授权套餐数量"`
|
||||
Status int `json:"status" description:"状态 1-启用 2-禁用"`
|
||||
Status int `json:"status" description:"状态 0=禁用 1=启用"`
|
||||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ type PaymentMerchantSetting struct {
|
||||
BankBranch string `gorm:"column:bank_branch;type:varchar(255);comment:开户行(仅银行卡)" json:"bank_branch"`
|
||||
IsVerified bool `gorm:"column:is_verified;type:boolean;default:false;comment:是否已验证" json:"is_verified"`
|
||||
IsDefault bool `gorm:"column:is_default;type:boolean;default:false;comment:是否默认账户" json:"is_default"`
|
||||
Status int `gorm:"column:status;type:int;default:1;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
Status int `gorm:"column:status;type:int;default:1;comment:状态 0=禁用 1=启用" json:"status"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
|
||||
@@ -38,7 +38,7 @@ type Package struct {
|
||||
RealDataMB int64 `gorm:"column:real_data_mb;type:bigint;default:0;comment:真流量额度(MB)" json:"real_data_mb"`
|
||||
VirtualDataMB int64 `gorm:"column:virtual_data_mb;type:bigint;default:0;comment:虚流量额度(MB,用于停机判断)" json:"virtual_data_mb"`
|
||||
EnableVirtualData bool `gorm:"column:enable_virtual_data;type:boolean;default:false;not null;comment:是否启用虚流量" json:"enable_virtual_data"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 0=禁用 1=启用" json:"status"`
|
||||
CostPrice int64 `gorm:"column:cost_price;type:bigint;default:0;comment:成本价(分为单位)" json:"cost_price"`
|
||||
SuggestedRetailPrice int64 `gorm:"column:suggested_retail_price;type:bigint;default:0;comment:建议售价(分为单位)" json:"suggested_retail_price"`
|
||||
ShelfStatus int `gorm:"column:shelf_status;type:int;default:2;not null;comment:上架状态 1-上架 2-下架" json:"shelf_status"`
|
||||
|
||||
@@ -12,7 +12,7 @@ type ShopPackageAllocation struct {
|
||||
AllocatorShopID uint `gorm:"column:allocator_shop_id;index;not null;default:0;comment:分配者店铺ID,0表示平台分配" json:"allocator_shop_id"`
|
||||
CostPrice int64 `gorm:"column:cost_price;type:bigint;not null;comment:该代理的成本价(分)" json:"cost_price"`
|
||||
SeriesAllocationID *uint `gorm:"column:series_allocation_id;index;comment:关联的系列分配ID" json:"series_allocation_id"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 0=禁用 1=启用" json:"status"`
|
||||
ShelfStatus int `gorm:"column:shelf_status;type:int;default:1;not null;comment:上架状态 1-上架 2-下架" json:"shelf_status"`
|
||||
RetailPrice int64 `gorm:"column:retail_price;type:bigint;not null;default:0;comment:代理面向终端客户的零售价(分)" json:"retail_price"`
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ import (
|
||||
type ShopSeriesAllocation struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
ShopID uint `gorm:"column:shop_id;index;not null;comment:被分配的店铺ID" json:"shop_id"`
|
||||
SeriesID uint `gorm:"column:series_id;index;not null;comment:套餐系列ID" json:"series_id"`
|
||||
AllocatorShopID uint `gorm:"column:allocator_shop_id;index;not null;default:0;comment:分配者店铺ID,0表示平台分配" json:"allocator_shop_id"`
|
||||
OneTimeCommissionAmount int64 `gorm:"column:one_time_commission_amount;type:bigint;default:0;not null;comment:该代理能拿的一次性佣金金额上限(分),固定模式有效" json:"one_time_commission_amount"`
|
||||
CommissionTiersJSON string `gorm:"column:commission_tiers_json;type:jsonb;default:'[]';not null;comment:梯度模式专属阶梯金额列表" json:"commission_tiers_json"`
|
||||
EnableForceRecharge bool `gorm:"column:enable_force_recharge;default:false;not null;comment:是否启用强制充值" json:"enable_force_recharge"`
|
||||
ForceRechargeAmount int64 `gorm:"column:force_recharge_amount;type:bigint;default:0;not null;comment:强制充值金额(分)" json:"force_recharge_amount"`
|
||||
ForceRechargeTriggerType int `gorm:"column:force_recharge_trigger_type;type:int;default:2;not null;comment:强充触发类型 1-单次充值 2-累计充值" json:"force_recharge_trigger_type"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
ShopID uint `gorm:"column:shop_id;index;not null;comment:被分配的店铺ID" json:"shop_id"`
|
||||
SeriesID uint `gorm:"column:series_id;index;not null;comment:套餐系列ID" json:"series_id"`
|
||||
AllocatorShopID uint `gorm:"column:allocator_shop_id;index;not null;default:0;comment:分配者店铺ID,0表示平台分配" json:"allocator_shop_id"`
|
||||
OneTimeCommissionAmount int64 `gorm:"column:one_time_commission_amount;type:bigint;default:0;not null;comment:该代理能拿的一次性佣金金额上限(分),固定模式有效" json:"one_time_commission_amount"`
|
||||
CommissionTiersJSON string `gorm:"column:commission_tiers_json;type:jsonb;default:'[]';not null;comment:梯度模式专属阶梯金额列表" json:"commission_tiers_json"`
|
||||
EnableForceRecharge bool `gorm:"column:enable_force_recharge;default:false;not null;comment:是否启用强制充值" json:"enable_force_recharge"`
|
||||
ForceRechargeAmount int64 `gorm:"column:force_recharge_amount;type:bigint;default:0;not null;comment:强制充值金额(分)" json:"force_recharge_amount"`
|
||||
ForceRechargeTriggerType int `gorm:"column:force_recharge_trigger_type;type:int;default:2;not null;comment:强充触发类型 1-单次充值 2-累计充值" json:"force_recharge_trigger_type"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 0=禁用 1=启用" json:"status"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
|
||||
@@ -17,7 +17,7 @@ type DevCapabilityConfig struct {
|
||||
AppSecret string `gorm:"column:app_secret;type:varchar(255);comment:应用密钥" json:"app_secret"`
|
||||
CallbackURL string `gorm:"column:callback_url;type:varchar(500);comment:回调地址" json:"callback_url"`
|
||||
IPWhitelist string `gorm:"column:ip_whitelist;type:text;comment:IP白名单(多个IP用逗号分隔)" json:"ip_whitelist"`
|
||||
Status int `gorm:"column:status;type:int;default:1;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
Status int `gorm:"column:status;type:int;default:1;comment:状态 0=禁用 1=启用" json:"status"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
|
||||
@@ -340,7 +340,7 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateShopSeriesGrantRequ
|
||||
RetailPrice: pkg.SuggestedRetailPrice,
|
||||
SeriesAllocationID: &allocation.ID,
|
||||
Status: constants.StatusEnabled,
|
||||
ShelfStatus: constants.StatusEnabled,
|
||||
ShelfStatus: constants.ShelfStatusOn,
|
||||
}
|
||||
pkgAlloc.Creator = operatorID
|
||||
pkgAlloc.Updater = operatorID
|
||||
@@ -674,7 +674,7 @@ func (s *Service) ManagePackages(ctx context.Context, id uint, req *dto.ManageGr
|
||||
RetailPrice: pkg.SuggestedRetailPrice,
|
||||
SeriesAllocationID: &allocation.ID,
|
||||
Status: constants.StatusEnabled,
|
||||
ShelfStatus: constants.StatusEnabled,
|
||||
ShelfStatus: constants.ShelfStatusOn,
|
||||
}
|
||||
pkgAlloc.Creator = operatorID
|
||||
pkgAlloc.Updater = operatorID
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-04-11
|
||||
@@ -0,0 +1,62 @@
|
||||
## Context
|
||||
|
||||
项目全局约定 `0=禁用, 1=启用`,定义在 `pkg/constants/constants.go`:
|
||||
|
||||
```go
|
||||
StatusDisabled = 0 // 禁用
|
||||
StatusEnabled = 1 // 启用
|
||||
```
|
||||
|
||||
但有 6 个 model 的 GORM comment 标签写的是 `1-启用 2-禁用`,与约定相反。
|
||||
经过排查,service 层代码已经使用正确的 `constants.StatusDisabled = 0`,**数据库里也不存在 status=2 的行**,因此本次变更属于纯文档/注释层面修正,无需数据迁移。
|
||||
|
||||
受影响的模块和当前状态:
|
||||
|
||||
| 文件 | 结构体 | 表名 | DB 行数 | status 现有值 |
|
||||
|------|--------|------|---------|--------------|
|
||||
| model/package.go | PackageSeries | tb_package_series | 7 | 全=1 |
|
||||
| model/package.go | Package | tb_package | 9 | 全=1 |
|
||||
| model/shop_package_allocation.go | ShopPackageAllocation | tb_shop_package_allocation | 6 | 全=1 |
|
||||
| model/shop_series_allocation.go | ShopSeriesAllocation | tb_shop_series_allocation | 6 | 全=1 |
|
||||
| model/system.go | DevCapabilityConfig | tb_dev_capability_config | 0 | — |
|
||||
| model/financial.go | PaymentMerchantSetting | tb_payment_merchant_setting | 0 | — |
|
||||
|
||||
另外,`pkg/constants/iot.go` 中有专为 DevCapabilityConfig 设计的僵尸常量:
|
||||
```go
|
||||
DevCapabilityStatusEnabled = 1 // 未被 service 调用
|
||||
DevCapabilityStatusDisabled = 2 // 未被 service 调用
|
||||
```
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 让 model GORM comment 与全局约定保持一致(`0=禁用 1=启用`)
|
||||
- 删除未使用的 `DevCapabilityStatusEnabled/Disabled` 常量
|
||||
- 修正 DTO description 中对 status 的错误枚举说明
|
||||
- 修正一处语义混用:`ShelfStatus: constants.StatusEnabled` → `constants.ShelfStatusOn`
|
||||
- 通过编译检查,确认没有代码依赖被删除的常量
|
||||
|
||||
**Non-Goals:**
|
||||
- 不涉及任何数据库迁移
|
||||
- 不变更 API 接口行为或响应结构
|
||||
- 不修改 `ShelfStatus 1=上架 2=下架` 约定(这是业务刻意区分的双维度设计,与启用/禁用独立)
|
||||
- 不重构 service 层逻辑(已经正确)
|
||||
|
||||
## Decisions
|
||||
|
||||
### 决策1:只改注释,不加数据库迁移
|
||||
|
||||
**理由**:service 代码已经用 `StatusDisabled=0`,DB 里没有 status=2 的行。如果加迁移反而制造风险(空操作 UPDATE 会锁表、影响上线流程)。
|
||||
|
||||
### 决策2:删除 DevCapabilityStatusEnabled/Disabled,不替换
|
||||
|
||||
**理由**:这两个常量未被任何 service 调用(仅在 openspec 历史归档文档中出现)。删除即可,未来如果 DevCapabilityConfig 的 service 有状态判断,直接用全局 `StatusEnabled/StatusDisabled` 即可。
|
||||
|
||||
### 决策3:DTO description 同步修正
|
||||
|
||||
DTO description 是 OpenAPI 文档的来源,如果注释说 `1:启用, 2:禁用`,生成的 API 文档就会误导前端开发者。必须一并修正。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[低风险] 前端如果对 status=2 有判断逻辑** → 但实际 API 从来没有返回过 status=2(service 代码从未写入2),此风险理论上不存在。如有疑虑,可先搜索前端代码。
|
||||
- **[极低风险] 将来添加 DevCapabilityConfig service 时忘记用全局常量** → 已在 AGENTS.md 中有规范约束(0=禁用 1=启用),删除僵尸常量反而消除了歧义。
|
||||
@@ -0,0 +1,34 @@
|
||||
## Why
|
||||
|
||||
model 层 6 个结构体的 `status` 字段注释写的是 `1-启用 2-禁用`,与项目全局约定 `0=禁用, 1=启用` 相反。虽然 service 层代码已经在用正确的 `constants.StatusDisabled = 0`,但错误注释会误导开发者,同时 DTO description 和一个僵尸常量也需要同步修正。
|
||||
|
||||
## What Changes
|
||||
|
||||
- **修正 6 个 model 注释**:将 `comment: "状态 1-启用 2-禁用"` 改为 `comment: "状态 0=禁用 1=启用"`
|
||||
- `internal/model/package.go`(PackageSeries.Status, Package.Status)
|
||||
- `internal/model/shop_package_allocation.go`(ShopPackageAllocation.Status)
|
||||
- `internal/model/shop_series_allocation.go`(ShopSeriesAllocation.Status)
|
||||
- `internal/model/system.go`(DevCapabilityConfig.Status)
|
||||
- `internal/model/financial.go`(PaymentMerchantSetting.Status)
|
||||
- **删除僵尸常量**:`pkg/constants/iot.go` 中的 `DevCapabilityStatusEnabled = 1` / `DevCapabilityStatusDisabled = 2` 从未被 service 层调用,直接删除
|
||||
- **修正 DTO description**:`internal/model/dto/` 中描述为 `(1:启用, 2:禁用)` 的字段改为 `(0:禁用, 1:启用)`(涉及 `package_series_dto.go`、`shop_series_grant_dto.go`、`my_package.go` 等)
|
||||
- **修正语义混用**:`shop_series_grant/service.go` 中 `ShelfStatus: constants.StatusEnabled` 改为 `constants.ShelfStatusOn`(值相同,但语义正确)
|
||||
|
||||
**无任何数据库迁移**:所有有数据的表中 status 均为 1,没有 status=2 的行;service 代码已在用 `0=禁用` 约定。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
无新能力引入。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
无 spec 级别的行为变更,仅修正文档注释与代码的一致性。
|
||||
|
||||
## Impact
|
||||
|
||||
- **受影响文件**:`internal/model/`(6 个 model)、`internal/model/dto/`(若干 DTO)、`pkg/constants/iot.go`、`internal/service/shop_series_grant/service.go`
|
||||
- **API 行为**:不变。status 字段的实际读写逻辑不变,仅注释和常量修正
|
||||
- **数据库**:不变。无需迁移
|
||||
- **前端/接口消费方**:接口返回的 status 值本就是 0/1(由 service 代码决定),与注释写什么无关,不受影响
|
||||
@@ -0,0 +1,29 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: model status 字段注释与全局约定一致
|
||||
所有 model 结构体的启用/禁用类 `status` 字段,其 GORM comment 标签 SHALL 使用 `0=禁用 1=启用` 格式,与 `pkg/constants/constants.go` 中 `StatusDisabled=0, StatusEnabled=1` 保持一致。
|
||||
|
||||
#### Scenario: 查看 model GORM comment
|
||||
- **WHEN** 开发者查看任意 model 结构体的 status 字段标签
|
||||
- **THEN** comment 中启用/禁用的数值与全局常量 StatusEnabled=1、StatusDisabled=0 一致
|
||||
|
||||
### Requirement: DTO description 与全局约定一致
|
||||
DTO 中描述启用/禁用状态的 `description` 标签 SHALL 使用 `(0:禁用, 1:启用)` 格式,不得写为 `(1:启用, 2:禁用)`。
|
||||
|
||||
#### Scenario: 查看 DTO description
|
||||
- **WHEN** 开发者或文档生成器读取 DTO 的 status 字段 description
|
||||
- **THEN** 枚举值与全局约定 0=禁用、1=启用 一致
|
||||
|
||||
### Requirement: 无未使用的状态常量
|
||||
`pkg/constants/` 中不 SHALL 存在与全局约定冲突的、且未被代码引用的状态常量。
|
||||
|
||||
#### Scenario: 删除僵尸常量后编译通过
|
||||
- **WHEN** 删除 `DevCapabilityStatusEnabled` 和 `DevCapabilityStatusDisabled` 后执行 `go build ./...`
|
||||
- **THEN** 编译无报错,证明这两个常量从未被引用
|
||||
|
||||
### Requirement: ShelfStatus 使用专用常量
|
||||
赋值 `ShelfStatus` 字段时 SHALL 使用 `constants.ShelfStatusOn` 或 `constants.ShelfStatusOff`,不得使用语义不相关的 `constants.StatusEnabled`。
|
||||
|
||||
#### Scenario: 初始化分配记录的 ShelfStatus
|
||||
- **WHEN** service 创建新的 ShopSeriesAllocation 或 ShopPackageAllocation 记录
|
||||
- **THEN** ShelfStatus 字段赋值使用 `constants.ShelfStatusOn`(值=1),而非 `constants.StatusEnabled`
|
||||
@@ -0,0 +1,41 @@
|
||||
## 1. 修正 model GORM comment 注释
|
||||
|
||||
- [x] 1.1 修改 `internal/model/package.go`:PackageSeries.Status 和 Package.Status 的 comment 从 `1-启用 2-禁用` 改为 `0=禁用 1=启用`
|
||||
- [x] 1.2 修改 `internal/model/shop_package_allocation.go`:ShopPackageAllocation.Status 的 comment 从 `1-启用 2-禁用` 改为 `0=禁用 1=启用`
|
||||
- [x] 1.3 修改 `internal/model/shop_series_allocation.go`:ShopSeriesAllocation.Status 的 comment 从 `1-启用 2-禁用` 改为 `0=禁用 1=启用`
|
||||
- [x] 1.4 修改 `internal/model/system.go`:DevCapabilityConfig.Status 的 comment 从 `1-启用 2-禁用` 改为 `0=禁用 1=启用`
|
||||
- [x] 1.5 修改 `internal/model/financial.go`:PaymentMerchantSetting.Status 的 comment 从 `1-启用 2-禁用` 改为 `0=禁用 1=启用`
|
||||
- [x] 1.6 验证:`go vet ./internal/model/...` 无报错
|
||||
|
||||
## 2. 删除僵尸常量
|
||||
|
||||
- [x] 2.1 删除 `pkg/constants/iot.go` 中的 `DevCapabilityStatusEnabled = 1` 和 `DevCapabilityStatusDisabled = 2` 两行
|
||||
- [x] 2.2 验证:`go build ./...` 编译通过,证明无代码依赖这两个常量
|
||||
|
||||
## 3. 修正 DTO validate 标签和 description(关键:修复 API 层约定冲突)
|
||||
|
||||
> 当前 DTO 有 `validate:"oneof=1 2"` 但 service 层用 `StatusDisabled=0`,二者不兼容。
|
||||
> 修复方向:将 DTO 对齐到全局约定 `oneof=0 1`。
|
||||
|
||||
- [x] 3.1 修改 `internal/model/dto/package_dto.go`:
|
||||
- `UpdatePackageStatusRequest.Status` 的 validate 从 `oneof=1 2` 改为 `oneof=0 1`,description 从 `(1:启用, 2:禁用)` 改为 `(0:禁用, 1:启用)`
|
||||
- `PackageListRequest.Status` 的 description 同步修正
|
||||
- `PackageResponse.Status` 的 description 同步修正
|
||||
- [x] 3.2 修改 `internal/model/dto/package_series_dto.go`:
|
||||
- `UpdatePackageSeriesStatusRequest.Status` 的 validate 从 `oneof=1 2` 改为 `oneof=0 1`,description 修正
|
||||
- `PackageSeriesListRequest.Status` 的 description 修正
|
||||
- `PackageSeriesResponse.Status` 的 description 修正
|
||||
- [x] 3.3 修改 `internal/model/dto/shop_series_grant_dto.go`:status 相关字段 description 全部修正为 `0=禁用 1=启用`
|
||||
- [x] 3.4 修改 `internal/model/dto/my_package.go`:status 相关字段 description 全部修正
|
||||
- [x] 3.5 验证:`go vet ./internal/model/dto/...` 无报错
|
||||
|
||||
## 4. 修正 service 层语义混用
|
||||
|
||||
- [x] 4.1 修改 `internal/service/shop_series_grant/service.go`:将所有 `ShelfStatus: constants.StatusEnabled` 改为 `ShelfStatus: constants.ShelfStatusOn`(两处,行约 342、676)
|
||||
- [x] 4.2 验证:`go vet ./internal/service/shop_series_grant/...` 无报错
|
||||
|
||||
## 5. 最终验证
|
||||
|
||||
- [x] 5.1 执行 `go build ./...` 确认全项目编译通过
|
||||
- [x] 5.2 执行 `go vet ./...` 无报错
|
||||
- [x] 5.3 执行 `go test ./internal/service/package/... ./internal/service/package_series/... ./internal/service/shop_series_grant/...` 确认测试通过
|
||||
29
openspec/specs/status-convention/spec.md
Normal file
29
openspec/specs/status-convention/spec.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: model status 字段注释与全局约定一致
|
||||
所有 model 结构体的启用/禁用类 `status` 字段,其 GORM comment 标签 SHALL 使用 `0=禁用 1=启用` 格式,与 `pkg/constants/constants.go` 中 `StatusDisabled=0, StatusEnabled=1` 保持一致。
|
||||
|
||||
#### Scenario: 查看 model GORM comment
|
||||
- **WHEN** 开发者查看任意 model 结构体的 status 字段标签
|
||||
- **THEN** comment 中启用/禁用的数值与全局常量 StatusEnabled=1、StatusDisabled=0 一致
|
||||
|
||||
### Requirement: DTO description 与全局约定一致
|
||||
DTO 中描述启用/禁用状态的 `description` 标签 SHALL 使用 `(0:禁用, 1:启用)` 格式,不得写为 `(1:启用, 2:禁用)`。
|
||||
|
||||
#### Scenario: 查看 DTO description
|
||||
- **WHEN** 开发者或文档生成器读取 DTO 的 status 字段 description
|
||||
- **THEN** 枚举值与全局约定 0=禁用、1=启用 一致
|
||||
|
||||
### Requirement: 无未使用的状态常量
|
||||
`pkg/constants/` 中不 SHALL 存在与全局约定冲突的、且未被代码引用的状态常量。
|
||||
|
||||
#### Scenario: 删除僵尸常量后编译通过
|
||||
- **WHEN** 删除 `DevCapabilityStatusEnabled` 和 `DevCapabilityStatusDisabled` 后执行 `go build ./...`
|
||||
- **THEN** 编译无报错,证明这两个常量从未被引用
|
||||
|
||||
### Requirement: ShelfStatus 使用专用常量
|
||||
赋值 `ShelfStatus` 字段时 SHALL 使用 `constants.ShelfStatusOn` 或 `constants.ShelfStatusOff`,不得使用语义不相关的 `constants.StatusEnabled`。
|
||||
|
||||
#### Scenario: 初始化分配记录的 ShelfStatus
|
||||
- **WHEN** service 创建新的 ShopSeriesAllocation 或 ShopPackageAllocation 记录
|
||||
- **THEN** ShelfStatus 字段赋值使用 `constants.ShelfStatusOn`(值=1),而非 `constants.StatusEnabled`
|
||||
@@ -250,12 +250,6 @@ const (
|
||||
ReplacementStatusCompleted = 4 // 已完成
|
||||
)
|
||||
|
||||
// 开发能力配置状态
|
||||
const (
|
||||
DevCapabilityStatusEnabled = 1 // 启用
|
||||
DevCapabilityStatusDisabled = 2 // 禁用
|
||||
)
|
||||
|
||||
// ========================================
|
||||
// 运营商编码
|
||||
// ========================================
|
||||
|
||||
Reference in New Issue
Block a user