c366614fcd
Task 0.5+0.6: SalesAuthController (login 200/422/403, me, logout) + маршруты /api/sales/auth и зона данных. Порядок middleware admin-db ДО auth:sales. Тест SalesAuthTest 7/7, весь sales-набор 25/25. Logout инвалидирует токен (в тесте Auth::forgetGuards() — артефакт мульти-запросов; в бою каждый запрос свежий). Larastan baseline: Pest false-pos SalesAuthTest. Заодно pint-канон моделей/трейта/SalesModelsTest. Один эскейп на сессию. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
69 lines
2.4 KiB
PHP
69 lines
2.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Concerns;
|
|
|
|
use App\Models\SalesClientAssignment;
|
|
use App\Models\SalesUser;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
|
|
/**
|
|
* Ограничение ownership для портала отдела продаж.
|
|
*
|
|
* Менеджер видит только клиентов, закреплённых за ним (tenant_ids из
|
|
* sales_client_assignments). Начальник (role='head') видит всех — null
|
|
* означает «без ограничения».
|
|
*
|
|
* Используется в контроллерах /api/sales/* для автоматической фильтрации
|
|
* данных в зависимости от роли авторизованного пользователя.
|
|
*
|
|
* Spec: docs/superpowers/plans/2026-06-30-sales-portal.md (Task 0.4)
|
|
*/
|
|
trait ScopesSalesOwnership
|
|
{
|
|
/**
|
|
* null => начальник (видит всех); массив => менеджер (только эти tenant_id).
|
|
*
|
|
* @return list<int>|null
|
|
*/
|
|
protected function ownedTenantIds(SalesUser $user): ?array
|
|
{
|
|
if ($user->isHead()) {
|
|
return null;
|
|
}
|
|
|
|
/** @var list<int> $ids */
|
|
$ids = SalesClientAssignment::query()
|
|
->where('sales_user_id', $user->id)
|
|
->pluck('tenant_id')
|
|
->all();
|
|
|
|
return $ids;
|
|
}
|
|
|
|
/**
|
|
* Применяет фильтр владения к Eloquent-запросу.
|
|
*
|
|
* Для начальника — возвращает запрос без изменений (видит всё).
|
|
* Для менеджера — добавляет whereIn по $column.
|
|
* Если у менеджера нет закреплённых клиентов — подставляет [-1],
|
|
* чтобы запрос вернул пустую коллекцию.
|
|
*
|
|
* @template TModel of \Illuminate\Database\Eloquent\Model
|
|
*
|
|
* @param Builder<TModel> $query
|
|
* @return Builder<TModel>
|
|
*/
|
|
protected function scopeByOwnership(Builder $query, SalesUser $user, string $column = 'tenant_id'): Builder
|
|
{
|
|
$ids = $this->ownedTenantIds($user);
|
|
|
|
if ($ids === null) {
|
|
return $query; // начальник — без ограничения
|
|
}
|
|
|
|
return $query->whereIn($column, $ids === [] ? [-1] : $ids); // пустой → ничего
|
|
}
|
|
}
|