'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'); });