|null */ public function ids(): ?array { return $this->ownedTenantIds($this->u); } public function scoped(Builder $query): Builder { return $this->scopeByOwnership($query, $this->u); } } // ── helpers ──────────────────────────────────────────────────────────────── function makeSalesUserOwn(string $role = 'manager'): SalesUser { return SalesUser::create([ 'name' => ucfirst($role).' '.uniqid(), 'email' => $role.uniqid().'@scope.local', 'password' => Hash::make('secret'), 'role' => $role, ]); } // ── 1. ownedTenantIds ────────────────────────────────────────────────────── test('ownedTenantIds для менеджера возвращает список его tenant_id', function () { $manager = makeSalesUserOwn('manager'); $t1 = Tenant::factory()->create(); $t2 = Tenant::factory()->create(); SalesClientAssignment::create([ 'sales_user_id' => $manager->id, 'tenant_id' => $t1->id, 'tariff_params' => [], 'assigned_at' => now(), ]); SalesClientAssignment::create([ 'sales_user_id' => $manager->id, 'tenant_id' => $t2->id, 'tariff_params' => [], 'assigned_at' => now(), ]); $probe = new OwnershipProbe($manager); $ids = $probe->ids(); expect($ids)->toBeArray() ->toEqualCanonicalizing([$t1->id, $t2->id]); }); test('ownedTenantIds для head возвращает null (нет ограничения)', function () { $head = makeSalesUserOwn('head'); $probe = new OwnershipProbe($head); expect($probe->ids())->toBeNull(); }); test('ownedTenantIds для менеджера без клиентов возвращает пустой массив', function () { $manager = makeSalesUserOwn('manager'); $probe = new OwnershipProbe($manager); $ids = $probe->ids(); expect($ids)->toBeArray()->toBeEmpty(); }); // ── 2. scopeByOwnership ──────────────────────────────────────────────────── test('scopeByOwnership для менеджера ограничивает запрос его tenant_id', function () { $manager = makeSalesUserOwn('manager'); $other = makeSalesUserOwn('manager'); $t1 = Tenant::factory()->create(); $t2 = Tenant::factory()->create(); $t3 = Tenant::factory()->create(); SalesClientAssignment::create([ 'sales_user_id' => $manager->id, 'tenant_id' => $t1->id, 'tariff_params' => [], 'assigned_at' => now(), ]); SalesClientAssignment::create([ 'sales_user_id' => $manager->id, 'tenant_id' => $t2->id, 'tariff_params' => [], 'assigned_at' => now(), ]); // t3 принадлежит другому менеджеру SalesClientAssignment::create([ 'sales_user_id' => $other->id, 'tenant_id' => $t3->id, 'tariff_params' => [], 'assigned_at' => now(), ]); $probe = new OwnershipProbe($manager); $results = $probe->scoped(SalesClientAssignment::query())->get(); $tenantIds = $results->pluck('tenant_id')->sort()->values()->all(); expect($tenantIds)->toEqualCanonicalizing([$t1->id, $t2->id]); }); test('scopeByOwnership для head не ограничивает запрос (видит всех)', function () { $head = makeSalesUserOwn('head'); $manager = makeSalesUserOwn('manager'); $t1 = Tenant::factory()->create(); $t2 = Tenant::factory()->create(); SalesClientAssignment::create([ 'sales_user_id' => $manager->id, 'tenant_id' => $t1->id, 'tariff_params' => [], 'assigned_at' => now(), ]); SalesClientAssignment::create([ 'sales_user_id' => $manager->id, 'tenant_id' => $t2->id, 'tariff_params' => [], 'assigned_at' => now(), ]); $probe = new OwnershipProbe($head); $results = $probe->scoped(SalesClientAssignment::query())->get(); // Head видит все записи (в контексте транзакции — минимум 2 наши) expect($results->count())->toBeGreaterThanOrEqual(2); }); test('scopeByOwnership для менеджера без клиентов возвращает пустую коллекцию', function () { $manager = makeSalesUserOwn('manager'); // Создаём другого менеджера с клиентом, чтобы таблица не была пустой $other = makeSalesUserOwn('manager'); $t1 = Tenant::factory()->create(); SalesClientAssignment::create([ 'sales_user_id' => $other->id, 'tenant_id' => $t1->id, 'tariff_params' => [], 'assigned_at' => now(), ]); $probe = new OwnershipProbe($manager); $results = $probe->scoped(SalesClientAssignment::query())->get(); expect($results)->toBeEmpty(); });