feat(billing): renewals, coupons, VAT numbering, billing cycles and invoice payment tracking
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
ea9a53f742
commit
25f23d541e
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\Api\Admin;
|
||||
|
||||
use App\Enums\Invoice\InvoiceStatus;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Tests\TestCase;
|
||||
|
||||
class InvoiceVatTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private function admin(array $permissions): User
|
||||
{
|
||||
$role = Role::create(['name' => 'role-' . uniqid(), 'guard_name' => 'admin']);
|
||||
foreach (['invoice.view', 'invoice.edit', 'customer.view', 'customer.edit'] as $name) {
|
||||
Permission::firstOrCreate(['name' => $name, 'guard_name' => 'admin']);
|
||||
}
|
||||
$role->givePermissionTo($permissions);
|
||||
|
||||
return tap(User::factory()->create())->assignRole($role);
|
||||
}
|
||||
|
||||
private function invoice(string $number, Customer $customer): Invoice
|
||||
{
|
||||
return Invoice::create([
|
||||
'invoice_number' => $number, 'customer_id' => $customer->id, 'invoice_type' => 1,
|
||||
'sub_total' => 1000, 'tax' => 0, 'total' => 1000, 'status' => InvoiceStatus::PAID->value,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_recording_vat_freezes_buyer_and_rejects_duplicate_number(): void
|
||||
{
|
||||
$customer = Customer::factory()->create(['tax_code' => '0312345678', 'invoice_company' => 'ABC']);
|
||||
$first = $this->invoice('INV-V1', $customer);
|
||||
$second = $this->invoice('INV-V2', $customer);
|
||||
$payload = ['vat_serial' => '1C26TCP', 'vat_number' => '15', 'vat_issued_at' => '2026-10-19'];
|
||||
$admin = $this->admin(['invoice.view', 'invoice.edit']);
|
||||
|
||||
$this->actingAs($admin, 'admin')->putJson("/api/v1/administrator/invoices/{$first->id}/vat", $payload)
|
||||
->assertOk()->assertJsonPath('data.buyer_locked', true);
|
||||
$customer->update(['tax_code' => '0999999999']);
|
||||
$this->actingAs($admin, 'admin')->getJson("/api/v1/administrator/invoices/{$first->id}/vat")
|
||||
->assertJsonPath('data.buyer.tax_code', '0312345678');
|
||||
|
||||
$this->actingAs($admin, 'admin')->putJson("/api/v1/administrator/invoices/{$second->id}/vat", $payload)
|
||||
->assertStatus(422)->assertJsonValidationErrors('vat_number');
|
||||
}
|
||||
|
||||
public function test_vat_endpoints_require_permissions(): void
|
||||
{
|
||||
$customer = Customer::factory()->create();
|
||||
$invoice = $this->invoice('INV-V3', $customer);
|
||||
$viewer = $this->admin(['invoice.view']);
|
||||
|
||||
$this->actingAs($viewer, 'admin')->putJson("/api/v1/administrator/invoices/{$invoice->id}/vat", [])->assertForbidden();
|
||||
$this->actingAs($viewer, 'admin')->putJson("/api/v1/administrator/customers/{$customer->uuid}/billing-profile", [])->assertForbidden();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user