228 lines
7.2 KiB
PHP
228 lines
7.2 KiB
PHP
<?php
|
|
|
|
use App\Models\Client;
|
|
use App\Models\ClientCustomer;
|
|
use App\Models\ClientInvoice;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
it('auto approves invoices created through the web form', function () {
|
|
$user = User::factory()->create();
|
|
$client = Client::create([
|
|
'name' => 'Acme',
|
|
'customer_id' => '1234567890',
|
|
'status' => 'ENABLED',
|
|
'time_zone' => 'Asia/Kuala_Lumpur',
|
|
'industry' => 'Marketing',
|
|
'sql_acc_code' => 'SEM-001',
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('client-invoices.store'), [
|
|
'client_id' => $client->id,
|
|
'customer_id' => $client->customer_id,
|
|
'invoice_no' => 'INV-1001',
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
])
|
|
->assertRedirect();
|
|
|
|
$invoice = ClientInvoice::where('invoice_no', 'INV-1001')->first();
|
|
|
|
expect($invoice)->not->toBeNull();
|
|
expect($invoice?->approved_at)->not->toBeNull();
|
|
});
|
|
|
|
it('keeps invoices created through the api pending approval', function () {
|
|
$client = Client::create([
|
|
'name' => 'Acme',
|
|
'customer_id' => '1234567891',
|
|
'status' => 'ENABLED',
|
|
'time_zone' => 'Asia/Kuala_Lumpur',
|
|
'industry' => 'Marketing',
|
|
'sql_acc_code' => 'SEM-002',
|
|
]);
|
|
|
|
$this->postJson(route('api.customer-invoices.store'), [
|
|
'client_id' => $client->id,
|
|
'invoice_no' => 'INV-2001',
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
])
|
|
->assertCreated()
|
|
->assertJsonPath('invoice.approved_at', null);
|
|
|
|
$invoice = ClientInvoice::where('invoice_no', 'INV-2001')->first();
|
|
|
|
expect($invoice)->not->toBeNull();
|
|
expect($invoice?->approved_at)->toBeNull();
|
|
});
|
|
|
|
it('links api invoices to existing clients by sql account code', function () {
|
|
$client = Client::create([
|
|
'name' => 'Acme',
|
|
'customer_id' => '1234567894',
|
|
'status' => 'ENABLED',
|
|
'time_zone' => 'Asia/Kuala_Lumpur',
|
|
'industry' => 'Marketing',
|
|
'sql_acc_code' => null,
|
|
]);
|
|
|
|
ClientCustomer::create([
|
|
'client_id' => $client->id,
|
|
'sql_acc_code' => 'SEM-005',
|
|
]);
|
|
|
|
$this->postJson(route('api.customer-invoices.store'), [
|
|
'sql_acc_code' => 'SEM-005',
|
|
'invoice_no' => 'INV-2002',
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
])
|
|
->assertCreated()
|
|
->assertJsonPath('invoice.client_id', $client->id)
|
|
->assertJsonPath('invoice.approved_at', null);
|
|
});
|
|
|
|
it('keeps api invoices pending without a client when sql account code is unknown', function () {
|
|
$this->postJson(route('api.customer-invoices.store'), [
|
|
'sql_acc_code' => 'SEM-006',
|
|
'client_name' => 'New Client',
|
|
'invoice_no' => 'INV-2003',
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
])
|
|
->assertCreated()
|
|
->assertJsonPath('invoice.client_id', null)
|
|
->assertJsonPath('invoice.pending_sql_acc_code', 'SEM-006')
|
|
->assertJsonPath('invoice.pending_client_name', 'New Client');
|
|
});
|
|
|
|
it('lists client invoices pending approval through the api', function () {
|
|
$client = Client::create([
|
|
'name' => 'Acme',
|
|
'customer_id' => '1234567893',
|
|
'status' => 'ENABLED',
|
|
'time_zone' => 'Asia/Kuala_Lumpur',
|
|
'industry' => 'Marketing',
|
|
'sql_acc_code' => 'SEM-004',
|
|
]);
|
|
|
|
ClientInvoice::create([
|
|
'client_id' => $client->id,
|
|
'invoice_no' => 'INV-PENDING',
|
|
'approved_at' => null,
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
]);
|
|
|
|
ClientInvoice::create([
|
|
'client_id' => $client->id,
|
|
'invoice_no' => 'INV-APPROVED',
|
|
'approved_at' => now(),
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
]);
|
|
|
|
$this->getJson(route('api.customer-invoices.pending'))
|
|
->assertOk()
|
|
->assertJsonPath('count', 1)
|
|
->assertJsonPath('invoices.0.invoice_no', 'INV-PENDING')
|
|
->assertJsonMissing(['invoice_no' => 'INV-APPROVED']);
|
|
});
|
|
|
|
it('splits repeated previous payment item amounts by invoice item totals', function () {
|
|
config([
|
|
'app.billing_url' => 'https://billing.test',
|
|
'app.billing_key' => 'secret',
|
|
]);
|
|
|
|
$client = Client::create([
|
|
'name' => 'Acme',
|
|
'customer_id' => '1234567895',
|
|
'status' => 'ENABLED',
|
|
'time_zone' => 'Asia/Kuala_Lumpur',
|
|
'industry' => 'Marketing',
|
|
'sql_acc_code' => 'SEM-007',
|
|
]);
|
|
|
|
ClientInvoice::create([
|
|
'client_id' => $client->id,
|
|
'invoice_no' => 'INV-REPEATED-AMOUNTS',
|
|
'payment_no' => 'PAY-CURRENT',
|
|
'approved_at' => null,
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
]);
|
|
|
|
Http::fake([
|
|
'https://billing.test/customer/invoices/getInvoicePaymentDetailsByInvoiceGoogle*' => Http::response([
|
|
'data' => [
|
|
[
|
|
'payment_number' => 'PAY-PREVIOUS',
|
|
'company_name' => 'Acme',
|
|
'status' => 'Processed',
|
|
'sql_created_at' => '2026-05-18 10:00:00',
|
|
'amount' => 1000,
|
|
'invoice' => [
|
|
'invoice_number' => 'INV-REPEATED-AMOUNTS',
|
|
],
|
|
'items' => [
|
|
[
|
|
'amount' => 1000,
|
|
'item' => [
|
|
'estimated_total' => 880,
|
|
'item' => [
|
|
'sql_acc_code' => 'G03',
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'amount' => 1000,
|
|
'item' => [
|
|
'estimated_total' => 120,
|
|
'item' => [
|
|
'sql_acc_code' => 'GOOGLE',
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
]),
|
|
]);
|
|
|
|
$this->getJson(route('api.customer-invoices.pending'))
|
|
->assertOk()
|
|
->assertJsonPath('invoices.0.previous_payments.0.media_fee', 880.0)
|
|
->assertJsonPath('invoices.0.previous_payments.0.management_fee', 120.0)
|
|
->assertJsonPath('invoices.0.previous_payments.0.invoice_media_fee', 880.0)
|
|
->assertJsonPath('invoices.0.previous_payments.0.invoice_management_fee', 120.0);
|
|
});
|
|
|
|
it('approves a pending invoice from the web approval action', function () {
|
|
$user = User::factory()->create();
|
|
$client = Client::create([
|
|
'name' => 'Acme',
|
|
'customer_id' => '1234567892',
|
|
'status' => 'ENABLED',
|
|
'time_zone' => 'Asia/Kuala_Lumpur',
|
|
'industry' => 'Marketing',
|
|
'sql_acc_code' => 'SEM-003',
|
|
]);
|
|
|
|
$invoice = ClientInvoice::create([
|
|
'client_id' => $client->id,
|
|
'invoice_no' => 'INV-3001',
|
|
'approved_at' => null,
|
|
'management_fee' => 120,
|
|
'media_fee' => 880,
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->patch(route('client-invoices.approve', $invoice))
|
|
->assertRedirect();
|
|
|
|
expect($invoice->refresh()->approved_at)->not->toBeNull();
|
|
});
|