mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 00:46:42 +00:00
feat(subscription): implement SQLite support for SubscriptionPlan table creation and migration
#2823
This commit is contained in:
106
model/main.go
106
model/main.go
@@ -271,7 +271,6 @@ func migrateDB() error {
|
||||
&TwoFA{},
|
||||
&TwoFABackupCode{},
|
||||
&Checkin{},
|
||||
&SubscriptionPlan{},
|
||||
&SubscriptionOrder{},
|
||||
&UserSubscription{},
|
||||
&SubscriptionPreConsumeRecord{},
|
||||
@@ -279,6 +278,15 @@ func migrateDB() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if common.UsingSQLite {
|
||||
if err := ensureSubscriptionPlanTableSQLite(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := DB.AutoMigrate(&SubscriptionPlan{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -309,7 +317,6 @@ func migrateDBFast() error {
|
||||
{&TwoFA{}, "TwoFA"},
|
||||
{&TwoFABackupCode{}, "TwoFABackupCode"},
|
||||
{&Checkin{}, "Checkin"},
|
||||
{&SubscriptionPlan{}, "SubscriptionPlan"},
|
||||
{&SubscriptionOrder{}, "SubscriptionOrder"},
|
||||
{&UserSubscription{}, "UserSubscription"},
|
||||
{&SubscriptionPreConsumeRecord{}, "SubscriptionPreConsumeRecord"},
|
||||
@@ -337,6 +344,15 @@ func migrateDBFast() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if common.UsingSQLite {
|
||||
if err := ensureSubscriptionPlanTableSQLite(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := DB.AutoMigrate(&SubscriptionPlan{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
common.SysLog("database migrated")
|
||||
return nil
|
||||
}
|
||||
@@ -349,9 +365,91 @@ func migrateLOGDB() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type sqliteColumnDef struct {
|
||||
Name string
|
||||
DDL string
|
||||
}
|
||||
|
||||
func ensureSubscriptionPlanTableSQLite() error {
|
||||
if !common.UsingSQLite {
|
||||
return nil
|
||||
}
|
||||
tableName := "subscription_plans"
|
||||
if !DB.Migrator().HasTable(tableName) {
|
||||
createSQL := `CREATE TABLE ` + "`" + tableName + "`" + ` (
|
||||
` + "`id`" + ` integer,
|
||||
` + "`title`" + ` varchar(128) NOT NULL,
|
||||
` + "`subtitle`" + ` varchar(255) DEFAULT '',
|
||||
` + "`price_amount`" + ` decimal(10,6) NOT NULL,
|
||||
` + "`currency`" + ` varchar(8) NOT NULL DEFAULT 'USD',
|
||||
` + "`duration_unit`" + ` varchar(16) NOT NULL DEFAULT 'month',
|
||||
` + "`duration_value`" + ` integer NOT NULL DEFAULT 1,
|
||||
` + "`custom_seconds`" + ` bigint NOT NULL DEFAULT 0,
|
||||
` + "`enabled`" + ` numeric DEFAULT 1,
|
||||
` + "`sort_order`" + ` integer DEFAULT 0,
|
||||
` + "`stripe_price_id`" + ` varchar(128) DEFAULT '',
|
||||
` + "`creem_product_id`" + ` varchar(128) DEFAULT '',
|
||||
` + "`max_purchase_per_user`" + ` integer DEFAULT 0,
|
||||
` + "`upgrade_group`" + ` varchar(64) DEFAULT '',
|
||||
` + "`total_amount`" + ` bigint NOT NULL DEFAULT 0,
|
||||
` + "`quota_reset_period`" + ` varchar(16) DEFAULT 'never',
|
||||
` + "`quota_reset_custom_seconds`" + ` bigint DEFAULT 0,
|
||||
` + "`created_at`" + ` bigint,
|
||||
` + "`updated_at`" + ` bigint,
|
||||
PRIMARY KEY (` + "`id`" + `)
|
||||
)`
|
||||
return DB.Exec(createSQL).Error
|
||||
}
|
||||
var cols []struct {
|
||||
Name string `gorm:"column:name"`
|
||||
}
|
||||
if err := DB.Raw("PRAGMA table_info(`" + tableName + "`)").Scan(&cols).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
existing := make(map[string]struct{}, len(cols))
|
||||
for _, c := range cols {
|
||||
existing[c.Name] = struct{}{}
|
||||
}
|
||||
required := []sqliteColumnDef{
|
||||
{Name: "title", DDL: "`title` varchar(128) NOT NULL"},
|
||||
{Name: "subtitle", DDL: "`subtitle` varchar(255) DEFAULT ''"},
|
||||
{Name: "price_amount", DDL: "`price_amount` decimal(10,6) NOT NULL"},
|
||||
{Name: "currency", DDL: "`currency` varchar(8) NOT NULL DEFAULT 'USD'"},
|
||||
{Name: "duration_unit", DDL: "`duration_unit` varchar(16) NOT NULL DEFAULT 'month'"},
|
||||
{Name: "duration_value", DDL: "`duration_value` integer NOT NULL DEFAULT 1"},
|
||||
{Name: "custom_seconds", DDL: "`custom_seconds` bigint NOT NULL DEFAULT 0"},
|
||||
{Name: "enabled", DDL: "`enabled` numeric DEFAULT 1"},
|
||||
{Name: "sort_order", DDL: "`sort_order` integer DEFAULT 0"},
|
||||
{Name: "stripe_price_id", DDL: "`stripe_price_id` varchar(128) DEFAULT ''"},
|
||||
{Name: "creem_product_id", DDL: "`creem_product_id` varchar(128) DEFAULT ''"},
|
||||
{Name: "max_purchase_per_user", DDL: "`max_purchase_per_user` integer DEFAULT 0"},
|
||||
{Name: "upgrade_group", DDL: "`upgrade_group` varchar(64) DEFAULT ''"},
|
||||
{Name: "total_amount", DDL: "`total_amount` bigint NOT NULL DEFAULT 0"},
|
||||
{Name: "quota_reset_period", DDL: "`quota_reset_period` varchar(16) DEFAULT 'never'"},
|
||||
{Name: "quota_reset_custom_seconds", DDL: "`quota_reset_custom_seconds` bigint DEFAULT 0"},
|
||||
{Name: "created_at", DDL: "`created_at` bigint"},
|
||||
{Name: "updated_at", DDL: "`updated_at` bigint"},
|
||||
}
|
||||
for _, col := range required {
|
||||
if _, ok := existing[col.Name]; ok {
|
||||
continue
|
||||
}
|
||||
if err := DB.Exec("ALTER TABLE `" + tableName + "` ADD COLUMN " + col.DDL).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
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() {
|
||||
// SQLite doesn't support ALTER COLUMN, and its type affinity handles this automatically
|
||||
// Skip early to avoid GORM parsing the existing table DDL which may cause issues
|
||||
if common.UsingSQLite {
|
||||
return
|
||||
}
|
||||
|
||||
tableName := "subscription_plans"
|
||||
columnName := "price_amount"
|
||||
|
||||
@@ -387,10 +485,6 @@ func migrateSubscriptionPlanPriceAmount() {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user