ifnex/04_Laravel/app/Models/Wallet.php
Kazem Alghasi e1c4385a9c feat(finance): implement Filament admin panel and expand wallet/discount features
Implement a comprehensive financial management suite within the Filament
admin panel, including new resources for payments and discount codes,
along with a financial dashboard.

- feat(ui): add Filament Dashboard with finance overview and transaction
  widgets
- feat(ui): implement PaymentResource for monitoring gateway transactions
- feat(ui): complete DiscountCodeResource with full CRUD and filtering
- feat(wallet): add automatic wallet creation on balance retrieval
- fix(wallet): resolve null handling in isFrozen() and balance viewing
- fix(db): correct enum type from 'percent' to 'percentage' in
  discount_codes migration
- fix(api): update pricing calculation endpoint to /api/v1/calculate
- test: add 21 new feature and service tests covering wallet, payment,
  and discount logic
- chore: remove obsolete PaymentGatewayService and update project status
2026-08-08 03:15:51 +03:30

112 lines
2.8 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Wallet extends Model
{
use SoftDeletes;
protected $fillable = [
'user_id',
'balance',
'total_deposited',
'total_withdrawn',
'is_frozen',
'freeze_reason',
'frozen_at',
'frozen_by',
];
protected $casts = [
'balance' => 'decimal:2',
'total_deposited' => 'decimal:2',
'total_withdrawn' => 'decimal:2',
'is_frozen' => 'boolean',
'frozen_at' => 'datetime',
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function transactions(): HasMany
{
return $this->hasMany(WalletTransaction::class)->orderByDesc('created_at');
}
public function completedTransactions(): HasMany
{
return $this->transactions()->where('status', 'completed');
}
public function pendingTransactions(): HasMany
{
return $this->transactions()->where('status', 'pending');
}
public function activityLogs(): HasMany
{
return $this->hasMany(WalletActivityLog::class)->orderByDesc('created_at');
}
public function frozenByUser(): BelongsTo
{
return $this->belongsTo(User::class, 'frozen_by');
}
// Helper methods
public function isFrozen(): bool
{
return (bool) ($this->is_frozen ?? false);
}
public function hasSufficientBalance(float $amount): bool
{
return $this->balance >= $amount && !$this->is_frozen;
}
public function freeze(string $reason, ?User $admin = null): bool
{
return $this->update([
'is_frozen' => true,
'freeze_reason' => $reason,
'frozen_at' => now(),
'frozen_by' => $admin?->id,
]);
}
public function unfreeze(?User $admin = null): bool
{
return $this->update([
'is_frozen' => false,
'freeze_reason' => null,
'frozen_at' => null,
'frozen_by' => null,
]);
}
public function refreshBalance(): self
{
$balance = $this->completedTransactions()->sum('amount');
$totalDeposited = $this->completedTransactions()
->where('type', 'deposit')
->sum('amount');
$totalWithdrawn = $this->completedTransactions()
->whereIn('type', ['withdrawal', 'order_payment'])
->sum('amount');
$this->update([
'balance' => $balance,
'total_deposited' => $totalDeposited,
'total_withdrawn' => abs($totalWithdrawn),
]);
return $this->fresh();
}
}