62 lines
1.7 KiB
PHP
62 lines
1.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Actions;
|
|
|
|
use App\Enums\WalletTransactionType;
|
|
use App\Exceptions\InsufficientBalance;
|
|
use App\Models\Wallet;
|
|
use App\Models\WalletTransaction;
|
|
use App\Models\WalletTransfer;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Throwable;
|
|
|
|
readonly class PerformWalletTransaction
|
|
{
|
|
/**
|
|
* @throws InsufficientBalance
|
|
*/
|
|
public function execute(Wallet $wallet, WalletTransactionType $type, int $amount, string $reason, ?WalletTransfer $transfer = null, bool $force = false): WalletTransaction
|
|
{
|
|
if (! $force && $type === WalletTransactionType::DEBIT) {
|
|
$this->ensureWalletHasEnoughFunds($wallet, $amount);
|
|
}
|
|
|
|
return DB::transaction(function () use ($wallet, $type, $amount, $reason, $transfer) {
|
|
$transaction = $wallet->transactions()->create([
|
|
'amount' => $amount,
|
|
'type' => $type,
|
|
'reason' => $reason,
|
|
'transfer_id' => $transfer?->id,
|
|
]);
|
|
|
|
$this->updateWallet($wallet, $type, $amount);
|
|
|
|
return $transaction;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @throws Throwable
|
|
*/
|
|
protected function updateWallet(Wallet $wallet, WalletTransactionType $type, int $amount): void
|
|
{
|
|
if ($type === WalletTransactionType::CREDIT) {
|
|
$wallet->increment('balance', $amount);
|
|
} else {
|
|
$wallet->decrement('balance', $amount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws InsufficientBalance
|
|
*/
|
|
protected function ensureWalletHasEnoughFunds(Wallet $wallet, int $amount): void
|
|
{
|
|
if ($wallet->balance < $amount) {
|
|
throw new InsufficientBalance($wallet, $amount);
|
|
}
|
|
}
|
|
}
|