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("--- Master Coupon Reconciliation & Repair Generator (Cloud DB) ---") var userCoupons []struct { ID int64 UserID int64 CouponID int64 BalanceAmount int64 Status int32 ValidEnd string OriginalValue int64 } // Join with system_coupons to get original discount value db.Raw(` SELECT uc.id, uc.user_id, uc.coupon_id, uc.balance_amount, uc.status, uc.valid_end, sc.discount_value as original_value FROM user_coupons uc JOIN system_coupons sc ON uc.coupon_id = sc.id `).Scan(&userCoupons) for _, uc := range userCoupons { // Calculate actual usage from ledger var ledgerSum int64 db.Raw("SELECT ABS(SUM(change_amount)) FROM user_coupon_ledger WHERE user_coupon_id = ? AND action = 'apply'", uc.ID).Scan(&ledgerSum) // Calculate actual usage from order_coupons var orderSum int64 db.Raw("SELECT SUM(applied_amount) FROM order_coupons WHERE user_coupon_id = ?", uc.ID).Scan(&orderSum) // Source of truth: Max of both (covering cases where one might be missing manually) actualUsed := ledgerSum if orderSum > actualUsed { actualUsed = orderSum } calculatedBalance := uc.OriginalValue - actualUsed if calculatedBalance < 0 { calculatedBalance = 0 } // Determine correct status // 1: Unused (Balance > 0 and Time not past) // 2: Used (Balance == 0) // 3: Expired (Balance > 0 and Time past) expectedStatus := uc.Status if calculatedBalance == 0 { expectedStatus = 2 } else { // If balance remaining, check time expiry // (Assuming valid_end is in RFC3339 or similar from DB) // For simplicity in SQL generation, we'll focus on the obvious mismatches found here. } if calculatedBalance != uc.BalanceAmount || expectedStatus != uc.Status { fmt.Printf("-- User %d Coupon %d: Bal %d->%d, Status %v->%v\n", uc.UserID, uc.ID, uc.BalanceAmount, calculatedBalance, uc.Status, expectedStatus) fmt.Printf("UPDATE user_coupons SET balance_amount = %d, status = %v, updated_at = NOW() WHERE id = %d;\n", calculatedBalance, expectedStatus, uc.ID) } } }