# ТЗ: Модуль Каталог общий Связанные документы: - [План реорганизации](plan.md) - [Карта нового меню](menu.md) - [ТЗ: Модуль ДКР](tz-dkr.md) - [Актуальный каталог с реальными данными](Каталог%20общий.xlsx) - [Предыдущий шаблон каталога](Шаблон%20Каталог%20ощий.xlsx) ## 1. Назначение `Каталог общий` — центральный справочник позиций платформы Manager 2.0. Он является базовым источником данных для модулей: - `Графики`; - `Рекламации`; - `Склад`; - `Технич. описание`; - `Калькуляции`. `Каталог общий` и каталог ДКР — разные сущности. Текущий каталог ДКР остается внутри модуля `ДКР`; общий каталог проектируется отдельно. ## 2. Статус Статус модуля: **ядро реализовано и проверено пользователем; переход на актуальный 30-колоночный формат с ценами реализован и ожидает пользовательской проверки**. Проверены создание и редактирование позиций, импорт и экспорт каталога. Реализация использует ключ модуля, маршрутов и прав `common-catalog`. Физические SQL-таблицы названы `common_catalog_items` и `common_catalog_item_documents` по принятому в Laravel соглашению snake_case. В текущей CRM уже есть раздел `Каталог` ДКР: - маршрут списка: `catalog.index`; - маршрут карточки: `catalog.show`; - контроллер: `ProductController`; - модель: `Product`; - загрузка изображения/thumbnail; - загрузка сертификата/документа; - экспорт каталога. Эта реализация относится к каталогу ДКР и не становится автоматически `Каталогом общим`. Ее можно использовать как источник UI/технических паттернов, но данные и назначение общего каталога должны быть отделены. ## 3. Место в меню Целевое меню: ```text Каталог общий ├── Позиции └── Карточка позиции ``` Требования: - пункт `Каталог общий` должен быть отдельным верхним пунктом меню; - пункт `Каталог` должен остаться внутри меню `ДКР`; - текущие маршруты `catalog.index` и `catalog.show` остаются маршрутами каталога ДКР; - маршруты `Каталог общий` должны использовать префикс `common-catalog/...`; - таблицы и права `Каталог общий` должны использовать техническое имя `common-catalog`; - выбранный год в CRM не влияет на отображение и данные общего каталога; - реорганизация меню выполняется сразу общей для всей платформы Manager 2.0. ## 4. Права доступа На первом этапе для заглушки используем доступ для всех авторизованных пользователей. | Действие | Permission | |---|---| | Просмотр заглушки | Любой авторизованный пользователь | | Просмотр общего каталога после реализации | `common-catalog.view` | | Создание/редактирование/удаление | Права с префиксом `common-catalog.*` | | Импорт | `common-catalog.import` | | Экспорт | `common-catalog.export`, по умолчанию только администратор | | Просмотр/редактирование отдельного поля | `common-catalog.fields.{field}.view/update` | Требования: - не переиспользовать `catalog.view` автоматически, потому что это право относится к каталогу ДКР; - новые права общего каталога использовать с техническим именем `common-catalog`; - заглушку `Каталог общий` показывать всем авторизованным пользователям. - восемь полей цен по умолчанию видны и доступны для редактирования только администратору; - доступ к каждой цене можно настраивать через существующий механизм прав отдельных полей; - экспорт общего каталога по умолчанию доступен только администратору. ## 5. Основные сущности Базовая сущность: позиция каталога. Возможная техническая основа для анализа: - модель `Product`; - карточка позиции через `catalog.show`; - связи с МАФ/SKU через текущую модель данных. Эти сущности относятся к каталогу ДКР и не должны смешиваться с общим каталогом без отдельной миграции или синхронизации. Целевая роль позиции: - единый справочник номенклатуры; - источник изображения, артикула, наименования, характеристик и единицы измерения для склада; - источник данных для графиков и рекламаций; - точка перехода в техническое описание; - точка перехода в калькуляцию. ## 6. Список позиций Список позиций должен поддерживать базовую функциональность справочника и быть подготовлен к расширению. Текущий каталог ДКР можно использовать как референс интерфейса, но не как источник данных общего каталога. Функционал: - просмотр списка позиций; - поиск; - фильтры; - пагинация; - переход в карточку позиции по двойному клику или текущему механизму таблицы; - экспорт; - импорт, если он будет предусмотрен для общего каталога. Источник полей и данных: файл [Каталог общий.xlsx](Каталог%20общий.xlsx), лист `Общие сведения`. Заголовок занимает строки 1–2, данные начинаются со строки 3. Файл содержит реальные позиции, изображения и цены. Колонки: 1. `Артикул`; 2. `Наименование`; 3. `Вид`; 4–6. `Габариты`: длина, ширина, высота; 7–8. `Размер участка`: длина, ширина; 9. `Высота падения`; 10. `Дополнительные сведения`; 11. `Единица измерения габаритов`; 12. `Вес, кг.`; 13. `Объем, м3`; 14. `Места`; 15. `Состав`; 16. `Возрастная группа`; 17. `Макс.кол-во пользователей`; 18. `Ед.`; 19. `Внешний вид`; 20. `Серия`; 21. `ТМ`; 22. `Калькулятор`; 23–30. цены `строители`, `опт`, `рек`, `розница`, `проект`, `проект+м`, `пик`, `рек+10`. Требования к колонкам: - указанный перечень, порядок и две строки заголовка являются целевым форматом общего каталога; - при импорте принимать заголовок `Единица измерения габаритов` в формате шаблона с переносом строки между словами `измерения` и `габаритов`; - поле `Артикул` хранить строкой, чтобы сохранять ведущие нули; - `Внешний вид` отображает фото позиции; - состав полей общего каталога не зависит от состава полей каталога ДКР; - все восемь цен хранятся непосредственно у позиции общего каталога; - цены хранятся точно до копеек и не зависят от складской партии; - габаритные поля хранятся строками, потому что реальные данные содержат диапазоны и текстовые значения (`от 180`, `0,19-0,72`); - при ручном создании обязательны артикул и наименование; - при импорте фактического каталога допускается пустое наименование: строка сохраняется без подстановки выдуманного значения; - остальные поля допускают постепенное заполнение. Предварительная модель полей по шаблону: | Колонка | Поле | Тип данных | Примечание | |---|---|---|---| | A | `article` | string | Сохранять ведущие нули, пример: `0254`. | | B | `calculator_name` | text | Наименование; внутреннее имя поля сохранено для совместимости. | | C | `kind` | string nullable | Категория/вид позиции. | | D–F | `dimension_length`, `dimension_width`, `dimension_height` | string nullable | Отдельные размеры; допускают диапазоны и текст. | | G–H | `site_length`, `site_width` | string nullable | Размеры участка. | | I | `fall_height` | decimal nullable | Высота падения. | | J | `additional_info` | text nullable | Дополнительное описание. | | K | `dimension_unit` | string nullable | Единица измерения габаритов. | | L–M | `weight`, `volume` | decimal nullable | Вес и объём. | | N | `places` | integer nullable | Количество мест. | | O | `composition` | text nullable | Состав комплекта/позиции. | | P | `age_group` | string nullable | Возрастная группа. | | Q | `max_users` | integer nullable | Максимальное количество пользователей. | | R | `unit` | string nullable | Единица учета. | | S | `image_file_id` | image/file nullable | Встроенное изображение импортируется через файловый механизм CRM. | | T–U | `series`, `trademark` | string nullable | Серия и торговая марка. | | V | `calculator_enabled` | boolean nullable | Значения `да` / `нет` / пусто. | | W–AD | восемь полей `*_price` | money nullable | Цены хранятся в копейках, в UI и XLSX отображаются в рублях. | ## 7. Карточка позиции Карточка позиции должна стать центральной карточкой товара/МАФ. Функционал карточки: - просмотр и редактирование полей позиции общего каталога; - загрузка фото МАФ/позиции; - хранение сопутствующих документов; - блок/выгрузка технического описания, встроенные в карточку общего каталога; - переход в `Калькуляции`; - отображение связанных МАФ/SKU, если это потребуется для новой логики; - сохранение привычных действий карточки каталога ДКР только как UI-паттерна, без смешивания данных. Текущие возможности каталога ДКР, которые можно использовать как паттерн: - `catalog.upload-thumbnail` — использовать как основу загрузки фото; - `catalog.upload-certificate` — использовать как основу загрузки документов, но расширить модель до нескольких произвольных документов, если текущая реализация ограничена сертификатом. ## 8. Фото и документы Фото: - хранится у позиции общего каталога; - используется в `Склад`; - используется в карточке позиции; - должно быть доступно для отображения в таблицах, где нужна картинка позиции. Документы: - у позиции должен быть блок `Документы`; - документы могут быть разных типов: сертификаты, инструкции, паспорта, прочие файлы; - хранение документов выполняется через текущий файловый механизм проекта; - загрузка, просмотр и удаление должны учитывать будущие права общего каталога; - если текущая реализация поддерживает только один сертификат, нужна доработка интерфейса до набора файлов без замены базового механизма хранения. ## 9. Импорт и экспорт Требования: - спроектировать импорт и экспорт общего каталога; - использовать текущий импорт/экспорт каталога ДКР как технический референс, если это ускорит реализацию; - использовать утвержденные колонки общего каталога в заданном порядке; - использовать [Каталог общий.xlsx](Каталог%20общий.xlsx) как целевой формат импорта/экспорта общего каталога; - проверять обе строки заголовка и начинать обработку данных со строки 3; - сохранять ведущие нули в артикулах; - учитывать реальные варианты с одинаковым артикулом и разными наименованиями: уникальность позиции определяется парой `Артикул + Наименование`; - если импортируемый файл содержит один вариант артикула и в базе найдена ровно одна такая позиция, разрешать обновление наименования без создания дубля; - импортировать встроенные изображения из колонки `S`; - применять field-permissions к импортируемым значениям, чтобы пользователь без права редактирования цены не мог изменить её импортом; - ошибки импорта должны быть понятны пользователю. ## 10. Связи с другими модулями | Модуль | Связь | Требование | |---|---|---| | ДКР | Имеет собственный каталог | Не смешивать каталог ДКР с общим каталогом. | | Склад | Использует картинку, артикул, наименование, характеристики и ед. изм. | Цены принадлежат общему каталогу и не хранятся в складских партиях. | | Графики | Используют данные по позициям | При разработке графиков опираться на общий каталог. | | Рекламации | Используют данные по позициям | Сохранить/добавить связь рекламаций с позициями общего каталога. | | Технич. описание | Является частью общего каталога | Описательные поля и DOCX-экспорты переносятся в карточку; согласованный вид цены читается из этой же позиции каталога. | | Калькуляции | Открываются из карточки позиции | Финальное поведение кнопки и способ реализации определяются отдельным ТЗ; исходный `calc.stroyprofit.com` используется как референс. | ## 11. Что не входит в первый этап В первый этап общего каталога не входит: - переименование текущих маршрутов `catalog.*`; - полная переработка модели `Product`; - внедрение новых прав доступа; - разработка модуля `Склад`; - отдельный модуль `Технич. описание`; - разработка калькуляций до получения отдельного ТЗ и согласования архитектуры; - изменение бизнес-логики ДКР. ## 12. Этапы реализации - [x] Проверить текущие маршруты `catalog.*`. - [x] Зафиксировать, что текущие маршруты `catalog.*` относятся к каталогу ДКР. - [x] Использовать префикс маршрутов `common-catalog/...` для `Каталог общий`. - [x] Использовать техническое имя `common-catalog` для модуля и прав, SQL-префикс `common_catalog` — для таблиц. - [x] Добавить верхний пункт `Каталог общий`. - [x] Заменить страницу-заглушку рабочим списком `Каталог общий`. - [x] Спроектировать и реализовать карточку позиции общего каталога. - [x] Проверить загрузку фото позиции. - [x] Реализовать загрузку документов позиции через текущий файловый механизм. - [x] Зафиксировать состав и порядок колонок общего каталога. - [x] Зафиксировать шаблон общего каталога как источник колонок. - [x] Зафиксировать предварительные типы данных по шаблону общего каталога. - [x] Спроектировать обязательность и валидацию утвержденных полей: при ручном вводе обязательны артикул и наименование, импорт принимает фактические строки без наименования; числовые значения неотрицательны; остальные поля допускают постепенное заполнение. - [x] Реализовать утвержденные поля в списке и карточке позиции. - [x] Реализовать первоначальный фоновый импорт/экспорт по 19-колоночному шаблону. - [x] Перевести импорт/экспорт на актуальный формат из 30 колонок и двух строк заголовка. - [x] Добавить пять раздельных размерных полей, признак калькулятора и восемь цен. - [x] Подключить field-permissions общего каталога; цены по умолчанию доступны только администратору. - [x] Ограничить экспорт общего каталога администратором по умолчанию. - [x] Реализовать блок документов как набор файлов. - [x] Зафиксировать, что `Технич. описание` включается внутрь карточки общего каталога. - [x] Добавить в карточку место под будущий модуль `Калькуляции`. - [x] Зафиксировать `common_catalog_items.id` как внешний ключ для будущих связей модулей; добавление связей выполняется вместе с соответствующими модулями. - [x] Настроить `common-catalog.view` для основных авторизованных ролей и отдельные права на изменение, файлы, импорт и экспорт. ## 13. Критерии приемки - В верхнем меню есть пункт `Каталог общий`. - В меню `ДКР` остается пункт `Каталог`. - Текущие маршруты `catalog.index` и `catalog.show` сохранены как маршруты каталога ДКР. - Рабочий раздел `Каталог общий` доступен основным авторизованным ролям через право `common-catalog.view`. - После реализации общий каталог не смешивает данные с каталогом ДКР без отдельной миграции/синхронизации. - Список, карточка, импорт и экспорт используют состав и порядок колонок из файла `docs/refactor/Каталог общий.xlsx`. - Пользователь без field-permission не видит цену и не может изменить её прямым POST-запросом или импортом. - Экспорт по умолчанию доступен только администратору. - Карточка позиции общего каталога поддерживает фото и набор документов; места интеграции техописания и калькуляции подготовлены до реализации соответствующих этапов. - ДКР продолжает использовать свой каталог без поломки существующих связей. - Реорганизация меню выполнена как часть общей структуры Manager 2.0. ## 14. Открытые вопросы - Какие дополнительные поля техописания добавляются напрямую в `common_catalog_items` после переноса источника? - Какое поведение кнопки калькуляции будет утверждено отдельным ТЗ?