architect/_archive/2025-11-09-marketplace-old/marketplace-mvp/PROJECT-MASTER.md

🎯 ПРОЕКТ: MARKETPLACE MVP

Дата создания: 2025-11-07
Версия: 2.0
Статус: В разработке


📋 ОПИСАНИЕ

Система управления продажами на маркетплейсах (Ozon, Wildberries, Яндекс.Маркет).

Основной функционал:
- Автоматическое подключение каналов продаж
- Управление юридическими лицами
- Управление складами и логистикой
- Обработка заказов
- Учёт товаров


🏗️ АРХИТЕКТУРА

Структура БД

User (пользователи)
  ↓
LegalEntity (юр.лица) → связь по ИНН
  ↓
Channel (каналы продаж)
  ↓
  ├─ Warehouse (склады)
  ├─ DeliveryService (службы доставки)
  └─ ChannelStatusMapping (маппинг статусов)

Order (заказы)
  ├─ OrderItem (позиции заказа)
  └─ OrderStatusHistory (история статусов)

Product (товары)
  ├─ ProductVariant (вариации)
  ├─ ProductImage (картинки)
  └─ ProductChannelMapping (связь с каналами)

📦 СКЛАДЫ - ТИПЫ И НАСТРОЙКИ

1. По владению (warehouse_type)

Тип Код Описание
Собственный own Физический склад продавца
Маркетплейс marketplace Склад маркетплейса (FBO)
Дропшиппер dropshipper Склад партнёра-дропшиппера
Партнёр partner Склад партнёра для дозаказа
Виртуальный virtual Виртуальный склад с фильтрацией

2. По схеме работы (fulfillment_type)

Схема Код Хранение Доставка Описание
FBO fbo Маркетплейс Маркетплейс Полный фулфилмент
FBS fbs Продавец Маркетплейс Со склада продавца
DBS dbs Продавец Продавец Своя доставка
Crossdock crossdock Транзит Смешанная Быстрая перегрузка

3. По режиму работы (work_mode)

Режим Код Описание
Круглосуточно 24/7 Работает всегда
По расписанию schedule Определённые часы
По запросу on_demand Нужна запись

Настройки времени по маркетплейсам (2025)

OZON:
- Максимум времени на сборку: 24 часа
- Минимум для планирования поставки: 12 часов
- График по умолчанию: 09:00-18:00 пн-пт

WILDBERRIES:
- Максимум на обработку: 120 часов (5 дней)
- Рекомендуется: 24 часа
- График по умолчанию: 08:00-22:00 ежедневно
- Штраф за просрочку: 50% от стоимости (мин. 100₽)

ЯНДЕКС.МАРКЕТ:
- Минимум рабочих дней: 5
- Целевое среднее время отгрузки: 36 часов
- График по умолчанию: 09:00-20:00 пн-вс
- Скидка 4% за 7 дней работы + отгрузка в день заказа

Поля модели Warehouse:

# Идентификация
external_id: str
name: str

# Типизация
warehouse_type: str         # own/marketplace/dropshipper/partner/virtual
fulfillment_type: str       # fbo/fbs/dbs/crossdock
work_mode: str             # 24/7/schedule/on_demand
work_schedule: str         # "09:00-18:00 пн-пт"

# Параметры работы
is_active: bool
can_ship_anytime: bool     # Можно грузить в любой момент (DBS)
requires_appointment: bool # Нужна запись (crossdock)
min_prep_time_hours: int   # Минимальное время подготовки

# Фильтрация (виртуальные склады)
filter_rules: JSON         # {"category": ["Одежда"], "price_min": 1000}

# Контакты
address: str
contact_person: str
phone: str

📦 СХЕМЫ FULFILLMENT (ОБРАБОТКИ ЗАКАЗОВ)

Обзор схем Ozon 2025

На маркетплейсе Ozon существует 3 основные схемы обработки заказов, которые различаются по месту хранения товара и способу доставки покупателю.

Схема Код Хранение Доставка Этикетки Трекинг Описание
FBO fbo Склад Ozon Ozon Ozon Ozon Полный фулфилмент
FBS fbs Склад продавца Ozon Ozon Ozon Со склада продавца
realFBS realfbs Склад продавца Продавец Свои Свои Своя доставка

Ключевое различие FBS vs realFBS:
- FBS: Товар на вашем складе, но доставляет Ozon → используются этикетки Ozon, трекинг Ozon, акты Ozon
- realFBS: Товар на вашем складе, доставляете вы сами → используются свои этикетки (СДЭК/Почта/курьер), свой трекинг, свои акты

1. FBO (Fulfillment by Ozon)

Суть: Товар хранится на складе Ozon, Ozon полностью берёт на себя обработку и доставку.

Процесс:

Товар → Склад Ozon → Заказ → Ozon упаковывает → Ozon доставляет → Покупатель

Что делает продавец:
- Поставляет товар на склад Ozon (FBO-поставки)
- Следит за остатками
- Обрабатывает возвраты (опционально)

Что делает Ozon:
- Хранит товар
- Упаковывает заказы
- Генерирует этикетки
- Доставляет покупателю
- Обрабатывает возвраты

Преимущества:
- Минимальная нагрузка на продавца
- Быстрая доставка (товар в регионах Ozon)
- Высокая конверсия (badge "Ozon")

Недостатки:
- Высокие комиссии
- Нужно хранить товар на складе Ozon
- Меньше контроля над процессом

SLA:
- Поставка на склад: минимум за 12 часов до забора
- Доставка покупателю: 1-7 дней (зависит от региона)

API методы:
- create_fbo_supply() - создать поставку
- get_fbo_supply_status() - статус поставки
- get_fbo_stocks() - остатки на складе Ozon


2. FBS (Fulfillment by Seller)

Суть: Товар хранится на складе продавца, но доставляет Ozon.

Процесс:

Заказ → Продавец собирает → Ozon забирает → Ozon доставляет → Покупатель

Что делает продавец:
- Хранит товар на своём складе
- Получает заказ → собирает → упаковывает
- Печатает этикетки Ozon
- Передаёт заказы курьеру Ozon

Что делает Ozon:
- Забирает заказы со склада продавца (по графику: 10:00, 15:00)
- Доставляет покупателю
- Обрабатывает возвраты (частично)

Преимущества:
- Нет затрат на хранение на складе Ozon
- Контроль над остатками
- Ниже комиссия, чем FBO

Недостатки:
- Нужен свой склад
- Строгие SLA на сборку (24 часа)
- График забора курьером Ozon (2 раза в день)

SLA:
- Время на сборку: 24 часа с момента заказа
- График забора курьером Ozon: 10:00, 15:00 (ежедневно)
- Доставка покупателю: 1-7 дней (Ozon)

Workflow в системе:
1. Загрузить заказы (статус awaiting_packaging)
2. Перевести в сборку: start_packing(posting_numbers)
3. Собрать и упаковать
4. Печать этикеток Ozon: get_posting_labels(posting_numbers) → PDF
5. Печать акта для курьера: get_posting_act(date, delivery_service) → PDF
6. Передать курьеру Ozon (10:00 или 15:00)
7. Отметить отгрузку: ship_posting(posting_number, ozon_tracking) (трек-номер получаем от Ozon!)

API методы:
- fetch_orders() - получить заказы FBS
- start_packing() - перевести в сборку
- get_posting_labels() - этикетки Ozon (PDF)
- get_posting_act() - акт приёма-передачи Ozon (PDF)
- ship_posting() - отметить отгрузку с трек-номером Ozon

Важно:
- Этикетки генерирует Ozon (не СДЭК, не Почта!)
- Трекинг ведёт Ozon (не ваш!)
- Акт для курьера получаете через Ozon API


3. realFBS (Real FBS / DBS - Delivery by Seller)

Суть: Товар хранится на складе продавца, доставляет продавец (или его служба доставки).

Процесс:

Заказ → Продавец собирает → Продавец доставляет → Покупатель
          ↓
    Свои этикетки (СДЭК/Почта/курьер)
    Свой трек-номер

Что делает продавец:
- Хранит товар
- Собирает и упаковывает
- Генерирует свои этикетки (через СДЭК API / Почта API / свои)
- Доставляет сам (курьером или через службу)
- Загружает свой трек-номер на Ozon

Что делает Ozon:
- Передаёт заказы продавцу
- Следит за соблюдением SLA
- Принимает трек-номера от продавца

Преимущества:
- Полный контроль над доставкой
- Можно использовать любую службу (СДЭК, Почта, Яндекс, свой курьер)
- Гибкость в выборе времени доставки
- Более высокая конверсия на экспресс-доставке

Недостатки:
- Нужно самому организовывать доставку
- Ответственность за срыв сроков
- Нужны интеграции с СДЭК/Почтой/и т.д.

SLA (3 типа):

Тип Код Время доставки Применение Конверсия
Стандартная standard До 30 дней Регионы, негабарит Базовая
Срочная (Comfort) comfort До 8 часов Город, популярные товары +8%
Экспресс express До 30 минут Еда, цветы, срочное +13%

Workflow в системе:

Стандартная realFBS (до 30 дней):
1. Загрузить заказы (фильтр: fulfillment_scheme='realfbs', realfbs_type='standard')
2. Собрать и упаковать
3. Создать заказ в СДЭК/Почте через их API → получить свой трек-номер
4. Напечатать свою этикетку (СДЭК/Почта PDF)
5. Загрузить трек-номер на Ozon: ship_posting(posting_number, own_tracking)
6. Передать в СДЭК/Почту/курьеру
7. Отслеживать доставку через СДЭК/Почту API

Срочная realFBS (до 8 часов):
1. Мониторинг SLA: каждый заказ имеет дедлайн = order_date + 8 часов
2. Цветовая индикация:
- 🟢 Зелёный: осталось > 2 часов
- 🟡 Жёлтый: осталось 1-2 часа
- 🔴 Красный: осталось < 1 часа или просрочено
3. Процесс аналогичен стандартной, но с жёстким контролем времени
4. Рекомендуется: курьер на линии, мгновенная передача заказа

Экспресс realFBS (до 30 минут):
1. Критичный SLA: дедлайн = order_date + 30 минут
2. Минутный мониторинг:
- 🟢 > 15 минут
- 🟡 10-15 минут
- 🔴 < 10 минут или просрочено
3. Процесс:
- Товар уже упакован и готов к отправке
- Курьер постоянно на месте или доставка роботом
- Мгновенная отгрузка после заказа
4. Применение: готовая еда, цветы, экстренные товары
5. Конверсия +13% - покупатели готовы платить за скорость

API методы:
- fetch_orders() - получить заказы realFBS
- ship_posting(posting_number, own_tracking) - загрузить свой трек-номер
- Интеграция с СДЭК API (отдельный модуль)
- Интеграция с Почтой России API (отдельный модуль)

Важно:
- Этикетки генерируете вы (через API СДЭК/Почты или свои)
- Трек-номер ваш (от СДЭК/Почты/своего курьера)
- Акты доставки ваши (не Ozon)
- Ozon только следит за соблюдением SLA


Сравнение схем

Параметр FBO FBS realFBS
Хранение Ozon Продавец Продавец
Доставка Ozon Ozon Продавец
Этикетки Ozon Ozon Свои
Трекинг Ozon Ozon Свой
Акты Ozon Ozon Свои
Контроль Минимальный Средний Полный
Комиссия Высокая Средняя Низкая
Сложность Низкая Средняя Высокая
SLA сборки - 24 часа 30 дней / 8 ч / 30 мин

Поля Order для схем

# Схема fulfillment
fulfillment_scheme = Column(String(50), default='fbs')
# Значения: 'fbo' / 'fbs' / 'realfbs'

realfbs_type = Column(String(50))
# Значения для realfbs: 'standard' / 'comfort' / 'express'
# NULL для fbo и fbs

# Доставка
delivery_type = Column(String(50))  # kts, pvz, courier, post
delivery_service = Column(String(50))  # pochta, yandex, kts, cdek, boxberry

# Трекинг
tracking_number = Column(String(255))
# FBO/FBS: трек-номер Ozon
# realFBS: NULL

own_tracking_number = Column(String(255))
# realFBS: свой трек от СДЭК/Почты/курьера
# FBO/FBS: NULL

track_uploaded = Column(Boolean, default=False)
shipped_at = Column(DateTime)  # Дата отгрузки

UI структура (pages/04_📋_Заказы.py)

📋 Заказы

├─ 📥 Загрузка заказов (expander, collapsed)

└─ 3 основных раздела (tabs):
   
   ├─ 📦 FBS - Доставка силами Ozon
      ├─ Фильтр: fulfillment_scheme = 'fbs'
      ├─ График забора: 10:00, 15:00
      ├─ SLA: 24 часа на сборку
      ├─ Операции:
         ├─ Перевести в сборку
         ├─ Печать этикеток Ozon (PDF)
         └─ Печать акта Ozon (PDF)
      └─ Кнопка отгрузки с Ozon трек-номером
   
   ├─ 🚚 Своя доставка (realFBS)
      
      └─ 3 подраздела (nested tabs):
          
          ├─ 📋 Обычная (до 30 дней)
             ├─ Фильтр: realfbs_type = 'standard'
             ├─ Выбор службы доставки (СДЭК/Почта/...)
             ├─ Ввод своего трек-номера
             └─ Загрузка трека на Ozon
          
          ├─  Срочная (до 8 часов)
             ├─ Фильтр: realfbs_type = 'comfort'
             ├─ SLA мониторинг: order_date + 8h
             ├─ Цветовая индикация:
                🟢 > 2 часов
                🟡 1-2 часа
                🔴 < 1 час / просрочено
             └─ Конверсия: +8%
          
          └─ 🔥 Экспресс (до 30 минут)
              ├─ Фильтр: realfbs_type = 'express'
              ├─ SLA мониторинг: order_date + 30min
              ├─ Минутный таймер:
                 🟢 > 15 минут
                 🟡 10-15 минут
                 🔴 < 10 минут / просрочено
              └─ Конверсия: +13%
   
   └─ 🏢 Поставки FBO
       ├─ Фильтр: fulfillment_scheme = 'fbo'
       ├─ Создание поставки на склад Ozon
       ├─ Статус поставки
       └─ Остатки на FBO складе

Пример workflow

Сценарий 1: FBS заказ

# 1. Загрузить заказы FBS
orders = api.fetch_orders(date_from, date_to)
fbs_orders = [o for o in orders if o['fulfillment_scheme'] == 'fbs']

# 2. Перевести в сборку
posting_numbers = [o['posting_number'] for o in fbs_orders]
api.start_packing(posting_numbers)

# 3. Собрать товары, упаковать

# 4. Печать этикеток Ozon
labels_pdf = api.get_posting_labels(posting_numbers)

# 5. Печать акта для курьера Ozon
act_pdf = api.get_posting_act(date="2025-11-08", delivery_service="ozon")

# 6. Передать курьеру Ozon (10:00 или 15:00)

# 7. Отгрузить (трек-номер Ozon даст курьер или получим из API)
api.ship_posting(posting_number, ozon_tracking_number)

Сценарий 2: realFBS Экспресс (30 минут)

# 1. Загрузить заказы realFBS Express
orders = api.fetch_orders(date_from, date_to)
express = [o for o in orders if o['fulfillment_scheme'] == 'realfbs'
           and o['realfbs_type'] == 'express']

# 2. Мониторинг SLA
for order in express:
    deadline = order['order_date'] + timedelta(minutes=30)
    time_left = (deadline - datetime.now()).total_seconds() / 60

    if time_left < 10:
        send_alert(f"🔴 КРИТИЧНО! Заказ {order['posting_number']} - {time_left} мин")

# 3. Товар УЖЕ упакован и готов

# 4. Передать курьеру немедленно

# 5. Загрузить свой трек-номер
api.ship_posting(order['posting_number'], own_tracking_from_courier)

# 6. Отслеживание доставки через GPS курьера

Дополнительные схемы (специальные)

Ozon Fresh (для скоропортящихся продуктов):
- Особый тип FBO с ускоренной обработкой
- Склады с холодильниками
- Доставка до 2 часов
- Высокие требования к упаковке

Crossdock (быстрая перегрузка):
- Товар не хранится на складе Ozon
- Передаётся через транзитный терминал
- Нужна запись на приёмку
- Минимум времени на обработку


Обновлено: 2025-11-08 (добавлена документация схем fulfillment)


🔄 ВИЗАРД ПОДКЛЮЧЕНИЯ КАНАЛА

Шаг 1: Подключение

Шаг 2: Импорт справочников

Шаг 3: Юр.лицо

Логика автоматического создания:

Ввод API ключей → Получение ИНН → Поиск юр.лица
                                        ↓
                                ┌───────┴───────┐
                                ↓               ↓
                              ЕСТЬ            НЕТ
                                ↓               ↓
                           Связать      ФНС API → Создать
                              канал         ↓
                                ↓       Создать канал
                                └───────┬───────┘
                                        ↓
                                   ✅ ГОТОВО

📚 БИБЛИОТЕКА DATETIME_HELPER

Модуль: modules/utils/datetime_helper.py

Основные классы:

WorkSchedule - работа с расписанием:

schedule = WorkSchedule.from_string("09:00-18:00 пн-пт")
schedule.is_working_now()  # True/False
schedule.next_working_datetime()  # Следующее рабочее время

MarketplaceSettings - настройки маркетплейсов:

MarketplaceSettings.OZON['max_prep_time_hours']  # 24
MarketplaceSettings.WILDBERRIES['max_prep_time_hours']  # 120
MarketplaceSettings.YANDEX['target_avg_hours']  # 36

Функции:

is_holiday(dt)                        # Праздник?
is_weekend(dt)                        # Выходной?
is_working_day(dt)                    # Рабочий день?
add_working_days(dt, days)            # +N рабочих дней
working_days_between(start, end)     # Количество рабочих дней
format_duration(hours)                # "2 д 4 ч"

Праздники РФ 2025:


🎯 API МЕТОДЫ

OzonAPI (modules/api/ozon.py):

api = OzonAPI(client_id, api_key)

# Основные
api.test_connection() -> bool
api.get_seller_info() -> Dict  # Включая ИНН!

# Заказы - Получение
api.fetch_orders(date_from, date_to) -> List[Dict]
api.get_order_details(posting_number) -> Dict

# Заказы - Обработка FBS
api.start_packing(posting_numbers: List[str]) -> Dict
api.ship_posting(posting_number: str, tracking: str) -> Dict
api.cancel_posting(posting_number: str, cancel_reason_id: int) -> Dict

# Заказы - Документы
api.get_posting_labels(posting_numbers: List[str]) -> bytes  # PDF этикеток
api.get_posting_act(date: str, delivery_service: str) -> bytes  # PDF акта
api.get_package_list(posting_numbers: List[str]) -> bytes  # PDF упаковочного листа

# Заказы - Трекинг (realFBS)
api.upload_tracking_numbers(data: List[Dict]) -> Dict

# Справочники
api.get_warehouses() -> List[Dict]
api.get_delivery_services() -> List[Dict]
api.get_posting_statuses() -> List[Dict]
api.get_categories(language="RU") -> List[Dict]

📦 ТОВАРЫ И ГРУППОВЫЕ КАРТОЧКИ

Типы товаров

Система поддерживает 4 типа товаров:

Тип Код Описание Использование
Простой simple Обычный товар Один SKU, одна цена, один остаток
Вариации variant_group Товар с вариантами Размеры/цвета через parent_id
Комплект kit Продаём → собираем Списываем компоненты при заказе
Набор bundle Собираем → продаём Собираем заранее, новый SKU

Групповые карточки (вариации)

Структура:

Родительский товар (variant_group)
├─ Футболка "Nike Air"
├─ parent_id = NULL
└─ Общее описание, фото
    
    ├─ Вариант 1: Размер S, Красный
       ├─ parent_id = ID родителя
       ├─ SKU: NIKE-AIR-S-RED
       └─ Свой остаток, своя цена
    
    ├─ Вариант 2: Размер M, Красный
       ├─ parent_id = ID родителя
       ├─ SKU: NIKE-AIR-M-RED
       └─ Свой остаток, своя цена
    
    └─ Вариант 3: Размер L, Синий
        ├─ parent_id = ID родителя
        ├─ SKU: NIKE-AIR-L-BLUE
        └─ Свой остаток, своя цена

Реализация через parent_id:
- Родительский товар имеет parent_id = NULL и product_type = 'variant_group'
- Дочерние товары имеют parent_id = <ID родителя> и product_type = 'simple'
- У каждого варианта свой SKU, остаток, цена

Комплекты и наборы

Комплект (продаём → собираем):

# Продаём "Набор инструментов" за 5000₽
# Состоит из: Молоток (1 шт) + Отвёртка (2 шт) + Гвозди (100 шт)

При заказе:
1. Проверяем наличие всех компонентов
2. Резервируем компоненты
3. При отгрузке списываем со склада

Набор (собираем → продаём):

# Собираем "Подарочный набор" заранее
# Создаём новый SKU с остатком

При сборке:
1. Списываем компоненты (Молоток -1, Отвёртка -2)
2. Создаём остаток набора +1
3. Продаём как обычный товар

Замены товаров

3 типа замен:

1. Автоматическая (AI)

Заказ: Товар A (нет в наличии)

AI анализирует:
- Та же категория
- Цена ±10%
- Похожие характеристики
- Есть в наличии
- Хорошие отзывы

Подбирает: Товар B (ai_confidence = 0.95)

Автоподстановка (если auto_apply = True)

2. Ручная замена менеджером

Заказ: Товар A (нет в наличии)

Создаётся задача менеджеру

Менеджер выбирает замену вручную

Клиент уведомляется

3. Предустановленные замены

# В системе заранее настроено:
Товар A  Товар B (priority = 1)
Товар A  Товар C (priority = 2)

При отсутствии A:
1. Проверяем наличие B
2. Если нет B  берём C

Ozon Product API методы

Импорт товаров (до 100 шт за раз)

POST /v3/product/import
{
    "items": [
        {
            "barcode": "1234567890123",
            "description_category_id": 17028922,
            "name": "Футболка мужская Nike",
            "offer_id": "SKU-12345",
            "price": "1299.00",
            "old_price": "1999.00",
            "vat": "0.2",
            "height": 10,
            "depth": 200,
            "width": 150,
            "dimension_unit": "mm",
            "weight": 200,
            "weight_unit": "g",
            "images": [
                "https://example.com/image1.jpg",
                "https://example.com/image2.jpg"
            ],
            "attributes": [
                {
                    "complex_id": 0,
                    "id": 8229,
                    "values": [{"value": "Nike"}]
                }
            ]
        }
    ]
}

 Возвращает task_id
 Проверка статуса: POST /v1/product/import/info

Получение товаров

POST /v2/product/list
{
    "filter": {
        "visibility": "ALL",  # ALL/VISIBLE/INVISIBLE
        "offer_id": ["SKU-001", "SKU-002"]
    },
    "limit": 100,
    "last_id": ""
}

Атрибуты категории

POST /v1/description-category/attribute
{
    "category_id": 17028922,
    "language": "RU"
}

 Возвращает список обязательных атрибутов

Значения справочников

POST /v1/description-category/attribute/values
{
    "category_id": 17028922,
    "attribute_id": 8229,
    "language": "RU",
    "limit": 1000
}

 Возвращает допустимые значения для атрибута

Обновление цен

POST /v1/product/import/prices
{
    "prices": [
        {
            "product_id": 123456,
            "price": "1299.00",
            "old_price": "1999.00"
        }
    ]
}

Обновление остатков

POST /v1/product/import/stocks
{
    "stocks": [
        {
            "offer_id": "SKU-12345",
            "product_id": 123456,
            "stock": 10,
            "warehouse_id": 789
        }
    ]
}

Сложные атрибуты (complex_id)

Пример: товар с несколькими видео

"attributes": [
    {
        "complex_id": 1,
        "id": 21841,  # Название видео
        "values": [{"value": "Обзор товара"}]
    },
    {
        "complex_id": 1,
        "id": 21837,  # URL видео
        "values": [{"value": "https://youtube.com/watch?v=xxx"}]
    },
    {
        "complex_id": 2,
        "id": 21841,  # Название видео
        "values": [{"value": "Инструкция"}]
    },
    {
        "complex_id": 2,
        "id": 21837,  # URL видео
        "values": [{"value": "https://youtube.com/watch?v=yyy"}]
    }
]

complex_id группирует связанные атрибуты:
- complex_id = 1: Обзор товара + его URL
- complex_id = 2: Инструкция + её URL

Массовые операции

Импорт из CSV:

SKU,Name,Category,Brand,Price,OldPrice,Stock,Weight,ImageURL
SKU-001,Футболка,Одежда,Nike,1299,1999,10,200,https://...
SKU-002,Джинсы,Одежда,Levis,2999,3999,5,400,https://...

Лимиты:
- Ozon API: 100 товаров за один запрос
- CSV импорт: рекомендуется до 1000 товаров
- Батчинг: разбиваем большие файлы на части по 100

Асинхронная обработка:
1. Отправка запроса → получаем task_id
2. Проверка статуса каждые 5 секунд
3. Получение результата с ошибками по каждому товару


💾 МОДЕЛИ БД

User

id, email, password_hash, full_name, role, active

LegalEntity

id, user_id, name_full, name_short, inn, ogrn, entity_type
address, director, is_default, active

Channel

id, entity_id, channel_name, channel_type, platform_type
client_id, api_key_encrypted, seller_id, status, active

Warehouse

id, channel_id, external_id, name
warehouse_type, fulfillment_type, work_mode, work_schedule
is_active, can_ship_anytime, requires_appointment
min_prep_time_hours, filter_rules
address, contact_person, phone

DeliveryService

id, channel_id, external_id, name, is_available
delivery_time_from, delivery_time_to

ChannelStatusMapping

id, channel_id, external_status, status_name, internal_status_id

Order

id, channel_id, entity_id, external_order_id, order_date
status_external, status_internal

# Fulfillment схема
fulfillment_scheme  # fbo/fbs/realfbs
realfbs_type        # standard/comfort/express (для realfbs)

# Доставка
delivery_type       # kts/pvz/courier/post
delivery_service    # pochta/yandex/kts/cdek/boxberry

# Трекинг
tracking_number         # Ozon трек (для FBO/FBS)
own_tracking_number     # Свой трек (для realFBS)
track_uploaded, shipped_at

# Клиент
customer_name, customer_phone, customer_email
address_json, items_json, total_amount

Product (Расширенная модель)

# Основные поля
id, user_id, sku, barcode, article, name, description

# Тип товара
product_type  # simple/variant_group/kit/bundle
parent_id     # Для вариаций: ссылка на родительский товар

# Категория и бренд
category, brand, ozon_category_id

# Цены
price, old_price, cost_price, min_price

# Габариты и вес
weight      # граммы
width       # мм
height      # мм
depth       # мм

# Остатки
stock_quantity, reserved_quantity, available_quantity

# Статус
is_active, is_visible

# Ozon
ozon_product_id, vat

# Метаданные
created_at, updated_at

ProductImage (Изображения товаров)

id, product_id, image_url, local_path
position, is_primary
image_type  # product/360/marketing/size_chart
width, height, file_size
created_at

ProductAttribute (Атрибуты для Ozon)

id, product_id
attribute_id, attribute_name  # ID и название атрибута Ozon
value
complex_id                    # Группировка сложных атрибутов
is_required, is_collection, dictionary_id
created_at

ProductComposition (Состав комплектов/наборов)

id, kit_id, component_id
quantity                      # Количество компонента в комплекте
position                      # Порядок
created_at

Substitution (Замены товаров)

id, product_id, substitute_product_id
substitution_type             # auto/manual/ai_suggested/approved
priority                      # Приоритет замены
max_price_diff_percent        # Макс. разница цены
active, auto_apply
times_used, last_used_at
ai_confidence, ai_reason      # AI оценка замены
created_by, created_at

ProductChannelMapping (Связь с каналами)

id, product_id, channel_id
external_product_id, external_sku
is_published, moderation_status
channel_price, channel_old_price
channel_stock
last_sync_at, sync_errors
created_at, updated_at

🚀 ТЕХНОЛОГИИ


📁 СТРУКТУРА ПРОЕКТА

marketplace-mvp/
├── app.py                      # Главная страница
├── PROJECT-MASTER.md           # Этот файл (вся документация)
├── requirements.txt
├── core/
│   ├── config.py               # Настройки
│   ├── database.py             # Подключение к БД
│   └── auth.py                 # Авторизация
├── database/
│   ├── models.py               # Все модели
│   └── init_db.py              # Инициализация БД
├── modules/
│   ├── api/
│   │   └── ozon.py             # Ozon API
│   ├── legal_entities/
│   │   ├── crud.py             # CRUD юр.лиц
│   │   └── inn_api.py          # Получение данных по ИНН
│   └── utils/
│       └── datetime_helper.py  # Работа с датами/временем
└── pages/
    ├── 01_🏢_Компании.py        # Управление юр.лицами
    ├── 02_📡_Каналы.py          # Управление каналами (визард)
    ├── 04_📋_Заказы.py          # Обработка заказов (3 схемы)
    └── 05_🏷️_Товары.py         # Управление товарами

🎨 БИБЛИОТЕКА СКРИПТОВ

Расположение: /opt/claude-workspace/scripts/

Цель: Экономия 90% токенов - не генерировать код заново!

Шаблоны:

Workflow:

# 1. Копировать шаблон
cp /opt/claude-workspace/scripts/python/streamlit/wizard_3_step.py pages/

# 2. Попросить Claude внести правки (не генерировать!)
"Замени поля на: name, inn, address"

✅ РЕАЛИЗОВАНО


🔜 ПЛАНЫ


📞 КОНТАКТЫ

Email: admin@example.com
Пароль: admin1234

Приложение: http://91.218.142.168:8502


Последнее обновление: 2025-11-07
Версия документации: 2.0


❌ НЕ РЕАЛИЗОВАНО (TODO)

📊 Складские остатки (Stock)

Модель: StockMovement

id, warehouse_id, product_id, variant_id
quantity_before, quantity_after, quantity_delta
movement_type  # in/out/reserve/unreserve/correction
order_id, user_id, reason, created_at

Функции:
- Учёт остатков по складам
- Резервирование при заказе
- Синхронизация с маркетплейсами
- История движения товаров
- Оповещения о низких остатках


💰 Финансы и транзакции

Модель: Transaction

id, channel_id, order_id
transaction_type  # sale/commission/refund/payout
amount, currency, marketplace_fee
status, transaction_date, payout_date

Модель: PriceHistory

id, product_id, channel_id
price, old_price, discount_percent
valid_from, valid_to, reason

Функции:
- Учёт продаж и комиссий
- История изменения цен
- Расчёт прибыли/убытков
- Акты сверки с маркетплейсами
- Выплаты (payout)


📦 Упаковка и отгрузка

Модель: Shipment

id, warehouse_id, shipment_date
shipment_number, carrier, tracking_number
status, boxes_count, total_weight

Модель: ShipmentBox

id, shipment_id, box_number
barcode, weight, dimensions
items_json  # [{order_id, product_id, quantity}]

Функции:
- Группировка заказов в отгрузки
- Печать этикеток и накладных
- Упаковочные листы
- Трекинг отгрузок


🔄 Возвраты

Модель: Return

id, order_id, channel_id
return_reason, return_type  # customer/defect/damage
status, return_date, refund_amount
warehouse_id, restocked, notes

Функции:
- Обработка возвратов
- Возврат товара на склад
- Возврат денег покупателю
- Статистика по причинам возвратов


📊 Аналитика и KPI

Показатели:
- GMV (Gross Merchandise Value)
- Конверсия по воронке
- Средний чек
- Процент возвратов
- Рейтинг продавца
- Скорость обработки заказов

Отчёты:
- Продажи по дням/неделям/месяцам
- ABC-анализ товаров
- Эффективность каналов
- Прибыльность по категориям


🔔 Уведомления

Модель: Notification

id, user_id, notification_type, priority
title, message, link, is_read
created_at

Типы уведомлений:
- Новый заказ
- Проблема с заказом
- Низкие остатки
- Изменение цен конкурентов
- Истечение API ключей
- Необходимость отгрузки

Каналы:
- Telegram бот
- Email
- Push-уведомления в браузере
- SMS (критические)


👥 Права доступа (RBAC)

Роли:
- owner - Владелец (полный доступ)
- admin - Администратор (управление без удаления)
- manager - Менеджер (заказы, товары, не видит финансы)
- warehouse - Кладовщик (только отгрузки)
- viewer - Наблюдатель (только просмотр)

Модель: UserPermission

id, user_id, entity_id, channel_id
role, can_view, can_edit, can_delete
granted_by, granted_at

🔐 Безопасность

Нужно добавить:
- Шифрование API ключей (AES-256)
- Двухфакторная аутентификация (2FA)
- Аудит действий пользователей
- Rate limiting для API
- Резервное копирование БД


🌐 Интеграции

Маркетплейсы:
- ✅ Ozon
- ⏳ Wildberries
- ⏳ Яндекс.Маркет
- ⏳ AliExpress
- ⏳ Lamoda

Сервисы:
- ⏳ СДЭК (доставка)
- ⏳ Почта России
- ⏳ Boxberry
- ⏳ 1С:Бухгалтерия
- ⏳ МойСклад
- ⏳ Telegram Bot API
- ⏳ Bitrix24 (CRM)


📱 Мобильное приложение

Планы:
- PWA (Progressive Web App)
- Быстрое создание заказа
- Сканер штрих-кодов
- Push-уведомления
- Offline режим


🎯 ПРИОРИТЕТЫ РАЗРАБОТКИ

📍 ТЕКУЩИЙ СТАТУС

Каналы: 3 активных Ozon канала
Заказы: 0 (страница готова, функционал загрузки реализован)
Товары: 0 (страница готова, интерфейс реализован)
Склады: Подключены через визард


Фаза 1: MVP Core (✅ ЗАВЕРШЕНА)


Фаза 2: Операции (🔴 В РАБОТЕ)

2.1 Товары

2.2 Заказы

2.3 Остатки


Фаза 3: Автоматизация (⏳ ПЛАНИРУЕТСЯ)

3.1 Автоправила

3.2 Уведомления

3.3 Аналитика


Фаза 4: Расширение (📋 БЭКЛОГ)

4.1 Маркетплейсы

4.2 Финансы

4.3 Возвраты

4.4 Отгрузки

4.5 Команда

4.6 Интеграции


🎯 ПРИОРИТЕТЫ ПРОЕКТА

Бизнес-модель

Основная схема работы: realFBS (своя доставка)

Проект создаётся для всех случаев (FBO/FBS/realFBS поддерживаются), но приоритет на realFBS с дропшиппингом и работой с поставщиками.

⭐ ВЫСОКИЙ ПРИОРИТЕТ (Must Have)

Эти функции критичны для ежедневной работы и должны быть реализованы в первую очередь:

1. 📦 Обработка заказов realFBS (КРИТИЧНО)

Что нужно:
- ✅ Загрузка заказов с Ozon (реализовано)
- ✅ Разделение по схемам FBS/realFBS/FBO (реализовано)
- ✅ UI с 3 разделами (реализовано)
- 🔴 Автоматическое создание заказов в СДЭК/Почте (приоритет #1)
- 🔴 Получение этикеток от СДЭК/Почты (приоритет #1)
- 🔴 Загрузка трек-номеров на Ozon (приоритет #1)
- 🔴 Мониторинг статусов доставки (приоритет #2)
- [ ] История изменений статусов заказов

Workflow realFBS:

Заказ Ozon → Автосоздание в СДЭК → Этикетка СДЭК → Трек на Ozon → Отслеживание

2. 🔄 Управление подменами (товаров)

Что нужно:
- [ ] Модель Substitution - связь товаров-подмен
- [ ] Правила подмены - автоматические/ручные
- [ ] UI управления подменами - страница настройки
- [ ] Применение при заказе - если товара нет, подменить автоматически
- [ ] Уведомления покупателю - согласование подмены
- [ ] История подмен - какой товар чем заменили

Сценарий:

Заказ: Товар A (остаток: 0)  Система: Подмена на Товар B  Уведомление покупателю

Модель Substitution:

id, product_id, substitute_product_id
substitution_type  # auto/manual/approved
priority           # порядок подмены (если несколько вариантов)
price_diff_percent # макс. разница цены
active, created_by, created_at

3. 🔙 Работа с возвратами

Что нужно:
- [ ] Загрузка возвратов с Ozon API
- [ ] UI списка возвратов - таблица с фильтрами
- [ ] Обработка возврата - причина, решение
- [ ] Возврат на склад - увеличение остатков (для realFBS)
- [ ] Возврат денег - статус refund
- [ ] Статистика - причины возвратов, проблемные товары
- [ ] Повторная отправка - если товар можно продать снова

Модель Return:

id, order_id, channel_id, external_return_id
return_reason       # customer_request/defect/damage/wrong_item
return_type         # full/partial
status              # new/approved/refunded/restocked
return_date, refund_amount, refund_date
warehouse_id        # куда вернули (для realFBS)
restocked           # вернули на склад?
condition           # new/damaged/defect
notes, created_at

4. 📊 Учёт остатков (Stock Management)

Что нужно:
- [ ] Синхронизация остатков с Ozon
- [ ] Резервирование при заказе - уменьшение available
- [ ] Списание при отгрузке - уменьшение quantity
- [ ] Возврат при отмене - увеличение available
- [ ] История движений - кто/когда/сколько изменил
- [ ] Оповещения о низких остатках
- [ ] Связь с дропшипперами - остатки с их складов

Модель StockMovement:

id, warehouse_id, product_id, variant_id
quantity_before, quantity_after, quantity_delta
movement_type  # in/out/reserve/unreserve/correction/return
order_id, user_id, reason
created_at

Логика резервирования:

Товар: quantity=100, reserved=0, available=100
Заказ  reserved=10, available=90
Отгрузка  quantity=90, reserved=0, available=90
Отмена  reserved=0, available=100

5. 🏢 Дропшиппинг и поставщики

Что нужно:
- [ ] Модель Supplier - поставщики
- [ ] Связь Product ↔ Supplier - кто поставляет товар
- [ ] Склады дропшипперов - warehouse_type='dropshipper'
- [ ] Остатки у дропшиппера - отдельный учёт
- [ ] Автозаказ у дропшиппера - при заказе на Ozon
- [ ] Отслеживание поставок - от поставщика
- [ ] Маржа и расчёты - price vs cost_price

Модель Supplier:

id, user_id, name, supplier_type  # dropshipper/wholesale/manufacturer
contact_person, phone, email, address
inn, contract_number, payment_terms  # 7/14/30 дней
is_dropshipper      # True если отправляет сам
margin_percent      # Наша маржа
rating, active, notes, created_at

Модель SupplierProduct:

id, supplier_id, product_id
supplier_sku        # Артикул у поставщика
cost_price          # Закупочная цена
stock_quantity      # Остаток у поставщика
lead_time_days      # Срок поставки
min_order_qty       # Минимальный заказ
active, updated_at

Workflow дропшиппинга:

Заказ Ozon (realFBS) → Проверка остатков → Нет на складе → Заказ у дропшиппера
→ Дропшиппер отправляет → Получение трека → Трек на Ozon → Доставка покупателю

🟡 СРЕДНИЙ ПРИОРИТЕТ (Should Have)

Функции для повышения эффективности работы:

6. 📈 Аналитика и отчёты

7. 🔔 Уведомления

8. 🚚 Интеграции доставки

9. 💰 Финансы


🟢 НИЗКИЙ ПРИОРИТЕТ (Nice to Have)

Функции для масштабирования:

10. Другие маркетплейсы

11. Команда и права доступа

12. Автоматизация


🔥 ROADMAP (ПЕРВЫЕ 3 МЕСЯЦА)

Месяц 1: Обработка заказов realFBS

Цель: Полный цикл realFBS с СДЭК

Неделя 1-2:
- [x] UI страницы заказов (3 раздела) - ГОТОВО
- [x] Модели БД для схем - ГОТОВО
- [ ] Интеграция СДЭК API (создание заказов, этикетки)
- [ ] Интеграция Почта России API

Неделя 3-4:
- [ ] Автоматическое создание заказов в СДЭК при новом заказе Ozon
- [ ] Загрузка трек-номеров на Ozon
- [ ] Отслеживание статусов доставки
- [ ] Тестирование полного цикла

Результат: Заказ Ozon → СДЭК → Доставка (полностью автоматически)


Месяц 2: Остатки и дропшиппинг

Цель: Учёт остатков с резервированием + работа с поставщиками

Неделя 1-2:
- [ ] Модель StockMovement + логика резервирования
- [ ] Синхронизация остатков с Ozon
- [ ] История движений товаров
- [ ] Оповещения о низких остатках

Неделя 3-4:
- [ ] Модели Supplier + SupplierProduct
- [ ] UI управления поставщиками
- [ ] Связь товаров с поставщиками
- [ ] Остатки на складах дропшипперов
- [ ] Автозаказ у дропшиппера

Результат: Заказ без остатков → Автозаказ у дропшиппера → Трек → Ozon


Месяц 3: Подмены и возвраты

Цель: Гибкая работа с ассортиментом + обработка возвратов

Неделя 1-2:
- [ ] Модель Substitution
- [ ] UI управления подменами
- [ ] Автоматическая подмена при отсутствии товара
- [ ] Согласование с покупателем

Неделя 3-4:
- [ ] Модель Return
- [ ] Загрузка возвратов с Ozon
- [ ] Обработка возвратов (возврат денег, на склад)
- [ ] Статистика по возвратам

Результат: Полная обработка исключительных ситуаций


📋 TODO ПЕРВООЧЕРЕДНЫЕ (следующие 2 недели)

  1. 🔴 СДЭК API интеграция (приоритет #1)
    - [ ] Модуль modules/delivery/cdek.py
    - [ ] Методы: создание заказа, получение этикетки, трекинг
    - [ ] Тестирование на sandbox СДЭК

  2. 🔴 Почта России API интеграция (приоритет #1)
    - [ ] Модуль modules/delivery/pochta.py
    - [ ] Методы: создание заказа, получение этикетки, трекинг
    - [ ] Тестирование на sandbox Почты

  3. 🔴 Автоматизация realFBS workflow (приоритет #2)
    - [ ] При загрузке заказа realFBS → автосоздание в СДЭК/Почте
    - [ ] Получение этикетки → сохранение в БД
    - [ ] Загрузка трек-номера на Ozon
    - [ ] Обновление статусов из СДЭК/Почты

  4. 🟡 Учёт остатков - базовая версия (приоритет #3)
    - [ ] Модель StockMovement
    - [ ] Резервирование при заказе
    - [ ] Списание при отгрузке
    - [ ] История движений


🎯 СЛЕДУЮЩИЕ ШАГИ (по порядку)

Ближайшие действия (неделя 1-2):

  1. 🔴 Интеграция СДЭК API - создание модуля с методами работы с СДЭК
  2. 🔴 Интеграция Почта России API - создание модуля с методами работы с Почтой
  3. 🔴 Автоматизация realFBS - автосоздание заказов в доставке при заказе Ozon
  4. 🟡 Базовый учёт остатков - резервирование/списание

Далее (неделя 3-4):

  1. Полный цикл realFBS - тестирование от заказа до доставки
  2. Модели дропшиппинга - Supplier, SupplierProduct
  3. UI поставщиков - страница управления поставщиками
  4. Модель Substitution - подмены товаров

Обновлено: 2025-11-08 02:00
Версия документации: 2.4

Последние изменения:
- ✅ Добавлена полная документация схем fulfillment (FBO/FBS/realFBS)
- ✅ Описаны workflow для каждой схемы
- ✅ Добавлены примеры кода
- ✅ Обновлён раздел API методов
- ✅ Обновлена модель Order с новыми полями
- ✨ Определены приоритеты проекта (realFBS + дропшиппинг)
- ✨ Добавлен roadmap на 3 месяца
- ✨ Определены первоочередные задачи (СДЭК/Почта API)
- ✨ Описаны модели: Substitution, Return, Supplier, StockMovement