diff --git a/internal/model/package.go b/internal/model/package.go index 70455e8..c3693a3 100644 --- a/internal/model/package.go +++ b/internal/model/package.go @@ -29,24 +29,25 @@ func (PackageSeries) TableName() string { // 只适用于 IoT 卡,支持真流量/虚流量共存机制 type Package struct { gorm.Model - BaseModel `gorm:"embedded"` - PackageCode string `gorm:"column:package_code;type:varchar(100);uniqueIndex:idx_package_code,where:deleted_at IS NULL;not null;comment:套餐编码" json:"package_code"` - PackageName string `gorm:"column:package_name;type:varchar(255);not null;comment:套餐名称" json:"package_name"` - SeriesID uint `gorm:"column:series_id;index;comment:套餐系列ID" json:"series_id"` - PackageType string `gorm:"column:package_type;type:varchar(50);not null;comment:套餐类型 formal-正式套餐 addon-附加套餐" json:"package_type"` - DurationMonths int `gorm:"column:duration_months;type:int;not null;comment:套餐时长(月数) 1-月套餐 12-年套餐" json:"duration_months"` - 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"` - 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"` - CalendarType string `gorm:"column:calendar_type;type:varchar(20);default:'by_day';comment:套餐周期类型 natural_month-自然月 by_day-按天" json:"calendar_type"` - DurationDays int `gorm:"column:duration_days;type:int;comment:套餐天数(calendar_type=by_day时必填)" json:"duration_days"` - DataResetCycle string `gorm:"column:data_reset_cycle;type:varchar(20);default:'monthly';comment:流量重置周期 daily-每日 monthly-每月 yearly-每年 none-不重置" json:"data_reset_cycle"` - EnableRealnameActivation bool `gorm:"column:enable_realname_activation;type:boolean;default:true;comment:是否启用实名激活 true-需实名后激活 false-立即激活" json:"enable_realname_activation"` - VirtualRatio float64 `gorm:"column:virtual_ratio;type:decimal(18,6);default:1.0;comment:虚流量比例(real_data_mb/virtual_data_mb),创建套餐时计算存储" json:"virtual_ratio"` + BaseModel `gorm:"embedded"` + PackageCode string `gorm:"column:package_code;type:varchar(100);uniqueIndex:idx_package_code,where:deleted_at IS NULL;not null;comment:套餐编码" json:"package_code"` + PackageName string `gorm:"column:package_name;type:varchar(255);not null;comment:套餐名称" json:"package_name"` + SeriesID uint `gorm:"column:series_id;index;comment:套餐系列ID" json:"series_id"` + PackageType string `gorm:"column:package_type;type:varchar(50);not null;comment:套餐类型 formal-正式套餐 addon-附加套餐" json:"package_type"` + DurationMonths int `gorm:"column:duration_months;type:int;not null;comment:套餐时长(月数) 1-月套餐 12-年套餐" json:"duration_months"` + 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"` + 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"` + CalendarType string `gorm:"column:calendar_type;type:varchar(20);default:'by_day';comment:套餐周期类型 natural_month-自然月 by_day-按天" json:"calendar_type"` + DurationDays int `gorm:"column:duration_days;type:int;comment:套餐天数(calendar_type=by_day时必填)" json:"duration_days"` + DataResetCycle string `gorm:"column:data_reset_cycle;type:varchar(20);default:'monthly';comment:流量重置周期 daily-每日 monthly-每月 yearly-每年 none-不重置" json:"data_reset_cycle"` + // ExpiryBase 到期时间基准:from_activation-实名激活时起算,from_purchase-购买时起算 + ExpiryBase string `gorm:"column:expiry_base;type:varchar(30);not null;default:'from_activation';comment:到期时间基准 from_activation-实名激活时起算 from_purchase-购买时起算" json:"expiry_base"` + VirtualRatio float64 `gorm:"column:virtual_ratio;type:decimal(18,6);default:1.0;comment:虚流量比例(real_data_mb/virtual_data_mb),创建套餐时计算存储" json:"virtual_ratio"` } // TableName 指定表名 diff --git a/internal/store/postgres/package_store.go b/internal/store/postgres/package_store.go index f35ba83..15291ba 100644 --- a/internal/store/postgres/package_store.go +++ b/internal/store/postgres/package_store.go @@ -20,12 +20,7 @@ func NewPackageStore(db *gorm.DB) *PackageStore { } func (s *PackageStore) Create(ctx context.Context, pkg *model.Package) error { - // GORM 对零值字段有特殊处理,先创建然后立即更新 enable_realname_activation 字段确保正确设置 - if err := s.db.WithContext(ctx).Omit("enable_realname_activation").Create(pkg).Error; err != nil { - return err - } - // 明确更新 enable_realname_activation 字段(包括零值 false) - return s.db.WithContext(ctx).Model(pkg).Update("enable_realname_activation", pkg.EnableRealnameActivation).Error + return s.db.WithContext(ctx).Create(pkg).Error } func (s *PackageStore) GetByID(ctx context.Context, id uint) (*model.Package, error) { diff --git a/migrations/000089_realname_expiry_base.down.sql b/migrations/000089_realname_expiry_base.down.sql new file mode 100644 index 0000000..2f6a10e --- /dev/null +++ b/migrations/000089_realname_expiry_base.down.sql @@ -0,0 +1,7 @@ +-- 回滚:恢复旧字段,移除新字段 +ALTER TABLE tb_package DROP COLUMN IF EXISTS expiry_base; + +ALTER TABLE tb_package + ADD COLUMN IF NOT EXISTS enable_realname_activation BOOLEAN NOT NULL DEFAULT TRUE; + +COMMENT ON COLUMN tb_package.enable_realname_activation IS '是否启用实名激活 true-需实名后激活 false-立即激活'; diff --git a/migrations/000089_realname_expiry_base.up.sql b/migrations/000089_realname_expiry_base.up.sql new file mode 100644 index 0000000..d77feb1 --- /dev/null +++ b/migrations/000089_realname_expiry_base.up.sql @@ -0,0 +1,13 @@ +-- REALNAME-01: 实名激活架构重构 +-- 移除旧的布尔字段 enable_realname_activation, +-- 新增 expiry_base 枚举字段控制套餐计时起点 +-- 注意:不做旧字段到新字段的数据迁移,现有记录全部默认 from_activation + +-- 移除旧字段 +ALTER TABLE tb_package DROP COLUMN IF EXISTS enable_realname_activation; + +-- 新增到期时间基准字段 +ALTER TABLE tb_package + ADD COLUMN IF NOT EXISTS expiry_base VARCHAR(30) NOT NULL DEFAULT 'from_activation'; + +COMMENT ON COLUMN tb_package.expiry_base IS '到期时间基准 from_activation-实名激活时起算 from_purchase-购买时起算';