catalog-data

Данные каталога — SQLite, поиск по названию, мягкое удаление, миграции, заливка каталога из выгрузки товароучёта. Использовать при правке моделей, репозиториев и импорта товаров.

SKILL.md

GitHub

Данные каталога

  • Поиск товаров по названию фильтруется в Python, а не в SQL: LIKE в SQLite не понимает регистра кириллицы.
  • Товары удаляются мягко (active = 0) — на них ссылается журнал операций.
  • Миграций пока нет, схема создаётся через create_all. При первом изменении моделей на устройстве с данными — вводить Alembic.
  • В БД от снимка хранится только имя файла (поле image); сами файлы, их привязка к товарам и подготовка к экрану — в скилле product-photos.
  • Каталог заливается из выгрузки товароучёта docs/prod.xlsx скриптом backend/tools/import_products.py. Выгрузка лежит в docs/, а не рядом со снимками: всё, что попадает в frontend/public/products, уезжает в сборку и раздаётся прибором, а список артикулов с наименованиями там ни к чему. Скрипт: артикул становится кодом товара, единица измерения читается из названия («… кг» весовой, «… шт» и «… 200гр» штучные), снимок находится по тому же артикулу. Цены и группы в выгрузке нет — ключ --random-prices ставит заглушку там, где цены ещё нет, а --groups= раскладывает группы по первому слову названия. Без --apply скрипт только показывает план.

Приём каталога из 1С

  • Приёмник — backend/app/api/import_1c.py, POST /api/catalog/1c-import. Формат диктует обработка 1С integrations/1c/original-Libra.bsl, которая уже работает у заказчика и не правится без явной просьбы: заголовок X-API-Key, код товара в поле article, проверка связи по GET /health. Что она шлёт и что мы отвечаем — integrations/1c/README.md; менять контракт можно только с обеих сторон разом.
  • Артикул из 1С и есть plu: покупатель набирает его на весах, он же пять цифр в штрихкоде. Позиция без числового артикула или длиннее пяти цифр не роняет пакет 422 — в схеме plu необязателен, а диапазон проверяет приёмник и кладёт позицию в errors[] ответа, чтобы 1С показала её в своём логе.
  • Синхронизация полная: чего нет в пакете, то гасится. Поэтому пустой пакет и пакет без единого пригодного артикула отклоняются (400) — сбой выгрузки не должен гасить каталог. После приёма — live.notify("catalog"), киоск перерисовывается.
  • 1С ходит на весы снаружи (сервер 1С только по RDP) через Cloudflare Tunnel с прибора — поэтому приём без токена закрыт (503), tools/dev.py слушает 0.0.0.0, а туннель и адреса описаны в docs/deploy.md (скилл deployment).
  • Групп как таблицы нет: они собираются из поля category товаров. Своего у группы две вещи, обе в category_covers: обложка (скилл product-photos) и место в порядке (sort_order, скилл kiosk-catalog).
  • Колонку к существующей таблице create_all не добавляет, а базу прибора пересоздавать нельзя — в ней каталог и журнал. Для таких правок в db.py есть список _ADDED_COLUMNS и ALTER TABLE на старте; когда их станет больше единиц — Alembic.
  • Та же чистка есть в админке («Товари» → «Очистити дані», POST /api/catalog/purge) тремя областями: журнал с растрами, скрытые товары, весь каталог. Журнал удаляется вместе с товарами, а не остаётся висеть: его записи ссылаются на товар по id. Снимки чистятся только приборные (data/photos) — демо-набор из сборки фронта не трогаем, он часть образа. Обложки групп чистка не трогает вовсе: их подбирают руками по одной, а группа с тем же именем придёт из 1С снова, и обложка встанет на место. После чистки — live.notify("catalog").
  • Перед сдачей прибора — tools/clean_db.py --apply: журнал операций, растры этикеток, товары с active = 0 (журнал пуст, держать их незачем) и снимки без товара в data/photos; каталог и живые снимки остаются. Без --apply — план.
  • Под проверку выгрузки из 1С рабочие данные разработки убираются в мок: tools/mock_data.py stash переносит базу и снимки в backend/data/mock/ (гитигнор), restore возвращает; оба — при остановленном бэкенде (SQLite занят). Чтобы пустая база не засеялась демо, в backend/.env ставится S2L_SEED_DEMO=0. Осторожно с uvicorn --reload на Windows: после убийства родителя дочерний процесс-воркер живёт дальше и держит s2l.db — искать по --multiprocessing-fork.