132 lines
5.4 KiB
PHP
132 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Api\Admin\Service;
|
|
|
|
use App\Enums\Invoice\InvoiceStatus;
|
|
use App\Enums\Order\OrderStatus;
|
|
use App\Models\Customer;
|
|
use App\Models\Invoice;
|
|
use App\Models\InvoiceAttachment;
|
|
use App\Models\Order;
|
|
use App\Models\OrderItem;
|
|
use App\Models\Service;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Spatie\Permission\Models\Role;
|
|
use Tests\TestCase;
|
|
|
|
class ServiceAttachmentTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private User $admin;
|
|
private Service $service;
|
|
private Invoice $invoice;
|
|
private Invoice $foreignInvoice;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
Storage::fake('public');
|
|
|
|
Role::firstOrCreate(['name' => 'Full Administrator', 'guard_name' => 'admin']);
|
|
$this->admin = User::factory()->create();
|
|
$this->admin->assignRole('Full Administrator');
|
|
|
|
$customer = Customer::factory()->create();
|
|
$order = $this->makeOrder($customer);
|
|
$item = OrderItem::create(['order_id' => $order->id, 'product_id' => null, 'billing_cycle' => 'monthly', 'months' => 1, 'quantity' => 1, 'price' => 100000]);
|
|
$this->service = Service::create(['customer_id' => $customer->id, 'order_item_id' => $item->id, 'status' => 'active']);
|
|
$this->invoice = $this->makeInvoice($customer, $order);
|
|
$this->foreignInvoice = $this->makeInvoice($customer, $this->makeOrder($customer));
|
|
}
|
|
|
|
public function test_upload_list_copy_to_invoice_and_delete(): void
|
|
{
|
|
$base = "/api/v1/administrator/services/{$this->service->id}/attachments";
|
|
$admin = $this->actingAs($this->admin, 'admin');
|
|
|
|
$id = $admin->post($base, ['file' => UploadedFile::fake()->create('spec.pdf', 10, 'application/pdf')], ['Accept' => 'application/json'])
|
|
->assertCreated()
|
|
->json('data.id');
|
|
|
|
$admin->getJson($base)
|
|
->assertOk()
|
|
->assertJsonPath('data.attachments.0.filename', 'spec.pdf')
|
|
->assertJsonCount(1, 'data.invoices')
|
|
->assertJsonPath('data.invoices.0.id', $this->invoice->id);
|
|
|
|
$admin->postJson("$base/$id/copy-to-invoice", ['invoice_id' => $this->foreignInvoice->id])->assertNotFound();
|
|
|
|
$admin->postJson("$base/$id/copy-to-invoice", ['invoice_id' => $this->invoice->id])->assertCreated();
|
|
$admin->postJson("$base/$id/copy-to-invoice", ['invoice_id' => $this->invoice->id])->assertCreated();
|
|
$copy = InvoiceAttachment::where('invoice_id', $this->invoice->id)->sole();
|
|
$this->assertSame(InvoiceAttachment::TYPE_DEPLOYMENT, $copy->type);
|
|
Storage::disk('public')->assertExists($copy->path);
|
|
|
|
$admin->deleteJson("$base/$id")->assertOk();
|
|
$this->assertDatabaseCount('service_attachments', 0);
|
|
Storage::disk('public')->assertExists($copy->path);
|
|
}
|
|
|
|
public function test_upload_accepts_zip_and_rejects_executables(): void
|
|
{
|
|
$base = "/api/v1/administrator/services/{$this->service->id}/attachments";
|
|
$admin = $this->actingAs($this->admin, 'admin');
|
|
|
|
$admin->post($base, ['file' => UploadedFile::fake()->create('source.zip', 10, 'application/zip')], ['Accept' => 'application/json'])
|
|
->assertCreated();
|
|
$admin->post($base, ['file' => UploadedFile::fake()->create('run.exe', 10, 'application/x-msdownload')], ['Accept' => 'application/json'])
|
|
->assertUnprocessable();
|
|
|
|
$this->assertDatabaseCount('service_attachments', 1);
|
|
}
|
|
|
|
public function test_list_and_detail_expose_linked_order_and_invoices(): void
|
|
{
|
|
$admin = $this->actingAs($this->admin, 'admin');
|
|
|
|
$admin->getJson('/api/v1/administrator/services')
|
|
->assertOk()
|
|
->assertJsonPath('data.items.0.order_item.order.order_num', $this->invoice->order->order_num)
|
|
->assertJsonCount(1, 'data.items.0.linked_invoices')
|
|
->assertJsonPath('data.items.0.linked_invoices.0.invoice_number', $this->invoice->invoice_number);
|
|
|
|
$admin->getJson("/api/v1/administrator/services/{$this->service->id}")
|
|
->assertOk()
|
|
->assertJsonPath('data.linked_invoices.0.id', $this->invoice->id)
|
|
->assertJsonPath('data.linked_invoices.0.amount_paid', 0);
|
|
}
|
|
|
|
public function test_rejects_unsupported_file_type(): void
|
|
{
|
|
$this->actingAs($this->admin, 'admin')
|
|
->post("/api/v1/administrator/services/{$this->service->id}/attachments", ['file' => UploadedFile::fake()->create('x.exe', 10)], ['Accept' => 'application/json'])
|
|
->assertStatus(422);
|
|
}
|
|
|
|
private function makeOrder(Customer $customer): Order
|
|
{
|
|
return Order::create(['order_num' => 'ORD-' . uniqid(), 'customer_id' => $customer->id, 'sub_total' => 100_000, 'total' => 100_000, 'status' => OrderStatus::PENDING->value]);
|
|
}
|
|
|
|
private function makeInvoice(Customer $customer, Order $order): Invoice
|
|
{
|
|
return Invoice::create([
|
|
'invoice_number' => 'INV-' . uniqid(),
|
|
'customer_id' => $customer->id,
|
|
'order_id' => $order->id,
|
|
'invoice_type' => 1,
|
|
'sub_total' => 100_000,
|
|
'tax' => 0,
|
|
'total' => 100_000,
|
|
'status' => InvoiceStatus::UNPAID->value,
|
|
'due_date' => now()->addDays(5)->toDateString(),
|
|
]);
|
|
}
|
|
}
|