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
181 lines
5.5 KiB
PHP
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);
|
|
}
|
|
}
|