ifnex/04_Laravel/tests/Feature/Services/WalletServiceTest.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

181 lines
5.5 KiB
PHP

<?php
namespace Tests\Feature\Services;
use App\Enums\PaymentGateway;
use App\Enums\TransactionStatus;
use App\Enums\TransactionType;
use App\Models\User;
use App\Models\Wallet;
use App\Models\WalletTransaction;
use App\Services\WalletService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class WalletServiceTest extends TestCase
{
use RefreshDatabase;
private WalletService $walletService;
private User $user;
private Wallet $wallet;
protected function setUp(): void
{
parent::setUp();
$this->walletService = app(WalletService::class);
$this->user = User::factory()->create();
$this->wallet = Wallet::create([
'user_id' => $this->user->id,
'balance' => 0,
'total_deposited' => 0,
'total_withdrawn' => 0,
]);
}
#[Test]
public function it_creates_deposit_transaction()
{
$transaction = $this->walletService->requestDeposit(
wallet: $this->wallet,
amount: 100000,
description: 'شارژ تستی',
user: $this->user
);
$this->assertInstanceOf(WalletTransaction::class, $transaction);
$this->assertEquals(100000, $transaction->amount);
$this->assertEquals(TransactionType::DEPOSIT, $transaction->type);
$this->assertEquals(TransactionStatus::PENDING, $transaction->status);
$this->assertEquals(0, $transaction->balance_after);
}
#[Test]
public function it_completes_deposit_and_updates_balance()
{
$transaction = $this->walletService->requestDeposit(
wallet: $this->wallet,
amount: 100000,
description: 'شارژ تستی',
user: $this->user
);
$completed = $this->walletService->completeDeposit(
transaction: $transaction,
gatewayReferenceId: 'REF123'
);
$this->wallet->refresh();
$this->assertEquals(100000, $this->wallet->balance);
$this->assertEquals(100000, $this->wallet->total_deposited);
$this->assertEquals(TransactionStatus::COMPLETED, $completed->status);
$this->assertEquals('REF123', $completed->gateway_reference_id);
}
#[Test]
public function it_processes_manual_deposit()
{
$admin = User::factory()->create();
$transaction = $this->walletService->manualDeposit(
wallet: $this->wallet,
amount: 500000,
description: 'شارژ دستی',
admin: $admin
);
$this->wallet->refresh();
$this->assertEquals(500000, $this->wallet->balance);
$this->assertEquals(500000, $this->wallet->total_deposited);
$this->assertEquals(TransactionStatus::COMPLETED, $transaction->status);
$this->assertEquals(PaymentGateway::MANUAL, $transaction->gateway);
}
#[Test]
public function it_processes_manual_withdrawal()
{
$this->wallet->update(['balance' => 1000000]);
$admin = User::factory()->create();
$transaction = $this->walletService->manualWithdrawal(
wallet: $this->wallet,
amount: 300000,
description: 'کسر دستی',
admin: $admin
);
$this->wallet->refresh();
$this->assertEquals(700000, $this->wallet->balance);
$this->assertEquals(300000, $this->wallet->total_withdrawn);
$this->assertEquals(-300000, $transaction->amount);
$this->assertEquals(TransactionStatus::COMPLETED, $transaction->status);
}
#[Test]
public function it_prevents_withdrawal_when_balance_is_insufficient()
{
$this->wallet->update(['balance' => 100000]);
$admin = User::factory()->create();
$this->expectException(\Exception::class);
$this->walletService->manualWithdrawal(
wallet: $this->wallet,
amount: 200000,
description: 'کسر دستی',
admin: $admin
);
}
#[Test]
public function it_processes_order_payment()
{
$this->wallet->update(['balance' => 500000]);
$order = new \stdClass();
$order->id = 1;
$transaction = $this->walletService->payOrder(
wallet: $this->wallet,
amount: 200000,
description: 'پرداخت سفارش #1',
order: $order
);
$this->wallet->refresh();
$this->assertEquals(300000, $this->wallet->balance);
$this->assertEquals(200000, $this->wallet->total_withdrawn);
$this->assertEquals(TransactionType::ORDER_PAYMENT, $transaction->type);
}
#[Test]
public function it_prevents_order_payment_when_balance_is_insufficient()
{
$this->wallet->update(['balance' => 100000]);
$this->expectException(\Exception::class);
$this->walletService->payOrder(
wallet: $this->wallet,
amount: 200000,
description: 'پرداخت سفارش'
);
}
#[Test]
public function it_fails_transaction()
{
$transaction = $this->walletService->requestDeposit(
wallet: $this->wallet,
amount: 100000,
description: 'شارژ تستی',
user: $this->user
);
$failed = $this->walletService->failTransaction(
$transaction,
'کاربر پرداخت را لغو کرد.'
);
$this->assertEquals(TransactionStatus::FAILED, $failed->status);
$this->assertEquals(0, $this->wallet->fresh()->balance);
}
}