# Commerce и МойСклад Commerce-контур хранит нормализованные товары, внешние привязки, продажи, возвраты, расходы, остатки и локальные изображения товаров. Источником истины для структуры данных служат модели `backend/commerce/models/`, для HTTP API — `backend/api/v1/commerce/`, для импорта — `backend/commerce/services/moysklad_sync.py`. ## Импорт Полная синхронизация запускается Celery-задачей `commerce.sync_moysklad_run`. Для работы ручного импорта нужен Celery worker, для расписания — также Celery Beat. Импорт выполняет следующие этапы: 1. Загружает ассортимент страницами по 100 позиций с `expand=images`. 2. Нормализует товары, модификации, комплекты, привязки и остатки. 3. Скачивает оригиналы изображений по авторизованному `downloadHref`, проверяет формат и лимит 25 МБ, создаёт локальную WebP-миниатюру. 4. Импортирует отгрузки и возвраты вместе с позициями. 5. Сохраняет итоговую статистику и публикует состояние через общий WebSocket. Прогресс запуска сохраняется и отправляется frontend каждые 25 товаров или документов. Ошибка отдельного изображения учитывается в `image_errors`, но не отменяет импорт товарных и финансовых данных. ## Изображения `ProductImage` хранит оригинал и миниатюру в `MEDIA_ROOT/commerce/products/`. Временные внешние ссылки МойСклад не возвращаются клиенту и не используются как публичные URL. Повторная синхронизация сравнивает внешний размер и время изменения, поэтому неизменённое изображение не скачивается повторно. Удалённые в источнике изображения удаляются локально после успешного чтения списка. REST `ProductSerializer` возвращает `images[]` с локальными `url` и `thumbnail_url`. Каталог использует миниатюру, карточка товара — оригинал для полноэкранного просмотра. ## Realtime и fallback Событие `commerce_connection_updated` содержит состояние подключения и последнего запуска, включая `processed`, `images` и `sales`. При рабочем WebSocket frontend не опрашивает connections endpoint. Если WebSocket недоступен во время активного импорта, включается REST fallback раз в 30 секунд. ## Проверка ```bash cd backend pytest tests/commerce -q python manage.py makemigrations --check --dry-run python manage.py check ruff check commerce api/v1/commerce tests/commerce ```