diff --git a/src/app/Console/Commands/WalletCharge.php b/src/app/Console/Commands/WalletCharge.php index a41b2333..55637a20 100644 --- a/src/app/Console/Commands/WalletCharge.php +++ b/src/app/Console/Commands/WalletCharge.php @@ -1,76 +1,76 @@ argument('wallet')) { // Find specified wallet by ID $wallet = Wallet::find($wallet); if (!$wallet || !$wallet->owner) { return 1; } $wallets = [$wallet]; } else { // Get all wallets, excluding deleted accounts $wallets = Wallet::select('wallets.*') ->join('users', 'users.id', '=', 'wallets.user_id') ->whereNull('users.deleted_at') - ->get(); + ->cursor(); } foreach ($wallets as $wallet) { $charge = $wallet->chargeEntitlements(); if ($charge > 0) { $this->info( "Charged wallet {$wallet->id} for user {$wallet->owner->email} with {$charge}" ); // Top-up the wallet if auto-payment enabled for the wallet \App\Jobs\WalletCharge::dispatch($wallet); } if ($wallet->balance < 0) { // Check the account balance, send notifications, suspend, delete \App\Jobs\WalletCheck::dispatch($wallet); } } } } diff --git a/src/tests/Feature/Console/WalletChargeTest.php b/src/tests/Feature/Console/WalletChargeTest.php index c56a868a..ec681731 100644 --- a/src/tests/Feature/Console/WalletChargeTest.php +++ b/src/tests/Feature/Console/WalletChargeTest.php @@ -1,137 +1,146 @@ deleteTestUser('wallet-charge@kolabnow.com'); } /** * {@inheritDoc} */ public function tearDown(): void { $this->deleteTestUser('wallet-charge@kolabnow.com'); parent::tearDown(); } /** * Test command run for a specified wallet */ public function testHandleSingle(): void { $user = $this->getTestUser('wallet-charge@kolabnow.com'); $wallet = $user->wallets()->first(); $wallet->balance = 0; $wallet->save(); Queue::fake(); // Non-existing wallet ID $this->artisan('wallet:charge 123') ->assertExitCode(1); Queue::assertNothingPushed(); // The wallet has no entitlements, expect no charge and no check $this->artisan('wallet:charge ' . $wallet->id) ->assertExitCode(0); Queue::assertNothingPushed(); // The wallet has no entitlements, but has negative balance $wallet->balance = -100; $wallet->save(); $this->artisan('wallet:charge ' . $wallet->id) ->assertExitCode(0); Queue::assertPushed(\App\Jobs\WalletCharge::class, 0); Queue::assertPushed(\App\Jobs\WalletCheck::class, 1); Queue::assertPushed(\App\Jobs\WalletCheck::class, function ($job) use ($wallet) { $job_wallet = TestCase::getObjectProperty($job, 'wallet'); return $job_wallet->id === $wallet->id; }); Queue::fake(); // The wallet has entitlements to charge, and negative balance $sku = \App\Sku::where('title', 'mailbox')->first(); $entitlement = \App\Entitlement::create([ 'wallet_id' => $wallet->id, 'sku_id' => $sku->id, 'cost' => 100, 'entitleable_id' => $user->id, 'entitleable_type' => \App\User::class, ]); \App\Entitlement::where('id', $entitlement->id)->update([ 'created_at' => \Carbon\Carbon::now()->subMonths(1), 'updated_at' => \Carbon\Carbon::now()->subMonths(1), ]); \App\User::where('id', $user->id)->update([ 'created_at' => \Carbon\Carbon::now()->subMonths(1), 'updated_at' => \Carbon\Carbon::now()->subMonths(1), ]); $this->assertSame(100, $wallet->fresh()->chargeEntitlements(false)); $this->artisan('wallet:charge ' . $wallet->id) ->assertExitCode(0); Queue::assertPushed(\App\Jobs\WalletCharge::class, 1); Queue::assertPushed(\App\Jobs\WalletCharge::class, function ($job) use ($wallet) { $job_wallet = TestCase::getObjectProperty($job, 'wallet'); return $job_wallet->id === $wallet->id; }); Queue::assertPushed(\App\Jobs\WalletCheck::class, 1); Queue::assertPushed(\App\Jobs\WalletCheck::class, function ($job) use ($wallet) { $job_wallet = TestCase::getObjectProperty($job, 'wallet'); return $job_wallet->id === $wallet->id; }); } /** * Test command run for all wallets */ public function testHandleAll(): void { $user = $this->getTestUser('john@kolab.org'); $wallet = $user->wallets()->first(); $wallet->balance = 0; $wallet->save(); // backdate john's entitlements and set balance=0 for all wallets $this->backdateEntitlements($user->entitlements, \Carbon\Carbon::now()->subWeeks(5)); \App\Wallet::where('balance', '<', '0')->update(['balance' => 0]); + $user2 = $this->getTestUser('wallet-charge@kolabnow.com'); + $wallet2 = $user2->wallets()->first(); + $wallet2->balance = -100; + $wallet2->save(); + Queue::fake(); // Non-existing wallet ID $this->artisan('wallet:charge')->assertExitCode(0); - Queue::assertPushed(\App\Jobs\WalletCheck::class, 1); + Queue::assertPushed(\App\Jobs\WalletCheck::class, 2); Queue::assertPushed(\App\Jobs\WalletCheck::class, function ($job) use ($wallet) { $job_wallet = TestCase::getObjectProperty($job, 'wallet'); return $job_wallet->id === $wallet->id; }); + Queue::assertPushed(\App\Jobs\WalletCheck::class, function ($job) use ($wallet2) { + $job_wallet = TestCase::getObjectProperty($job, 'wallet'); + return $job_wallet->id === $wallet2->id; + }); Queue::assertPushed(\App\Jobs\WalletCharge::class, 1); Queue::assertPushed(\App\Jobs\WalletCharge::class, function ($job) use ($wallet) { $job_wallet = TestCase::getObjectProperty($job, 'wallet'); return $job_wallet->id === $wallet->id; }); } }