-
-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathMatchUsersWithStripeCustomers.php
More file actions
110 lines (86 loc) · 3.22 KB
/
MatchUsersWithStripeCustomers.php
File metadata and controls
110 lines (86 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?php
namespace App\Console\Commands;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Sleep;
use Stripe\Customer;
use Stripe\Exception\ApiErrorException;
class MatchUsersWithStripeCustomers extends Command
{
protected $signature = 'users:match-stripe-customers
{--limit= : Limit the number of users to process}
{--dry-run : Show what would be updated without making changes}';
protected $description = 'Match users without Stripe IDs to their Stripe customer records';
public function handle(): int
{
$query = User::whereNull('stripe_id');
$totalUsers = $query->count();
if ($totalUsers === 0) {
$this->info('No users found without Stripe IDs.');
return self::SUCCESS;
}
$this->info("Found {$totalUsers} users without Stripe IDs.");
$limit = $this->option('limit');
if ($limit) {
$query->limit((int) $limit);
$this->info("Processing first {$limit} users...");
}
$dryRun = $this->option('dry-run');
if ($dryRun) {
$this->warn('DRY RUN MODE - No changes will be made');
}
$users = $query->get();
$matched = 0;
$notFound = 0;
$errors = 0;
$progressBar = $this->output->createProgressBar($users->count());
$progressBar->start();
/** @var User $user */
foreach ($users as $user) {
try {
/** @var Customer $customer */
$customer = $user->findStripeCustomerRecords()->first(fn (Customer $result) => $result->next_invoice_sequence === 1);
if ($customer) {
$matched++;
if (! $dryRun) {
$user->update(['stripe_id' => $customer->id]);
}
$this->newLine();
$this->line(" ✓ Matched: {$user->email} → {$customer->id}");
} else {
$notFound++;
$this->newLine();
$this->line(" - No match: {$user->email}");
}
} catch (ApiErrorException $e) {
$errors++;
$this->newLine();
$this->error(" ✗ Error for {$user->email}: {$e->getMessage()}");
} catch (\Exception $e) {
$errors++;
$this->newLine();
$this->error(" ✗ Unexpected error for {$user->email}: {$e->getMessage()}");
}
$progressBar->advance();
// Add a small delay to avoid rate limiting
Sleep::usleep(100000); // 0.1 seconds
}
$progressBar->finish();
$this->newLine(2);
// Summary
$this->info('Summary:');
$this->table(
['Status', 'Count'],
[
['Matched', $matched],
['Not Found', $notFound],
['Errors', $errors],
['Total Processed', $users->count()],
]
);
if ($dryRun) {
$this->warn('This was a dry run. Run without --dry-run to apply changes.');
}
return self::SUCCESS;
}
}