// Command wallet-migrate moves customer_points and customer_tokens balances into the // EnakPoint & EnakCoin wallet (docs/prd-point-coin.md ยง10). Safe to run more than once: // each run credits only what earlier runs have not. // // ENV_MODE=staging go run ./cmd/wallet-migrate -dry-run // ENV_MODE=staging go run ./cmd/wallet-migrate // // It exits non-zero when the legacy totals and the migrated totals disagree. package main import ( "context" "flag" "fmt" "log" "os" "apskel-pos-be/config" "apskel-pos-be/internal/db" "apskel-pos-be/internal/processor" "apskel-pos-be/internal/repository" ) func main() { dryRun := flag.Bool("dry-run", false, "report what would be credited without writing anything") batchSize := flag.Int("batch", 500, "customers read per batch") flag.Parse() cfg := config.LoadConfig() pg, err := db.NewPostgres(cfg.Database) if err != nil { log.Fatal(err) } migrator := processor.NewWalletMigrationProcessor( repository.NewWalletMigrationRepository(pg), processor.NewWalletProcessor(repository.NewWalletRepository(pg)), repository.NewTxManager(pg), ) report, err := migrator.Run(context.Background(), *dryRun, *batchSize) if err != nil { log.Fatalf("wallet migration failed: %v", err) } verb := "credited" if report.DryRun { verb = "would credit" } t := report.Totals fmt.Printf("customers scanned: %d\n", report.CustomersScanned) fmt.Printf("EnakPoint: %s %d in %d rows\n", verb, report.PointsCredited, report.PointCredits) fmt.Printf("EnakCoin: %s %d in %d rows\n", verb, report.CoinsCredited, report.CoinCredits) fmt.Printf("\n%-10s %15s %15s %15s\n", "", "legacy", "migrated", "wallet balance") fmt.Printf("%-10s %15d %15d %15d\n", "EnakPoint", t.LegacyPoints, t.MigratedPoints, t.WalletPoints) fmt.Printf("%-10s %15d %15d %15d\n", "EnakCoin", t.LegacyCoins, t.MigratedCoins, t.WalletCoins) if len(report.Discrepancies) > 0 { fmt.Printf("\n%d balances shrank in the legacy tables after they were migrated.\n", len(report.Discrepancies)) fmt.Println("They were left as they are in the wallet; correct them with an adjustment if needed:") for _, d := range report.Discrepancies { fmt.Printf(" customer %s %s: legacy %d, migrated %d\n", d.CustomerID, d.Currency, d.Legacy, d.Migrated) } } if report.DryRun { return } if !report.Balanced() { fmt.Println("\nNOT BALANCED: legacy and migrated totals differ") os.Exit(1) } fmt.Println("\nbalanced: legacy totals = migrated totals") }