← Схема разделения

Инструкция · work/classification

Как работают файлы классификации

От старой категории в HTML до нового значения в карточке — каждый шаг, файл и правило.

Открыть предпросмотр →

1. Для чего нужны эти файлы

В старом каталоге одно поле «категории» содержит разные по смыслу вещи: «Бифлекс» описывает вид ткани, «Для платьев» — назначение, «Гипоаллергенные» — свойство, а «Акция» — рекламную подборку. В назначениях тоже встречаются виды ткани, например «Трикотаж».

Папка work/classification задаёт предлагаемое разделение этих значений. Её JSON-файлы работают как промежуточный слой правил: какой старый ключ в какой новый справочник и значение направить. Меняя файл, вы меняете результат предпросмотра для всех товаров с этим источником.

«Замена» выполняется только в памяти во время запроса. Старые категории остаются в HTML как были. База, товары и их связи не изменяются; будущие таблицы пока не создаются.

На странице разделения категорий можно увидеть будущие поля товара и проверить происхождение каждого значения. Эта инструкция объясняет механизм, а раздел «Текущие правила» на отдельной странице читает актуальные JSON при каждом открытии.

2. Что происходит при открытии товара

1 · Снимок HTML →Категории и назначенияОтдельный файл для UK и RU
2 · Ключ источника →category:путь или purpose:slugНазвание не используется для поиска категории
3 · Правила JSON →Все совпадения в sourcesРазделение и объединение
4 · ПредпросмотрНовые поля и расшифровкаРезультат на языке карточки
  1. Составляется список товаров. Приложение обходит work/raw_pages/uk и work/raw_pages/ru, включая вложенные папки. В список попадают имена HTML-файлов без расширения. Имя служит ключом товара; числовые имена тоже допустимы. Наличие имени ещё не гарантирует, что внутри действительно карточка товара.
  2. Загружаются правила. Читаются все файлы *.json непосредственно в work/classification/rules. Вложенные папки правил не обходятся. JSON проверяется, затем для каждого источника собирается список подходящих новых значений.
  3. Читаются снимки выбранного товара. Например, для bifleks-rubchik нужны uk/bifleks-rubchik.html и ru/bifleks-rubchik.html. Всё содержимое каталога при этом не разбирается. Обращения к действующему магазину нет.
  4. Проверяется карточка. Парсеры проверяют признаки страницы товара, заголовок, блок метаданных и, если в canonical распознан slug товара, его соответствие имени файла. Пустой файл, страница каталога или другая карточка не становятся достоверным результатом.
  5. Извлекаются категории. Берутся ссылки внутри product_meta → posted_in, а не ссылки из меню сайта. Из адреса после /product-category/ выделяется полный путь категории, без языкового префикса и завершающего слеша.
  6. Извлекаются назначения. Парсер читает подписи из блока «назначение:» / «призначення:» и сопоставляет их со знакомыми slug. Если подписей нет, но на товаре есть классы pa_naznachenie-*, используется этот запасной источник. Неизвестная подпись получает ключ из парсера и может потребовать нового правила.
  7. Применяются совпадения. Каждый источник направляется во все указанные для него значения. Повтор одного значения объединяется, а список источников сохраняется. Спорные и неизвестные источники отмечаются отдельно.
  8. Показываются две версии. Для UK выводятся новые украинские названия, для RU — русские. Сверху видно, совпали ли итоговые наборы. Ниже доступны исходные данные, объяснения переносов и файлы правил.

Без выбранного товара страница показывает список доступных файлов и правила. Предпросмотр карточки появляется после выбора. При обновлении страницы и HTML, и правила читаются заново.

3. Что лежит в work/classification

work/classification/
├── README.md                 Краткая инструкция для работы в редакторе
├── sources.json              Исходный список категорий и назначений
└── rules/                    Действующие правила предпросмотра
    ├── fabric_types.json     Виды ткани
    ├── materials.json        Материалы
    ├── material_groups.json  Группы по происхождению
    ├── purposes.json         Назначения
    ├── properties.json       Свойства
    ├── finishes.json         Поверхность и отделка
    ├── processing.json       Пригодность для обработки
    ├── collections.json      Подборки и продвижение
    ├── catalog_sections.json Общие разделы каталога
    └── manual_review.json    Очередь неоднозначных рубрик

README.md — текстовое объяснение

Нужен человеку, который открывает папку в редакторе. Изменения этого файла не влияют на карточки. Текст этой веб-инструкции также не исполняется как правило.

sources.json — исходная опись

Сохраняет предоставленные 82 категории и 18 назначений. Для каждой записи указаны source — ключ с префиксом, number — номер в исходном списке, uk и ru — старые названия, counts.uk и counts.ru — исходные количества товаров.

Эти количества исторические: они не пересчитываются при открытии товара. Предпросмотр не берёт названия или правила из sources.json. Файл нужен для сверки полноты; автоматический тест проверяет, что каждый источник из описи присутствует в правилах. Если в новых HTML появился дополнительный ключ, он будет виден как неизвестный до добавления правила.

rules/*.json — то, что действительно меняет результат

ФайлЧто сюда относитсяГраница смысла
fabric_types.jsonБифлекс, трикотаж, деним, креп, подкладочная и пальтовая ткани.Торговый вид ткани; он не определяет точный состав.
materials.jsonЛён, вискоза, шёлк, кашемир, тенсел.Материал, названный в старой рубрике; это не утверждение о 100% волокна.
material_groups.jsonНатуральные и синтетические.Широкая группа происхождения отдельно от конкретного материала.
purposes.jsonБрюки, рубашки, платья, спорт, декор и другие применения.Что можно изготовить или где использовать ткань.
properties.jsonПлотная, стрейч, светоотражающая, гипоаллергенная.Заявленное в рубрике свойство; испытания и состав не проверяются.
finishes.jsonМатовая поверхность, пайетки, плиссированная ткань.Уже существующая поверхность или отделка.
processing.jsonДля печати, для плиссирования.Пригодность к обработке; готовый принт или складки из этого не следуют.
collections.jsonАкция, новинки, премиум.Подборки из снимка. Срок акции, цена и дата поступления не вычисляются.
catalog_sections.jsonТкани для одежды.Общий раздел, который сам по себе не задаёт конкретное назначение.
manual_review.jsonСмешанные рубрики, смысл которых нужно уточнить.Рабочая очередь, а не будущий справочник значений товара.

Это начальная схема. Можно добавлять свои справочники. Для программы имя файла служит подсказкой в расшифровке; идентификатор справочника задаётся полем table внутри JSON. Исключение в отображении: manual_review не показывается как поле карточки.

4. Формат JSON: что означает каждое поле

Ниже учебный пример файла с одним значением. В действующем purposes.json значений больше; при редактировании не заменяйте весь файл этим примером.

{
  "table": "purposes",
  "title": "Назначения",
  "title_uk": "Призначення",
  "description": "Изделия и области применения.",
  "terms": [
    {
      "key": "shirts",
      "uk": "Сорочки",
      "ru": "Рубашки",
      "sources": [
        "category:tkani-dlya-odezhdy/dlya-rubashek",
        "purpose:rubashka"
      ],
      "note": "Два источника объединяются в одно назначение.",
      "review": false
    }
  ]
}
ПолеЧто задаётТребования
tableОбщий ключ справочника, например purposes.Обязательно. Латинские строчные буквы, цифры, подчёркивание; первый символ — буква. Уникально среди файлов.
titleРусское название раздела и заголовок в интерфейсе правил.Обязательная непустая строка.
title_ukУкраинский заголовок поля в карточке.Необязательно. Если отсутствует, используется title. Для полной локализации лучше заполнять.
descriptionОбъяснение назначения справочника.Обязательная непустая строка. Не участвует в сопоставлении.
termsСписок новых значений этого справочника.Обязательный JSON-массив []. Может быть пустым.
terms[].keyСтабильный ключ значения, например shirts.Обязательно. Строчные латинские буквы, цифры, дефис и подчёркивание; начало — буква или цифра. Уникален внутри справочника.
terms[].uk, terms[].ruНовые названия значения на двух языках.Обе непустые строки обязательны. Перевод не генерируется автоматически.
terms[].sourcesСписок старых ключей, которые дают это значение.Обязательный непустой массив строк с префиксом category: или purpose:.
terms[].noteПояснение конкретной замены или сомнения.Необязательная строка. Видна в расшифровке, не меняет результат.
terms[].reviewНужно ли отложить это значение для проверки.Необязательно; по умолчанию false. Допустимы boolean true / false без кавычек.

JSON пишется в UTF-8, с двойными кавычками, без комментариев и запятой после последнего элемента. Если нужно оставить объяснение, используйте note или description. Отдельных условий по товару, регулярных выражений или команд в JSON сейчас нет.

5. Как определяются совпадения и замены

Источник — это тип и точный ключ

category:rubashka и purpose:rubashka — два разных источника. Первый соответствует старой составной категории «Рубашка Платье Блуза», второй — назначению «РУБАШКА». Одинаковая часть после двоеточия не делает их одним правилом.

Для вложенной категории сохраняется полный путь: category:tkani-dlya-odezhdy/dlya-rubashek. Сокращение до category:dlya-rubashek не совпадёт. Ключи ищутся буквально: нет поиска по подстроке, автоматического перевода или угадывания по названию товара.

В sources перечислены альтернативы

Если у значения два источника, достаточно любого одного, чтобы получить это значение. Наличие обоих не требуется. Если присутствуют оба, в карточке всё равно будет одно значение, а в расшифровке сохранятся оба основания.

Один источник может дать несколько значений

Программа применяет все совпадения во всех файлах. Здесь нет приоритета «последний файл побеждает». Если один источник указан в трёх значениях, все три сработают, кроме помеченных review: true.

Повторы объединяются по table + key

Два источника для purposes + shirts дают одну «Рубашки». Одинаковые названия с разными ключами останутся разными значениями. И наоборот, новые подписи UK/RU могут различаться, но один ключ означает одно смысловое значение.

Автоматического наследования нет. «Мужские костюмы» не добавляет «Костюмы», а «Для пальто» не создаёт вид «Пальтовая ткань», если для этого не указано отдельное совпадение.

6. Примеры: что куда переходит

Эти примеры объясняют начальное разделение. Если вы поменяете JSON, актуальный результат смотрите в предпросмотре и списке текущих правил.

Два старых источника → одно назначение

category:tkani-dlya-odezhdy/dlya-rubashek ─┐
purpose:rubashka ────────────────────────┴→ purposes / shirts
                                           UK: Сорочки
                                           RU: Рубашки

Если товар имеет только один из этих источников, результат будет тем же. При двух источниках дубликат «Рубашки» не появится.

Составная категория → три разных признака

category:bifleks-matovyi-shchilnyi
  → fabric_types / biflex  → Біфлекс / Бифлекс
  → finishes / matte      → Матова / Матовая
  → properties / dense    → Щільна / Плотная

В названии явно присутствуют вид, поверхность и плотность. Поэтому один источник записан в трёх справочниках. Если дополнительно есть категория bifleks, она объединится с уже полученным видом ткани.

Ошибочно размещённое назначение → вид ткани

purpose:trikotazh направляется в fabric_types / knit. В будущих назначениях «Трикотаж» больше не появляется, но в исходных данных остаётся видимым.

Пиджаки и жакеты → два отдельных назначения

category:tkani-dlya-odezhdy/dlya-pidzhakov и purpose:pidzhak дают purposes / blazers — «Піджаки / Пиджаки». Категория category:tkani-dlya-odezhdy/tkani-dlya-zhaketov даёт purposes / jackets — «Жакети / Жакеты». Эти значения не объединяются. Если у товара есть оба источника, в назначениях будут оба значения.

Назначение плаща и подкладки → отдельно от вида ткани

purpose:plashhevye даёт purposes / raincoats — «Плащі / Плащи» и объединяется с категорией «Для плащей». purpose:podklad даёт purposes / lining — «Підкладка / Подкладка». Эти старые назначения сами по себе не добавляют вид ткани.

«Плащова тканина / Плащевая ткань» в fabric_types / raincoat и «Підкладкова тканина / Подкладочная ткань» в fabric_types / lining берутся из соответствующих старых категорий. Если в снимке есть и категория вида, и назначение, карточка покажет оба признака в разных полях.

Уже обработана и подходит для обработки — разные поля

category:plissirovanaya-tkan даёт отделку «Плиссированная». category:tkan-dlya-plissirovaniya даёт «Для плиссирования» в пригодности к обработке. Эти значения не объединяются.

Неоднозначная категория → очередь проверки

category:neopren в исходном списке называется «Сетка спорт, Неопрен». Назначить товару сразу оба вида было бы предположением. Сейчас источник ведёт в manual_review.json с review: true, поэтому в карточку значение не добавляется, а причина показывается ниже.

7. Как самостоятельно менять правила

  1. Откройте нужный товар в предпросмотре. В «Исходных данных» найдите значение, а в «Что куда перешло» — его точный ключ, файл и новое значение.
  2. Откройте соответствующий JSON в work/classification/rules в редакторе. Перед крупной перестройкой сохраните копию вне папки rules: копия с расширением .json в этой папке тоже будет прочитана как правило.
  3. Измените нужную запись, сохраните корректный JSON и обновите страницу товара. Перезапуск Docker и очистка кеша Laravel не нужны.
  4. Проверьте обе версии, объяснения переносов, спорные значения и ещё несколько товаров с тем же источником. Изменение действует на все соответствующие товары.

Переименовать значение или исправить перевод

Меняйте uk и/или ru. Для заголовка поля меняйте title и title_uk. Ключи table и key при обычном переименовании оставляйте прежними: они определяют идентичность значения.

Перенести источник в другой справочник

Удалите его строку из старого sources и добавьте в sources нужного значения в другом файле. Если старый список стал пустым, удалите всю ненужную запись из terms: пустой sources не допускается. Если оставить источник в обоих местах, он даст оба результата.

Объединить синонимы

Соберите их исходные ключи в одном sources у одного значения. Отдельные старые записи с ненужными новыми ключами удалите. Пример начального объединения: «Костюм» и «Костюмная ткань» ведут в один вид ткани suiting.

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

Добавьте один и тот же исходный ключ нескольким значениям. Разделение будет применяться ко всем товарам с этой рубрикой; отдельных исключений по slug товара текущий формат не поддерживает.

Добавить новый справочник

Создайте файл вроде my_group.json прямо в rules. Задайте уникальный table, названия, описание и массив terms по формату выше. Новая группа появится в предпросмотре автоматически. Новая таблица в базе при этом не создастся.

Разобрать спорную рубрику

Перенесите её источники из manual_review.json в нужные рабочие справочники и удалите запись очереди. Не просто снимайте review внутри manual_review: эта группа скрыта среди полей карточки. В обычном справочнике можно временно поставить review: true, чтобы отложить конкретное значение.

Что произойдёт при удалении

Удалённое правило перестанет давать результат при следующем открытии. Если для источника больше нет совпадений, он попадёт в нераспределённые. Удаление целого файла само по себе не считается ошибкой формата, пока остаются другие корректные файлы: приложение не хранит обязательный список имён справочников.

На странице нет редактора или кнопки сохранения правил. Изменения делаются в файлах проекта; веб-страницы показывают их результат и расшифровку.

8. Как работают UK и RU

Две стороны рассчитываются независимо: украинские источники читаются только из файла в raw_pages/uk, русские — из raw_pages/ru. Отсутствующее значение не дополняется из соседнего языка.

Исходные подписи показываются такими, как они записаны в снимке, даже если там опечатка или русский текст в украинской версии. В новых полях используются uk и ru из правил. Поэтому старое «ДЛЯ ПРИНТОВАНИЯ» в UK может превратиться в корректное «Для друку» без редактирования HTML.

СитуацияРезультат
Одинаковые источники, разные языкиКлючи итоговых значений совпадают, подписи локализованы. Статус — значения совпадают.
Разные источники объединились в один новый ключИтог может совпадать, хотя набор старых категорий различался. Для проверки старых наборов есть отдельные страницы сравнения.
В одной версии нет источникаЕсли ничто другое не даёт то же значение, итоговые наборы различаются. Уникальные значения выделяются.
Одного файла нет или он ошибочныйЭта сторона не получает предпросмотр, сравнение недоступно. Корректная сторона может отображаться.
Язык в HTML не соответствует папкеПоказывается предупреждение. Файл не переносится между языками автоматически; для результата используется язык папки.

Сравнение проводится по парам table + key, а не по тексту перевода. Если итоговые значения совпадают, но часть источников требует проверки, рядом будет отдельная отметка о неполном результате.

9. Ошибки, предупреждения и очередь проверки

«Правило отсутствует»

Источник прочитан из HTML, но его точного ключа нет ни в одном sources. Он остаётся в расшифровке, не добавляет значение и увеличивает счётчик нераспределённых. Скопируйте ключ из страницы и добавьте правило.

«Требует проверки»

Совпадение найдено, но у него review: true. Это конкретное значение не переносится. Если у того же источника есть другие совпадения без такой отметки, они всё равно применяются. Счётчик показывает число исходных ключей с проблемами, а не число всех отложенных назначений.

Начальная очередь содержит четыре рубрики: «Сетка спорт, Неопрен», «Рубашка Платье Блуза», «Для сорочек и пижам» и «Хай-тек». Причины и текущий состав очереди можно посмотреть в текущих правилах на отдельной странице.

«Ошибка правил»

Ошибка синтаксиса JSON, пропущенное обязательное поле, неверный тип, повтор table между файлами или повтор key внутри группы останавливают предпросмотр обеих версий. В сообщении указано имя файла и причина. Так ошибка одного справочника не выглядит как успешное частичное преобразование.

Если папка правил пуста или ни одного JSON не найдено, это тоже ошибка. Но корректность формата не гарантирует правильный смысл: допустимый, но ошибочно набранный путь категории просто не совпадёт с источником.

Ошибки снимков

Отсутствующий, пустой, нечитаемый файл, нераспознанная карточка, страница каталога, другой товар в canonical, нераспознанный адрес категории или отсутствие категорий блокируют результат соответствующей версии. В таком случае нужно проверить исходный снимок, а не пытаться исправить его правилом.

Несовпадение языка и повреждённые символы UTF-8 показываются предупреждениями. Предпросмотр может строиться, но предупреждение остаётся видимым.

Правила не проверяют физические свойства ткани. «Натуральные», «Гипоаллергенные» или «Шёлк» переносятся из старых рубрик; это не подтверждение состава, испытаний или актуальности информации.

10. Где это работает в коде

Этот раздел пригодится, если потребуется менять сам механизм, а не только список соответствий.

Файл проектаОтветственность
app/Services/ClassificationRules.phpload() читает и проверяет JSON, строит индекс источников. apply() применяет совпадения, объединяет значения и формирует расшифровку.
app/Services/ClassificationPreview.phpНаходит локальные товары, вызывает парсеры, рассчитывает UK/RU и сравнивает итоговые ключи.
app/Services/CategoryAudit.php
app/Services/PurposeAudit.php
Извлекают категории и назначения из HTML, проверяют карточки и собирают предупреждения.
app/Http/Controllers/ClassificationPreviewController.phpПринимает выбранный product, передаёт результат в страницу. Ответ не кешируется браузером.
resources/views/audit/classification.blade.phpПоказывает поля товара, исходники, переносы и список правил.
app/Http/Controllers/ClassificationGuideController.php
resources/views/audit/classification-guide.blade.php
Текущее разделение по файлам правил. HTML товаров здесь не разбирается.
resources/views/audit/classification-instructions.blade.phpЭта инструкция. Открывается отдельно от просмотра действующих правил.
tests/Feature/ClassificationPreviewTest.phpПроверки покрытия исходного списка, объединений, языков, обновления файлов, ошибок и отсутствия SQL-запросов в предпросмотре.

Данные результата существуют только до завершения запроса. Постоянный файл с «переписанным товаром» не создаётся. Если позже понадобится перенос в базу, это будет отдельная операция с согласованной схемой и отдельной проверкой данных.

Перейти к проверке товара →