Skip to content

Раздел 1: Архитектура

Проект: Интеллектуальная система управления логистикой маркетплейсов
Модуль: Logistic / Architecture
Версия: 2.1
Дата: Февраль 2026
Заменяет: Раздел 1 v2.0


1.1 Обзор архитектуры

Принципы проектирования

ПринципОписание
МодульностьНезависимые компоненты с чёткими интерфейсами
ОтказоустойчивостьGraceful degradation при недоступности Ozon API или файла 1С
КэшированиеМинимизация запросов к API через Redis
АсинхронностьФоновая синхронизация через Celery
Dual-sourceДва независимых источника данных: Ozon API + PostgreSQL 1C_* таблицы (из 1С)
РасширяемостьПодготовка к Wildberries / Yandex.Market в v2.0

Архитектурная диаграмма


1.2 Компоненты системы

Слой адаптеров

КомпонентНазначениеТехнология
OzonLogisticAdapterЕдиная точка интеграции с Ozon Seller APIaiohttp
OneCDataReaderЧтение данных из 1C_* таблиц PostgreSQLSQL
RateLimiterКонтроль частоты запросов к Ozon APIRedis + asyncio
RetryHandlerПовторные попытки при ошибкахtenacity

Слой сервисов

СервисНазначениеВходные данныеВыходные данные
StockServiceПолучение и кэширование остатков FBO по кластерамOzon APIClusterStock[]
AnalyticsServiceПолучение аналитики продаж и оборачиваемостиOzon APISalesData[], Turnover[]
WarehouseServiceУправление списком кластеров/складовOzon APIWarehouse[]
SupplyTaskServiceCRUD наряд-заданий, workflow статусовDomain modelsSupplyTask[]
AlertServiceГенерация и отправка алертовDomain eventsAlert[]
HistoryServiceСинхронизация и история остатков из 1C_*OneCDataReaderWarehouseStock[]

Доменный слой

КомпонентНазначениеЛогика
StockMonitorОтслеживание уровня остатков по кластерамСравнение с порогами, расчёт дней до обнуления
DemandForecasterПрогноз спроса по кластерамWeighted moving average, тренды, сезонность
SupplyCalculatorРасчёт оптимального распределенияДефицит = Прогноз − Остаток FBO − В пути
TaskGeneratorФормирование наряд-заданийПриоритизация, проверка наличия на складе 1С

1.3 Потоки данных

Поток 1: Синхронизация остатков Ozon

Поток 2: Синхронизация остатков из 1C_*

Поток 3: Формирование наряд-заданий

Поток 4: Workflow наряд-задания


1.4 Интеграция с ADOLF Core

Используемые компоненты Core

Middleware интеграция

MiddlewareИспользование
AuthMiddlewareВалидация JWT/API Key
RoleMiddlewareПроверка прав доступа
BrandFilterMiddlewareФильтрация данных по brand_id
PromptInjectionMiddlewareДобавление контекста для AI

Shared PostgreSQL схема

Модуль Logistic использует:

  • Собственные таблицы с префиксом logistic_*
  • Общие таблицы Core: users, brands, notifications
  • FK связи с другими модулями минимизированы

1.5 Структура кодовой базы

adolf/
├── modules/
│   └── logistic/
│       ├── __init__.py
│       ├── config.py                 # Конфигурация модуля
│       │
│       ├── adapters/                 # Слой адаптеров
│       │   ├── __init__.py
│       │   ├── ozon_adapter.py       # OzonLogisticAdapter
│       │   ├── 1c_data_reader.py    # OneCDataReader (1C_* таблицы)
│       │   ├── rate_limiter.py       # RateLimiter
│       │   └── retry_handler.py      # RetryHandler
│       │
│       ├── services/                 # Слой сервисов
│       │   ├── __init__.py
│       │   ├── stock_service.py      # StockService
│       │   ├── analytics_service.py  # AnalyticsService
│       │   ├── warehouse_service.py  # WarehouseService
│       │   ├── supply_task_service.py # SupplyTaskService
│       │   ├── alert_service.py      # AlertService
│       │   └── import_service.py     # ImportService (1С)
│       │
│       ├── domain/                   # Доменный слой
│       │   ├── __init__.py
│       │   ├── models.py             # Pydantic models
│       │   ├── stock_monitor.py      # StockMonitor
│       │   ├── demand_forecaster.py  # DemandForecaster
│       │   ├── supply_calculator.py  # SupplyCalculator
│       │   └── task_generator.py     # TaskGenerator
│       │
│       ├── api/                      # FastAPI endpoints
│       │   ├── __init__.py
│       │   ├── router.py             # Main router
│       │   ├── stocks.py             # /stocks endpoints
│       │   ├── supply_tasks.py       # /supply-tasks endpoints
│       │   ├── analytics.py          # /analytics endpoints
│       │   ├── imports.py            # /imports endpoints
│       │   ├── alerts.py             # /alerts endpoints
│       │   └── schemas.py            # Request/Response schemas
│       │
│       ├── tasks/                    # Celery tasks
│       │   ├── __init__.py
│       │   ├── sync_ozon_stocks.py   # Синхронизация остатков Ozon
│       │   ├── sync_ozon_analytics.py # Синхронизация аналитики
│       │   ├── sync_1c_stocks.py    # Синхронизация 1C_*
│       │   ├── generate_supply_tasks.py # Генерация наряд-заданий
│       │   └── generate_alerts.py    # Генерация алертов
│       │
│       ├── db/                       # Database
│       │   ├── __init__.py
│       │   ├── models.py             # SQLAlchemy models
│       │   └── repositories.py       # Data access
│       │
│       └── owui/                     # Open WebUI integration
│           ├── __init__.py
│           ├── pipeline.py           # Pipeline handler
│           └── tools.py              # Function tools

1.6 Конфигурация

Переменные окружения

python
# config.py
from pydantic_settings import BaseSettings
from pathlib import Path

class LogisticSettings(BaseSettings):
    """Настройки модуля Logistic."""
    
    # Ozon API
    ozon_client_id: str
    ozon_api_key: str
    ozon_api_url: str = "https://api-seller.ozon.ru"
    
    # 1C_* синхронизация
    1c_freshness_threshold_hours: int = 26
    1c_sync_schedule_cron: str = "30 6 * * *"  # 06:30
    
    # Rate limits (requests per second)
    ozon_rps: int = 5  # Ozon default
    
    # Sync intervals (minutes)
    sync_stocks_interval: int = 30
    sync_analytics_interval: int = 1440  # daily
    sync_warehouses_interval: int = 10080  # weekly
    
    # Alert thresholds
    critical_days_threshold: int = 3      # дней до обнуления
    warning_days_threshold: int = 7
    min_stock_threshold: int = 5          # минимальный остаток шт
    
    # Forecast settings
    forecast_window_days: int = 28        # окно анализа
    forecast_horizon_days: int = 14       # горизонт прогноза
    forecast_safety_factor: float = 1.2   # коэффициент запаса
    
    # Supply task settings
    task_generation_cron: str = "0 7 * * *"  # ежедневно в 07:00
    task_auto_cancel_hours: int = 48      # автоотмена неподтверждённых
    
    # Cache TTL (seconds)
    cache_stocks_ttl: int = 1500      # 25 min
    cache_analytics_ttl: int = 3600   # 1 hour
    cache_warehouses_ttl: int = 604800  # 7 days
    
    class Config:
        env_prefix = "LOGISTIC_"

Пример .env

bash
# Ozon API
LOGISTIC_OZON_CLIENT_ID=your_client_id
LOGISTIC_OZON_API_KEY=your_api_key

# 1С Import
LOGISTIC_IMPORT_1C_PATH=/data/imports/1c
LOGISTIC_IMPORT_1C_SCHEDULE_CRON=0 8,14 * * *

# Thresholds
LOGISTIC_CRITICAL_DAYS_THRESHOLD=3
LOGISTIC_WARNING_DAYS_THRESHOLD=7
LOGISTIC_MIN_STOCK_THRESHOLD=5

# Forecast
LOGISTIC_FORECAST_WINDOW_DAYS=28
LOGISTIC_FORECAST_SAFETY_FACTOR=1.2

1.7 Кэширование

Стратегия кэширования

ДанныеХранилищеTTLКлюч Redis
Остатки FBO по кластерамRedis25 минlogistic:ozon:stocks:{date}
Аналитика продажRedis1 часlogistic:ozon:analytics:{date}
ОборачиваемостьRedis1 часlogistic:ozon:turnover:{date}
Список кластеровRedis7 днейlogistic:ozon:warehouses
Остатки 1СRedisдо след. synclogistic:brain:stocks:latest

Структура кэша остатков по кластерам

python
# Redis key: logistic:ozon:stocks:2026-02-06
{
    "updated_at": "2026-02-06T10:30:00Z",
    "source": "ozon_api",
    "clusters": [
        {
            "cluster_name": "Москва, МО и Дальние регионы",
            "items": [
                {
                    "sku": 924771727,
                    "article": "51005/54",
                    "product_name": "Шорты Ohana market Стильно и модно",
                    "fbo_stock": 12,
                    "fbs_stock": 0,
                    "in_transit": 0,
                    "avg_daily_sales": 5.2,
                    "days_to_zero": 2
                }
            ]
        }
    ]
}

Структура кэша остатков 1С

python
# Redis key: logistic:1c:stocks:imp_20260206_0800
{
    "import_id": "imp_20260206_0800",
    "imported_at": "2026-02-06T08:00:00Z",
    "source": "1C_stock_balance",
    "items": [
        {
            "article": "51005/54",
            "product_name": "Шорты Стильно и модно",
            "warehouse_stock": 340,
            "unit": "шт"
        }
    ]
}

Cache-aside pattern


1.8 Обработка ошибок

Типы ошибок

ОшибкаИсточникКодОбработка
OzonAPIErrorOzon API500Retry с exponential backoff
OzonRateLimitErrorOzon API429Ожидание, затем retry
OzonAuthErrorOzon API401/403Алерт администратору
OneCDataStaleError1C_* таблицыАлерт, повтор через 1 час
OneCDataEmptyError1C_* таблицыАлерт администратору
SKUMappingErrorМаппингЛогирование, пропуск записи
DataValidationErrorЛюбой422Логирование, пропуск записи
CacheErrorRedisFallback на прямой запрос

Retry стратегия

python
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=4, max=60),
    retry=retry_if_exception_type(OzonAPIError)
)
async def fetch_stocks(self) -> list[ClusterStock]:
    """Получение остатков с retry."""
    ...

Circuit Breaker

Обработка ошибок синхронизации 1C_*


1.9 Мониторинг и логирование

Метрики (Prometheus)

МетрикаТипОписание
logistic_ozon_api_requests_totalCounterОбщее число запросов к Ozon API
logistic_ozon_api_errors_totalCounterОшибки Ozon API
logistic_ozon_api_latency_secondsHistogramЛатентность запросов
logistic_stocks_sync_duration_secondsHistogramВремя синхронизации остатков
logistic_1c_sync_totalCounterКоличество синхронизаций 1C_*
logistic_1c_stale_totalCounterУстаревшие данные 1C_*
logistic_supply_tasks_generated_totalCounterСгенерированные наряд-задания
logistic_supply_tasks_completed_totalCounterВыполненные наряд-задания
logistic_alerts_generated_totalCounterСгенерированные алерты
logistic_cluster_deficit_totalGaugeТекущий дефицит по кластерам

Структурированное логирование

python
import structlog

logger = structlog.get_logger("logistic")

# Пример: синхронизация остатков
logger.info(
    "ozon_stocks_synced",
    sku_count=2400,
    cluster_count=31,
    duration_ms=4200,
    cache_updated=True
)

# Пример: синхронизация 1C_*
logger.info(
    "1c_sync_completed",
    source="1C_stock_balance",
    records_validated=2380,
    records_unmapped=20,
    anomalies=3,
    duration_ms=800
)

# Пример: наряд-задание
logger.info(
    "supply_tasks_generated",
    date="2026-02-06",
    tasks_total=20,
    priority_urgent=3,
    priority_planned=5,
    priority_recommended=12,
    total_quantity=847
)

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

API ключи Ozon

АспектРеализация
ХранениеПеременные окружения / Vault
ФорматClient-Id + Api-Key (два параметра)
ПередачаHTTP заголовки Client-Id, Api-Key
РотацияПоддержка hot-reload конфигурации
АудитЛогирование всех API-вызовов

Безопасность синхронизации 1C_*

АспектРеализация
Директория импортаОграниченные права доступа (0750)
Валидация данныхПроверка свежести loaded_at, маппинг артикулов
Максимальный размер50 МБ
КарантинНекорректные файлы перемещаются в /quarantine
АрхивированиеОбработанные файлы → /archive с timestamp

Доступ к данным


1.11 Масштабирование

Горизонтальное масштабирование

КомпонентСтратегия
APIStateless, несколько инстансов за LB
Celery WorkersУвеличение числа воркеров
RedisCluster mode (при необходимости)
PostgreSQLRead replicas (v2.0)
1C_* синхронизацияОдин обработчик, последовательное чтение

Ограничения Ozon API

АспектЗначениеСтратегия
Rate limit~5 RPS (базовый)Регулируемый RateLimiter
Premium rate limitРасширенныйНастройка при наличии Premium
Пагинацияoffset/limit, cursorАвтоматическая обработка
Размер ответаДо 1000 записейПагинация с аккумуляцией

1.12 Диаграмма развёртывания


1.13 Зависимости

Python пакеты

txt
# requirements-logistic.txt
aiohttp>=3.9.0
tenacity>=8.2.0
redis>=5.0.0
celery>=5.3.0
structlog>=24.1.0
pydantic>=2.5.0
sqlalchemy>=2.0.0
# openpyxl, lxml — больше не требуются (файловый импорт удалён)
numpy>=1.26.0         # Demand forecasting

Внутренние зависимости

МодульЗависимостьТип
CoreMiddleware, PostgreSQL, Redis, Celery, NotificationsHard
CFOОтправка данных о логистических издержкахSoft (v2.0)
ScoutПолучение прогнозов продажSoft (v2.0)

1.14 Структура файлов модуля

/app/modules/logistic/
├── __init__.py
├── config.py
├── adapters/
│   ├── __init__.py
│   ├── ozon_adapter.py
│   ├── 1c_data_reader.py
│   ├── rate_limiter.py
│   └── retry_handler.py
├── services/
│   ├── __init__.py
│   ├── stock_service.py
│   ├── analytics_service.py
│   ├── warehouse_service.py
│   ├── supply_task_service.py
│   ├── alert_service.py
│   └── import_service.py
├── domain/
│   ├── __init__.py
│   ├── models.py
│   ├── stock_monitor.py
│   ├── demand_forecaster.py
│   ├── supply_calculator.py
│   └── task_generator.py
├── api/
│   ├── __init__.py
│   ├── router.py
│   ├── stocks.py
│   ├── supply_tasks.py
│   ├── analytics.py
│   ├── imports.py
│   ├── alerts.py
│   └── schemas.py
├── tasks/
│   ├── __init__.py
│   ├── sync_ozon_stocks.py
│   ├── sync_ozon_analytics.py
│   ├── import_1c_stocks.py
│   ├── generate_supply_tasks.py
│   └── generate_alerts.py
├── db/
│   ├── __init__.py
│   ├── models.py
│   └── repositories.py
└── owui/
    ├── __init__.py
    ├── pipeline.py
    └── tools.py

Документ подготовлен: Февраль 2026
Версия: 2.0
Статус: Черновик
Заменяет: adolf_logistic_1_architecture_v1_0.md

Документация ADOLF Platform