Files
portal-api/tests/Feature/Api/Admin/Customer/CreateServicePaymentStatusTest.php

114 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Api\Admin\Customer;
use App\Enums\Invoice\InvoiceStatus;
use App\Models\Customer;
use App\Models\Invoice;
use App\Models\Product;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Role;
use Tests\TestCase;
class CreateServicePaymentStatusTest extends TestCase
{
use RefreshDatabase;
private User $admin;
private Customer $customer;
private Product $product;
protected function setUp(): void
{
parent::setUp();
Role::firstOrCreate(['name' => 'Full Administrator', 'guard_name' => 'admin']);
$this->admin = User::factory()->create();
$this->admin->assignRole('Full Administrator');
$this->customer = Customer::factory()->create(['total' => 1_000_000]);
$this->product = Product::factory()->create(['product_type' => 'hosting']);
}
private function createService(array $data)
{
return $this->actingAs($this->admin, 'admin')->postJson(
"/api/v1/administrator/customers/{$this->customer->uuid}/services",
['product_id' => $this->product->id, 'server_name' => 'site.vn', 'price' => 500_000, ...$data],
);
}
public function test_paid_in_full_marks_invoice_paid(): void
{
$this->createService(['payment_status' => 'paid', 'payment_method' => 'balance'])->assertCreated();
$invoice = Invoice::sole();
$this->assertSame(InvoiceStatus::PAID->value, (int) $invoice->status);
$this->assertSame(500_000, (int) $invoice->amount_paid);
$this->assertSame(500_000, (int) $this->customer->fresh()->total);
}
public function test_partial_payment_keeps_invoice_unpaid_with_prepaid_amount(): void
{
$this->createService(['payment_status' => 'partial', 'payment_method' => 'balance', 'amount_paid' => 200_000])->assertCreated();
$invoice = Invoice::sole();
$this->assertSame(InvoiceStatus::UNPAID->value, (int) $invoice->status);
$this->assertSame(500_000, (int) $invoice->total);
$this->assertSame(200_000, (int) $invoice->amount_paid);
$this->assertSame(200_000, (int) Transaction::sole()->amount);
$this->assertSame(800_000, (int) $this->customer->fresh()->total);
}
public function test_service_detail_lists_every_payment_installment_of_an_invoice(): void
{
$serviceId = $this->createService(['payment_status' => 'partial', 'payment_method' => 'balance', 'amount_paid' => 200_000])
->assertCreated()
->json('data.id');
$invoice = Invoice::sole();
$admin = $this->actingAs($this->admin, 'admin');
$admin->postJson("/api/v1/administrator/invoices/{$invoice->id}/paid", ['received_amount' => 100_000])->assertOk();
$admin->postJson("/api/v1/administrator/invoices/{$invoice->id}/paid", ['note' => 'Đợt cuối'])->assertOk();
$payments = $admin->getJson("/api/v1/administrator/services/{$serviceId}")
->assertOk()
->json('data.linked_invoices.0.payments');
$this->assertSame([200_000, 100_000, 200_000], array_column($payments, 'amount'));
$this->assertSame(InvoiceStatus::PAID->value, (int) $invoice->fresh()->status);
}
public function test_decimal_amounts_are_rounded_to_whole_dong(): void
{
$this->createService(['price' => 731.33, 'payment_status' => 'partial', 'payment_method' => 'balance', 'amount_paid' => 400.6])->assertCreated();
$invoice = Invoice::sole();
$this->assertSame(731, (int) $invoice->total);
$this->assertSame(401, (int) $invoice->amount_paid);
}
public function test_partial_payment_must_be_less_than_price(): void
{
$this->createService(['payment_status' => 'partial', 'payment_method' => 'balance', 'amount_paid' => 500_000])->assertStatus(422);
$this->createService(['payment_status' => 'partial', 'payment_method' => 'balance'])->assertStatus(422);
$this->assertSame(0, Invoice::count());
}
public function test_unpaid_creates_unpaid_invoice_without_transaction(): void
{
$this->createService(['payment_status' => 'unpaid'])->assertCreated();
$invoice = Invoice::sole();
$this->assertSame(InvoiceStatus::UNPAID->value, (int) $invoice->status);
$this->assertSame(0, (int) $invoice->amount_paid);
$this->assertSame(0, Transaction::count());
$this->assertSame(1_000_000, (int) $this->customer->fresh()->total);
}
}