Signage Estimator — README проекта

10 мин. чтения

Статус Актуально
Последняя проверка 2026-10-07 (соответствует Git на момент импорта; содержание повторно не проверялось)
Источник Git
Исходный файл README.md — открыть на GitHub
Язык статьи перевод с английского оригинала (файл перевода: translations/ru/README.md)
Git-репозиторий git@github.com:advertech/signage-estimator.git (сервер: /root/signage-estimator)
Git-коммит d22587c1f7e3add9efd54c7ffc0be0a01b296fa3 (master)
Файл последний раз изменён 79bbaf22f0a9 от 2026-09-27
Последний импорт 2026-10-07T09:14:19+02:00
Примечание Источник истины — Git. Меняйте файл в репозитории и перезапускайте /root/wiki-sign-expert/import_git_docs.py; правки, сделанные здесь, будут перезаписаны следующим импортом.

Независимое приложение для расчёта коммерческих предложений и векторной раскладки (nesting). React/Vite отрисовывает нормализованную SVG-геометрию; FastAPI обрабатывает REST, импорт файлов, раскладку, калькуляцию, шаринг и экспорт. SQLAlchemy поддерживает SQLite локально и PostgreSQL в Compose. Нормализованная модель деталей GeoJSON, а не загруженный файл, питает превью, раскладку и цены.

Production-развёртывание #

Подготовленное развёртывание calc.sign-expert.eu использует backend под
systemd на 127.0.0.1:8000, автоматический HTTPS в Caddy и собранные файлы
frontend, раздаваемые из /var/www/signage-estimator. Оно переиспользует
существующую базу SQLite и хранилище; новая база не создаётся. Порядок
переключения, бэкапа, проверки здоровья, отката и верификации — в
deploy/DEPLOYMENT.md.
Репозиторий также содержит дополнительный сайт Caddy,
unit systemd и
проверку production только для чтения. Сервис на
хосте, firewall, DNS, TLS и проверку GitHub нужно выполнить на реальном сервере;
ограниченная сборочная оболочка не может удостоверить публичное развёртывание.

Локальный запуск на этом сервере #

cd /root/signage-estimator
python3 -m venv .venv
.venv/bin/pip install -r backend/requirements.txt
cd frontend && npm ci && cd ..
cd backend && ../.venv/bin/alembic upgrade head && cd ..
.venv/bin/python -m backend.app.bootstrap_admin
.venv/bin/uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 --no-access-log
# в другом терминале
cd frontend && npm run dev

Откройте http://SERVER-IP:5173 для локальной разработки или разработки в доверенной сети. Сервер Vite проксирует /api на порт 8000 и перенаправляет неаутентифицированные приватные маршруты UI на /login. Защищённая документация REST — по адресу http://SERVER-IP:8000/docs. Одноразовая команда bootstrap запрашивает email и пароль длиной не менее 12 символов; она отказывается работать, если уже существует хотя бы один пользователь. Задайте DATABASE_URL и STORAGE_DIR для нестандартных расположений. Миграции запускаются из backend/ командой ../.venv/bin/alembic upgrade head. Установите TRUSTED_HOSTS в точное имя хоста или IP разработки, который используют клиенты. Обслуживайте production-вход через HTTPS и установите SESSION_COOKIE_SECURE=true.

Развёртывание через Docker #

На проверенном хосте Docker не был установлен, поэтому эта конфигурация подготовлена, но здесь не запускалась.

cp .env.example .env
# задайте в .env надёжный POSTGRES_PASSWORD, TRUSTED_HOSTS и нужный WEB_PORT
docker compose up -d --build
docker compose exec backend python -m backend.app.bootstrap_admin

По умолчанию Compose привязывает порт 8080 к 127.0.0.1. Он запускает приватный PostgreSQL, backend от непривилегированного пользователя с миграциями и Nginx, раздающий собранный frontend. Поставьте перед ним TLS, установите TRUSTED_HOSTS в публичный домен и SESSION_COOKIE_SECURE=true, затем используйте обратный прокси, например дополнительный пример Caddy. Не открывайте Vite или uvicorn напрямую как конечную точку входа production. Существующая конфигурация обратного прокси не меняется. Bootstrap выполняется один раз и интерактивно; держите .env в секрете.

Учётные записи и мастер-данные #

Каждая операция API, кроме health и login, требует отзываемой HttpOnly-cookie сессии. Изменения также требуют CSRF-токена сессии. Admin и Estimator имеют одинаковые права на расчёты, поставщиков, станки, операции и настройки AI; только Admin может управлять пользователями и просматривать UI аудита. Профиль пользователя задаёт отображаемое имя, email, пароль, предпочитаемый язык, имя Copilot и предпочтение голоса. Имя Copilot по умолчанию — Vlad (Влад при выборе русского языка).

В Settings теперь есть Suppliers, Price Lists, Supplier Offers, Machines & Technology, Operation Rules, AI / Copilot, а также только для Admin — Users и Audit Log. Загружайте XLSX, XLS, CSV или PDF в карточке поставщика. Все непустые разобранные строки сохраняются как продукты поставщика, включая неиспользуемые. Прайс-листы начинают со статуса STAGED; проверьте предложенные сопоставления, подтвердите их и активируйте список. Извлечение из PDF намеренно помечается как ненадёжное для ручной проверки. Продукты поставщиков хранятся отдельно от канонических материалов. Подтверждённые активные предложения можно сравнивать и явно отмечать как предпочтительные.

Новые строки материалов фиксируют снимок цены с поставщиком, продуктом, ревизией прайс-листа, валютой, размерами и ценой листа. Строки резки замораживают выбранный настроенный профиль технологии, подачу станка и почасовую ставку. Последующие правки у поставщика или станка не переписывают существующие цены незаметно; POST /api/calculations/{id}/refresh-prices явно берёт текущие предложения и технологию. Сохранённые ревизии расчёта включают снимки.

Конфигурируемые технологии изделий теперь поддерживают версионируемые поля, правила, материальные компоненты, маршруты операций, кэши раскладки по компонентам и замороженные снимки цен/ставок. Жизненный цикл, входные данные кэша, предупреждения о демо-ставках и шаги добавления новой технологии изделия без правки кода ядра описаны в руководстве по архитектуре и расширению Channel Letters.

Векторный импорт сохраняет исходные контуры и перед раскладкой использует отдельный слой интерпретации Geometry Review. Роли, поведение ревизий и текущие ограничения топологии — в статье Импорт геометрии и производственная интерпретация.

Использование #

Создайте расчёт, выберите тип изделия, затем добавьте прямоугольник/круг или загрузите PDF/SVG/DXF. Правила изделия предлагают группу материалов и список ожидаемых операций; детальные сборки объёмных букв всё ещё требуют ручных строк. Для чертежа в масштабе 1:10 установите масштаб источника 10. Выберите материал и запустите раскладку. Сохраняемый статус задания показывает подготовку, реальное число обработанных деталей, проверку раскладки, сохранение, завершение или ошибку; кнопка Cancel останавливает выполняющееся задание. Все листы показываются в одном вертикальном рабочем пространстве с общим масштабом и истинными пропорциями листа. Переопределение редактируется двойным щелчком по ячейке калькуляции, затем Save. Номер ревизии увеличивается при каждом сохранении. Share копирует ссылку на UI только для чтения. Панель Copilot работает без AI-ключа на детерминированных командах, например Calculate 300 rectangles 600x387 mm from 5 mm PMMA и Try to fit this on 3 sheets. Беседа сохраняется для каждого расчёта и остаётся доступной после восстановления ревизии.

Используйте Print / PDF над рабочим пространством раскладки, чтобы открыть векторный предпросмотр печати. Выберите один или два листа раскладки на страницу A4 и ориентацию Auto, Portrait или Landscape, затем распечатайте или сохраните в PDF из браузера. Чертежи пропорционально масштабируются на печатную область; размерные подписи остаются в миллиметрах. Предпросмотр — производственный обзор, а не шаблон резки 1:1.

Детали, превышающие размер листа, остаются неразмещёнными. Выберите деталь, укажите горизонтальную или вертикальную позицию разреза и перезапустите раскладку. Раскладку листа можно экспортировать в SVG, таблицу — в CSV, сводку — в PDF. Ручное размещение использует поля X/Y/поворот с проверкой столкновений и границ листа.

API и данные #

Основные эндпоинты: POST /api/calculations, GET /api/calculations/{id}, POST /api/calculations/{id}/files, GET /api/calculations/{id}/parts, POST /api/calculations/{id}/nest, GET /api/calculations/{id}/totals, эндпоинты ревизий и шаринга, а также /api/settings. POST /api/calculations/{id}/nest возвращает HTTP 202 с nesting_run_id; опрашивайте GET /api/nesting-runs/{id}, чтобы получить этап, прогресс, прошедшее время, число размещённых деталей, текущие листы, коэффициент использования и ошибки. POST /api/nesting-runs/{id}/cancel запрашивает отмену. Раскладку выполняет небольшой пул воркеров внутри процесса, поэтому сервис Redis для этого развёртывания не нужен. Активные задания, прерванные перезапуском backend, помечаются как failed и могут быть запущены заново. Записи заданий и история Copilot проекта хранятся в базе данных. GET /api/calculations/{id}/copilot/messages возвращает основной тред проекта и сообщения; каждое сообщение фиксирует активную ревизию. Действия инструментов используют текущее состояние расчёта, а история переживает ревизии. OpenAPI доступен по /docs. Copilot вызывает тот же ограниченный слой действий, что открыт по /api/calculations/{id}/copilot/actions; инструмента прямого доступа к базе данных у него нет.

Дополнительные эндпоинты: /api/auth/login, /api/auth/me, /api/auth/logout, /api/profile, для Admin /api/users, /api/suppliers, /api/suppliers/{id}/price-lists, /api/price-lists/{id}/products, /api/supplier-products/{id}/mapping, /api/materials/{id}/offers, /api/machines, /api/technology-profiles, /api/operation-rules, /api/calculations/{id}/operations, /api/ai-config и для Admin /api/audit-logs. API-клиенты должны сохранять cookie и при записи отправлять значение cookie signage_csrf в заголовке X-CSRF-Token.

Copilot и голос #

local_adapter / deterministic активен, когда провайдер не настроен. Выберите Gemini или OpenAI-совместимый эндпоинт в настройках AI либо задайте AI_PROVIDER и AI_MODEL в окружении backend. Для Gemini задайте GEMINI_API_KEY; сервер использует SDK google-genai. Для локальной модели задайте LOCAL_AI_BASE_URL и при необходимости LOCAL_AI_API_KEY; эндпоинт должен быть доступен из процесса backend. Локальная модель необязательна. Инференс только на CPU может быть медленным; оборудование и квантизацию подбирайте отдельно под выбранную модель.

Текстовый Copilot и голос используют один тред проекта. Голосовая панель предлагает офлайн-режим разговорного тестирования с распознаванием речи в браузере и озвученными ответами. Нужен поддерживаемый браузер и HTTPS или localhost для доступа к микрофону. Чтобы использовать Gemini Live, настройте AI_PROVIDER=gemini, AI_VOICE_MODEL на модель с поддержкой Live, GEMINI_API_KEY и включите голос в настройках AI. Браузер отправляет PCM 16 кГц в серверный WebSocket-мост; сервер хранит API-ключ, выполняет только разрешённые инструменты и возвращает события аудио и расшифровки. Реальное аудио Gemini Live на этом хосте не проверялось из-за отсутствия учётных данных. Доступность голоса в браузере и реальное качество звука нужно проверить после настройки HTTPS и учётных данных.

Полигоны Shapely сохраняют внешние кольца и отверстия. Векторы PDF берутся из get_drawings() PyMuPDF, а не из OCR. Эвристика раскладки проверяет реальное расстояние/пересечение полигонов с учётом зазора и отступа. Это быстрая конструктивная эвристика, а не глобально оптимальный оптимизатор. Цены считаются за настроенный лист, распределяются по деталям пропорционально площади, плюс настроенное время/ставка резки. Демо-конфигурацию материалов и резки нужно проверить перед коммерческими предложениями.

Тесты и бэкапы #

.venv/bin/pytest -q
cd frontend && npm run build

Делайте резервную копию и базы данных, и хранилища исходных файлов. Для локального SQLite скопируйте signage.db после остановки backend, а также storage/. Для Compose выполните docker compose exec -T db pg_dump -U signage signage > signage-backup.sql и сохраните том source_files. Восстанавливайте SQL в новую базу, а файлы — по их сохранённым путям. Проверьте восстановление, прежде чем полагаться на бэкапы.

Известные ограничения: сложная семантика clipping/прозрачности PDF и DXF-файлы без единиц требуют проверки на конкретных макетах; раскладка произвольных контуров эвристическая; все аутентифицированные пользователи имеют общий доступ к расчётам (организаций и разделения по владельцам пока нет); раскладка со смешанными материалами использует один размер листа на расчёт; произвольные PDF-каталоги поставщиков требуют проверки; экспорта в DXF пока нет. См. TODO.md и SECURITY.md.

Прежний аудит безопасности сверен по пунктам в SECURITY_RECONCILIATION.md. Текущие ограничения: количество детали — до 10 000, всего деталей в раскладке — до 20 000, размеры — до 100 000 мм, масштаб источника — 0,001–1000, страниц PDF — до 100, векторных контуров — до 5 000, векторных точек — до 200 000. Раскладка выполняется в прерываемом подпроцессе с настраиваемым 180-секундным пределом реального времени. Решатель переиспользует подготовленные ориентации, держит число опорных точек-кандидатов линейным относительно размещённых контуров и проверяет кэшированные границы перед точным расстоянием/пересечением полигонов. Логи воркера включают тайминги подготовки геометрии, генерации кандидатов, столкновений и предикатов GEOS, самые медленные детали и время проверки раскладки. Обычная раскладка 32 кругов занимает около секунды на сервере разработки; предел безопасности — не ожидаемое время работы. Разбор документов выполняется в короткоживущем подпроцессе с 30-секундным бюджетом парсера, лимитами памяти/CPU и без секретов backend в окружении. Размер тела загрузки ограничивается до разбора multipart; импорт прайс-листов дополнительно ограничивает распаковку XLSX, число строк и длину ячеек. Лимиты настраиваются переменными окружения MAX_* в security.py. Счётчики лимитов HTTP локальны для процесса; для нескольких реплик нужны лимиты на границе или распределённые лимиты.

Прогресс раскладки отражает реально обработанные детали в задании по этапам. Текущий этап «optimizing» проверяет геометрию и сообщает результат эвристики; второго глобального поиска оптимизации он не выполняет. NESTING_PERFORMANCE.md фиксирует исследование тайм-аута на 32 кругах и замеры до/после. Очередь внутри процесса подходит для одного процесса backend. Используйте надёжную внешнюю очередь и общий механизм отмены перед запуском нескольких реплик backend или при большом числе одновременных раскладок. Вывод A4 PDF из браузера сохраняет SVG-векторы, но всё ещё требует производственного оформления печати и проверки полей конкретных принтеров.

Обновлено 07.10.2026