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("--- Activity-Based Coupon Data Repair Auditor (Cloud DB) ---") var records []struct { ID int64 UserID int64 CouponID int64 BalanceAmount int64 Status int32 ValidEnd string OriginalValue int64 DiscountType int32 } // Fetch all coupons joined with system data 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, sc.discount_type FROM user_coupons uc JOIN system_coupons sc ON uc.coupon_id = sc.id `).Scan(&records) for _, r := range records { // Calculate total usage from order_coupons var orderUsage int64 db.Raw("SELECT SUM(applied_amount) FROM order_coupons WHERE user_coupon_id = ?", r.ID).Scan(&orderUsage) // Calculate total usage from ledger var ledgerUsage int64 db.Raw("SELECT ABS(SUM(change_amount)) FROM user_coupon_ledger WHERE user_coupon_id = ? AND action = 'apply'", r.ID).Scan(&ledgerUsage) // Max usage between sources finalUsage := orderUsage if ledgerUsage > finalUsage { finalUsage = ledgerUsage } expectedBalance := r.OriginalValue - finalUsage if expectedBalance < 0 { expectedBalance = 0 } // Determine Correct Status // 1: Unused (or Partially Used but still valid) // 2: Used (Exhausted) // 3: Expired (Unused/Partially Used and time past) expectedStatus := r.Status if expectedBalance == 0 { expectedStatus = 2 } else { // Logic for expired vs unused would go here if needed, // but we prioritize "Used" if balance is 0. // Currently if balance > 0 and Status is 2, it's definitely an error. if r.Status == 2 { expectedStatus = 1 // Revert to unused/partial if balance > 0 } } if expectedBalance != r.BalanceAmount || expectedStatus != r.Status { fmt.Printf("-- Coupon %d (User %d): Bal %d->%d, Status %v->%v, Usage %d/%d\n", r.ID, r.UserID, r.BalanceAmount, expectedBalance, r.Status, expectedStatus, finalUsage, r.OriginalValue) fmt.Printf("UPDATE user_coupons SET balance_amount = %d, status = %v, updated_at = NOW() WHERE id = %d;\n", expectedBalance, expectedStatus, r.ID) } } }