mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 05:20:18 +00:00
feat(subscription): validate price amount and migrate database column type
- Add validation to ensure subscription plan price amount is non-negative and does not exceed 9999. - Migrate the price_amount column from float/double to decimal(10,6) in the database for improved precision. - Update SubscriptionPlan model to reflect the new decimal type for price_amount.
This commit is contained in:
@@ -118,6 +118,14 @@ func AdminCreateSubscriptionPlan(c *gin.Context) {
|
||||
common.ApiErrorMsg(c, "套餐标题不能为空")
|
||||
return
|
||||
}
|
||||
if req.Plan.PriceAmount < 0 {
|
||||
common.ApiErrorMsg(c, "价格不能为负数")
|
||||
return
|
||||
}
|
||||
if req.Plan.PriceAmount > 9999 {
|
||||
common.ApiErrorMsg(c, "价格不能超过9999")
|
||||
return
|
||||
}
|
||||
if req.Plan.Currency == "" {
|
||||
req.Plan.Currency = "USD"
|
||||
}
|
||||
@@ -172,6 +180,14 @@ func AdminUpdateSubscriptionPlan(c *gin.Context) {
|
||||
common.ApiErrorMsg(c, "套餐标题不能为空")
|
||||
return
|
||||
}
|
||||
if req.Plan.PriceAmount < 0 {
|
||||
common.ApiErrorMsg(c, "价格不能为负数")
|
||||
return
|
||||
}
|
||||
if req.Plan.PriceAmount > 9999 {
|
||||
common.ApiErrorMsg(c, "价格不能超过9999")
|
||||
return
|
||||
}
|
||||
req.Plan.Id = id
|
||||
if req.Plan.Currency == "" {
|
||||
req.Plan.Currency = "USD"
|
||||
|
||||
@@ -248,6 +248,9 @@ func InitLogDB() (err error) {
|
||||
}
|
||||
|
||||
func migrateDB() error {
|
||||
// Migrate price_amount column from float/double to decimal for existing tables
|
||||
migrateSubscriptionPlanPriceAmount()
|
||||
|
||||
err := DB.AutoMigrate(
|
||||
&Channel{},
|
||||
&Token{},
|
||||
@@ -346,6 +349,61 @@ func migrateLOGDB() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// migrateSubscriptionPlanPriceAmount migrates price_amount column from float/double to decimal(10,6)
|
||||
// This is safe to run multiple times - it checks the column type first
|
||||
func migrateSubscriptionPlanPriceAmount() {
|
||||
tableName := "subscription_plans"
|
||||
columnName := "price_amount"
|
||||
|
||||
// Check if table exists first
|
||||
if !DB.Migrator().HasTable(tableName) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if column exists
|
||||
if !DB.Migrator().HasColumn(&SubscriptionPlan{}, columnName) {
|
||||
return
|
||||
}
|
||||
|
||||
var alterSQL string
|
||||
if common.UsingPostgreSQL {
|
||||
// PostgreSQL: Check if already decimal/numeric
|
||||
var dataType string
|
||||
DB.Raw(`SELECT data_type FROM information_schema.columns
|
||||
WHERE table_name = ? AND column_name = ?`, tableName, columnName).Scan(&dataType)
|
||||
if dataType == "numeric" {
|
||||
return // Already decimal/numeric
|
||||
}
|
||||
alterSQL = fmt.Sprintf(`ALTER TABLE %s ALTER COLUMN %s TYPE decimal(10,6) USING %s::decimal(10,6)`,
|
||||
tableName, columnName, columnName)
|
||||
} else if common.UsingMySQL {
|
||||
// MySQL: Check if already decimal
|
||||
var columnType string
|
||||
DB.Raw(`SELECT COLUMN_TYPE FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ?`,
|
||||
tableName, columnName).Scan(&columnType)
|
||||
if strings.HasPrefix(strings.ToLower(columnType), "decimal") {
|
||||
return // Already decimal
|
||||
}
|
||||
alterSQL = fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN %s decimal(10,6) NOT NULL DEFAULT 0",
|
||||
tableName, columnName)
|
||||
} else if common.UsingSQLite {
|
||||
// SQLite doesn't support ALTER COLUMN, but its type affinity handles this automatically
|
||||
// The column will accept decimal values without modification
|
||||
return
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
if alterSQL != "" {
|
||||
if err := DB.Exec(alterSQL).Error; err != nil {
|
||||
common.SysLog(fmt.Sprintf("Warning: failed to migrate %s.%s to decimal: %v", tableName, columnName, err))
|
||||
} else {
|
||||
common.SysLog(fmt.Sprintf("Successfully migrated %s.%s to decimal(10,6)", tableName, columnName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func closeDB(db *gorm.DB) error {
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
|
||||
@@ -149,7 +149,7 @@ type SubscriptionPlan struct {
|
||||
Subtitle string `json:"subtitle" gorm:"type:varchar(255);default:''"`
|
||||
|
||||
// Display money amount (follow existing code style: float64 for money)
|
||||
PriceAmount float64 `json:"price_amount" gorm:"type:double;not null;default:0"`
|
||||
PriceAmount float64 `json:"price_amount" gorm:"type:decimal(10,6);not null;default:0"`
|
||||
Currency string `json:"currency" gorm:"type:varchar(8);not null;default:'USD'"`
|
||||
|
||||
DurationUnit string `json:"duration_unit" gorm:"type:varchar(16);not null;default:'month'"`
|
||||
|
||||
Reference in New Issue
Block a user