fix(01-01): 统一实名状态常量(CRITICAL-01 核心)

- polling_handler.go: parseRealnameStatus 不再返回硬编码 2,改为 constants.RealNameStatusVerified(=1)
- polling_handler.go: isFirstRealname 判断改用常量比较,不再使用 == 2
- polling_handler.go: HandleProtectConsistencyCheck 注释更正为 real_name_status=1
- iot_card.go: RealNameStatus gorm comment 统一为 0-未实名 1-已实名(去除行业卡说明)
- asset_dto.go: RealNameStatus description 更正为 0未实名 1已实名(去除错误的 1实名中 2已实名)
- scheduler.go: getCardCondition 改用常量替代硬编码 0/1/2 判断
- iot_card/service.go: parseGatewayRealnameStatus 注释更正,返回值改为常量
This commit is contained in:
2026-03-27 22:53:30 +08:00
parent bfcea1c18f
commit 1fd0072f69
5 changed files with 29 additions and 28 deletions

View File

@@ -19,7 +19,7 @@ type AssetResolveResponse struct {
CreatedAt time.Time `json:"created_at" description:"创建时间"`
UpdatedAt time.Time `json:"updated_at" description:"更新时间"`
// 状态聚合字段
RealNameStatus int `json:"real_name_status" description:"实名状态0未实名 1实名中 2已实名"`
RealNameStatus int `json:"real_name_status" description:"实名状态0未实名 1已实名"`
CurrentPackage string `json:"current_package" description:"当前套餐名称(无套餐时为空)"`
PackageTotalMB int64 `json:"package_total_mb" description:"当前套餐总虚流量(MB)已按virtual_ratio换算"`
PackageUsedMB float64 `json:"package_used_mb" description:"当前已用虚流量(MB)已按virtual_ratio换算"`
@@ -77,24 +77,24 @@ type AssetRealtimeStatusResponse struct {
// AssetPackageResponse 资产套餐信息
type AssetPackageResponse struct {
PackageUsageID uint `json:"package_usage_id" description:"套餐使用记录ID"`
PackageID uint `json:"package_id" description:"套餐ID"`
PackageName string `json:"package_name" description:"套餐名称"`
PackageType string `json:"package_type" description:"套餐类型formal/addon"`
UsageType string `json:"usage_type" description:"使用类型single_card/device"`
Status int `json:"status" description:"状态0待生效 1生效中 2已用完 3已过期 4已失效"`
StatusName string `json:"status_name" description:"状态名称"`
DataLimitMB int64 `json:"data_limit_mb" description:"套餐真流量总量(MB)"`
VirtualLimitMB int64 `json:"virtual_limit_mb" description:"套餐虚流量总量(MB)按virtual_ratio换算"`
DataUsageMB int64 `json:"data_usage_mb" description:"已用真流量(MB)"`
VirtualUsedMB float64 `json:"virtual_used_mb" description:"已用虚流量(MB)按virtual_ratio换算"`
VirtualRemainMB float64 `json:"virtual_remain_mb" description:"剩余虚流量(MB)按virtual_ratio换算"`
VirtualRatio float64 `json:"virtual_ratio" description:"虚流量比例(real/virtual)"`
PackageUsageID uint `json:"package_usage_id" description:"套餐使用记录ID"`
PackageID uint `json:"package_id" description:"套餐ID"`
PackageName string `json:"package_name" description:"套餐名称"`
PackageType string `json:"package_type" description:"套餐类型formal/addon"`
UsageType string `json:"usage_type" description:"使用类型single_card/device"`
Status int `json:"status" description:"状态0待生效 1生效中 2已用完 3已过期 4已失效"`
StatusName string `json:"status_name" description:"状态名称"`
DataLimitMB int64 `json:"data_limit_mb" description:"套餐真流量总量(MB)"`
VirtualLimitMB int64 `json:"virtual_limit_mb" description:"套餐虚流量总量(MB)按virtual_ratio换算"`
DataUsageMB int64 `json:"data_usage_mb" description:"已用真流量(MB)"`
VirtualUsedMB float64 `json:"virtual_used_mb" description:"已用虚流量(MB)按virtual_ratio换算"`
VirtualRemainMB float64 `json:"virtual_remain_mb" description:"剩余虚流量(MB)按virtual_ratio换算"`
VirtualRatio float64 `json:"virtual_ratio" description:"虚流量比例(real/virtual)"`
ActivatedAt *time.Time `json:"activated_at,omitempty" description:"激活时间(待生效套餐为空)"`
ExpiresAt *time.Time `json:"expires_at,omitempty" description:"到期时间(待生效套餐为空)"`
MasterUsageID *uint `json:"master_usage_id,omitempty" description:"主套餐ID加油包时有值"`
Priority int `json:"priority" description:"优先级"`
CreatedAt time.Time `json:"created_at" description:"创建时间"`
MasterUsageID *uint `json:"master_usage_id,omitempty" description:"主套餐ID加油包时有值"`
Priority int `json:"priority" description:"优先级"`
CreatedAt time.Time `json:"created_at" description:"创建时间"`
}
// AssetResolveRequest 资产解析请求(路径参数)

View File

@@ -27,7 +27,7 @@ type IotCard struct {
ShopID *uint `gorm:"column:shop_id;index;comment:店铺ID(NULL=平台所有,有值=店铺所有)" json:"shop_id,omitempty"`
ActivatedAt *time.Time `gorm:"column:activated_at;comment:激活时间" json:"activated_at"`
ActivationStatus int `gorm:"column:activation_status;type:int;default:0;not null;comment:激活状态 0-未激活 1-已激活" json:"activation_status"`
RealNameStatus int `gorm:"column:real_name_status;type:int;default:0;not null;comment:实名状态 0-未实名 1-已实名(行业卡可以保持0)" json:"real_name_status"`
RealNameStatus int `gorm:"column:real_name_status;type:int;default:0;not null;comment:实名状态 0-未实名 1-已实名" json:"real_name_status"`
NetworkStatus int `gorm:"column:network_status;type:int;default:0;not null;comment:网络状态 0-停机 1-开机" json:"network_status"`
DataUsageMB int64 `gorm:"column:data_usage_mb;type:bigint;default:0;comment:累计流量使用(MB)" json:"data_usage_mb"`
CurrentMonthUsageMB float64 `gorm:"column:current_month_usage_mb;type:decimal(10,2);default:0;comment:本月已用流量(MB) - Gateway返回的自然月流量总量" json:"current_month_usage_mb"`

View File

@@ -629,10 +629,10 @@ func (s *Scheduler) matchConfigConditions(cfg *model.PollingConfig, card *model.
// getCardCondition 获取卡的状态条件
func (s *Scheduler) getCardCondition(card *model.IotCard) string {
// 根据卡的实名状态和激活状态确定条件
if card.RealNameStatus == 0 || card.RealNameStatus == 1 {
if card.RealNameStatus != constants.RealNameStatusVerified {
return "not_real_name" // 未实名
}
if card.RealNameStatus == 2 {
if card.RealNameStatus == constants.RealNameStatusVerified {
if card.NetworkStatus == 1 {
return "activated" // 已激活
}

View File

@@ -870,12 +870,12 @@ func parseNetworkStatus(cardStatus string) int {
}
// parseGatewayRealnameStatus 将网关返回的实名状态布尔值转换为 real_name_status 数值
// true=已实名(2)false=未实名(0)
// true=已实名(1)false=未实名(0)
func parseGatewayRealnameStatus(realStatus bool) int {
if realStatus {
return 2
return constants.RealNameStatusVerified
}
return 0
return constants.RealNameStatusNotVerified
}
// UpdatePollingStatus 更新卡的轮询状态

View File

@@ -166,8 +166,9 @@ func (h *PollingHandler) HandleRealnameCheck(ctx context.Context, t *asynq.Task)
zap.Int("old_status", card.RealNameStatus),
zap.Int("new_status", newRealnameStatus))
// 任务 21.2-21.4: 检测首次实名0/1 → 2),触发待激活套餐激活
isFirstRealname := (card.RealNameStatus == 0 || card.RealNameStatus == 1) && newRealnameStatus == 2
// 检测首次实名(之前未实名 → 现在已实名),触发待激活套餐激活
isFirstRealname := card.RealNameStatus != constants.RealNameStatusVerified &&
newRealnameStatus == constants.RealNameStatusVerified
if isFirstRealname {
h.triggerFirstRealnameActivation(ctx, uint(cardID))
}
@@ -695,9 +696,9 @@ func (h *PollingHandler) stopCards(ctx context.Context, cards []*model.IotCard,
// Gateway 返回 bool 类型true=已实名, false=未实名
func (h *PollingHandler) parseRealnameStatus(realStatus bool) int {
if realStatus {
return 2 // 已实名
return constants.RealNameStatusVerified // = 1已实名
}
return 0 // 未实名
return constants.RealNameStatusNotVerified // = 0未实名
}
// extractTaskType 从完整的任务类型中提取简短的类型名
@@ -948,7 +949,7 @@ func (h *PollingHandler) getCardWithCache(ctx context.Context, cardID uint) (*mo
}
// HandleProtectConsistencyCheck 保护期一致性检查
// 检查绑定设备is_standalone=false且已实名real_name_status=2)的卡
// 检查绑定设备is_standalone=false且已实名real_name_status=1)的卡
// stop 保护期 + 开机 → 调网关停机start 保护期 + 停机 → 调网关复机
func (h *PollingHandler) HandleProtectConsistencyCheck(ctx context.Context, t *asynq.Task) error {
var payload PollingTaskPayload