Перейти до вмісту

Інтеграція з Prom, Rozetka, Hotline

Матеріал з K2 ERP Wiki Ukraine — База знань з автоматизації та санкцій в Україні


SEO title: Технічне завдання: Інтеграція з Prom, Rozetka, Hotline для Python SEO description: Технічне завдання на реалізацію Python-сервісу для інтеграції K2 ERP, CRM або інтернет-магазину з Prom.ua, Rozetka Marketplace та Hotline: товари, ціни, залишки, замовлення, статуси, фіди, XML/YML, ставки, помилки, dashboard та журналювання. SEO keywords: Python, Prom.ua API, Rozetka API, Hotline XML, маркетплейси, інтеграція, товари, замовлення, ціни, залишки, K2 ERP, FastAPI, XML feed, YML, seller API Alternative to:



Головна ідея: розробити Python-сервіс, який інтегрує K2 ERP / CRM / інтернет-магазин із маркетплейсами та прайс-агрегаторами Prom.ua, Rozetka Marketplace і Hotline для синхронізації товарів, цін, залишків, замовлень, статусів, фідів, ставок, помилок і аналітики.

Критично важливо: інтеграція не повинна створювати дублікати товарів, замовлень або фідів. Кожен товар, замовлення, зміна ціни, залишку, статусу, фід, XML-файл, API-запит і помилка повинні мати внутрішній ID, external_id, журнал подій і захист від повторної обробки.

Важливо: Prom, Rozetka і Hotline мають різну логіку інтеграції. Prom та Rozetka мають API для продавців, а Hotline у базовому сценарії працює через товарні фіди, вимоги до прайсів і окремий API керування ставками.

Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker, XML/YML generator.

Управлінський результат: менеджер і керівник повинні бачити, які товари синхронізовані, які мають помилки, які замовлення отримані, які ціни та залишки передані, які товари не пройшли модерацію, які фіди сформовані, які ставки Hotline активні та які канали продажів дають результат.

1. Мета

Метою задачі є створення Python-сервісу для інтеграції з трьома зовнішніми каналами продажів і просування:

  • Prom.ua;
  • Rozetka Marketplace;
  • Hotline.

Сервіс повинен забезпечити:

  • централізовану картку інтеграції по кожному каналу;
  • синхронізацію товарів;
  • синхронізацію цін;
  • синхронізацію залишків;
  • отримання замовлень;
  • оновлення статусів замовлень;
  • передачу номерів ТТН / ЕН;
  • генерацію товарних фідів;
  • валідацію товарів перед передачею;
  • контроль помилок API;
  • контроль помилок фідів;
  • журнал усіх запитів і відповідей;
  • dashboard по маркетплейсах;
  • захист від дублювання товарів і замовлень.

2. Область застосування

Інтеграція призначена для:

  • інтернет-магазинів;
  • ERP;
  • CRM;
  • WMS;
  • торгових компаній;
  • дистриб'юторів;
  • компаній, які продають одночасно на декількох маркетплейсах;
  • компаній, які ведуть товари, ціни, залишки і замовлення в K2 ERP.

3. Канали інтеграції

Канал Основний тип інтеграції Основні сценарії Коментар
Prom.ua Public API Товари, замовлення, статуси, ціни, залишки. API-токени керуються в кабінеті компанії.
Rozetka Seller API + товарний фід Замовлення через API, товари/ціни/залишки через API або XML-фід залежно від сценарію. Потрібно звірити актуальний API продавця.
Hotline XML/YML/CSV/XLS/TXT фіди + API ставок Передача товарів через фід, контроль акцій, керування ставками. Це більше price-comparison / рекламний канал, ніж класичний marketplace.

Prom.ua офіційно має публічне API для віддаленого керування даними в кабінеті компанії, а API-токени можна керувати в кабінеті компанії у розділі налаштувань. :contentReference[oaicite:1]{index=1}

Rozetka Marketplace має API для інтеграції продавців: офіційна довідка описує API як набір інструментів для інтеграції системи продавця з ROZETKA Маркетплейс, а API-документація вказує можливість роботи із замовленнями, товарами, листуванням і контролем процесів. :contentReference[oaicite:2]{index=2}

Hotline офіційно описує вимоги до товарних фідів, зокрема Hotline XML і YML, а також має API для керування ставками по пропозиціях магазину. :contentReference[oaicite:3]{index=3}

4. Передумови

Для реалізації задачі необхідно отримати:

  • доступ до кабінету продавця Prom.ua;
  • API token Prom.ua;
  • доступ до кабінету продавця Rozetka;
  • API credentials Rozetka;
  • актуальну API-документацію Rozetka Seller API;
  • вимоги Rozetka до товарного фіду, якщо використовується фід;
  • доступ до кабінету Hotline;
  • вимоги Hotline до XML/YML/CSV-фідів;
  • auth token Hotline для API ставок, якщо використовується;
  • список категорій товарів;
  • правила мапінгу категорій K2 ERP → Prom / Rozetka / Hotline;
  • правила мапінгу характеристик;
  • правила округлення цін;
  • правила синхронізації залишків;
  • правила резервування товару після отримання замовлення;
  • правила оновлення статусів замовлень;
  • правила передачі ТТН.

Критично важливо: доступи до Prom, Rozetka і Hotline потрібно зберігати тільки в secret storage або в зашифрованому вигляді. Заборонено зберігати API token, логіни, паролі або auth token у коді, Git, frontend-змінних або відкритих логах.

5. Основні бізнес-сценарії

5.1. Передача товарів

K2 ERP є головним джерелом товарів.

Python-сервіс повинен:

  • отримувати товари з K2 ERP;
  • перевіряти обов'язкові поля;
  • мапити категорії;
  • мапити характеристики;
  • формувати опис;
  • перевіряти фото;
  • формувати ціну;
  • формувати залишок;
  • передавати товар у Prom / Rozetka через API або фід;
  • включати товар у фід Hotline;
  • зберігати зовнішні ID товарів.

5.2. Синхронізація цін

K2 ERP передає нові ціни.

Python-сервіс повинен:

  • визначити активні канали для товару;
  • застосувати правила націнки;
  • застосувати промо-ціну, якщо є;
  • застосувати мінімальну ціну;
  • сформувати зміну ціни;
  • передати зміну в Prom;
  • передати зміну в Rozetka;
  • оновити XML/YML-фід Hotline;
  • зберегти історію зміни ціни.

5.3. Синхронізація залишків

K2 ERP передає залишки по складах.

Python-сервіс повинен:

  • отримати актуальний залишок;
  • врахувати резерви;
  • врахувати мінімальний страховий залишок;
  • визначити доступну кількість для продажу;
  • передати залишок у канали;
  • приховати товар, якщо залишок 0;
  • відновити товар, якщо залишок з'явився.

5.4. Отримання замовлень

Prom і Rozetka можуть бути джерелами замовлень.

Python-сервіс повинен:

  • регулярно отримувати нові замовлення;
  • перевіряти, чи замовлення вже імпортовано;
  • створювати замовлення в K2 ERP;
  • створювати покупця або прив'язувати до існуючого;
  • створювати резерв товарів;
  • зберігати джерело замовлення;
  • зберігати external_order_id;
  • передавати статус обробки назад у маркетплейс.

5.5. Оновлення статусів замовлень

K2 ERP є джерелом операційних статусів.

Python-сервіс повинен:

  • отримувати статус із K2 ERP;
  • мапити статус у статус маркетплейса;
  • передавати статус у Prom / Rozetka;
  • передавати номер ТТН / ЕН;
  • зберігати історію статусів;
  • логувати помилки оновлення.

5.6. Hotline як фід і канал просування

Hotline у MVP розглядається як канал передачі товарних пропозицій через фід.

Python-сервіс повинен:

  • формувати XML/YML-фід;
  • включати тільки активні товари;
  • передавати актуальні ціни;
  • передавати актуальні залишки;
  • передавати URL товару;
  • передавати фото;
  • передавати характеристики;
  • формувати фід акцій, якщо потрібно;
  • керувати ставками через API ставок, якщо підключено.

6. Основні сутності

Сутність Опис
Marketplace Integration Налаштування інтеграції з Prom, Rozetka або Hotline.
Product Товар у K2 ERP.
Marketplace Product Товар у конкретному каналі.
Category Mapping Мапінг категорій K2 ERP до категорій каналу.
Attribute Mapping Мапінг характеристик.
Price Rule Правило формування ціни.
Stock Rule Правило формування доступного залишку.
Order Замовлення з маркетплейса.
Order Status Статус замовлення.
Feed XML/YML/CSV-фід для Hotline або Rozetka.
Bid Ставка Hotline по товарній пропозиції.
API Event Подія інтеграції.

7. User Story

7.1. Товари

Як менеджер товарного каталогу, я хочу один раз вести товар у K2 ERP, щоб він автоматично передавався в Prom, Rozetka і Hotline.

7.2. Ціни

Як комерційний менеджер, я хочу змінити ціну в K2 ERP, щоб вона автоматично оновилась у всіх підключених каналах.

7.3. Залишки

Як склад, я хочу, щоб залишки з K2 ERP автоматично оновлювались на маркетплейсах, щоб не продавати товар, якого немає.

7.4. Замовлення

Як менеджер продажів, я хочу отримувати замовлення з Prom і Rozetka в K2 ERP, щоб обробляти їх в єдиній системі.

7.5. Hotline

Як маркетолог, я хочу автоматично формувати фід для Hotline, щоб товари були актуальні за ціною, наявністю і характеристиками.

7.6. Dashboard керівника

Як керівник, я хочу бачити продажі, помилки, статуси товарів і ефективність каналів, щоб контролювати якість інтеграції.

8. Функціональні вимоги

8.1. Налаштування інтеграції

Поле Тип Обов'язковість Опис
integration_name string Так Назва інтеграції.
marketplace enum Так PROM, ROZETKA, HOTLINE.
base_url string Так URL API або endpoint фіду.
api_token secret Ні Token для API.
login secret Ні Логін, якщо потрібен.
password secret Ні Пароль, якщо потрібен.
feed_public_url string Ні URL фіду для Hotline/Rozetka.
sync_products_enabled boolean Так Чи синхронізувати товари.
sync_prices_enabled boolean Так Чи синхронізувати ціни.
sync_stocks_enabled boolean Так Чи синхронізувати залишки.
sync_orders_enabled boolean Так Чи імпортувати замовлення.
is_active boolean Так Ознака активності.

8.2. Товар для синхронізації

Поле Тип Опис
sku string Артикул товару.
external_product_id string ID товару в маркетплейсі.
name string Назва.
description text Опис.
category_id string Категорія K2 ERP.
marketplace_category_id string Категорія маркетплейса.
price numeric Базова ціна.
old_price numeric Стара ціна, якщо є.
stock_quantity numeric Залишок.
brand string Бренд.
images array Фото.
attributes object Характеристики.
barcode string Штрихкод.
warranty string Гарантія.
is_active boolean Активність.

8.3. Замовлення з маркетплейса

Поле Тип Опис
marketplace enum PROM або ROZETKA.
external_order_id string ID замовлення в маркетплейсі.
order_number string Номер замовлення.
order_date datetime Дата замовлення.
customer_name string ПІБ покупця.
customer_phone string Телефон покупця.
customer_email string Email.
delivery_service string Нова пошта, Укрпошта тощо.
delivery_address text Адреса або відділення.
payment_type string Оплата.
total_amount numeric Сума замовлення.
status string Статус.
items array Товари замовлення.

9. Статуси товарів

Статус Код Опис Колір
Чернетка DRAFT Товар створений у K2 ERP, але ще не готовий до передачі. Сірий
Очікує валідації PENDING_VALIDATION Товар очікує перевірки. Жовтий
Потребує виправлення NEEDS_CORRECTION Не вистачає фото, категорії, характеристик або опису. Помаранчевий
Готовий до синхронізації READY_TO_SYNC Товар готовий до передачі. Блакитний
Синхронізується SYNCING Виконується API-запит або генерація фіду. Блакитний
Передано SYNCED Товар передано в канал. Зелений
На модерації MODERATION Товар очікує перевірки маркетплейса. Жовтий
Опубліковано PUBLISHED Товар доступний покупцям. Зелений
Відхилено REJECTED Товар відхилено каналом. Червоний
Помилка синхронізації SYNC_ERROR API або фід повернув помилку. Червоний
Приховано HIDDEN Товар приховано через залишок, правило або вручну. Сірий

10. Статуси замовлень

Статус K2 ERP Код Опис Колір
Нове NEW Замовлення отримано з маркетплейса. Жовтий
Імпортується IMPORTING Створюється в K2 ERP. Блакитний
Імпортовано IMPORTED Замовлення створено в K2 ERP. Зелений
Потребує перевірки NEEDS_REVIEW Не знайдено товар, клієнта або адресу. Помаранчевий
Підтверджено CONFIRMED Замовлення прийнято в роботу. Зелений
Комплектується PROCESSING Замовлення збирається. Блакитний
Відправлено SHIPPED Передано ТТН / ЕН. Блакитний
Виконано COMPLETED Замовлення завершено. Зелений
Скасовано CANCELLED Замовлення скасовано. Сірий
Помилка ERROR Помилка імпорту або оновлення. Червоний

11. Єдина логіка кольорів

Колір HTML Значення Де використовується
Зелений #c8e6c9 Успішно: синхронізовано, опубліковано, імпортовано, виконано. Dashboard, список товарів, список замовлень.
Блакитний #bbdefb Операція виконується або дані в процесі передачі. Черги, API-запити, статуси обробки.
Жовтий #fff9c4 Очікування дії або модерації. Модерація, нові замовлення, очікування.
Помаранчевий #ffcc80 Потрібна дія менеджера. Помилки валідації, невідомі товари, retry.
Червоний #ef9a9a Критична помилка або відхилення. API error, rejected, sync error.
Фіолетовий #f3e5f5 Спеціальний або ручний сценарій. Ручна перевірка, нестандартний фід.
Сірий #eeeeee Чернетка, приховано, скасовано або архів. Архів, hidden, cancelled.

12. Архітектура рішення

12.1. Загальна схема

K2 ERP / CRM / WMS
        |
        | 1. Товари, ціни, залишки, статуси
        v
Python Marketplace Integration Service
        |
        | 2. Валідація, мапінг, черги, дедублікація
        v
Marketplace Adapters
        |
        | 3. Prom API / Rozetka API / Hotline Feed + Bids API
        v
Prom.ua / Rozetka / Hotline
        |
        | 4. Замовлення, статуси, модерація, фіди
        v
Python Sync Workers
        |
        | 5. Оновлення K2 ERP
        v
K2 ERP / Dashboard / Менеджери

12.2. Основні компоненти Python-сервісу

Компонент Опис
API Layer REST API для команд із K2 ERP.
Product Validator Перевіряє товари перед передачею.
Category Mapper Мапить категорії K2 ERP до категорій каналів.
Attribute Mapper Мапить характеристики.
Price Engine Формує ціну по правилах.
Stock Engine Формує доступний залишок.
Prom Adapter Робота з API Prom.ua.
Rozetka Adapter Робота з API Rozetka.
Hotline Feed Generator Генерація XML/YML/CSV-фідів Hotline.
Hotline Bid Client API керування ставками Hotline.
Order Import Worker Імпорт замовлень.
Status Export Worker Передача статусів і ТТН.
Feed Publisher Публікація фідів за публічним URL.
Audit Logger Запити, відповіді, помилки, статуси.
Dashboard API Статистика по товарах, замовленнях, помилках і каналах.

13. Marketplace Client Interface

13.1. Загальний інтерфейс

from abc import ABC, abstractmethod


class MarketplaceClient(ABC):
    @abstractmethod
    async def check_connection(self) -> dict:
        pass

    @abstractmethod
    async def sync_product(self, product: dict) -> dict:
        pass

    @abstractmethod
    async def update_price(self, external_product_id: str, price: dict) -> dict:
        pass

    @abstractmethod
    async def update_stock(self, external_product_id: str, stock: dict) -> dict:
        pass

    @abstractmethod
    async def import_orders(self, filters: dict) -> list[dict]:
        pass

    @abstractmethod
    async def update_order_status(self, external_order_id: str, status: dict) -> dict:
        pass

13.2. Prom Client

class PromClient(MarketplaceClient):
    def __init__(self, base_url: str, api_token: str):
        self.base_url = base_url
        self.api_token = api_token

    async def check_connection(self) -> dict:
        pass

    async def sync_product(self, product: dict) -> dict:
        pass

    async def update_price(self, external_product_id: str, price: dict) -> dict:
        pass

    async def update_stock(self, external_product_id: str, stock: dict) -> dict:
        pass

    async def import_orders(self, filters: dict) -> list[dict]:
        pass

    async def update_order_status(self, external_order_id: str, status: dict) -> dict:
        pass

13.3. Rozetka Client

class RozetkaClient(MarketplaceClient):
    def __init__(self, base_url: str, username: str | None = None, password: str | None = None, token: str | None = None):
        self.base_url = base_url
        self.username = username
        self.password = password
        self.token = token

    async def authenticate(self) -> dict:
        pass

    async def check_connection(self) -> dict:
        pass

    async def sync_product(self, product: dict) -> dict:
        pass

    async def update_price(self, external_product_id: str, price: dict) -> dict:
        pass

    async def update_stock(self, external_product_id: str, stock: dict) -> dict:
        pass

    async def import_orders(self, filters: dict) -> list[dict]:
        pass

    async def update_order_status(self, external_order_id: str, status: dict) -> dict:
        pass

13.4. Hotline Client

class HotlineClient:
    def __init__(self, feed_storage_url: str, bid_api_token: str | None = None):
        self.feed_storage_url = feed_storage_url
        self.bid_api_token = bid_api_token

    async def generate_product_feed(self, products: list[dict], format: str = "xml") -> bytes:
        pass

    async def publish_feed(self, feed: bytes, filename: str) -> str:
        pass

    async def generate_action_feed(self, actions: list[dict]) -> bytes:
        pass

    async def get_bids(self) -> list[dict]:
        pass

    async def update_bid(self, offer_id: str, bid_value: int) -> dict:
        pass

14. API Python-сервісу

14.1. Створення інтеграції

POST /api/v1/marketplaces/integrations

14.2. Перевірка підключення

POST /api/v1/marketplaces/integrations/{integration_id}/check-connection

14.3. Синхронізація товару

POST /api/v1/marketplaces/products/{product_id}/sync

14.4. Масова синхронізація товарів

POST /api/v1/marketplaces/products/sync-batch

14.5. Оновлення цін

POST /api/v1/marketplaces/prices/sync

14.6. Оновлення залишків

POST /api/v1/marketplaces/stocks/sync

14.7. Імпорт замовлень

POST /api/v1/marketplaces/orders/import

14.8. Оновлення статусу замовлення

POST /api/v1/marketplaces/orders/{order_id}/update-status

14.9. Генерація фіду Hotline

POST /api/v1/marketplaces/hotline/feed/generate

14.10. Публікація фіду Hotline

POST /api/v1/marketplaces/hotline/feed/publish

14.11. Оновлення ставок Hotline

POST /api/v1/marketplaces/hotline/bids/update

14.12. Dashboard

GET /api/v1/marketplaces/dashboard?date_from=2026-05-01&date_to=2026-05-31

15. Приклад запиту на синхронізацію товару

{
  "product_id": "K2-PRODUCT-000123",
  "sku": "SKU-001",
  "name": "Смартфон Example X 128GB",
  "description": "Опис товару без HTML-помилок та заборонених символів.",
  "brand": "Example",
  "category_id": "phones",
  "marketplace_categories": {
    "prom": "prom-category-ref",
    "rozetka": "rozetka-category-id",
    "hotline": "hotline-category-code"
  },
  "price": 12999.00,
  "old_price": 13999.00,
  "stock_quantity": 12,
  "barcode": "4820000000000",
  "images": [
    "https://example.com/images/sku-001-1.jpg",
    "https://example.com/images/sku-001-2.jpg"
  ],
  "attributes": {
    "memory": "128GB",
    "color": "Black",
    "warranty": "12 місяців"
  },
  "channels": ["PROM", "ROZETKA", "HOTLINE"]
}

16. Приклад XML-фіду Hotline

<price>
  <date>2026-05-07 12:00</date>
  <firmName>Example Store</firmName>
  <firmId>12345</firmId>
  <categories>
    <category>
      <id>phones</id>
      <name>Смартфони</name>
    </category>
  </categories>
  <items>
    <item>
      <id>K2-PRODUCT-000123</id>
      <code>SKU-001</code>
      <categoryId>phones</categoryId>
      <vendor>Example</vendor>
      <name>Смартфон Example X 128GB</name>
      <description>Опис товару</description>
      <url>https://example.com/product/sku-001</url>
      <image>https://example.com/images/sku-001-1.jpg</image>
      <priceRUAH>12999</priceRUAH>
      <stock>В наявності</stock>
      <guarantee>12 місяців</guarantee>
    </item>
  </items>
</price>

Важливо: структура XML вище є прикладом. Production-фід потрібно формувати за актуальною специфікацією Hotline XML або YML.

17. Валідація товарів

Перед передачею товару система повинна перевірити:

  • SKU заповнений;
  • назва заповнена;
  • опис заповнений;
  • категорія K2 ERP визначена;
  • категорія каналу замаплена;
  • бренд заповнений, якщо обов'язковий;
  • ціна більша за 0;
  • залишок не від'ємний;
  • фото доступні за URL;
  • характеристики заповнені;
  • штрихкод валідний, якщо потрібен;
  • гарантія заповнена, якщо потрібна;
  • товар не заборонений правилами каналу;
  • назва не містить HTML або службового сміття;
  • опис не містить заборонених тегів;
  • для Hotline є URL товару на сайті магазину;
  • для Rozetka є категорія й характеристики згідно з вимогами категорії;
  • для Prom є коректний статус публікації.

Критично важливо: товар без категорії, фото, ціни або обов'язкових характеристик не повинен автоматично передаватись у канали. Він повинен потрапляти в статус NEEDS_CORRECTION.

18. Дедублікація

Система повинна не допускати дублювання товарів і замовлень.

18.1. Дедублікація товарів

Ключ Призначення
sku Основний артикул.
product_id ID товару K2 ERP.
marketplace_product_id ID товару в каналі.
barcode Штрихкод.
product_hash Hash назви, ціни, залишку, характеристик.

18.2. Дедублікація замовлень

Ключ Призначення
marketplace Джерело замовлення.
external_order_id ID замовлення в маркетплейсі.
order_number Номер замовлення.
idempotency_key Ключ повторної обробки.

19. Черги синхронізації

19.1. Логіка синхронізації товарів

1. K2 ERP змінює товар.
2. Python-сервіс отримує подію.
3. Товар проходить валідацію.
4. Для кожного активного каналу створюється sync task.
5. Worker передає товар через API або додає у фід.
6. Результат зберігається.
7. K2 ERP отримує статус.

19.2. Логіка імпорту замовлень

1. Worker регулярно запитує нові замовлення Prom / Rozetka.
2. Перевіряє external_order_id.
3. Якщо замовлення нове — створює його в K2 ERP.
4. Якщо товар не знайдено — статус NEEDS_REVIEW.
5. Якщо все коректно — статус IMPORTED.
6. Резервує товар у K2 ERP.

19.3. Пріоритети задач

Задача Пріоритет Коментар
Імпорт замовлень Критичний Впливає на продажі.
Оновлення залишків Критичний Захищає від продажу відсутнього товару.
Оновлення цін Високий Впливає на маржу.
Оновлення статусів замовлень Високий Впливає на клієнтський досвід.
Синхронізація товарів Середній Каталог.
Генерація фідів Середній Hotline / Rozetka feed.
Оновлення ставок Hotline Середній Маркетинг.

20. Модель даних

20.1. marketplace_integrations

Поле Тип Опис
id uuid ID інтеграції.
marketplace varchar PROM, ROZETKA, HOTLINE.
name varchar Назва.
base_url varchar URL API.
api_token_encrypted text Зашифрований token.
login_encrypted text Зашифрований login.
password_encrypted text Зашифрований password.
feed_public_url varchar URL фіду.
sync_products_enabled boolean Синхронізація товарів.
sync_prices_enabled boolean Синхронізація цін.
sync_stocks_enabled boolean Синхронізація залишків.
sync_orders_enabled boolean Імпорт замовлень.
is_active boolean Активність.

20.2. marketplace_products

Поле Тип Опис
id uuid ID запису.
product_id uuid ID товару K2 ERP.
marketplace varchar PROM, ROZETKA, HOTLINE.
external_product_id varchar ID товару в каналі.
sku varchar Артикул.
status varchar Статус синхронізації.
marketplace_category_id varchar Категорія каналу.
last_synced_price numeric Остання передана ціна.
last_synced_stock numeric Останній переданий залишок.
raw_response jsonb Відповідь API.
error_message text Остання помилка.
updated_at timestamp Дата оновлення.

20.3. marketplace_orders

Поле Тип Опис
id uuid ID замовлення.
marketplace varchar PROM або ROZETKA.
external_order_id varchar ID замовлення в каналі.
order_number varchar Номер.
k2_order_id uuid ID замовлення K2 ERP.
customer_name varchar Покупець.
customer_phone varchar Телефон.
total_amount numeric Сума.
status varchar Статус K2 ERP.
marketplace_status varchar Оригінальний статус.
delivery_service varchar Служба доставки.
tracking_number varchar ТТН / ЕН.
raw_payload jsonb Дані замовлення.
created_at timestamp Дата створення.

20.4. marketplace_feeds

Поле Тип Опис
id uuid ID фіду.
marketplace varchar HOTLINE або ROZETKA.
feed_type varchar products, actions, prices.
format varchar XML, YML, CSV.
public_url varchar URL фіду.
file_id uuid Файл.
status varchar Статус генерації.
products_count integer Кількість товарів.
errors_count integer Кількість помилок.
generated_at timestamp Дата генерації.

20.5. marketplace_events

Поле Тип Опис
id uuid ID події.
marketplace varchar PROM, ROZETKA, HOTLINE.
entity_type varchar product, order, feed, price, stock, bid.
entity_id uuid ID сутності.
event_type varchar Тип події.
old_status varchar Старий статус.
new_status varchar Новий статус.
payload jsonb Технічні дані.
created_at timestamp Дата.

21. Приклад Python-логіки

21.1. Синхронізація товару

async def sync_product_to_marketplaces(product_id: str, channels: list[str], db: "Session") -> None:
    product = product_repository.get_by_id(db, product_id)

    validation_result = product_validator.validate(product)

    if not validation_result.is_valid:
        product_status_service.set_status(
            product_id=product_id,
            status="NEEDS_CORRECTION",
            errors=validation_result.errors,
            db=db,
        )
        return

    for channel in channels:
        sync_queue.enqueue(
            task_name="sync_product_to_channel",
            payload={
                "product_id": product_id,
                "marketplace": channel,
            },
        )

21.2. Worker передачі товару

async def sync_product_to_channel(product_id: str, marketplace: str, db: "Session") -> None:
    product = product_repository.get_by_id(db, product_id)
    integration = integration_repository.get_active(db, marketplace)

    client = marketplace_client_factory.create(integration)
    payload = marketplace_mapper.to_payload(product, marketplace)

    mp_product = marketplace_product_repository.get_or_create(
        db=db,
        product_id=product.id,
        marketplace=marketplace,
    )

    try:
        mp_product.status = "SYNCING"
        db.commit()

        response = await client.sync_product(payload)

        mp_product.external_product_id = response.get("external_product_id")
        mp_product.status = "SYNCED"
        mp_product.raw_response = response
        mp_product.last_synced_price = product.price
        mp_product.last_synced_stock = product.available_stock

        audit_logger.log(
            marketplace=marketplace,
            entity_type="product",
            entity_id=mp_product.id,
            event_type="PRODUCT_SYNCED",
            new_status="SYNCED",
            payload=response,
        )

    except Exception as exc:
        mp_product.status = "SYNC_ERROR"
        mp_product.error_message = str(exc)

    finally:
        db.commit()

21.3. Імпорт замовлень

async def import_marketplace_orders(marketplace: str, db: "Session") -> None:
    integration = integration_repository.get_active(db, marketplace)
    client = marketplace_client_factory.create(integration)

    orders = await client.import_orders(filters={"status": "new"})

    for order_payload in orders:
        external_order_id = order_payload["external_order_id"]

        existing = marketplace_order_repository.get_by_external_id(
            db=db,
            marketplace=marketplace,
            external_order_id=external_order_id,
        )

        if existing:
            continue

        try:
            k2_order = k2_order_service.create_from_marketplace(order_payload)

            marketplace_order_repository.create(
                db=db,
                data={
                    "marketplace": marketplace,
                    "external_order_id": external_order_id,
                    "order_number": order_payload.get("order_number"),
                    "k2_order_id": k2_order.id,
                    "customer_name": order_payload.get("customer_name"),
                    "customer_phone": order_payload.get("customer_phone"),
                    "total_amount": order_payload.get("total_amount"),
                    "status": "IMPORTED",
                    "marketplace_status": order_payload.get("status"),
                    "raw_payload": order_payload,
                },
            )

        except Exception as exc:
            marketplace_order_repository.create_error_record(
                db=db,
                marketplace=marketplace,
                external_order_id=external_order_id,
                payload=order_payload,
                error=str(exc),
            )

    db.commit()

22. Обробка помилок

Тип помилки Опис Дія системи
AuthError Невірний token, login або password. Зупинити інтеграцію, повідомити адміністратора.
ValidationError Некоректний товар або замовлення. Перевести в NEEDS_CORRECTION / NEEDS_REVIEW.
CategoryMappingError Не знайдено категорію каналу. Передати менеджеру каталогу.
AttributeMappingError Не замаплені характеристики. Передати менеджеру каталогу.
ImageError Фото недоступне або некоректне. Заблокувати передачу товару.
PriceError Ціна некоректна. Заблокувати синхронізацію ціни.
StockError Залишок некоректний. Заблокувати синхронізацію залишку.
ApiError API повернув помилку. Зберегти raw-відповідь.
FeedGenerationError Помилка генерації XML/YML. Не публікувати фід.
DuplicateOrderError Замовлення вже імпортовано. Повернути існуюче замовлення.
UnknownStatusError Канал повернув невідомий статус. Перевести в ручну перевірку.

23. Retry-логіка

Retry дозволений для:

  • timeout;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасової недоступності API;
  • тимчасової помилки імпорту замовлень;
  • тимчасової помилки оновлення ціни;
  • тимчасової помилки оновлення залишку;
  • тимчасової помилки генерації фіду.

Retry заборонений для:

  • неправильного API token;
  • помилок категорії;
  • помилок характеристик;
  • товару без фото;
  • товару без ціни;
  • дубліката замовлення;
  • відхиленого товару без виправлення даних.

24. Dashboard керівника

24.1. Основні KPI

KPI Опис Колір
Активні товари Кількість товарів, активних у каналах. Інформація
Синхронізовано Товари успішно передані. Норма
На модерації Товари очікують перевірки. Увага
Відхилено Товари відхилені каналом. Критично
Помилки синхронізації Товари або замовлення з помилками. Критично
Нові замовлення Отримані з Prom/Rozetka. Увага
Імпортовано замовлень Успішно створено в K2 ERP. Норма
Фіди сформовані XML/YML-фіди згенеровані. Норма
Проблемні фіди Помилки XML/YML. Критично

24.2. Приклад dashboard

Показник Prom Rozetka Hotline Стан
Активні товари 12 450 8 210 10 980 Інформація
Синхронізовано 12 100 7 940 10 900 Норма
На модерації 120 180 - Увага
Відхилено 35 52 - Критично
Помилки 18 24 6 Критично
Нові замовлення 42 28 - Увага
Імпортовано замовлень 39 27 - Норма

24.3. Проблемні товари

SKU Назва Канал Статус Помилка Дія
SKU-001 Смартфон Example X Rozetka Потребує виправлення Не замаплена характеристика «Пам'ять» Заповнити мапінг
SKU-002 Навушники Example Air Prom Помилка Фото недоступне Перевірити URL фото
SKU-003 Кавоварка Example Hotline Помилка фіду Некоректний XML-символ в описі Очистити опис

25. Безпека

Система повинна забезпечити:

  • зберігання API token і credentials тільки у secret storage;
  • заборону логування secrets;
  • HTTPS для всіх API-запитів;
  • перевірку SSL;
  • рольову модель доступу;
  • окремі права на синхронізацію товарів;
  • окремі права на зміну цін;
  • окремі права на зміну залишків;
  • окремі права на оновлення ставок Hotline;
  • журнал усіх дій;
  • маскування персональних даних покупців;
  • контроль доступу до замовлень;
  • захист від дублювання.

26. Логування та аудит

Система повинна логувати:

Подія Що зберігати
Синхронізація товару SKU, канал, статус, відповідь.
Зміна ціни Стара ціна, нова ціна, канал.
Зміна залишку Старий залишок, новий залишок, канал.
Імпорт замовлення Канал, external_order_id, статус.
Оновлення статусу Старий статус, новий статус, канал.
Генерація фіду Канал, формат, кількість товарів, помилки.
Оновлення ставки Hotline offer ID, стара ставка, нова ставка.
Помилка API Код, текст, raw-відповідь.
Retry Хто або який worker запустив, причина, результат.

27. Acceptance Criteria

27.1. Інтеграції

Критерій Очікуваний результат
AC-1 Адміністратор створює інтеграцію Prom. Інтеграція зберігається і проходить check_connection.
AC-2 Адміністратор створює інтеграцію Rozetka. Інтеграція зберігається і проходить check_connection.
AC-3 Адміністратор створює інтеграцію Hotline. Система формує тестовий фід або перевіряє налаштування.
AC-4 Token неправильний. Система показує AuthError і не виконує синхронізацію.

27.2. Товари

Критерій Очікуваний результат
AC-5 Товар має всі обов'язкові поля. Він передається в активні канали.
AC-6 Товар не має фото. Він переходить у NEEDS_CORRECTION.
AC-7 Категорія не замаплена. Товар не передається і показується менеджеру.
AC-8 Товар успішно передано. Статус стає SYNCED або PUBLISHED.

27.3. Ціни та залишки

Критерій Очікуваний результат
AC-9 У K2 ERP змінилась ціна. Система передає нову ціну в канали.
AC-10 У K2 ERP змінився залишок. Система передає новий залишок.
AC-11 Залишок став 0. Товар приховується або передається як недоступний за правилом.

27.4. Замовлення

Критерій Очікуваний результат
AC-12 Prom має нове замовлення. Воно імпортується в K2 ERP.
AC-13 Rozetka має нове замовлення. Воно імпортується в K2 ERP.
AC-14 Замовлення вже імпортоване. Дубль не створюється.
AC-15 Товар у замовленні не знайдено. Замовлення переходить у NEEDS_REVIEW.

27.5. Hotline

Критерій Очікуваний результат
AC-16 Система генерує Hotline XML. Фід доступний за public URL.
AC-17 У товарі некоректний XML-символ. Фід не публікується або товар виключається за правилом.
AC-18 Користувач оновлює ставку Hotline. Ставка передається через API ставок і логуються.

27.6. Dashboard

Критерій Очікуваний результат
AC-19 Керівник відкриває dashboard. Він бачить товари, замовлення, фіди, помилки по Prom/Rozetka/Hotline.
AC-20 Є відхилені товари. Вони підсвічуються червоним.
AC-21 Є товари без мапінгу. Вони підсвічуються помаранчевим.

28. MVP

До MVP входить:

  • створення інтеграцій Prom, Rozetka, Hotline;
  • перевірка підключення;
  • мапінг категорій;
  • мапінг характеристик;
  • синхронізація товарів;
  • синхронізація цін;
  • синхронізація залишків;
  • імпорт замовлень з Prom;
  • імпорт замовлень з Rozetka;
  • оновлення статусів замовлень;
  • передача ТТН;
  • генерація Hotline XML/YML-фіду;
  • публікація фіду за URL;
  • базове керування ставками Hotline, якщо є token;
  • дедублікація;
  • retry-механізм;
  • журнал подій;
  • dashboard API;
  • unit-тести;
  • mock clients для Prom/Rozetka/Hotline.

До MVP не входить:

  • повна підтримка всіх API-методів Prom;
  • повна підтримка всіх API-методів Rozetka;
  • повна автоматизація модерації;
  • автоматичне виправлення характеристик;
  • складна аналітика реклами;
  • повна інтеграція з кабінетами маркетплейсів;
  • ML-мапінг категорій;
  • автоматичне створення рекламних кампаній.

29. Етапи реалізації

Етап 1. Аналіз API та вимог

  • отримати Prom API token;
  • отримати Rozetka API credentials;
  • отримати Hotline feed specs;
  • отримати Hotline bid API token, якщо потрібно;
  • перевірити тестові запити;
  • визначити список категорій;
  • визначити правила мапінгу.

Етап 2. Базовий Python-сервіс

  • створити FastAPI-проєкт;
  • налаштувати PostgreSQL;
  • створити моделі інтеграцій, товарів, замовлень, фідів, подій;
  • налаштувати Alembic;
  • реалізувати healthcheck.

Етап 3. Marketplace Adapters

  • реалізувати PromClient;
  • реалізувати RozetkaClient;
  • реалізувати HotlineFeedGenerator;
  • реалізувати HotlineBidClient;
  • реалізувати client factory;
  • реалізувати обробку помилок.

Етап 4. Товари

  • реалізувати product mapper;
  • реалізувати category mapper;
  • реалізувати attribute mapper;
  • реалізувати валідацію;
  • реалізувати sync workers.

Етап 5. Ціни та залишки

  • реалізувати price engine;
  • реалізувати stock engine;
  • реалізувати чергу оновлення;
  • реалізувати історію змін.

Етап 6. Замовлення

  • реалізувати order import workers;
  • реалізувати дедублікацію;
  • реалізувати створення замовлення в K2 ERP;
  • реалізувати status export;
  • реалізувати передачу ТТН.

Етап 7. Фіди Hotline / Rozetka

  • реалізувати XML/YML generator;
  • реалізувати валідацію XML;
  • реалізувати публікацію файлу;
  • реалізувати журнал генерацій;
  • реалізувати фід акцій, якщо потрібно.

Етап 8. Dashboard та аудит

  • реалізувати dashboard API;
  • реалізувати список проблемних товарів;
  • реалізувати список проблемних замовлень;
  • реалізувати список помилок фідів;
  • реалізувати експорт, якщо потрібно.

Етап 9. Production hardening

  • додати rate limiting;
  • додати retry policy;
  • додати dead letter queue;
  • додати alerting;
  • додати моніторинг;
  • додати резервне копіювання;
  • додати безпечне зберігання secret-ів.

30. Ризики

Ризик Опис Як зменшити
Зміна API Prom або Rozetka можуть змінити методи. Версіонування клієнтів і contract-тести.
Помилки категорій Товари не проходять модерацію. Мапінг категорій і dashboard проблем.
Помилки характеристик Rozetka часто потребує точних характеристик категорій. Attribute mapping і валідація.
Дублювання замовлень Повторний імпорт може створити дубль. external_order_id + marketplace unique constraint.
Продаж відсутнього товару Залишки не оновились вчасно. Високий пріоритет stock sync.
Некоректний XML Hotline не прийме фід. XML validation перед публікацією.
Token недійсний API не працює. Check-connection і alert адміністратору.
Невідомий статус Канал повернув новий статус. UNKNOWN_STATUS і ручний мапінг.

31. Відкриті питання

  1. Чи K2 ERP є головним джерелом товарів?
  2. Які категорії товарів потрібно підтримати в MVP?
  3. Чи потрібна повна синхронізація товарів у Prom через API?
  4. Чи Rozetka товари приймає через API, фід або змішано?
  5. Який формат фіду Rozetka потрібен?
  6. Який формат Hotline використовуємо: XML, YML, CSV?
  7. Чи потрібно керувати ставками Hotline?
  8. Чи потрібно імпортувати замовлення з Prom?
  9. Чи потрібно імпортувати замовлення з Rozetka?
  10. Чи потрібно оновлювати статуси замовлень у маркетплейсах?
  11. Чи потрібно передавати ТТН Нової пошти / Укрпошти?
  12. Чи потрібна підтримка декількох магазинів Prom?
  13. Чи потрібна підтримка декількох кабінетів Rozetka?
  14. Чи потрібні окремі правила цін для кожного каналу?
  15. Чи потрібні окремі склади для залишків по каналах?
  16. Чи потрібно автоматично приховувати товари без залишку?
  17. Як часто оновлювати ціни?
  18. Як часто оновлювати залишки?
  19. Як часто імпортувати замовлення?

32. Джерела

33. Див. також