Files
portal/app/tests/Feature/Sales/SalesAttachmentServiceTest.php
T

171 lines
7.1 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Mail\Sales\AttachmentNotFoundMail;
use App\Mail\Sales\AttachmentSubmittedMail;
use App\Models\SalesAttachmentRequest;
use App\Models\SalesClientAssignment;
use App\Models\SalesUser;
use App\Models\Tenant;
use App\Models\TenantRequisites;
use App\Services\Sales\SalesAttachmentService;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Mail;
/**
* TDD: SalesAttachmentService — поиск клиента и подача заявки на привязку.
*
* Покрывает Task 2.1: lookup() и submit() со всеми ветками:
* - not_found → status='not_found' + AttachmentNotFoundMail менеджеру
* - свободен → status='pending' + AttachmentSubmittedMail менеджеру и всем начальникам
* - занят другим → status='pending' + comment с именем другого менеджера
* - уже у этого → DomainException "Этот клиент уже ваш."
*
* Изоляция: DatabaseTransactions — откат в конце каждого теста.
* DB_DATABASE=liderra_testing, DEFAULT connection (pgsql).
*/
uses(DatabaseTransactions::class);
// ── helpers ─────────────────────────────────────────────────────────────────
function makeManager(array $attrs = []): SalesUser
{
return SalesUser::create(array_merge([
'name' => 'Менеджер '.uniqid(),
'email' => 'mgr'.uniqid().'@sales.local',
'password' => bcrypt('secret'),
'role' => 'manager',
], $attrs));
}
function makeHead(array $attrs = []): SalesUser
{
return SalesUser::create(array_merge([
'name' => 'Руководитель '.uniqid(),
'email' => 'head'.uniqid().'@sales.local',
'password' => bcrypt('secret'),
'role' => 'head',
'is_active' => true,
], $attrs));
}
function makeService(): SalesAttachmentService
{
return app(SalesAttachmentService::class);
}
// ── lookup() ─────────────────────────────────────────────────────────────────
test('lookup находит тенанта по contact_email', function (): void {
$tenant = Tenant::factory()->create(['contact_email' => 'client-email@example.com']);
$found = makeService()->lookup('client-email@example.com');
expect($found)->not->toBeNull()
->and($found->id)->toBe($tenant->id);
});
test('lookup находит тенанта по ИНН из tenant_requisites', function (): void {
$tenant = Tenant::factory()->create();
TenantRequisites::create([
'tenant_id' => $tenant->id,
'subject_type' => 'sole_proprietor',
'contact_name' => 'Тест ИП',
'contact_phone' => '+79000000001',
'inn' => '245210851872',
]);
$found = makeService()->lookup('245210851872');
expect($found)->not->toBeNull()
->and($found->id)->toBe($tenant->id);
});
test('lookup возвращает null если нет совпадения ни по email ни по ИНН', function (): void {
$result = makeService()->lookup('nobody@nowhere.test');
expect($result)->toBeNull();
});
// ── submit() — not_found ──────────────────────────────────────────────────────
test('submit для несуществующего логина создаёт заявку not_found и шлёт AttachmentNotFoundMail', function (): void {
Mail::fake();
$manager = makeManager();
$req = makeService()->submit($manager, 'nobody@nowhere.test');
expect($req)->toBeInstanceOf(SalesAttachmentRequest::class)
->and($req->status)->toBe('not_found')
->and($req->sales_user_id)->toBe($manager->id)
->and($req->login_input)->toBe('nobody@nowhere.test')
->and($req->tenant_id)->toBeNull();
Mail::assertQueued(AttachmentNotFoundMail::class, fn ($mail): bool => $mail->hasTo($manager->email)
);
});
// ── submit() — свободный клиент ───────────────────────────────────────────────
test('submit для свободного клиента создаёт pending-заявку и шлёт AttachmentSubmittedMail менеджеру и начальнику', function (): void {
Mail::fake();
$manager = makeManager();
$head = makeHead();
$tenant = Tenant::factory()->create(['contact_email' => 'free-client@example.com']);
$req = makeService()->submit($manager, 'free-client@example.com');
expect($req->status)->toBe('pending')
->and($req->tenant_id)->toBe($tenant->id)
->and($req->comment)->toBeNull();
// Письмо должно уйти менеджеру
Mail::assertQueued(AttachmentSubmittedMail::class, fn ($mail): bool => $mail->hasTo($manager->email)
);
// Письмо должно уйти начальнику
Mail::assertQueued(AttachmentSubmittedMail::class, fn ($mail): bool => $mail->hasTo($head->email)
);
});
// ── submit() — клиент уже занят другим менеджером ─────────────────────────────
test('submit для клиента занятого другим менеджером создаёт pending с комментарием о конфликте', function (): void {
Mail::fake();
$manager = makeManager();
$otherManager = makeManager(['name' => 'Другой Менеджер']);
$tenant = Tenant::factory()->create(['contact_email' => 'taken-client@example.com']);
SalesClientAssignment::create([
'sales_user_id' => $otherManager->id,
'tenant_id' => $tenant->id,
'tariff_params' => [],
'assigned_at' => now(),
]);
$req = makeService()->submit($manager, 'taken-client@example.com');
expect($req->status)->toBe('pending')
->and($req->tenant_id)->toBe($tenant->id)
->and($req->comment)->toContain('Другой Менеджер');
});
// ── submit() — клиент уже у этого менеджера ──────────────────────────────────
test('submit для клиента уже привязанного к этому менеджеру бросает DomainException', function (): void {
Mail::fake();
$manager = makeManager();
$tenant = Tenant::factory()->create(['contact_email' => 'own-client@example.com']);
SalesClientAssignment::create([
'sales_user_id' => $manager->id,
'tenant_id' => $tenant->id,
'tariff_params' => [],
'assigned_at' => now(),
]);
expect(fn (): SalesAttachmentRequest => makeService()->submit($manager, 'own-client@example.com'))
->toThrow(DomainException::class, 'Этот клиент уже ваш.');
});