Initial commit

This commit is contained in:
James
2024-12-03 21:27:44 +01:00
commit 613e1a767c
125 changed files with 16298 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
<?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);
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace App\Actions;
use App\Enums\WalletTransactionType;
use App\Exceptions\InsufficientBalance;
use App\Models\User;
use App\Models\WalletTransfer;
use Illuminate\Support\Facades\DB;
readonly class PerformWalletTransfer
{
public function __construct(protected PerformWalletTransaction $performWalletTransaction) {}
/**
* @throws InsufficientBalance
*/
public function execute(User $sender, User $recipient, int $amount, string $reason): WalletTransfer
{
return DB::transaction(function () use ($sender, $recipient, $amount, $reason) {
$transfer = WalletTransfer::create([
'amount' => $amount,
'source_id' => $sender->wallet->id,
'target_id' => $recipient->wallet->id,
]);
$this->performWalletTransaction->execute(
wallet: $sender->wallet,
type: WalletTransactionType::DEBIT,
amount: $amount,
reason: $reason,
transfer: $transfer
);
$this->performWalletTransaction->execute(
wallet: $recipient->wallet,
type: WalletTransactionType::CREDIT,
amount: $amount,
reason: $reason,
transfer: $transfer
);
return $transfer;
});
}
}