Версия: 1.0.0
Дата: 2025-11-28
┌─────────────────────────────────────────────────────────────────┐
│ УРОВЕНЬ 0 │
│ (нет зависимостей) │
│ ┌────────────┐ ┌────────────┐ │
│ │ Suppliers │ │ Categories │ │
│ └─────┬──────┘ └─────┬──────┘ │
└────────┼─────────────────┼──────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ УРОВЕНЬ 1 │
│ (зависит от справочников) │
│ ┌─────────────────────────┐ │
│ │ Products │ │
│ │ supplier → Suppliers │ │
│ │ category → Categories │ │
│ └───────────┬─────────────┘ │
└────────────────────────┼────────────────────────────────────────┘
│
┌───────┬───────┼───────┬───────┐
▼ ▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ УРОВЕНЬ 2 │
│ (зависит от Products) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ PIM_Catalog │ │ SKU_Mappings│ │ Images │ │
│ │ article → │ │ article → │ │ article → │ │
│ │ Products │ │ Products │ │ Products │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Prices_History │ │ Bundles │ │
│ │ article → Products │ │ bundle_article → │ │
│ │ supplier → Suppliers│ │ Products │ │
│ └─────────────────────┘ │ component_article → │ │
│ │ Products │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
1. Suppliers — поставщики
2. Categories — категории товаров
Источники:
- Suppliers: ручной ввод или pirotehnika/products/CLAUDE.md
- Categories: из 1С или ручной ввод
Валидация:
- code уникален
- Обязательные поля заполнены
3. Products — основной каталог
Зависимости:
- supplier → должен существовать в Suppliers.code
- category → должен существовать в Categories.code
Источники:
- Экспорт из 1С
- Прайс-листы поставщиков (первичное создание)
Валидация:
- article уникален
- supplier существует в Suppliers
- category существует в Categories
4. PIM_Catalog — характеристики пиротехники
5. SKU_Mappings — маппинг на маркетплейсы
6. Images — изображения
7. Prices_History — история цен
8. Bundles — наборы
Зависимости:
| Таблица | Поле | Ссылается на |
|---|---|---|
| PIM_Catalog | article | Products.article |
| SKU_Mappings | article | Products.article |
| Images | article | Products.article |
| Prices_History | article | Products.article |
| Prices_History | supplier | Suppliers.code |
| Bundles | bundle_article | Products.article |
| Bundles | component_article | Products.article |
┌──────────────┐
│ Прайс XLSX │
│ от поставщика│
└──────┬───────┘
▼
┌──────────────┐ ┌──────────────┐
│ Парсинг │────▶│Prices_History│ (история)
│ прайса │ └──────────────┘
└──────┬───────┘
│
▼ новые артикулы?
┌──────────────┐ ┌──────────────┐
│ Создать │────▶│ Products │ (новые товары)
│ Products │ └──────────────┘
└──────┬───────┘
│
▼ обновить цены
┌──────────────┐
│ Пересчёт цен │
│ base → ozon │
│ base → wb │
└──────────────┘
┌──────────────┐
│ Экспорт 1С │
│ (XML/CSV) │
└──────┬───────┘
▼
┌──────────────┐
│ Сравнение с │
│ Products │
└──────┬───────┘
│
├──▶ Новые → INSERT в Products
├──▶ Изменённые → UPDATE Products
└──▶ Удалённые → пометить archived
┌──────────────┐
│ Products │
│ (active) │
└──────┬───────┘
│
▼
┌──────────────┐ ┌──────────────┐
│ Проверка │────▶│ PIM_Catalog │ (характеристики)
│ готовности │ └──────────────┘
└──────┬───────┘ ┌──────────────┐
│ ────▶│ Images │ (фото)
│ └──────────────┘
▼
┌──────────────┐
│ Создать SKU │
│ на OZON/WB │
└──────┬───────┘
│
▼
┌──────────────┐
│ SKU_Mappings │ (сохранить связь)
└──────────────┘
┌──────────────┐
│ Выбрать │
│ компоненты │
│ из Products │
└──────┬───────┘
│
▼
┌──────────────┐
│ Создать │
│ Products │ (bundle_article)
│ type=bundle │
└──────┬───────┘
│
▼
┌──────────────┐
│ Bundles │ (связи компонентов)
│ bundle → PRD │
│ component → │
│ PRD-001 │
│ PRD-002 │
└──────────────┘
LOAD_ORDER = [
# Этап 0: Справочники
("Suppliers", "suppliers.csv", []),
("Categories", "categories.csv", []),
# Этап 1: Мастер
("Products", "products.csv", ["Suppliers", "Categories"]),
# Этап 2: Детали
("PIM_Catalog", "pim.csv", ["Products"]),
("SKU_Mappings", "sku_mappings.csv", ["Products"]),
("Images", "images.csv", ["Products"]),
("Prices_History", "prices.csv", ["Products", "Suppliers"]),
("Bundles", "bundles.csv", ["Products"]),
]
def load_all():
loaded = set()
for table, file, deps in LOAD_ORDER:
# Проверить зависимости
for dep in deps:
if dep not in loaded:
raise Exception(f"{table} requires {dep}")
# Загрузить
load_table(table, file)
loaded.add(table)
-- Products: проверить supplier
SELECT p.article, p.supplier
FROM Products p
LEFT JOIN Suppliers s ON p.supplier = s.code
WHERE s.code IS NULL;
-- Products: проверить category
SELECT p.article, p.category
FROM Products p
LEFT JOIN Categories c ON p.category = c.code
WHERE c.code IS NULL;
-- SKU_Mappings: проверить article
SELECT sm.article
FROM SKU_Mappings sm
LEFT JOIN Products p ON sm.article = p.article
WHERE p.article IS NULL;
-- Bundles: проверить компоненты
SELECT b.bundle_article, b.component_article
FROM Bundles b
LEFT JOIN Products p ON b.component_article = p.article
WHERE p.article IS NULL;
┌─────────────────────────────────────────────────────────┐
│ S3 HUB (Beget) │
│ /pim/images/*.jpg │
│ ЕДИНСТВЕННОЕ МЕСТО ХРАНЕНИЯ │
│ файлов картинок │
└─────────────────────┬───────────────────────────────────┘
│
│ публичный URL
│
┌─────────────┼─────────────┬─────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ MongoDB │ │ Drupal │ │ NocoDB │ │ OZON │
│ (ссылка)│ │ (ссылка)│ │ (ссылка)│ │ (ссылка)│
└─────────┘ └─────────┘ └─────────┘ └─────────┘
Правило: Файлы НЕ дублируются. Везде только URL на S3.
| Параметр | Значение |
|---|---|
| Провайдер | Beget S3 |
| Bucket | fe2c1d30dc11-s3-0kt |
| Папка | /pim/images/ |
| Файлов | 227 |
| Доступ | Публичный (read) |
| Base URL | https://s3.ru1.storage.beget.cloud/fe2c1d30dc11-s3-0kt/ |
https://s3.ru1.storage.beget.cloud/fe2c1d30dc11-s3-0kt/pim/images/{filename}.jpg
Файл: pim/images/images_index.xlsx
| Колонка | Описание |
|---|---|
| Производитель | Название поставщика |
| Артикул | Ключ связи с Products |
| Название | Название товара |
| S3 URL | Полный публичный URL |
| S3 Key | Путь внутри bucket |
| Имя файла | filename.jpg |
При добавлении картинки:
1. Загрузить файл → S3 /pim/images/
2. Обновить images_index.xlsx
3. Обновить ссылку в MongoDB
4. Обновить ссылку в Drupal
5. Обновить ссылку в NocoDB Images
Images таблица:
├── article → Products.article
├── image_url → S3 публичный URL (НЕ файл!)
├── is_main → главное фото
├── sort_order → порядок
└── source → откуда взято (supplier/manual)
| Статус | Описание | Можно публиковать |
|---|---|---|
| draft | Черновик | ❌ |
| active | Активный | ✅ |
| paused | Приостановлен | ❌ |
| archived | В архиве | ❌ |
| out_of_stock | Нет в наличии | ❌ |
| Статус | Описание |
|---|---|
| active | Опубликован |
| paused | Снят с продажи |
| archived | Удалён |
| pending | Ожидает модерации |
ON UPDATE Products.purchase_price:
→ Пересчитать base_price, ozon_price, wb_price
→ Записать в Prices_History
ON DELETE Products:
→ Проверить нет ли в Bundles
→ Пометить SKU_Mappings как archived
ON UPDATE Suppliers.code:
→ Обновить Products.supplier
→ Обновить Prices_History.supplier
Версия: 1.0.0