Прототип Channel Letters построен на общем движке конфигурации изделий в backend/app/products.py. ProductType имеет варианты Technology; каждая технология владеет неизменяемыми опубликованными определениями TechnologyVersion. Расчёт хранит ID выбранной версии технологии, ручные входные параметры, замороженные снимки цен/ставок, сводки раскладки по компонентам и итоговый результат. Снимки ревизий включают эту конфигурацию, поэтому старые ревизии сохраняют точное определение и основу цен.
Правила и поля оценки #
Строки TechnologyParameter определяют поля UI, тип ввода, значение по умолчанию, условие видимости, границы и признак автоматического поля. Строки TechnologyRule вычисляют белый список свойств геометрии в порядке приоритета. Эффективное значение берётся из корректного ручного переопределения; иначе автоматическое поле использует первое подходящее правило, а затем настроенное значение по умолчанию. Результат хранит для каждого поля автоматическое значение, эффективное значение, источник (auto, default или manual) и причину правила. Конфигурация хранит только ручной ввод; сброс удаляет переопределение и заново вычисляет правило.
Текущие правила для алюминия выбирают тыл 1,5 мм для букв высотой до 800 мм и 2,0 мм выше; глубина борта — 60 мм до 600 мм и 100 мм выше. Это прототипные правила, их должно подтвердить производство. Композитный тыл использует ACP 3 мм и имеет собственный профиль предварительно окрашенного борта. При переключении технологии сохраняются только ключи параметров, доступные в целевой версии: например, сохраняется предложение поставщика LED, но отбрасываются параметры, относящиеся только к покраске.
Компоненты, маршруты и калькуляция #
TechnologyMaterial описывает каждый компонент стоимости и метод его расчёта: NESTED_SHEET, PERIMETER_LENGTH, AREA, LENGTH_INPUT или MANUAL_COST. Листовые компоненты выбирают из канонических материалов и используют существующий движок раскладки контуров. BACK и FACE раскладываются независимо, с размерами листа выбранного для каждого материала. Линейные и площадные компоненты используют нормализованную геометрию расчёта.
TechnologyOperation направляет операцию на драйвер оценки и категорию стоимости. Условные маршруты могут проверять поля оценки. Драйверы включают фиксированные, поштучные, метровые, квадратно-метровые, полистовые, поминутные, LED-количества и машинное время. Материалы и ставки операций/мастер-данных фиксируются снимком по идентичности в каталоге при первом расчёте. Обновление цен — явное действие. Категории разбивки изделия превращаются в существующие строки расчёта, которые по-прежнему формируют наценку, цену продажи и маржу; построчные строки деталей удаляются, пока активно конфигурируемое изделие, чтобы избежать двойного учёта.
Выборочный кэш раскладки #
Каждый раскладываемый компонент кэширует ключ из идентичности нормализованной геометрии, ID выбранного материала, ширины/высоты листа этого материала, зазора и отступа от края. Пересчёт сравнивает ключи независимо по коду компонента. Изменение только стоимости LED, выбора/ставки покраски или другого негеометрического маршрута не запускает раскладку. Смена толщины/материала тыла инвалидирует BACK, когда меняется его материал/ключ; смена толщины/материала лица инвалидирует FACE аналогично. Изменение геометрии, зазора или отступа инвалидирует каждый раскладываемый компонент, который использует эти входные данные. Это кэш результата расчёта, а не общий/глобальный кэш.
Расчёт фиксируется (commit) до запуска изолированной раскладки, чтобы не держать соединение с базой данных, пока работает подпроцесс. Результат записывает, какие задания по компонентам реально выполнялись; в детальном просмотре раскладки остальных компонентов помечены как переиспользованные.
Жизненный цикл технологии и расширение каталога #
Версии DRAFT редактируются через Settings → Product Types. Публикация архивирует предыдущую опубликованную версию; опубликованные и архивные версии отклоняют изменения. Чтобы внести правки, создайте новый черновик из опубликованной версии. Расчёт остаётся привязан к исходной версии, пока оценщик явно не обновит/не выберет её заново.
Примечание wiki (нет в оригинале): более новое поведение редактора (прямая правка текущей версии, снимок технологии в оценке) описано в статье «Technology Editor — справочник» (
docs/TECHNOLOGY_EDITOR.md).
Чтобы добавить следующую технологию изделия без изменения кода ядра:
- Создайте или выберите Product Type и добавьте Technology.
- Создайте черновик версии; добавьте параметры и детерминированные правила, используя поддерживаемые свойства геометрии.
- Добавьте материальные компоненты, выбирая существующий материал каталога или явно помеченный демо-материал. Настройте для каждого компонента selector/family, метод, коэффициент отходов и группу стоимости.
- Добавьте маршруты операций с поддерживаемыми драйверами, условиями и категориями стоимости; настройте мастер-ставки и профили станков.
- Задайте наценку и примечания оценки, затем опубликуйте версию. Проверьте её на типичной геометрии перед выставлением предложения.
Расширение движка ядра требуется только для новых метрик, выводимых из геометрии, методов расчёта, драйверов операций или операторов правил. Бизнес-логика конкретных поставщиков и определения отдельных изделий относятся к данным версии.
Демо- и неполные коммерческие ставки #
Все стартовые значения, созданные как демо-данные, помечены is_demo. Оценки показывают предупреждение «не для коммерческого использования», если строка в снимке использует демо-ставку. Маршруты с нулевым значением дополнительно выдают предупреждение «no rate configured» при использовании. Стартовый набор намеренно оставляет порошковую покраску, транспорт на покраску и покраску рамы нулевыми до получения реальных ставок поставщиков/производства. Замените все демо-ставки материалов и операций перед выставлением коммерческого предложения.
Список тестов «section 33», на который ссылалась передача задачи, отсутствовал в репозитории, истории веток, документации и заготовках тестов. Реализация добавляет 12 именованных приёмочных тестов в backend/tests/test_channel_letters_products.py для восстановленного минимального поведения.