102 lines
4.0 KiB
PHP
102 lines
4.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\Project;
|
|
use App\Models\ReportJob;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Services\Reports\Providers\ManagersSummaryProvider;
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
uses(DatabaseTransactions::class);
|
|
|
|
beforeEach(function () {
|
|
$this->tenant = Tenant::factory()->create();
|
|
$this->project = Project::factory()->create(['tenant_id' => $this->tenant->id]);
|
|
});
|
|
|
|
/** Вставляет сделку напрямую (deals партиционирована, фабрики нет). */
|
|
function seedManagerDeal(int $tenantId, int $projectId, array $overrides = []): void
|
|
{
|
|
DB::table('deals')->insert(array_merge([
|
|
'tenant_id' => $tenantId,
|
|
'project_id' => $projectId,
|
|
'phone' => '+7999'.random_int(1000000, 9999999),
|
|
'status' => 'new',
|
|
'received_at' => Carbon::now()->startOfMonth()->addDays(10),
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now(),
|
|
], $overrides));
|
|
}
|
|
|
|
/** ReportJob без сохранения — провайдер читает только tenant_id + parameters. */
|
|
function managersJob(int $tenantId): ReportJob
|
|
{
|
|
return new ReportJob([
|
|
'tenant_id' => $tenantId,
|
|
'type' => 'managers_summary',
|
|
'parameters' => [
|
|
'format' => 'csv',
|
|
'date_from' => Carbon::now()->startOfMonth()->toDateString(),
|
|
'date_to' => Carbon::now()->endOfMonth()->toDateString(),
|
|
],
|
|
]);
|
|
}
|
|
|
|
test('headers: 4 колонки', function () {
|
|
expect((new ManagersSummaryProvider)->headers())
|
|
->toBe(['Менеджер', 'Всего сделок', 'Оплачено', 'Конверсия (%)']);
|
|
});
|
|
|
|
test('slug = managers', function () {
|
|
expect((new ManagersSummaryProvider)->slug())->toBe('managers');
|
|
});
|
|
|
|
test('агрегирует сделки по менеджеру: total, won, конверсия', function () {
|
|
$manager = User::factory()->create([
|
|
'tenant_id' => $this->tenant->id, 'first_name' => 'Иван', 'last_name' => 'Петров',
|
|
]);
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => $manager->id, 'status' => 'won']);
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => $manager->id, 'status' => 'won']);
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => $manager->id, 'status' => 'new']);
|
|
|
|
$rows = (new ManagersSummaryProvider)->rows(managersJob($this->tenant->id));
|
|
|
|
expect($rows)->toHaveCount(1);
|
|
expect($rows[0])->toBe(['Иван Петров', 3, 2, 66.7]);
|
|
});
|
|
|
|
test('сделки без менеджера → строка «Не назначен»', function () {
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => null, 'status' => 'new']);
|
|
|
|
$rows = (new ManagersSummaryProvider)->rows(managersJob($this->tenant->id));
|
|
|
|
expect($rows)->toHaveCount(1);
|
|
expect($rows[0][0])->toBe('Не назначен');
|
|
});
|
|
|
|
test('исключает soft-deleted и тестовые сделки', function () {
|
|
$manager = User::factory()->create(['tenant_id' => $this->tenant->id]);
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => $manager->id]);
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => $manager->id, 'deleted_at' => Carbon::now()]);
|
|
seedManagerDeal($this->tenant->id, $this->project->id, ['manager_id' => $manager->id, 'is_test' => true]);
|
|
|
|
$rows = (new ManagersSummaryProvider)->rows(managersJob($this->tenant->id));
|
|
|
|
expect($rows)->toHaveCount(1);
|
|
expect($rows[0][1])->toBe(1);
|
|
});
|
|
|
|
test('изолирует по tenant_id', function () {
|
|
$other = Tenant::factory()->create();
|
|
$otherProject = Project::factory()->create(['tenant_id' => $other->id]);
|
|
seedManagerDeal($other->id, $otherProject->id);
|
|
|
|
$rows = (new ManagersSummaryProvider)->rows(managersJob($this->tenant->id));
|
|
|
|
expect($rows)->toBe([]);
|
|
});
|