85 lines
6.1 KiB
Markdown
85 lines
6.1 KiB
Markdown
# Commerce, МойСклад и маркетплейсы
|
||
|
||
Commerce-контур хранит нормализованные товары, внешние привязки, продажи,
|
||
возвраты, расходы, остатки и локальные изображения товаров. Источником истины
|
||
для структуры данных служат модели `backend/commerce/models/`, для HTTP API —
|
||
`backend/api/v1/commerce/`, для импорта — provider-specific services в
|
||
`backend/commerce/services/`.
|
||
|
||
## Импорт
|
||
|
||
Синхронизация любого подключения запускается Celery-задачей
|
||
`commerce.sync_connection_run`; сервис выбирается по `connection.provider`.
|
||
Для работы ручного импорта нужен Celery worker,
|
||
для расписания — также Celery Beat.
|
||
|
||
Импорт МойСклад выполняет следующие этапы:
|
||
|
||
1. Загружает ассортимент страницами по 100 позиций с `expand=images`.
|
||
2. Нормализует товары, модификации, комплекты, привязки и остатки.
|
||
3. Скачивает оригиналы изображений по авторизованному `downloadHref`, проверяет
|
||
формат и лимит 25 МБ, создаёт локальную WebP-миниатюру.
|
||
4. Импортирует отгрузки и возвраты вместе с позициями.
|
||
5. Сохраняет итоговую статистику и публикует состояние через общий WebSocket.
|
||
|
||
Прогресс запуска сохраняется и отправляется frontend каждые 25 товаров или
|
||
документов. Ошибка отдельного изображения учитывается в `image_errors`, но не
|
||
отменяет импорт товарных и финансовых данных.
|
||
|
||
## Wildberries
|
||
|
||
Подключение принимает API-токен с категорией «Финансы». Проверка токена читает
|
||
`GET https://common-api.wildberries.ru/api/v1/seller-info`, сохраняет ID,
|
||
название магазина и ИНН без сохранения токена в открытом виде, а затем вызывает
|
||
`GET https://finance-api.wildberries.ru/ping`, чтобы подтвердить доступ именно
|
||
к финансовой категории.
|
||
|
||
Финансовая синхронизация использует актуальный
|
||
`POST https://finance-api.wildberries.ru/api/finance/v1/sales-reports/detailed`.
|
||
Отключённый 15 июля 2026 года legacy-метод `reportDetailByPeriod` не используется.
|
||
Каждая строка отчёта сохраняется как `SourceRecord`, затем идемпотентно создаёт
|
||
или обновляет `Sale`, `SaleLine` и связанные `Cost`. Поддерживаются продажи,
|
||
возвраты, комиссия, эквайринг, доставка, хранение, приёмка, удержания, штрафы и
|
||
расходы программы лояльности.
|
||
|
||
Товар сопоставляется сначала по существующей WB-привязке, затем по артикулу и
|
||
штрихкоду. Неоднозначные строки сохраняются, но не привязываются к случайному
|
||
товару; их количество видно в `unmatched_products`. Повторный импорт после
|
||
ручной привязки дополняет аналитику.
|
||
|
||
Один ответ ограничен 100 000 строками. После каждой непустой страницы `rrdId` и
|
||
границы периода сохраняются в metadata источника, а следующий запуск продолжает
|
||
импорт. Завершённым отчёт считается только после ответа WB `204`; длина страницы
|
||
не используется как признак конца. После завершения первичной истории каждый
|
||
запуск повторно проверяет последние 30 дней, чтобы корректировки финансового
|
||
отчёта обновили существующие факты.
|
||
|
||
## Изображения
|
||
|
||
`ProductImage` хранит оригинал и миниатюру в `MEDIA_ROOT/commerce/products/`.
|
||
Временные внешние ссылки МойСклад не возвращаются клиенту и не используются как
|
||
публичные URL. Повторная синхронизация сравнивает внешний размер и время
|
||
изменения, поэтому неизменённое изображение не скачивается повторно. Удалённые
|
||
в источнике изображения удаляются локально после успешного чтения списка.
|
||
|
||
REST `ProductSerializer` возвращает `images[]` с локальными `url` и
|
||
`thumbnail_url`. Каталог использует миниатюру, карточка товара — оригинал для
|
||
полноэкранного просмотра.
|
||
|
||
## Realtime и fallback
|
||
|
||
Событие `commerce_connection_updated` содержит состояние подключения и
|
||
последнего запуска, включая `processed`, `images`, `sales` и `costs`. При рабочем
|
||
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
|
||
```
|