package main import ( "fmt" "log" "gorm.io/driver/mysql" "gorm.io/gorm" ) const ( DbDSN = "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local" ) func main() { db, err := gorm.Open(mysql.Open(DbDSN), &gorm.Config{}) if err != nil { log.Fatalf("DB connection failed: %v", err) } fmt.Println("--- Advanced Coupon Data Reconciliation (Cloud DB) ---") var userCoupons []struct { ID int64 UserID int64 SystemAmount int64 BalanceAmount int64 Status int32 ValidEnd string } // Join with system_coupons to get original amount db.Raw(` SELECT uc.id, uc.user_id, sc.discount_value as system_amount, uc.balance_amount, uc.status, uc.valid_end FROM user_coupons uc JOIN system_coupons sc ON uc.coupon_id = sc.id `).Scan(&userCoupons) fmt.Println("Generating repair SQL based on ledger and order association...") for _, uc := range userCoupons { // Calculate total deduction from ledger var totalDeduction struct { Sum int64 } db.Raw("SELECT ABS(SUM(change_amount)) as sum FROM user_coupon_ledger WHERE user_coupon_id = ? AND action = 'apply'", uc.ID).Scan(&totalDeduction) // Calculate total deduction from order_coupons (secondary verification) var orderDeduction struct { Sum int64 } db.Raw("SELECT SUM(applied_amount) as sum FROM order_coupons WHERE user_coupon_id = ?", uc.ID).Scan(&orderDeduction) // Choose the source of truth (ledger usually preferred) actualUsed := totalDeduction.Sum if orderDeduction.Sum > actualUsed { actualUsed = orderDeduction.Sum } expectedBalance := uc.SystemAmount - actualUsed if expectedBalance < 0 { expectedBalance = 0 } expectedStatus := uc.Status if expectedBalance == 0 { expectedStatus = 2 // Fully Used } else if expectedBalance > 0 { // Check if it should be expired or unused // We won't downgrade Expired (3) back to Unused (1) unless balance > 0 and time is not up. // However, usually if balance > 0 and Status is 2, it's a bug. } // Check for status 3 that shouldn't be // (Currently the user says they see status 3 but it's used?) // If balance == 0, status must be 2. if expectedBalance != uc.BalanceAmount || expectedStatus != uc.Status { fmt.Printf("-- Coupon %d (User %d): Bal %d->%d, Status %v->%v (Used: %d, Orig: %d)\n", uc.ID, uc.UserID, uc.BalanceAmount, expectedBalance, uc.Status, expectedStatus, actualUsed, uc.SystemAmount) fmt.Printf("UPDATE user_coupons SET balance_amount = %d, status = %v WHERE id = %d;\n", expectedBalance, expectedStatus, uc.ID) } } }