Документация ЛК
Модули

Типы

Модуль "Типы"

Версия: 1.0
Дата: 2025-11-20
Статус: Реализован


Содержание

  1. Общее описание
  2. Текущая реализация
  3. Права доступа
  4. Описание полей
  5. UI/UX
  6. Бизнес-логика
  7. Выявленные проблемы
  8. Рекомендации

1. Общее описание

1.1 Предназначение модуля

Модуль "Типы" предназначен для управления справочником типов товаров. Это классификация товаров по основному назначению (Септик, Погреб, Кессон и т.д.).

Основные функции:

  • Создание и редактирование типов товаров
  • Привязка типа к товарам
  • Массовое удаление типов

1.2 Связь с другими модулями

МодульСвязь
Товарыproduct.type — тип товара (строковое поле)
КаталогФильтрация по типу
ЗаказыТип товара отображается в составе

1.3 Статистика

МетрикаЗначение
Всего типов4

1.4 Список типов с товарами

IDНазваниеТоваров
1Септик69
2Погреб7
3Кессон6
4Другое63

2. Текущая реализация

2.1 Архитектура

┌─────────────────────────────────────────────────────────────────────────────┐
│                            МОДУЛЬ "ТИПЫ"                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  РОУТЫ (routes/web.php)                                                      │
│  └── GET /types → TypeController@index → Список                              │
│                                                                              │
│  КОНТРОЛЛЕР (TypeController.php)                                             │
│  └── Проверка: только group_id = 1 (администраторы)                         │
│                                                                              │
│  LIVEWIRE КОМПОНЕНТЫ                                                         │
│  ├── Type/Add.php     — Модальное создание                                  │
│  └── Type/Listing.php — Таблица с inline-редактированием                    │
│                                                                              │
│  МОДЕЛЬ                                                                      │
│  └── Type — Тип товара                                                      │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

2.2 Структура БД

Таблица types

ПолеТипОписание
idbigintPK
indexintПорядок сортировки (не используется)
namestringНазвание типа
created_attimestamp
updated_attimestamp

⚠️ Особенность: Связь с товарами через строковое поле product.type, а не FK.

2.3 Файлы модуля

app/
├── Http/Controllers/
│   └── TypeController.php
├── Livewire/Type/
│   ├── Add.php     — Модальное создание
│   └── Listing.php — Таблица с inline-редактированием
└── Models/
    └── Type.php

database/migrations/
└── 2024_04_14_113519_create_types_table.php

3. Права доступа

3.1 Проверка в контроллере

// TypeController.php — ТОЛЬКО АДМИНИСТРАТОРЫ
public function index(Request $request)
{
    $user = $request->user();
    if (!$user or $user->group_id != 1)  // Жёсткая проверка group_id
        abort(403);
    return view('templates.types.table');
}

⚠️ Особенность: Проверка по group_id, а не через политики!

3.2 Политики в Livewire

// Listing.php
$disableEdit = $this->authUser->check_access('type_can_edit');
$canDelete = $this->authUser->check_access('type_can_delete');

// В getActions()
$canDelete = ($this->authUser->check_access('type_can_delete') 
    or $this->authUser->check_access('type_manager_can_delete'));

3.3 Политики модуля

ПолитикаОписание
type_can_editРедактирование типов
type_can_deleteУдаление типов
type_manager_can_deleteУдаление для менеджеров

3.4 Матрица доступа

РольПросмотр URLРедактированиеУдаление
Администратор✅*✅*
Менеджер
Производство
Дилер

*Зависит от индивидуальных политик


4. Описание полей

4.1 Модальное создание (Add.php)

ПолеТипОбязательноеОписание
nameTextInputНазвание типа

4.2 Inline-редактирование (Listing.php)

ПолеТипОписание
nameTextInputНазвание типа

4.3 Колонки таблицы

КолонкаОписаниеОсобенности
nameИмяПоиск

5. UI/UX

5.1 Список типов

┌─────────────────────────────────────────────────────────────────────────────┐
│ Типы                                                        [+ Создать]     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                    [Поиск...] [Столбцы ▾]   │
├────────────────────────────────────────────────────┬────────────────────────┤
│ ☐ Имя                                              │                        │
├────────────────────────────────────────────────────┼────────────────────────┤
│ ☐ Другое                                           │ [Изменить] [Удалить]   │
│ ☐ Кессон                                           │ [Изменить] [Удалить]   │
│ ☐ Погреб                                           │ [Изменить] [Удалить]   │
│ ☐ Септик                                           │ [Изменить] [Удалить]   │
└────────────────────────────────────────────────────┴────────────────────────┘

Особенности:
✅ Модальное создание (без перехода на другую страницу)
✅ Inline-редактирование в модальном окне
✅ Массовое удаление
❌ Нет drag & drop для сортировки (хотя поле index есть)

5.2 Модальное создание

┌─────────────────────────────────────────────────────────────────────────────┐
│                              Создать тип                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   Название*                                                                 │
│   [                                                                     ]   │
│                                                                              │
│                                               [Отмена]    [Создать]         │
└─────────────────────────────────────────────────────────────────────────────┘

6. Бизнес-логика

6.1 Связь с товарами

Типы связаны с товарами через строковое поле product.type:

// Product/Listing.php
Tables\Columns\SelectColumn::make('type')
    ->options(Type::all()->pluck('name', 'name'))  // name → name!
    ->searchable(),

// Product/Control.php
Select::make('type')
    ->options(Type::all()->pluck('name', 'name'))  // name → name!

⚠️ Внимание! Это не FK, а строковое значение! Если переименовать тип — связи с товарами разорвутся.

6.2 Использование типа в товаре

// В карточке товара
Select::make('type')
    ->required()
    ->options(Type::all()->pluck('name', 'name'))

// Дополнительный тип
Select::make('add_type')
    ->options(Type::all()->pluck('name', 'name'))  // Опционально

6.3 Пример данных

Товар: "Топас 5"
├── type: "Септик"
└── add_type: null

Товар: "Погреб Волжанин"
├── type: "Погреб"
└── add_type: null

6.4 Классификация

Типы используются для основной классификации товаров в каталоге:

ТипОписание
СептикОчистные сооружения
ПогребПогреба и хранилища
КессонКессоны для скважин
ДругоеПрочие товары

7. Выявленные проблемы

7.1 Критические

#ПроблемаФайлВлияние
1Строковая связь вместо FKproducts.typeПри переименовании типа связи разрываются

7.2 Средние

#ПроблемаОписаниеРешение
2Неиспользуемое поле indexЕсть поле для сортировки, но нет reorderableДобавить drag & drop
3Неиспользуемая переменная$disableEdit не применяетсяУбрать или использовать
4Нет защиты от удаления используемыхМожно удалить тип, который привязан к товарамДобавить проверку

7.3 Низкие

#ПроблемаОписание
5Нет подсчёта товаровНе видно сколько товаров используют тип
6Жёсткая проверка group_idВ контроллере проверяется group_id, а не политики

8. Рекомендации

8.1 Приоритет: Критический

Рефакторинг связи с товарами

Заменить строковую связь на FK:

// 1. Добавить миграцию
Schema::table('products', function (Blueprint $table) {
    $table->foreignId('type_id')->nullable()->constrained('types');
});

// 2. Мигрировать данные
Product::all()->each(function ($product) {
    $type = Type::where('name', $product->type)->first();
    if ($type) {
        $product->type_id = $type->id;
        $product->save();
    }
});

// 3. Обновить формы
Select::make('type_id')
    ->options(Type::all()->pluck('name', 'id'))  // name → id!

8.2 Приоритет: Высокий

Добавить защиту от удаления используемых

// Listing.php — в getActions()
Action::make('delete')
    ->hidden(fn (Type $record) => Product::where('type', $record->name)->exists())
    ->requiresConfirmation()
    ->action(fn (Type $record) => $record->delete())

Использовать политики в контроллере

// TypeController.php — было:
if (!$user or $user->group_id != 1) abort(403);

// Стало:
if (!$user or !$user->check_access('type_can_view')) abort(403);

8.3 Приоритет: Средний

Добавить drag & drop

// Listing.php
->reorderable('index')
->defaultSort('index', 'asc')

Добавить колонку с количеством товаров

Tables\Columns\TextColumn::make('products_count')
    ->label('Товаров')
    ->getStateUsing(fn ($record) => Product::where('type', $record->name)->count())
    ->sortable(),

Приложение: SQL для аналитики

Типы с количеством товаров

SELECT 
    t.id,
    t.name,
    COUNT(p.id) as products_count
FROM types t
LEFT JOIN products p ON t.name = p.type
GROUP BY t.id, t.name
ORDER BY products_count DESC;

Товары без типа

SELECT id, name
FROM products
WHERE type IS NULL OR type = '';

Товары с несуществующим типом

SELECT p.id, p.name, p.type
FROM products p
WHERE p.type NOT IN (SELECT name FROM types)
AND p.type IS NOT NULL;

Неиспользуемые типы

SELECT t.id, t.name
FROM types t
WHERE t.name NOT IN (SELECT DISTINCT type FROM products WHERE type IS NOT NULL);

Документ подготовлен на основе анализа исходного кода проекта

On this page

Модуль "Типы"Содержание1. Общее описание1.1 Предназначение модуля1.2 Связь с другими модулями1.3 Статистика1.4 Список типов с товарами2. Текущая реализация2.1 Архитектура2.2 Структура БДТаблица types2.3 Файлы модуля3. Права доступа3.1 Проверка в контроллере3.2 Политики в Livewire3.3 Политики модуля3.4 Матрица доступа4. Описание полей4.1 Модальное создание (Add.php)4.2 Inline-редактирование (Listing.php)4.3 Колонки таблицы5. UI/UX5.1 Список типов5.2 Модальное создание6. Бизнес-логика6.1 Связь с товарами6.2 Использование типа в товаре6.3 Пример данных6.4 Классификация7. Выявленные проблемы7.1 Критические7.2 Средние7.3 Низкие8. Рекомендации8.1 Приоритет: КритическийРефакторинг связи с товарами8.2 Приоритет: ВысокийДобавить защиту от удаления используемыхИспользовать политики в контроллере8.3 Приоритет: СреднийДобавить drag & dropДобавить колонку с количеством товаровПриложение: SQL для аналитикиТипы с количеством товаровТовары без типаТовары с несуществующим типомНеиспользуемые типы