Files
InvoiceShelf/tests/Feature/Admin/CreditNoteSchemaTest.php
T
Darko Gjorgjijoski 5ef7804e60 refactor: adopt modular domain architecture (#747)
* refactor: stabilize model identities for domain migration

* refactor: extract module platform context

* refactor: assign models to domain contexts

* refactor: extract ai platform context

* refactor: extract storage platform context

* refactor: extract mail platform context

* refactor: extract pdf platform context

* refactor: extract operations platform context

* refactor: move installation into operations platform

* refactor: extract money domain context

* refactor: extract taxation domain context

* refactor: extract catalog domain context

* refactor: extract metadata domain context

* refactor: extract reporting domain context

* refactor: extract purchases domain context

* refactor: extract receivables domain context

* refactor: extract accounts domain context

* refactor: complete reporting statement boundary

* refactor: extract contacts domain context

* refactor: extract sales domain context

* refactor: remove legacy application layers

* fix: migrate legacy bouncer role identities
2026-08-05 17:40:03 +02:00

96 lines
3.2 KiB
PHP

<?php
use App\Domains\Accounts\Models\Company;
use App\Domains\Accounts\Models\CompanySetting;
use App\Domains\Sales\Models\Invoice;
use App\Domains\Sales\Models\InvoiceItem;
use App\Domains\Taxation\Models\Tax;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schema;
beforeEach(function () {
Artisan::call('db:seed', ['--class' => 'DatabaseSeeder', '--force' => true]);
Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]);
});
/**
* Resolve a column definition from the information schema so nullability can
* be asserted without reaching for driver-specific SQL.
*/
function creditNoteColumn(string $table, string $column): array
{
$definition = collect(Schema::getColumns($table))
->firstWhere('name', $column);
expect($definition)->not->toBeNull();
return $definition;
}
test('the credit note columns exist with the expected nullability', function () {
expect(Schema::hasColumn('invoices', 'type'))->toBeTrue();
expect(Schema::hasColumn('invoices', 'related_invoice_id'))->toBeTrue();
expect(Schema::hasColumn('invoices', 'credit_reason'))->toBeTrue();
expect(Schema::hasColumn('invoice_items', 'source_invoice_item_id'))->toBeTrue();
// "type" is non-nullable and defaults to INVOICE so pre-existing rows fall
// inside the type-scoped serial-number queries.
expect(creditNoteColumn('invoices', 'type')['nullable'])->toBeFalse();
expect(creditNoteColumn('invoices', 'related_invoice_id')['nullable'])->toBeTrue();
expect(creditNoteColumn('invoices', 'credit_reason')['nullable'])->toBeTrue();
expect(creditNoteColumn('invoice_items', 'source_invoice_item_id')['nullable'])->toBeTrue();
});
test('invoices created without a type default to INVOICE', function () {
$invoice = Invoice::factory()->create();
expect($invoice->fresh()->type)->toBe(Invoice::TYPE_INVOICE);
});
test('a tax row persists a negative base amount', function () {
$tax = Tax::factory()->create([
'amount' => -2500,
'base_amount' => -2500,
]);
$this->assertDatabaseHas('taxes', [
'id' => $tax->id,
'amount' => -2500,
'base_amount' => -2500,
]);
expect((int) $tax->fresh()->base_amount)->toBe(-2500);
});
test('an invoice item persists a negative price and links its source line', function () {
$invoice = Invoice::factory()->hasItems(1)->create();
$sourceItem = $invoice->items()->first();
$creditLine = InvoiceItem::factory()->create([
'invoice_id' => $invoice->id,
'source_invoice_item_id' => $sourceItem->id,
'price' => -1500,
'base_price' => -1500,
'total' => -1500,
]);
$this->assertDatabaseHas('invoice_items', [
'id' => $creditLine->id,
'source_invoice_item_id' => $sourceItem->id,
'price' => -1500,
'base_price' => -1500,
]);
});
test('every seeded company has a credit note number format', function () {
$companies = Company::all();
expect($companies)->not->toBeEmpty();
$companies->each(function ($company) {
expect(CompanySetting::getSetting('credit_note_number_format', $company->id))
->toBe('{{SERIES:CN}}{{DELIMITER:-}}{{SEQUENCE:6}}');
});
});