Initial commit
This commit is contained in:
		
							
								
								
									
										61
									
								
								app/Actions/PerformWalletTransaction.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								app/Actions/PerformWalletTransaction.php
									
									
									
									
									
										Normal 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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								app/Actions/PerformWalletTransfer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/Actions/PerformWalletTransfer.php
									
									
									
									
									
										Normal 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;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user