Менеджеры
Модуль "Менеджеры"
Версия: 1.0
Дата: 2025-11-23
Статус: Реализован
Содержание
- Общее описание
- Текущая реализация
- Права доступа
- Описание полей
- UI/UX
- Бизнес-логика
- Выявленные проблемы
- Рекомендации
1. Общее описание
1.1 Предназначение модуля
Модуль "Менеджеры" предназначен для управления менеджерами дилерских компаний (group_id = 3). Менеджеры — это сотрудники компании, которые курируют дилерские организации и их представителей.
Основные функции:
- Создание и редактирование учётных записей менеджеров
- Назначение индивидуальных прав (политик) доступа
- Просмотр компаний, закреплённых за менеджером
- Авторизация под учётной записью менеджера (impersonate)
1.2 Связь с другими модулями
| Модуль | Связь |
|---|---|
| Дилеры (компании) | company.manager_id → менеджер курирует компании |
| Дилеры (менеджеры) | user.manager_id → менеджер курирует дилеров |
| Заказы | Менеджер видит заказы своих компаний |
| Политики доступа | Индивидуальные права через user_policies |
1.3 Статистика
| Метрика | Значение |
|---|---|
| Всего менеджеров | 10 |
| Активных | 10 |
| С Telegram | 7 |
| Компаний у менеджеров | 183 |
2. Текущая реализация
2.1 Архитектура
┌─────────────────────────────────────────────────────────────────────────────┐
│ МОДУЛЬ "МЕНЕДЖЕРЫ" │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ РОУТЫ (routes/web.php) │
│ ├── GET /managers → ManagerController@index → Список │
│ ├── GET /managers/add → ManagerController@create → Создание │
│ └── GET /managers/edit/{id} → ManagerController@show → Редактирование │
│ │
│ КОНТРОЛЛЕР (ManagerController.php) │
│ └── Проверка прав: manager_can_view, manager_can_add │
│ │
│ LIVEWIRE КОМПОНЕНТЫ │
│ ├── Managers/Listing.php — Таблица менеджеров │
│ ├── Managers/Add.php — Форма создания │
│ ├── Managers/Edit.php — Форма редактирования с 3 вкладками │
│ ├── Managers/Policies.php — Таблица политик (вкладка "Права") │
│ └── Managers/Dealers.php — Таблица компаний менеджера (вкладка "Дилеры") │
│ │
│ МОДЕЛЬ │
│ └── User (group_id = 3) — менеджеры в общей таблице users │
│ │
└─────────────────────────────────────────────────────────────────────────────┘2.2 Структура данных
Менеджеры хранятся в таблице users с group_id = 3.
Поля менеджера в таблице users
| Поле | Тип | Описание |
|---|---|---|
id | bigint | PK |
group_id | int | 3 для менеджеров |
email | string | Email (уникальный) |
password | string | Хэш пароля |
name | string | Имя |
lastname | string | Фамилия |
middlename | string | Отчество |
position | string | Должность |
phone | string | Телефон |
tg_id | string | ID Telegram |
image | string | Аватар |
active | boolean | Активен |
last_auth | datetime | Последняя авторизация |
created_at | timestamp | — |
updated_at | timestamp | — |
2.3 Файлы модуля
app/
├── Http/Controllers/
│ └── ManagerController.php
├── Livewire/Managers/
│ ├── Add.php — Форма создания
│ ├── Edit.php — Форма редактирования (3 вкладки)
│ ├── Listing.php — Таблица списка
│ ├── Policies.php — Таблица политик
│ └── Dealers.php — Таблица компаний менеджера
└── Models/
└── User.php (group_id = 3)
resources/views/templates/managers/
├── table.blade.php
├── add.blade.php
├── edit.blade.php
├── policies.blade.php
└── dealers.blade.php3. Права доступа
3.1 Политики модуля
| Политика | Описание |
|---|---|
manager_can_view | Просмотр списка менеджеров |
manager_can_add | Создание менеджера |
manager_can_edit | Редактирование данных менеджера |
manager_can_delete | Удаление менеджера |
manager_can_auth | Авторизация под менеджером (impersonate) |
manager_can_edit_policy | Редактирование прав менеджера |
manager_can_view_dealers | Просмотр вкладки "Дилеры" с компаниями |
3.2 Проверка в контроллере
// ManagerController.php
public function index(Request $request)
{
if (!$user->check_access('manager_can_view'))
abort(403);
}
public function show(string $id, Request $request)
{
if (!$user->check_access('manager_can_view'))
abort(403);
$manager = User::find($id);
if (!$manager or $manager->group_id !== 3) abort(404); // Проверка group_id
}
public function create(Request $request)
{
if (!$user->check_access('manager_can_add'))
abort(403);
}3.3 Матрица доступа по ролям
| Роль | Просмотр | Создание | Редактир. | Удаление | Impersonate | Права | Дилеры |
|---|---|---|---|---|---|---|---|
| Администратор | ✅* | ✅* | ✅* | ✅* | ✅* | ✅* | ✅* |
| Менеджер | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Производство | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Дилер | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
*Зависит от индивидуальных политик пользователя
4. Описание полей
4.1 Форма создания (Add.php)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
email | TextInput | ✅ | Email (unique) |
password | Password | ✅ | Пароль |
lastname | TextInput | ✅ | Фамилия |
name | TextInput | ✅ | Имя |
middlename | TextInput | ❌ | Отчество |
position | TextInput | ❌ | Должность |
phone | TextInput | ❌ | Телефон (маска +7) |
active | Toggle | ✅ | Активен (по умолчанию true) |
image | FileUpload | ❌ | Аватар (1:1, crop) |
При создании автоматически: group_id = 3
4.2 Форма редактирования (Edit.php)
Вкладка "Данные"
| Поле | Тип | Особенности |
|---|---|---|
email | TextInput | Disabled если нет прав, unique(ignoreRecord) |
password | Password | Hidden если нет прав, хэшируется |
lastname | TextInput | — |
name | TextInput | — |
middlename | TextInput | — |
position | TextInput | — |
tg_id | TextInput | ID Telegram |
phone | TextInput | Маска +7(999) 999 99 99 |
last_auth | TextInput | Только чтение |
active | Toggle | — |
image | FileUpload | Аватар |
Вкладка "Права"
Доступна при наличии manager_can_edit_policy.
Содержит таблицу политик (Policies.php):
- Группировка по категориям
- ToggleColumn для включения/выключения
- Фильтр по категориям
Вкладка "Дилеры"
Доступна при наличии manager_can_view_dealers.
Содержит таблицу компаний менеджера (Dealers.php):
- Организация, договор, телефон, email, скидка
- Клик ведёт на карточку компании
4.3 Колонки таблицы списка
| Колонка | Описание | Особенности |
|---|---|---|
image | Аватар | ImageColumn |
email | Поиск | |
name | Имя | Поиск |
lastname | Фамилия | Поиск |
phone | Телефон | Поиск |
tg_id | ID Telegram | Поиск |
active | Активен | ToggleColumn |
5. UI/UX
5.1 Список менеджеров
┌─────────────────────────────────────────────────────────────────────────────┐
│ Менеджеры [+ Создать] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Поиск...] [Столбцы ▾] │
├──────┬──────┬────────────────────────┬─────────┬──────────┬──────────┬──────┤
│ ☐ │ Фото │ Email │ Имя │ Фамилия │ Телефон │Актив.│
├──────┼──────┼────────────────────────┼─────────┼──────────┼──────────┼──────┤
│ ☐ │ [📷] │ slavyana@wwtp.ru │ Славяна │ Маркина │ +7(930)..│ [●] │
│ ☐ │ [📷] │ v.dubrovin@trade-h... │ Валерий │ Дубровин │ +7(930)..│ [●] │
│ ☐ │ [📷] │ ka@trade-house.ru │ Андрей │ Кулик │ +7(930)..│ [●] │
└──────┴──────┴────────────────────────┴─────────┴──────────┴──────────┴──────┘
Действия:
✅ [Авторизоваться] — войти под учёткой (impersonate)
✅ [Удалить] — с подтверждением
Особенности:
- Кнопка "Создать" ведёт на отдельную страницу
- Клик по строке → карточка редактирования
- Массовое удаление5.2 Карточка редактирования (3 вкладки)
┌─────────────────────────────────────────────────────────────────────────────┐
│ [← Назад] Редактирование менеджера [Удалить] [Сохранить] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Данные] [Права] [Дилеры] │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────┐ ┌────────────────────────┐ │
│ │ Email [slavyana@wwtp.ru ] │ │ Изображение │ │
│ │ │ │ ┌────────────────────┐ │ │
│ │ Пароль [•••••••• ] [👁] │ │ │ │ │ │
│ │ │ │ │ [📷 Аватар] │ │ │
│ │ Фамилия [Маркина ] │ │ │ │ │ │
│ │ Имя [Славяна ] │ │ └────────────────────┘ │ │
│ │ Отчество [ ] │ │ │ │
│ │ Должность [ ] │ └────────────────────────┘ │
│ │ ID телеграмма [8214776166 ] │ │
│ │ Телефон [+7(930) 035 11 06 ] │ │
│ │ Посл. авторизация [ ] │ │
│ │ Активен [●] │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘5.3 Вкладка "Дилеры"
┌─────────────────────────────────────────────────────────────────────────────┐
│ [Данные] [Права] [Дилеры] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Поиск...] │
├────────────────────────┬────────────────┬──────────┬──────────┬─────────────┤
│ Компания │ Договор │ Телефон │ Email │ Скидка │
├────────────────────────┼────────────────┼──────────┼──────────┼─────────────┤
│ ООО "ЭКОРУСЬ" │ 2025-001 │ +7(495)..│ info@... │ 15% │
│ ООО "ЯРТОРГ" │ 2025-002 │ +7(4852).│ sales@.. │ 10% │
│ ИП Иванов И.И. │ 2025-003 │ +7(999)..│ ivan@... │ 5% │
└────────────────────────┴────────────────┴──────────┴──────────┴─────────────┘
│ Показано с 1 по 10 из 25 [10][50][100][Все] │
└─────────────────────────────────────────────────────────────────────────────┘
Особенности:
- Показывает только компании, где manager_id = текущий менеджер
- Клик по строке → карточка компании (company-edit)
- Только просмотр, без редактирования6. Бизнес-логика
6.1 Роль менеджера в системе
Менеджер — это куратор дилерских компаний. Он может:
- Видеть и редактировать свои компании (при наличии
company_manager_can_*) - Видеть и редактировать дилеров своих компаний (при наличии
dealer_manager_can_*) - Видеть заказы своих компаний
6.2 Связь с компаниями
Company.manager_id → User.id (group_id = 3)Компонент Dealers.php показывает компании, где manager_id = ID менеджера:
// Dealers.php
->query(Company::query()
->with('manager')
->where('manager_id', $this->record->id))6.3 Политики для менеджера (manager_can_ vs manager_can)
В системе есть два типа политик:
| Политика | Кто использует | Описание |
|---|---|---|
manager_can_* | Администраторы | Управление самими менеджерами |
*_manager_can_* | Менеджеры | Права менеджера на сущности |
Примеры:
manager_can_view— админ видит список менеджеровcompany_manager_can_view— менеджер видит свои компанииdealer_manager_can_edit— менеджер редактирует дилеров своих компаний
6.4 Автоматическое создание UserPolicy
При открытии карточки редактирования:
// Edit.php — mount()
$policies = Policy::all();
foreach ($policies as $policy) {
UserPolicy::firstOrCreate(
['user_id' => $this->record->id, 'policy_id' => $policy->id],
['value' => false]
);
}6.5 Хэширование пароля
TextInput::make('password')
->dehydrateStateUsing(fn ($state) => $state ? Hash::make($state) : null)
->dehydrated(fn ($state) => filled($state)) // Только если заполнен6.6 Проверка group_id в контроллере
// ManagerController.php — show()
$manager = User::find($id);
if (!$manager or $manager->group_id !== 3) abort(404);Защита от просмотра пользователей других групп.
7. Выявленные проблемы
7.1 Критические
| # | Проблема | Файл | Влияние |
|---|---|---|---|
| — | Критических проблем не обнаружено | — | — |
7.2 Средние
| # | Проблема | Описание | Решение |
|---|---|---|---|
| 1 | Инверсия логики $can_edit | $can_edit = !check_access() в Listing.php | Переименовать в $disableEdit |
| 2 | Policies рендерит неправильный view | 'livewire.news.listing' вместо правильного | Заменить на 'livewire.base.listing' |
| 3 | Dealers рендерит неправильный view | 'livewire.news.listing' вместо правильного | Заменить на 'livewire.base.listing' |
| 4 | Разные маски телефона | В Add: +7 (999)..., в Edit: +7(999)... | Унифицировать |
7.3 Низкие
| # | Проблема | Описание |
|---|---|---|
| 5 | Нет экспорта | Нельзя выгрузить список менеджеров |
| 6 | Нет истории изменений прав | Не видно кто и когда менял политики |
| 7 | Нет фильтров | Например, фильтр по количеству компаний |
8. Рекомендации
8.1 Приоритет: Высокий
Исправить view в Policies и Dealers
// Policies.php:58 — было:
return view('livewire.news.listing');
// Стало:
return view('livewire.base.listing');// Dealers.php:59 — было:
return view('livewire.news.listing');
// Стало:
return view('livewire.base.listing');8.2 Приоритет: Средний
Исправить именование переменной
// Listing.php:28 — было:
$can_edit = !$this->authUser->check_access('manager_can_edit');
// Стало:
$disableEdit = !$this->authUser->check_access('manager_can_edit');Унифицировать маску телефона
// Использовать везде:
->mask('+7(999) 999 99 99')8.3 Приоритет: Низкий
Добавить статистику компаний в таблицу
Tables\Columns\TextColumn::make('companies_count')
->label('Компаний')
->counts('companies')
->sortable(),Приложение: SQL для аналитики
Менеджеры с количеством компаний
SELECT
u.id,
u.email,
u.name,
u.lastname,
COUNT(c.id) as companies_count
FROM users u
LEFT JOIN companies c ON u.id = c.manager_id
WHERE u.group_id = 3
GROUP BY u.id, u.email, u.name, u.lastname
ORDER BY companies_count DESC;Менеджеры без компаний
SELECT id, email, name, lastname
FROM users
WHERE group_id = 3
AND id NOT IN (SELECT DISTINCT manager_id FROM companies WHERE manager_id IS NOT NULL);Статистика заказов по менеджерам
SELECT
u.name as manager,
COUNT(o.id) as orders_count,
SUM(o.cost) as total_cost
FROM users u
JOIN companies c ON u.id = c.manager_id
JOIN orders o ON c.id = o.company_id
WHERE u.group_id = 3
GROUP BY u.id, u.name
ORDER BY orders_count DESC;Все политики менеджера
SELECT
p.key,
p.name,
p.category,
up.value
FROM user_policies up
JOIN policies p ON up.policy_id = p.id
WHERE up.user_id = :manager_id
ORDER BY p.category, p.name;Документ подготовлен на основе анализа исходного кода проекта