2026-01-27 01:33:32 +08:00

86 lines
2.6 KiB
Go

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)
}
}
}