namespace App\Traits; use App\Models\Wallet; use App\Models\Transaction; use App\Models\Deposit; use App\Models\Withdrawal; trait HasWallet { public function initializeHasWallet() { $this->appends = array_merge($this->appends, [ 'wallet_balance', 'wallet_pending', ]); } public static function bootHasWallet() { static::created(function ($model) { $model->wallet()->create([ 'balance' => 0, 'pending_balance' => 0, 'total_deposited' => 0, 'total_withdrawn' => 0, 'total_spent' => 0, 'currency' => config('app.currency', 'USD'), ]); }); } public function wallet() { return $this->hasOne(Wallet::class); } public function getWalletBalanceAttribute() { return $this->wallet ? $this->wallet->balance : 0; } public function getWalletPendingAttribute() { return $this->wallet ? $this->wallet->pending_balance : 0; } public function getAvailableBalanceAttribute() { return $this->wallet ? $this->wallet->available_balance : 0; } public function hasSufficientBalance($amount) { return $this->available_balance >= $amount; } public function creditWallet($amount, $description, $type = 'deposit', $reference = null) { if (!$this->wallet) { $this->wallet()->create(['balance' => 0]); $this->load('wallet'); } return $this->wallet->credit($amount, $description, $type, $reference); } public function debitWallet($amount, $description, $type = 'order', $reference = null) { if (!$this->wallet) { throw new \Exception('Wallet not found'); } return $this->wallet->debit($amount, $description, $type, $reference); } public function transactions() { return $this->hasMany(Transaction::class); } public function debitWallet($amount, $description) { return DB::transaction(function () use ($amount, $description) { $wallet = Wallet::where('user_id', $this->id) ->lockForUpdate() ->first(); if ($wallet->available_balance < $amount) { throw new \Exception('Insufficient balance'); } $wallet->balance -= $amount; $wallet->save(); return $this->createTransaction($amount, $description); }); } public function deposits() { return $this->hasMany(Deposit::class); } public function withdrawals() { return $this->hasMany(Withdrawal::class); } public function getTotalDepositedAttribute() { return $this->transactions() ->where('type', 'deposit') ->where('status', 'completed') ->sum('amount'); } public function getTotalSpentAttribute() { return $this->transactions() ->where('type', 'order') ->where('status', 'completed') ->sum('amount'); } public function getTotalWithdrawnAttribute() { return $this->transactions() ->where('type', 'withdrawal') ->where('status', 'completed') ->sum('amount'); } public function getMonthlySpendingAttribute() { return $this->transactions() ->where('type', 'order') ->where('status', 'completed') ->whereMonth('created_at', now()->month) ->sum('amount'); } public function getTodaySpendingAttribute() { return $this->transactions() ->where('type', 'order') ->where('status', 'completed') ->whereDate('created_at', today()) ->sum('amount'); } }