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
158 lines
4.1 KiB
PHP
158 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Api;
|
|
|
|
use App\Models\DiscountCode;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Tests\TestCase;
|
|
|
|
class DiscountCodeControllerTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
#[Test]
|
|
public function it_returns_active_discount_codes()
|
|
{
|
|
DiscountCode::create([
|
|
'code' => 'TEST10',
|
|
'type' => 'percentage',
|
|
'value' => 10,
|
|
'min_order_amount' => 100000,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
DiscountCode::create([
|
|
'code' => 'INACTIVE',
|
|
'type' => 'fixed',
|
|
'value' => 50000,
|
|
'is_active' => false,
|
|
]);
|
|
|
|
$response = $this->get('/api/v1/discount-codes');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'codes' => [
|
|
[
|
|
'code' => 'TEST10',
|
|
'type' => 'percentage',
|
|
'value' => 10,
|
|
],
|
|
],
|
|
])
|
|
->assertJsonCount(1, 'codes');
|
|
}
|
|
|
|
#[Test]
|
|
public function it_validates_discount_code_successfully()
|
|
{
|
|
DiscountCode::create([
|
|
'code' => 'PERCENT10',
|
|
'type' => 'percentage',
|
|
'value' => 10,
|
|
'min_order_amount' => 100000,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
$response = $this->post('/api/v1/discount-codes/validate', [
|
|
'code' => 'PERCENT10',
|
|
'total_price' => 500000,
|
|
]);
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'valid' => true,
|
|
'type' => 'percentage',
|
|
'value' => 10,
|
|
'discount_amount' => 50000,
|
|
'final_price' => 450000,
|
|
]);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_rejects_invalid_discount_code()
|
|
{
|
|
$response = $this->post('/api/v1/discount-codes/validate', [
|
|
'code' => 'INVALID',
|
|
'total_price' => 500000,
|
|
]);
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'valid' => false,
|
|
'message' => 'کد تخفیف نامعتبر است.',
|
|
]);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_rejects_expired_discount_code()
|
|
{
|
|
DiscountCode::create([
|
|
'code' => 'EXPIRED',
|
|
'type' => 'fixed',
|
|
'value' => 50000,
|
|
'is_active' => true,
|
|
'expires_at' => now()->subDay(),
|
|
]);
|
|
|
|
$response = $this->post('/api/v1/discount-codes/validate', [
|
|
'code' => 'EXPIRED',
|
|
'total_price' => 500000,
|
|
]);
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'valid' => false,
|
|
'message' => 'این کد تخفیف منقضی شده است.',
|
|
]);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_rejects_code_below_minimum_order_amount()
|
|
{
|
|
DiscountCode::create([
|
|
'code' => 'MIN500',
|
|
'type' => 'fixed',
|
|
'value' => 50000,
|
|
'min_order_amount' => 500000,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
$response = $this->post('/api/v1/discount-codes/validate', [
|
|
'code' => 'MIN500',
|
|
'total_price' => 100000,
|
|
]);
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'valid' => false,
|
|
])
|
|
->assertJsonStructure(['message']);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_calculates_fixed_discount_correctly()
|
|
{
|
|
DiscountCode::create([
|
|
'code' => 'FIXED50',
|
|
'type' => 'fixed',
|
|
'value' => 50000,
|
|
'min_order_amount' => 100000,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
$response = $this->post('/api/v1/discount-codes/validate', [
|
|
'code' => 'FIXED50',
|
|
'total_price' => 500000,
|
|
]);
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'valid' => true,
|
|
'discount_amount' => 50000,
|
|
'final_price' => 450000,
|
|
]);
|
|
}
|
|
}
|