Модули
Характеристики
Версия: 1.0
Дата: 2025-11-20
Статус: Реализован
Общее описание
Текущая реализация
Права доступа
Описание полей
UI/UX
Бизнес-логика
Выявленные проблемы
Рекомендации
Модуль "Характеристики" предназначен для управления справочником характеристик товаров . Это базовый справочник, который определяет какие свойства можно присваивать товарам (вес, размер, производительность и т.д.).
Основные функции:
Создание и редактирование характеристик
Указание единиц измерения
Изменение порядка отображения (drag & drop)
Привязка к товарам с указанием значений
Модуль Связь Товары property_product — значения характеристик для товаровКаталог Характеристики отображаются в карточке товара Заказы Характеристики товаров видны в составе заказа
Метрика Значение Всего характеристик 4 Связей с товарами 84
ID Название Единицы измерения 1 Человек — 2 Производительность м3/сутки 3 Размеры — 4 Вес кг.
┌─────────────────────────────────────────────────────────────────────────────┐
│ МОДУЛЬ "ХАРАКТЕРИСТИКИ" │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ РОУТЫ (routes/web.php) │
│ └── GET /properties → PropertyController@index → Список │
│ │
│ КОНТРОЛЛЕР (PropertyController.php) │
│ └── БЕЗ ПРОВЕРКИ ПРАВ! Доступен всем авторизованным │
│ │
│ LIVEWIRE КОМПОНЕНТЫ │
│ ├── Property/Listing.php — Таблица с inline-редактированием │
│ └── Property/Control.php — Модальное создание │
│ │
│ МОДЕЛИ │
│ ├── Property — Характеристика │
│ └── PropertyProduct — Pivot: значение характеристики для товара │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Поле Тип Описание idbigint PK indexint Порядок сортировки namestring Название характеристики unitsstring Единицы измерения (nullable) created_attimestamp — updated_attimestamp —
Поле Тип Описание idbigint PK product_idFK Товар property_idFK Характеристика valuestring Значение характеристики
app/
├── Http/Controllers/
│ └── PropertyController.php
├── Livewire/Property/
│ ├── Control.php — Модальное создание + редактирование
│ └── Listing.php — Таблица с inline-редактированием
└── Models/
├── Property.php
└── PropertyProduct.php
database/migrations/
├── 2024_03_21_101832_create_properties_table.php
└── 2024_03_21_154118_create_property_products_table.php
// PropertyController.php — НЕТ ПРОВЕРКИ!
public function index ()
{
return view ( 'templates.property.table' );
}
⚠️ Внимание! Модуль доступен всем авторизованным пользователям. Нет проверки прав доступа в контроллере.
В Listing.php проверяются права:
$disableEdit = $this -> authUser -> check_access ( 'property_can_edit' );
$canDelete = $this -> authUser -> check_access ( 'property_can_delete' );
// В getActions()
$canDelete = ( $this -> authUser -> check_access ( 'property_can_delete' )
or $this -> authUser -> check_access ( 'property_manager_can_delete' ));
Политика Описание property_can_editРедактирование характеристик property_can_deleteУдаление характеристик property_manager_can_deleteУдаление для менеджеров
Роль Просмотр URL Редактирование Удаление Администратор ✅ ✅* ✅* Менеджер ✅ ❌ ✅* Производство ✅ ❌ ❌ Дилер ✅ ❌ ❌
*Зависит от индивидуальных политик
Поле Тип Обязательное Описание nameTextInput ✅ Название характеристики unitsTextInput ❌ Единицы измерения
Поле Тип Описание nameTextInput Название unitsTextInput Единицы измерения
Колонка Описание Особенности nameНазвание Поиск, сортировка unitsЕдиницы измерения Поиск, сортировка
┌─────────────────────────────────────────────────────────────────────────────┐
│ Характеристики [+ Создать] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [↕] [Поиск...] [Столбцы ▾] │
├────────────────────────────────┬──────────────────────┬─────────────────────┤
│ Название ▾ │ Единицы измерения ▾ │ │
├────────────────────────────────┼──────────────────────┼─────────────────────┤
│ Человек │ │ [Изменить][Удалить] │
│ Производительность │ м3/сутки │ [Изменить][Удалить] │
│ Размеры │ │ [Изменить][Удалить] │
│ Вес │ кг. │ [Изменить][Удалить] │
└────────────────────────────────┴──────────────────────┴─────────────────────┘
Особенности:
✅ Drag & Drop для изменения порядка (reorderable)
✅ Кнопка "Изменить порядок" для активации режима
✅ Модальное создание (без перехода на другую страницу)
✅ Inline-редактирование в модальном окне
✅ Сортировка по колонкам
┌─────────────────────────────────────────────────────────────────────────────┐
│ Создать характеристику │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Название* │
│ [ ] │
│ │
│ Единицы измерения │
│ [ ] │
│ │
│ [Отмена] [Создать] │
└─────────────────────────────────────────────────────────────────────────────┘
Характеристики связаны с товарами через pivot-таблицу property_product:
// Product.php
public function propertiesItems ()
{
return $this -> belongsToMany ( Property ::class , 'property_product' , 'product_id' , 'property_id' )
-> withPivot ([ 'value' ]);
}
public function productProperties ()
{
return $this -> hasMany ( PropertyProduct ::class );
}
В карточке товара (Product/Control.php) есть Repeater для характеристик:
Repeater :: make ( 'productProperties' )
-> relationship ()
-> schema ([
Hidden :: make ( 'product_id' ) -> default ($recordID),
Select :: make ( 'property_id' )
-> options ( Property :: all () -> pluck ( 'name' , 'id' )),
TextInput :: make ( 'value' ) -> maxLength ( 255 ) -> required (),
])
Товар: "Септик Топас 5"
├── Производительность: 1 м3/сутки
├── Вес: 230 кг
├── Человек: 5
└── Размеры: 1100x1200x2500 мм
Характеристики имеют поле index для сортировки:
-> reorderable ( 'index' )
-> defaultSort ( 'index' , 'asc' )
# Проблема Файл Влияние — Критических проблем не обнаружено — —
# Проблема Описание Решение 1 Нет проверки прав в контроллере URL доступен всем авторизованным Добавить проверку property_can_view 2 Неиспользуемая переменная $disableEdit не используетсяУбрать или использовать 3 Нет защиты от удаления используемых Можно удалить характеристику, которая привязана к товарам Добавить проверку
# Проблема Описание 4 Control.php: redirect в каталог После удаления идёт redirect в catalog, а не properties 5 Нет экспорта Нельзя выгрузить список характеристик 6 Нет подсчёта использований Не видно сколько товаров используют характеристику
// PropertyController.php — было:
public function index ()
{
return view ( 'templates.property.table' );
}
// Стало:
public function index ( Request $request)
{
$user = $request -> user ();
if ( ! $user or ! $user -> check_access ( 'property_can_view' ))
abort ( 403 );
return view ( 'templates.property.table' );
}
// Listing.php — в getActions()
Action :: make ( 'delete' )
-> hidden ( fn ( Property $record) => PropertyProduct :: where ( 'property_id' , $record -> id) -> exists ())
-> requiresConfirmation ()
-> action ( fn ( Property $record) => $record -> delete ())
Tables\Columns\TextColumn :: make ( 'products_count' )
-> label ( 'Товаров' )
-> getStateUsing ( fn ($record) => PropertyProduct :: where ( 'property_id' , $record -> id) -> count ())
-> sortable (),
// Control.php:106-110 — было:
if ( $this -> parentId) {
redirect () -> route ( 'category' , $this -> parentId);
} else {
redirect () -> route ( 'catalog' );
}
// Стало:
redirect () -> route ( 'properties' );
SELECT
p . id ,
p . name ,
p . units ,
COUNT ( pp . id ) as products_count
FROM properties p
LEFT JOIN property_product pp ON p . id = pp . property_id
GROUP BY p . id , p . name , p . units
ORDER BY p . index ;
SELECT id, name , units
FROM properties
WHERE id NOT IN ( SELECT DISTINCT property_id FROM property_product);
SELECT
pr . name as product,
p . name as property,
p . units ,
pp . value
FROM property_product pp
JOIN products pr ON pp . product_id = pr . id
JOIN properties p ON pp . property_id = p . id
WHERE pr . id = :product_id
ORDER BY p . index ;
SELECT
pr . id ,
pr . name ,
pp . value
FROM products pr
JOIN property_product pp ON pr . id = pp . product_id
WHERE pp . property_id = :property_id
ORDER BY pr . name ;
Документ подготовлен на основе анализа исходного кода проекта