153 lines
5.9 KiB
PHP
153 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Services\Invoice;
|
|
|
|
use App\Enums\DocumentModalityEnum;
|
|
use App\Enums\DocumentPriorityEnum;
|
|
use App\Enums\DocumentStatusEnum;
|
|
use App\Enums\InvoicePaymentMethodEnum;
|
|
use App\Enums\InvoiceStatusEnum;
|
|
use App\Jobs\SendPatternSms;
|
|
use App\Models\Document;
|
|
use App\Models\Invoice;
|
|
use App\Models\User;
|
|
use App\Services\Invoice\InvoiceService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Tests\TestCase;
|
|
|
|
class InvoiceServiceTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected InvoiceService $service;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
Queue::fake();
|
|
$this->service = app(InvoiceService::class);
|
|
}
|
|
|
|
public function test_create_for_document_creates_pending_invoice_priced_by_modality(): void
|
|
{
|
|
$document = Document::factory()->registered()->create(['modality' => DocumentModalityEnum::Mri->value]);
|
|
|
|
$invoice = $this->service->createForDocument($document);
|
|
|
|
$this->assertSame(InvoiceStatusEnum::Pending, $invoice->status);
|
|
$this->assertSame(DocumentModalityEnum::Mri->price(), $invoice->amount);
|
|
$this->assertNull($invoice->payment_method);
|
|
$this->assertNull($invoice->paid_at);
|
|
$this->assertDatabaseHas('invoices', [
|
|
'id' => $invoice->id,
|
|
'document_id' => $document->id,
|
|
'user_id' => $document->requester_id,
|
|
'amount' => 1200000,
|
|
]);
|
|
}
|
|
|
|
public function test_create_for_document_sets_number_as_zero_padded_id(): void
|
|
{
|
|
$document = Document::factory()->registered()->create();
|
|
|
|
$invoice = $this->service->createForDocument($document);
|
|
|
|
$this->assertSame(str_pad((string) $invoice->id, 5, '0', STR_PAD_LEFT), $invoice->fresh()->number);
|
|
}
|
|
|
|
public function test_create_for_document_generates_unique_numbers(): void
|
|
{
|
|
$first = $this->service->createForDocument(Document::factory()->registered()->create());
|
|
$second = $this->service->createForDocument(Document::factory()->registered()->create());
|
|
|
|
$this->assertNotSame($first->fresh()->number, $second->fresh()->number);
|
|
}
|
|
|
|
public function test_mark_paid_updates_invoice_status_method_and_paid_at(): void
|
|
{
|
|
Carbon::setTestNow('2026-09-21 10:00:00');
|
|
$invoice = Invoice::factory()->create();
|
|
|
|
$paid = $this->service->markPaid($invoice, InvoicePaymentMethodEnum::Gateway);
|
|
|
|
$this->assertSame(InvoiceStatusEnum::Paid, $paid->status);
|
|
$this->assertSame(InvoicePaymentMethodEnum::Gateway, $paid->payment_method);
|
|
$this->assertTrue($paid->paid_at->eq(Carbon::parse('2026-09-21 10:00:00')));
|
|
$this->assertDatabaseHas('invoices', [
|
|
'id' => $invoice->id,
|
|
'status' => InvoiceStatusEnum::Paid->value,
|
|
'payment_method' => InvoicePaymentMethodEnum::Gateway->value,
|
|
]);
|
|
}
|
|
|
|
public function test_mark_paid_moves_registered_document_to_in_progress_with_deadline_by_priority(): void
|
|
{
|
|
Carbon::setTestNow('2026-09-21 10:00:00');
|
|
$document = Document::factory()->registered()->high()->create(['processing_deadline' => null]);
|
|
$invoice = Invoice::factory()->create(['document_id' => $document->id, 'user_id' => $document->requester_id]);
|
|
|
|
$this->service->markPaid($invoice, InvoicePaymentMethodEnum::Wallet);
|
|
|
|
$document->refresh();
|
|
$this->assertSame(DocumentStatusEnum::InProgress, $document->status);
|
|
$this->assertTrue($document->processing_deadline->eq(Carbon::parse('2026-09-21 13:00:00')));
|
|
}
|
|
|
|
public function test_mark_paid_uses_medium_priority_hours_for_deadline(): void
|
|
{
|
|
Carbon::setTestNow('2026-09-21 10:00:00');
|
|
$document = Document::factory()->registered()->create(['priority' => DocumentPriorityEnum::Medium, 'processing_deadline' => null]);
|
|
$invoice = Invoice::factory()->create(['document_id' => $document->id, 'user_id' => $document->requester_id]);
|
|
|
|
$this->service->markPaid($invoice, InvoicePaymentMethodEnum::Wallet);
|
|
|
|
$this->assertTrue($document->fresh()->processing_deadline->eq(Carbon::parse('2026-09-22 10:00:00')));
|
|
}
|
|
|
|
public function test_mark_paid_does_not_change_document_that_is_not_registered(): void
|
|
{
|
|
$document = Document::factory()->completed()->create();
|
|
$originalDeadline = $document->processing_deadline;
|
|
$invoice = Invoice::factory()->create(['document_id' => $document->id, 'user_id' => $document->requester_id]);
|
|
|
|
$this->service->markPaid($invoice, InvoicePaymentMethodEnum::Wallet);
|
|
|
|
$document->refresh();
|
|
$this->assertSame(DocumentStatusEnum::Completed, $document->status);
|
|
$this->assertEquals($originalDeadline, $document->processing_deadline);
|
|
}
|
|
|
|
public function test_mark_paid_works_for_invoice_without_document(): void
|
|
{
|
|
$invoice = Invoice::factory()->create(['document_id' => null]);
|
|
|
|
$paid = $this->service->markPaid($invoice, InvoicePaymentMethodEnum::Wallet);
|
|
|
|
$this->assertSame(InvoiceStatusEnum::Paid, $paid->status);
|
|
}
|
|
|
|
public function test_mark_paid_dispatches_payment_confirmed_sms_to_invoice_user(): void
|
|
{
|
|
config(['services.iranpayamak.patterns.payment_confirmed' => 'pattern-code']);
|
|
$user = User::factory()->create(['phone' => '09120000000']);
|
|
$invoice = Invoice::factory()->create(['user_id' => $user->id]);
|
|
|
|
$this->service->markPaid($invoice, InvoicePaymentMethodEnum::Wallet);
|
|
|
|
Queue::assertPushed(SendPatternSms::class, 1);
|
|
}
|
|
|
|
public function test_mark_paid_does_not_dispatch_sms_when_pattern_is_not_configured(): void
|
|
{
|
|
config(['services.iranpayamak.patterns.payment_confirmed' => null]);
|
|
$invoice = Invoice::factory()->create();
|
|
|
|
$this->service->markPaid($invoice, InvoicePaymentMethodEnum::Wallet);
|
|
|
|
Queue::assertNothingPushed();
|
|
}
|
|
}
|