103 lines
3.8 KiB
PHP
103 lines
3.8 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Models\LegalEntity;
|
||
|
|
use App\Models\SaasInvoice;
|
||
|
|
use App\Models\Tenant;
|
||
|
|
use App\Models\TenantRequisites;
|
||
|
|
use App\Models\User;
|
||
|
|
use App\Services\Billing\Invoice\InvoiceService;
|
||
|
|
use App\Services\Billing\Invoice\RequisitesIncompleteException;
|
||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||
|
|
use Illuminate\Support\Facades\Storage;
|
||
|
|
|
||
|
|
uses(DatabaseTransactions::class);
|
||
|
|
|
||
|
|
function makeSellerLe(): LegalEntity
|
||
|
|
{
|
||
|
|
return LegalEntity::create([
|
||
|
|
'code' => 'seller_'.uniqid(), 'name' => 'ИП Лидерра', 'legal_form' => 'IP',
|
||
|
|
'inn' => '770000000001', 'bank_name' => 'ВТБ', 'bank_bik' => '044525187',
|
||
|
|
'bank_account' => '40802810000000000001', 'bank_corr' => '30101810700000000187',
|
||
|
|
'is_default' => true,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeClientRequisites(int $tenantId): TenantRequisites
|
||
|
|
{
|
||
|
|
return TenantRequisites::create([
|
||
|
|
'tenant_id' => $tenantId,
|
||
|
|
'subject_type' => 'legal_entity',
|
||
|
|
'contact_name' => 'Иван Клиентов',
|
||
|
|
'contact_phone' => '+79150000000',
|
||
|
|
'inn' => '5000000000',
|
||
|
|
'legal_name' => 'ООО Клиент',
|
||
|
|
'kpp' => '500001001',
|
||
|
|
'legal_address' => 'г. Москва, ул. Пример, 1',
|
||
|
|
'bank_account' => '40702810000000000002',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
it('создаёт счёт issued с позицией, без НДС, номером и PDF', function () {
|
||
|
|
Storage::fake('local');
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
makeSellerLe();
|
||
|
|
makeClientRequisites($tenant->id);
|
||
|
|
|
||
|
|
$invoice = app(InvoiceService::class)->create($tenant->id, '1500.00', null);
|
||
|
|
|
||
|
|
expect($invoice->status)->toBe(SaasInvoice::STATUS_ISSUED)
|
||
|
|
->and((string) $invoice->amount_total)->toBe('1500.00')
|
||
|
|
->and((float) $invoice->vat_amount)->toBe(0.0)
|
||
|
|
->and($invoice->invoice_number)->toStartWith('СЧ-')
|
||
|
|
->and($invoice->pdf_path)->not->toBeNull()
|
||
|
|
->and($invoice->payer_name)->toBe('ООО Клиент')
|
||
|
|
->and($invoice->items()->count())->toBe(1)
|
||
|
|
->and($invoice->payment_purpose)->toContain($invoice->invoice_number);
|
||
|
|
|
||
|
|
Storage::disk('local')->assertExists($invoice->pdf_path);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('бросает доменную ошибку если реквизиты клиента не заполнены', function () {
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
makeSellerLe();
|
||
|
|
|
||
|
|
app(InvoiceService::class)->create($tenant->id, '1500.00', null);
|
||
|
|
})->throws(RequisitesIncompleteException::class);
|
||
|
|
|
||
|
|
it('POST /api/billing/invoices создаёт счёт и возвращает 201 с pdf-ссылкой', function () {
|
||
|
|
Storage::fake('local');
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
makeSellerLe();
|
||
|
|
makeClientRequisites($tenant->id);
|
||
|
|
$this->actingAs(User::factory()->create(['tenant_id' => $tenant->id]));
|
||
|
|
|
||
|
|
$this->postJson('/api/billing/invoices', ['amount_rub' => 2000])
|
||
|
|
->assertStatus(201)
|
||
|
|
->assertJsonStructure(['invoice' => ['id', 'invoice_number', 'amount_total', 'pdf_url']]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('POST /api/billing/invoices без реквизитов → 422', function () {
|
||
|
|
Storage::fake('local');
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
makeSellerLe();
|
||
|
|
$this->actingAs(User::factory()->create(['tenant_id' => $tenant->id]));
|
||
|
|
|
||
|
|
$this->postJson('/api/billing/invoices', ['amount_rub' => 2000])->assertStatus(422);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('GET /api/billing/invoices/{id}/pdf скачивает PDF своего счёта', function () {
|
||
|
|
Storage::fake('local');
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
makeSellerLe();
|
||
|
|
makeClientRequisites($tenant->id);
|
||
|
|
$this->actingAs(User::factory()->create(['tenant_id' => $tenant->id]));
|
||
|
|
|
||
|
|
$invoice = app(InvoiceService::class)->create($tenant->id, '2000.00', null);
|
||
|
|
|
||
|
|
$this->get("/api/billing/invoices/{$invoice->id}/pdf")
|
||
|
|
->assertOk()
|
||
|
|
->assertHeader('content-type', 'application/pdf');
|
||
|
|
});
|