Skip to content

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

Проект: Автоматическое управление рекламными кампаниями
Модуль: Marketing / Architecture
Версия: 1.0
Дата: Январь 2026


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

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

ПринципОписание
Periodic ExecutionЦикл обработки каждые 15 минут
Strategy PatternПодключаемые стратегии биддинга
Hybrid DataДанные Watcher + real-time API
Safety FirstАвтоматические ограничители расходов
Graceful DegradationСбой одного МП не влияет на другие
Audit TrailЛогирование всех изменений ставок

Общая схема


1.2 Компоненты модуля

1.2.1 REST API

Назначение: Точка входа для запросов из Open WebUI и внешних систем.

Базовый путь: /api/v1/marketing

Группы endpoints:

ГруппаПутьОписание
Campaigns/campaignsCRUD рекламных кампаний
Keywords/keywordsУправление ключевыми словами
Bids/bidsУправление ставками
Stats/statsСтатистика и метрики
Reports/reportsОтчёты
Settings/settingsНастройки модуля

1.2.2 Campaign Manager

Назначение: Управление жизненным циклом рекламных кампаний.

Функции:

ФункцияОписание
CreateСоздание кампании через API маркетплейса
UpdateИзменение параметров кампании
PauseПриостановка кампании
ResumeВозобновление кампании
ArchiveАрхивирование кампании
SyncСинхронизация состояния с маркетплейсом

Workflow создания кампании:

1.2.3 Bid Engine

Назначение: Расчёт и применение ставок согласно выбранной стратегии.

Компоненты:

Стратегии биддинга:

СтратегияАлгоритмПараметры
Position Holdnew_bid = competitor_bid[target_pos] + bid_steptarget_position, bid_step
Min Pricenew_bid = min_bid_for_placement
Aggressivenew_bid = max(budget_allows, competitor_top + bid_step)daily_limit, bid_step
ROI Optimizenew_bid = (avg_order_value × target_margin) / conversion_ratetarget_drr

1.2.4 Safety Logic

Назначение: Защита от неэффективных расходов.

Правила:

Параметры Safety Logic:

ПараметрЗначение по умолчаниюНастраиваемый
Target CTR3%✅ (Admin)
Min Views1000✅ (Admin)
Max ДРР15%✅ (Admin)
Budget Alert Threshold80%✅ (Admin)

1.2.5 Stats Collector

Назначение: Сбор статистики рекламных кампаний с маркетплейсов.

Собираемые метрики:

МетрикаОписаниеИсточник
ViewsКоличество показовAPI МП
ClicksКоличество кликовAPI МП
CTRClick-Through RateРасчёт
SpentРасходAPI МП
CPCCost Per ClickРасчёт
OrdersКоличество заказовAPI МП
CPOCost Per OrderРасчёт
RevenueВыручка с рекламыAPI МП
ДРРДоля рекламных расходовРасчёт

Периодичность сбора:

Тип данныхПериодичность
Текущая статистикаКаждые 15 минут
Детальная статистика по ключамКаждый час
Исторические данныеЕжедневно (ночью)

1.2.6 Analytics Engine

Назначение: Анализ эффективности и генерация рекомендаций.

Функции:

ФункцияAI-модельОписание
Trend AnalysisGPT-5 miniВыявление трендов в статистике
Anomaly DetectionGPT-5 miniОбнаружение аномалий расходов
RecommendationsClaude Opus 4.5Рекомендации по оптимизации
ForecastingClaude Opus 4.5Прогноз расходов и эффективности

1.2.7 Report Builder

Назначение: Формирование отчётов по рекламным кампаниям.

Типы отчётов:

ОтчётПериодичностьФормат
Daily PerformanceЕжедневноJSON / Markdown
Weekly SummaryЕженедельноJSON / Markdown / Excel
Top KeywordsЕженедельноJSON / Markdown
ДРР DynamicsЕженедельноJSON / Chart
AI InsightsПо запросуMarkdown

1.2.8 Alert Engine

Назначение: Генерация и отправка уведомлений о событиях.

Интеграция с Notifications:


1.3 Зависимости от ADOLF Core

1.3.1 Middleware

Расширение Middleware:

middleware/
├── routes/
│   └── marketing.py           # API endpoints
├── models/
│   └── marketing.py           # SQLAlchemy models
└── services/
    └── marketing/            
        ├── __init__.py
        ├── campaign_service.py
        ├── bid_service.py
        ├── stats_service.py
        └── analytics_service.py

Функции Middleware для Marketing:

ФункцияОписание
АвторизацияПроверка роли (Manager+)
Фильтрация по брендуbrand_id injection
ПроксированиеМаршрутизация /api/v1/marketing/*
АудитЛогирование всех действий
Rate LimitingЗащита от превышения лимитов API МП

1.3.2 Celery Workers

Задачи Marketing:

ЗадачаОчередьПериодичностьОписание
marketing.collect_statsdefault*/15 минутСбор статистики РК
marketing.run_bid_cycledefault*/15 минут :07Цикл корректировки ставок
marketing.check_budgetscritical*/15 минут :03Проверка бюджетов
marketing.sync_campaignsdefault*/30 минутСинхронизация состояния РК
marketing.generate_daily_reportdefault08:00 ежедневноЕжедневный отчёт
marketing.generate_weekly_reportdefaultПн 09:00Еженедельный отчёт
marketing.cleanup_old_statsheavy03:00 ежедневноАгрегация старой статистики
marketing.ai_analysisheavy07:00 ежедневноAI-анализ и рекомендации

Смещение задач (offset):

Для равномерной нагрузки задачи запускаются со смещением:

  • :00 — collect_stats (WB)
  • :03 — check_budgets
  • :05 — collect_stats (Ozon)
  • :07 — run_bid_cycle
  • :10 — collect_stats (YM)

1.3.3 PostgreSQL

Новые таблицы:

ТаблицаНазначение
marketing_campaignsРекламные кампании
marketing_keywordsКлючевые слова
marketing_bidsТекущие ставки
marketing_bid_historyИстория изменений ставок
marketing_statsСтатистика (детальная)
marketing_stats_dailyАгрегированная дневная статистика
marketing_stats_monthlyАгрегированная месячная статистика
marketing_alertsИстория алертов
marketing_settingsНастройки модуля
marketing_strategiesКонфигурации стратегий

Используемые таблицы Core:

ТаблицаИспользование
usersРоль, brand_id для фильтрации
audit_logЗапись действий пользователей
notificationsСоздание уведомлений
settingsГлобальные настройки

1.3.4 Redis

Использование:

ПрименениеКлючTTLОписание
Celery BrokerОчередь задач
Rate Limitingmarketing:rate:{mp}:{endpoint}60sКонтроль частоты запросов к API МП
Cache Statsmarketing:stats:{campaign_id}15mКэш текущей статистики
Lockmarketing:lock:bid_cycle5mПредотвращение параллельных циклов
Competitor Bidsmarketing:bids:{sku}:{mp}1hКэш ставок конкурентов

1.3.5 Notifications

События Marketing:

Событиеevent_typeУровеньПолучатели
Кампания приостановлена (бюджет)marketing.campaign_paused_budgetwarningManager, Senior
Ключ приостановлен (CTR)marketing.keyword_paused_ctrinfoManager
Ключ приостановлен (ДРР)marketing.keyword_paused_drrwarningManager, Senior
Ставка ограничена Max Bidmarketing.bid_cappedwarningManager, Senior
Ошибка API МПmarketing.api_errorcriticalAdministrator
Бюджет 80%marketing.budget_warninginfoManager
Аномальный рост расходовmarketing.spending_anomalywarningSenior, Director
Дневной отчёт готовmarketing.daily_report_readyinfoManager, Senior
Еженедельный отчёт готовmarketing.weekly_report_readyinfoSenior, Director

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

1.4.1 Получение данных о конкурентах

1.4.2 API Watcher для Marketing

EndpointМетодОписание
/api/v1/watcher/prices/competitorsGETЦены и ставки конкурентов
/api/v1/watcher/positions/{sku}GETПозиции SKU в выдаче

Параметры запроса:

ПараметрТипОписание
skustringАртикул товара
marketplacestringwb / ozon / ym
include_bidsboolВключить данные о ставках

Пример ответа:

json
{
  "sku": "OM-12345",
  "marketplace": "wildberries",
  "competitors": [
    {
      "seller": "Fashion Store",
      "position": 1,
      "price": 2599,
      "estimated_bid": 150
    },
    {
      "seller": "Style Shop", 
      "position": 2,
      "price": 2499,
      "estimated_bid": 120
    }
  ],
  "our_position": 5,
  "our_price": 2450,
  "data_freshness": "2026-01-15T03:00:00Z"
}

1.5 Интеграция с маркетплейсами

1.5.1 Общая схема адаптеров

1.5.2 Унифицированный интерфейс адаптера

python
from abc import ABC, abstractmethod
from typing import List, Optional
from dataclasses import dataclass

@dataclass
class Campaign:
    id: str
    external_id: str
    marketplace: str
    name: str
    status: str  # active, paused, archived
    campaign_type: str
    daily_budget: float
    total_budget: Optional[float]
    start_date: datetime
    end_date: Optional[datetime]
    brand_id: str

@dataclass
class Keyword:
    id: str
    campaign_id: str
    keyword: str
    match_type: str  # exact, phrase, broad
    status: str
    current_bid: float
    
@dataclass
class CampaignStats:
    campaign_id: str
    date: date
    views: int
    clicks: int
    ctr: float
    spent: float
    cpc: float
    orders: int
    revenue: float
    drr: float

class MarketplaceAdapter(ABC):
    """Базовый класс адаптера маркетплейса."""
    
    @abstractmethod
    async def get_campaigns(self, brand_id: str) -> List[Campaign]:
        """Получить список кампаний."""
        pass
    
    @abstractmethod
    async def create_campaign(self, campaign: Campaign) -> str:
        """Создать кампанию, вернуть external_id."""
        pass
    
    @abstractmethod
    async def update_campaign(self, campaign: Campaign) -> bool:
        """Обновить кампанию."""
        pass
    
    @abstractmethod
    async def pause_campaign(self, external_id: str) -> bool:
        """Приостановить кампанию."""
        pass
    
    @abstractmethod
    async def resume_campaign(self, external_id: str) -> bool:
        """Возобновить кампанию."""
        pass
    
    @abstractmethod
    async def get_keywords(self, campaign_id: str) -> List[Keyword]:
        """Получить ключевые слова кампании."""
        pass
    
    @abstractmethod
    async def add_keywords(self, campaign_id: str, keywords: List[Keyword]) -> bool:
        """Добавить ключевые слова."""
        pass
    
    @abstractmethod
    async def update_bid(self, keyword_id: str, new_bid: float) -> bool:
        """Обновить ставку."""
        pass
    
    @abstractmethod
    async def pause_keyword(self, keyword_id: str) -> bool:
        """Приостановить ключевое слово."""
        pass
    
    @abstractmethod
    async def get_stats(
        self, 
        campaign_id: str, 
        date_from: date, 
        date_to: date
    ) -> List[CampaignStats]:
        """Получить статистику кампании."""
        pass
    
    @abstractmethod
    async def get_realtime_position(self, sku: str, keyword: str) -> Optional[int]:
        """Получить текущую позицию (real-time)."""
        pass

1.5.3 Rate Limiting

Конфигурация лимитов:

МаркетплейсRequests/minStrategy
Wildberries100Token Bucket
Ozon60Token Bucket
Яндекс.Маркет30Token Bucket

Примечание: Указаны ориентировочные значения. Требуется уточнение по актуальной документации API.

Реализация:

python
import asyncio
from datetime import datetime, timedelta

class RateLimiter:
    """Token Bucket Rate Limiter."""
    
    def __init__(self, rate: int, per: int = 60):
        self.rate = rate  # tokens per period
        self.per = per    # period in seconds
        self.tokens = rate
        self.last_update = datetime.now()
        self._lock = asyncio.Lock()
    
    async def acquire(self):
        """Acquire a token, wait if necessary."""
        async with self._lock:
            now = datetime.now()
            elapsed = (now - self.last_update).total_seconds()
            
            # Replenish tokens
            self.tokens = min(
                self.rate,
                self.tokens + elapsed * (self.rate / self.per)
            )
            self.last_update = now
            
            if self.tokens < 1:
                wait_time = (1 - self.tokens) * (self.per / self.rate)
                await asyncio.sleep(wait_time)
                self.tokens = 0
            else:
                self.tokens -= 1

1.5.4 Retry Logic

Стратегия повторных попыток:

Код ошибкиДействиеMax RetriesBackoff
429 (Rate Limit)Exponential backoff52^n × 10s
500-503 (Server)Retry330s fixed
400 (Bad Request)Log, skip0
401/403 (Auth)Alert, stop0
TimeoutRetry315s fixed
python
import asyncio
from functools import wraps

def with_retry(max_retries: int = 3, backoff_base: float = 2.0):
    """Декоратор для retry с exponential backoff."""
    
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            last_exception = None
            
            for attempt in range(max_retries + 1):
                try:
                    return await func(*args, **kwargs)
                except RateLimitError:
                    wait = (backoff_base ** attempt) * 10
                    await asyncio.sleep(wait)
                    last_exception = e
                except ServerError:
                    await asyncio.sleep(30)
                    last_exception = e
                except (AuthError, BadRequestError):
                    raise  # Don't retry
                    
            raise last_exception
        return wrapper
    return decorator

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

middleware/
├── routes/
│   └── marketing.py               # FastAPI routes
├── models/
│   └── marketing.py               # SQLAlchemy models
├── schemas/
│   └── marketing.py               # Pydantic schemas
└── services/
    └── marketing/
        ├── __init__.py
        ├── campaign_service.py    # Campaign CRUD
        ├── bid_service.py         # Bid Engine
        ├── stats_service.py       # Stats Collector
        ├── analytics_service.py   # Analytics Engine
        ├── safety_service.py      # Safety Logic
        ├── report_service.py      # Report Builder
        └── adapters/
            ├── __init__.py
            ├── base.py            # Abstract adapter
            ├── wildberries.py     # WB adapter
            ├── ozon.py            # Ozon adapter
            └── yandex_market.py   # YM adapter

tasks/
└── marketing_tasks.py             # Celery tasks

pipelines/
└── marketing_pipeline.py          # Open WebUI Pipeline

tools/
├── marketing_campaigns.py         # Campaign management tool
├── marketing_stats.py             # Stats tool
├── marketing_bids.py              # Bid management tool
└── marketing_reports.py           # Reports tool

1.7 Конфигурация модуля

1.7.1 Environment Variables

ПеременнаяОписаниеПример
WB_PROMO_API_KEYAPI-ключ WB Promotionxxx...
OZON_PERF_CLIENT_IDClient ID Ozon Performance123456
OZON_PERF_API_KEYAPI-ключ Ozon Performancexxx...
YM_OAUTH_TOKENOAuth-токен Яндекс.Маркетxxx...
YM_CAMPAIGN_IDID кампании Яндекс.Маркет789012
MARKETING_BID_CYCLE_INTERVALИнтервал цикла (минуты)15
MARKETING_DEFAULT_MAX_BIDMax Bid по умолчанию500
MARKETING_DEFAULT_TARGET_CTRTarget CTR по умолчанию3.0
MARKETING_DEFAULT_MAX_DRRMax ДРР по умолчанию15.0

1.7.2 Настройки в БД (marketing_settings)

КлючТипОписание
default_strategystringСтратегия по умолчанию
target_ctrfloatЦелевой CTR
min_views_thresholdintМинимум показов
max_drrfloatМаксимальный ДРР
budget_alert_thresholdfloatПорог алерта бюджета (%)
rate_limitsjsonЛимиты API по маркетплейсам

1.8 Мониторинг и метрики

1.8.1 Health Checks

ПроверкаИнтервалКритичность
WB API доступность5 минHigh
Ozon API доступность5 минHigh
YM API доступность5 минHigh
Watcher API доступность5 минMedium
Celery workers1 минHigh
Redis1 минHigh

1.8.2 Prometheus Metrics

МетрикаТипОписание
marketing_bid_changes_totalCounterКоличество изменений ставок
marketing_api_requests_totalCounterЗапросы к API МП
marketing_api_errors_totalCounterОшибки API МП
marketing_bid_cycle_duration_secondsHistogramДлительность цикла
marketing_active_campaignsGaugeАктивные кампании
marketing_daily_spendGaugeДневной расход

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

1.9.1 Хранение credentials

СекретХранениеДоступ
API-ключи МПEnvironment variablesТолько Celery workers
OAuth токеныEnvironment variablesТолько Celery workers
Session tokensRedis (encrypted)TTL 1 час

1.9.2 Аудит действий

Все действия логируются в audit_log:

ДействиеДанные
Создание кампанииcampaign_id, user_id, params
Изменение ставкиkeyword_id, old_bid, new_bid, reason
Пауза кампанииcampaign_id, reason (manual/auto)
Изменение настроекsetting_key, old_value, new_value

Документ подготовлен: Январь 2026
Версия: 1.0
Статус: Черновик

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