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

Інтеграція з Horoshop

Матеріал з K2 ERP Wiki


SEO title: Технічне завдання: Інтеграція з Horoshop / Хорошоп для Python SEO description: Технічне завдання на реалізацію Python-сервісу для інтеграції K2 ERP, CRM або WMS з Horoshop: товари, категорії, характеристики, ціни, залишки, замовлення, клієнти, статуси, оплати, доставки, API, фіди, помилки, dashboard та журналювання. SEO keywords: Python, Horoshop, Хорошоп, Horoshop API, Хорошоп API, інтеграція інтернет-магазину, K2 ERP, CRM, WMS, товари, замовлення, ціни, залишки, FastAPI, ecommerce Alternative to:



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

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

Важливо: Horoshop API прив'язаний до домену конкретного магазину. Тому для кожного сайту потрібно зберігати власний base_url, логін, пароль, статус інтеграції, правила синхронізації та технічний журнал.

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

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

1. Мета

Метою задачі є створення Python-сервісу для інтеграції K2 ERP / CRM / WMS з інтернет-магазином на платформі Horoshop.

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

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

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

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

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

3. Основні можливості інтеграції

Напрям Опис Джерело істини Коментар
Товари Створення та оновлення товарів на Horoshop. K2 ERP ERP є головним джерелом каталогу.
Категорії Синхронізація структури каталогу. K2 ERP або Horoshop Визначається правилами проєкту.
Характеристики Передача атрибутів товарів. K2 ERP Потрібні для фільтрів і SEO.
Ціни Оновлення базових, акційних, роздрібних цін. K2 ERP Важливо для комерційного контролю.
Залишки Оновлення доступної кількості. K2 ERP / WMS Критичний процес.
Замовлення Імпорт замовлень із Horoshop. Horoshop Замовлення створюються покупцями на сайті.
Клієнти Імпорт або оновлення клієнтів. Horoshop / K2 ERP Залежить від бізнес-логіки.
Статуси Оновлення статусів замовлень на сайті. K2 ERP ERP керує виконанням замовлень.
Доставка Передача служби доставки, адреси, ТТН. K2 ERP / служби доставки Нова пошта, Укрпошта тощо.
Оплата Статус і тип оплати. Horoshop / платіжний сервіс / K2 ERP Потребує мапінгу.

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

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

  • домен сайту Horoshop;
  • API base URL;
  • API login;
  • API password;
  • доступ до адмінпанелі Horoshop;
  • список API-методів, які доступні на конкретному тарифі / сайті;
  • актуальну документацію API;
  • правила мапінгу категорій;
  • правила мапінгу характеристик;
  • список статусів замовлень Horoshop;
  • список статусів замовлень K2 ERP;
  • список типів оплат;
  • список типів доставок;
  • правила синхронізації цін;
  • правила синхронізації залишків;
  • правила обробки замовлень;
  • правила передачі ТТН.

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

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

5.1. Передача товарів з K2 ERP у Horoshop

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

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

  • отримати товар із K2 ERP;
  • перевірити обов'язкові поля;
  • визначити категорію;
  • підготувати назву;
  • підготувати опис;
  • підготувати характеристики;
  • підготувати фото;
  • підготувати ціну;
  • підготувати залишок;
  • створити або оновити товар у Horoshop;
  • зберегти external_product_id;
  • записати результат у журнал.

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

Коли ціна змінюється в K2 ERP, Python-сервіс повинен:

  • отримати подію зміни ціни;
  • визначити канали продажу;
  • перевірити активність товару;
  • застосувати правила округлення;
  • застосувати правила акційної ціни;
  • передати нову ціну в Horoshop;
  • зберегти історію зміни.

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

Коли змінюється залишок на складі, Python-сервіс повинен:

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

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

Horoshop є джерелом замовлень, які створюють покупці на сайті.

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

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

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

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

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

  • отримати статус замовлення з K2 ERP;
  • замапити його у статус Horoshop;
  • передати статус у Horoshop;
  • передати ТТН / ЕН, якщо є;
  • передати коментар менеджера, якщо підтримується;
  • записати подію в журнал.

5.6. Обмін клієнтами

Система повинна підтримувати:

  • створення нового клієнта в K2 ERP на основі замовлення Horoshop;
  • пошук клієнта за телефоном;
  • пошук клієнта за email;
  • оновлення ПІБ;
  • оновлення адреси доставки;
  • історію замовлень клієнта;
  • мапінг customer_id Horoshop ↔ customer_id K2 ERP.

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

Сутність Опис
Horoshop Integration Налаштування підключення до конкретного сайту.
Product Товар у K2 ERP.
Horoshop Product Товар на сайті Horoshop.
Category Категорія товарів.
Attribute Характеристика товару.
Product Variant Варіант / модифікація товару.
Product Image Фото товару.
Price Ціна товару.
Stock Залишок товару.
Customer Покупець.
Order Замовлення.
Order Item Рядок замовлення.
Payment Оплата.
Delivery Доставка.
API Event Технічна подія інтеграції.

7. User Story

7.1. Менеджер товарного каталогу

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

7.2. Склад

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

7.3. Менеджер продажів

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

7.4. Керівник

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

7.5. Адміністратор

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

8. Напрями синхронізації

Об'єкт Напрям Джерело Призначення
Категорії K2 ERP → Horoshop або Horoshop → K2 ERP Залежить від проєкту Єдина структура каталогу.
Товари K2 ERP → Horoshop K2 ERP Публікація каталогу.
Ціни K2 ERP → Horoshop K2 ERP Актуальні ціни на сайті.
Залишки K2 ERP/WMS → Horoshop K2 ERP / WMS Актуальна наявність.
Замовлення Horoshop → K2 ERP Horoshop Обробка продажів.
Клієнти Horoshop → K2 ERP Horoshop Створення клієнтів із замовлень.
Статуси замовлень K2 ERP → Horoshop K2 ERP Покупець бачить актуальний статус.
ТТН / ЕН K2 ERP → Horoshop K2 ERP / доставка Інформування покупця про доставку.

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

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

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

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

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

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

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

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

K2 ERP / CRM / WMS
        |
        | 1. Товари, ціни, залишки, статуси
        v
Python Horoshop Integration Service
        |
        | 2. Валідація, мапінг, черги, дедублікація
        v
Horoshop API Client
        |
        | 3. HTTP/HTTPS API Horoshop
        v
Інтернет-магазин Horoshop
        |
        | 4. Замовлення, клієнти, статуси
        v
Order Import Worker
        |
        | 5. Імпорт у K2 ERP
        v
K2 ERP / Dashboard / Менеджери

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

Компонент Опис
API Layer REST API для команд із K2 ERP.
Horoshop Client Python-клієнт для Horoshop API.
Product Mapper Перетворює товар K2 ERP у формат Horoshop.
Order Mapper Перетворює замовлення Horoshop у формат K2 ERP.
Category Mapper Мапить категорії.
Attribute Mapper Мапить характеристики.
Price Engine Формує ціни для сайту.
Stock Engine Формує доступний залишок.
Product Sync Worker Передає товари.
Price Sync Worker Передає ціни.
Stock Sync Worker Передає залишки.
Order Import Worker Імпортує замовлення.
Status Export Worker Передає статуси назад у Horoshop.
Audit Logger Запити, відповіді, помилки, статуси.
Dashboard API Дані для контролю інтеграції.

13. Horoshop API Client

13.1. Призначення

Horoshop API Client — це Python-клас або пакет, який інкапсулює роботу з API конкретного сайту Horoshop.

13.2. Загальні принципи

API-запити виконуються до шлюзу:

http(s)://<DOMAIN>/api/

Функції API викликаються через URL:

http(s)://<DOMAIN>/api/<FUNCTION>/

Це відповідає офіційній документації Horoshop API, де вказано, що шлюз має формат `http(s)://<DOMAIN>/api/`, а функції передаються через адресний рядок. :contentReference[oaicite:2]{index=2}

13.3. Основні методи клієнта

class HoroshopClient:
    def check_connection(self) -> "ConnectionStatus":
        pass

    def authenticate(self) -> "AuthResult":
        pass

    def call_api(self, function: str, payload: dict | None = None) -> dict:
        pass

    def get_orders(self, filters: dict) -> "OrderListResponse":
        pass

    def get_order(self, order_id: str) -> "OrderResponse":
        pass

    def update_order_status(self, order_id: str, payload: dict) -> "OrderStatusResponse":
        pass

    def create_or_update_product(self, payload: dict) -> "ProductResponse":
        pass

    def update_product_price(self, product_id: str, payload: dict) -> "PriceResponse":
        pass

    def update_product_stock(self, product_id: str, payload: dict) -> "StockResponse":
        pass

    def create_or_update_category(self, payload: dict) -> "CategoryResponse":
        pass

    def get_customers(self, filters: dict) -> "CustomerListResponse":
        pass

Важливо: назви методів Python-клієнта є внутрішньою абстракцією. Реальні назви функцій Horoshop API потрібно брати з актуальної документації конкретного магазину.

14. Конфігурація клієнта

from pydantic_settings import BaseSettings


class HoroshopSettings(BaseSettings):
    base_url: str
    api_login: str
    api_password: str
    timeout_seconds: int = 30
    retry_count: int = 3
    retry_backoff_seconds: int = 5
    verify_ssl: bool = True
    language: str = "ua"

Приклад `.env`:

HOROSHOP_BASE_URL=https://example.com/api/
HOROSHOP_API_LOGIN=integration_user
HOROSHOP_API_PASSWORD=********
HOROSHOP_TIMEOUT_SECONDS=30
HOROSHOP_RETRY_COUNT=3
HOROSHOP_RETRY_BACKOFF_SECONDS=5
HOROSHOP_LANGUAGE=ua

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

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

POST /api/v1/horoshop/integrations

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

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

15.3. Синхронізація категорій

POST /api/v1/horoshop/categories/sync

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

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

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

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

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

POST /api/v1/horoshop/prices/sync

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

POST /api/v1/horoshop/stocks/sync

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

POST /api/v1/horoshop/orders/import

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

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

15.10. Передача ТТН / ЕН

POST /api/v1/horoshop/orders/{order_id}/tracking-number

15.11. Dashboard

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

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

{
  "product_id": "K2-PRODUCT-000123",
  "sku": "SKU-001",
  "name": "Смартфон Example X 128GB",
  "description": "Опис товару для сайту.",
  "category_id": "phones",
  "horoshop_category_id": "h-category-001",
  "brand": "Example",
  "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 місяців"
  },
  "is_active": true
}

17. Приклад замовлення з Horoshop

{
  "external_order_id": "HS-ORDER-000123",
  "order_number": "000123",
  "order_date": "2026-05-07T12:10:00+03:00",
  "customer": {
    "external_customer_id": "HS-CUSTOMER-001",
    "name": "Іван Петренко",
    "phone": "+380671112233",
    "email": "client@example.com"
  },
  "items": [
    {
      "sku": "SKU-001",
      "name": "Смартфон Example X 128GB",
      "quantity": 1,
      "price": 12999.00,
      "amount": 12999.00
    }
  ],
  "payment": {
    "type": "online_card",
    "status": "paid",
    "amount": 12999.00
  },
  "delivery": {
    "service": "nova_poshta",
    "city": "Київ",
    "warehouse": "Відділення №1",
    "address": null
  },
  "comment": "Зателефонувати перед відправкою",
  "total_amount": 12999.00,
  "status": "new"
}

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

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

  • SKU заповнений;
  • назва заповнена;
  • опис заповнений;
  • категорія визначена;
  • категорія Horoshop замаплена;
  • ціна більша за 0;
  • залишок не від'ємний;
  • фото доступні;
  • головне фото визначене;
  • характеристики заповнені;
  • бренд заповнений, якщо потрібен;
  • штрихкод валідний, якщо використовується;
  • товар не дублюється за SKU;
  • товар не дублюється за external_product_id;
  • текст опису не містить небезпечного HTML;
  • активність товару відповідає правилам публікації.

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

19. Валідація замовлень

Перед створенням замовлення в K2 ERP система повинна перевірити:

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

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

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

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

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

Ключ Призначення
external_order_id ID замовлення Horoshop.
order_number Номер замовлення.
horoshop_site_id ID сайту, якщо магазинів декілька.
idempotency_key Ключ повторної обробки.

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

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

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

21.2. Логіка оновлення залишків

1. WMS або K2 ERP змінює залишок.
2. Python-сервіс формує доступну кількість.
3. Враховуються резерви та страховий залишок.
4. Створюється задача Stock Sync.
5. Worker передає залишок у Horoshop.
6. Результат записується в журнал.

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

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

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

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

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

22.1. horoshop_integrations

Поле Тип Опис
id uuid ID інтеграції.
name varchar Назва інтеграції.
site_domain varchar Домен сайту.
base_url varchar URL API.
api_login_encrypted text Зашифрований API login.
api_password_encrypted text Зашифрований API password.
sync_products_enabled boolean Синхронізація товарів.
sync_prices_enabled boolean Синхронізація цін.
sync_stocks_enabled boolean Синхронізація залишків.
sync_orders_enabled boolean Імпорт замовлень.
sync_statuses_enabled boolean Оновлення статусів.
is_active boolean Активність.
created_at timestamp Дата створення.
updated_at timestamp Дата оновлення.

22.2. horoshop_products

Поле Тип Опис
id uuid ID запису.
k2_product_id uuid ID товару K2 ERP.
horoshop_product_id varchar ID товару Horoshop.
sku varchar Артикул.
status varchar Статус синхронізації.
horoshop_category_id varchar Категорія Horoshop.
last_synced_price numeric Остання передана ціна.
last_synced_stock numeric Останній переданий залишок.
product_hash varchar Hash даних товару.
raw_response jsonb Відповідь API.
error_message text Остання помилка.
updated_at timestamp Дата оновлення.

22.3. horoshop_orders

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

22.4. horoshop_order_items

Поле Тип Опис
id uuid ID рядка.
order_id uuid Замовлення.
sku varchar Артикул.
k2_product_id uuid ID товару K2 ERP.
name varchar Назва товару.
quantity numeric Кількість.
price numeric Ціна.
amount numeric Сума.

22.5. horoshop_category_mappings

Поле Тип Опис
id uuid ID мапінгу.
k2_category_id varchar Категорія K2 ERP.
horoshop_category_id varchar Категорія Horoshop.
is_active boolean Активність.

22.6. horoshop_status_mappings

Поле Тип Опис
id uuid ID мапінгу.
k2_status varchar Статус K2 ERP.
horoshop_status varchar Статус Horoshop.
direction varchar IMPORT або EXPORT.
is_active boolean Активність.

22.7. horoshop_events

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

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

23.1. Базовий Horoshop Client

import httpx


class HoroshopApiError(Exception):
    pass


class HoroshopClient:
    def __init__(self, base_url: str, api_login: str, api_password: str, timeout_seconds: int = 30):
        self.base_url = base_url.rstrip("/")
        self.api_login = api_login
        self.api_password = api_password
        self.timeout_seconds = timeout_seconds

    async def call_api(self, function: str, payload: dict | None = None) -> dict:
        url = f"{self.base_url}/{function.strip('/')}/"

        request_payload = payload or {}
        request_payload["login"] = self.api_login
        request_payload["password"] = self.api_password

        async with httpx.AsyncClient(timeout=self.timeout_seconds) as client:
            response = await client.post(url, json=request_payload)

        if response.status_code >= 400:
            raise HoroshopApiError(response.text)

        data = response.json()

        if data.get("status") in ["error", "failed"]:
            raise HoroshopApiError(str(data))

        return data

Важливо: приклад авторизації є архітектурним. Точну схему передачі login/password, token або session потрібно звірити з актуальною документацією Horoshop API для конкретного методу.

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

async def sync_product_to_horoshop(product_id: 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

    integration = horoshop_integration_repository.get_active(db)
    client = horoshop_client_factory.create(integration)

    payload = horoshop_product_mapper.to_payload(product)

    hs_product = horoshop_product_repository.get_or_create(
        db=db,
        k2_product_id=product.id,
        sku=product.sku,
    )

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

        response = await client.call_api(
            function="catalog/import/",
            payload=payload,
        )

        hs_product.horoshop_product_id = response.get("product_id") or hs_product.horoshop_product_id
        hs_product.status = "SYNCED"
        hs_product.raw_response = response
        hs_product.last_synced_price = product.price
        hs_product.last_synced_stock = product.available_stock

        audit_logger.log(
            entity_type="product",
            entity_id=hs_product.id,
            event_type="HOROSHOP_PRODUCT_SYNCED",
            new_status="SYNCED",
            payload=response,
        )

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

    finally:
        db.commit()

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

async def import_horoshop_orders(db: "Session") -> None:
    integration = horoshop_integration_repository.get_active(db)
    client = horoshop_client_factory.create(integration)

    response = await client.call_api(
        function="orders/get/",
        payload={
            "status": "new",
            "date_from": sync_state_repository.get_last_order_sync_date(db),
        },
    )

    orders = response.get("orders", [])

    for order_payload in orders:
        external_order_id = str(order_payload["id"])

        existing = horoshop_order_repository.get_by_external_id(
            db=db,
            external_order_id=external_order_id,
        )

        if existing:
            continue

        try:
            k2_order = k2_order_service.create_from_horoshop(order_payload)

            horoshop_order_repository.create(
                db=db,
                data={
                    "external_order_id": external_order_id,
                    "order_number": order_payload.get("number"),
                    "k2_order_id": k2_order.id,
                    "customer_name": order_payload.get("customer", {}).get("name"),
                    "customer_phone": order_payload.get("customer", {}).get("phone"),
                    "customer_email": order_payload.get("customer", {}).get("email"),
                    "total_amount": order_payload.get("total"),
                    "payment_type": order_payload.get("payment", {}).get("type"),
                    "payment_status": order_payload.get("payment", {}).get("status"),
                    "delivery_service": order_payload.get("delivery", {}).get("service"),
                    "status": "IMPORTED",
                    "horoshop_status": order_payload.get("status"),
                    "raw_payload": order_payload,
                },
            )

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

    db.commit()

23.4. Оновлення залишку

async def sync_stock_to_horoshop(product_id: str, db: "Session") -> None:
    product = product_repository.get_by_id(db, product_id)
    integration = horoshop_integration_repository.get_active(db)
    client = horoshop_client_factory.create(integration)

    available_stock = stock_engine.calculate_available_stock(
        product_id=product.id,
        warehouse_id=product.default_warehouse_id,
    )

    payload = {
        "sku": product.sku,
        "quantity": available_stock,
    }

    try:
        response = await client.call_api(
            function="catalog/update_stock/",
            payload=payload,
        )

        horoshop_product_repository.update_stock_sync_result(
            db=db,
            k2_product_id=product.id,
            stock=available_stock,
            response=response,
        )

    except Exception as exc:
        horoshop_product_repository.set_sync_error(
            db=db,
            k2_product_id=product.id,
            error=str(exc),
        )

    db.commit()

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

async def export_order_status_to_horoshop(k2_order_id: str, db: "Session") -> None:
    order = k2_order_repository.get_by_id(db, k2_order_id)
    hs_order = horoshop_order_repository.get_by_k2_order_id(db, k2_order_id)

    if not hs_order:
        return

    horoshop_status = status_mapping_repository.map_k2_to_horoshop(
        db=db,
        k2_status=order.status,
    )

    payload = {
        "order_id": hs_order.external_order_id,
        "status": horoshop_status,
        "tracking_number": order.tracking_number,
        "comment": order.manager_comment,
    }

    integration = horoshop_integration_repository.get_active(db)
    client = horoshop_client_factory.create(integration)

    response = await client.call_api(
        function="orders/update_status/",
        payload=payload,
    )

    audit_logger.log(
        entity_type="order",
        entity_id=hs_order.id,
        event_type="HOROSHOP_ORDER_STATUS_EXPORTED",
        payload=response,
    )

    db.commit()

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

Тип помилки Опис Дія системи
AuthError Невірний API login або password. Зупинити інтеграцію, повідомити адміністратора.
ConnectionError API Horoshop недоступне. Retry, dashboard warning.
ValidationError Некоректний товар або замовлення. NEEDS_CORRECTION / NEEDS_REVIEW.
CategoryMappingError Не знайдено категорію Horoshop. Передати менеджеру каталогу.
AttributeMappingError Не замаплені характеристики. Передати менеджеру каталогу.
ImageError Фото недоступне. Заблокувати передачу товару.
PriceError Некоректна ціна. Заблокувати синхронізацію ціни.
StockError Некоректний залишок. Заблокувати синхронізацію залишку.
DuplicateOrderError Замовлення вже імпортовано. Повернути існуюче замовлення.
UnknownStatusError Статус не замаплений. Перевести в ручну перевірку.

25. Retry-логіка

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

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

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

  • неправильного API login/password;
  • товару без SKU;
  • товару без категорії;
  • товару без ціни;
  • товару без фото;
  • незамапленого статусу;
  • дубліката замовлення;
  • помилки бізнес-логіки K2 ERP.

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

26.1. Основні KPI

KPI Опис Колір
Товарів у синхронізації Кількість товарів, що передаються на сайт. Інформація
Синхронізовано товарів Товари успішно передані. Норма
Помилки товарів Товари з помилками валідації або API. Критично
Оновлено цін Кількість успішних оновлень цін. Норма
Оновлено залишків Кількість успішних оновлень залишків. Норма
Нові замовлення Нові замовлення з Horoshop. Увага
Імпортовано замовлень Замовлення створені в K2 ERP. Норма
Потребують перевірки Замовлення з невідомими товарами або даними. Потрібна дія
Помилки API Технічні помилки інтеграції. Критично

26.2. Приклад dashboard

Показник Значення Стан
Активні товари 12 450 Інформація
Синхронізовано 12 100 Норма
Потребують виправлення 180 Потрібна дія
Помилки синхронізації 24 Критично
Оновлено цін сьогодні 820 Норма
Оновлено залишків сьогодні 1 540 Норма
Нові замовлення 42 Увага
Імпортовано замовлень 39 Норма
Замовлення на перевірці 3 Потрібна дія

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

SKU Назва Статус Помилка Дія
SKU-001 Смартфон Example X Потребує виправлення Не замаплена категорія Заповнити мапінг
SKU-002 Навушники Example Air Помилка Фото недоступне Перевірити URL фото
SKU-003 Кавоварка Example Потребує виправлення Немає ціни Заповнити ціну

26.4. Проблемні замовлення

Дата Замовлення Клієнт Статус Причина Дія
07.05.2026 HS-ORDER-001 Іван Петренко Потребує перевірки Не знайдено SKU Прив'язати товар
07.05.2026 HS-ORDER-002 Олена Сидоренко Помилка Не створено клієнта Перевірити телефон/email
07.05.2026 HS-ORDER-003 ТОВ «Альфа» Потребує перевірки Невідомий тип доставки Заповнити мапінг доставки

27. Безпека

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

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

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

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

Подія Що зберігати
Перевірка підключення URL, результат, час, без пароля.
Синхронізація товару SKU, статус, відповідь API.
Зміна ціни Стара ціна, нова ціна, дата.
Зміна залишку Старий залишок, новий залишок, склад.
Імпорт замовлення external_order_id, номер, статус.
Створення клієнта Телефон/email у замаскованому вигляді.
Оновлення статусу Старий статус, новий статус.
Передача ТТН Номер замовлення, ТТН, служба доставки.
Помилка API Код, текст, raw-відповідь без секретів.
Retry Причина, кількість спроб, результат.

29. Acceptance Criteria

29.1. Інтеграція

Критерій Очікуваний результат
AC-1 Адміністратор створює інтеграцію Horoshop. Інтеграція зберігається в системі.
AC-2 Адміністратор перевіряє підключення. Система повертає успішний або помилковий статус.
AC-3 Login/password неправильні. Система показує AuthError і не виконує синхронізацію.

29.2. Товари

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

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

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

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

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

29.5. Статуси та ТТН

Критерій Очікуваний результат
AC-15 K2 ERP змінила статус замовлення. Статус передається в Horoshop.
AC-16 У K2 ERP з'явилась ТТН. ТТН передається в Horoshop.
AC-17 Статус не замаплений. Замовлення потрапляє в ручну перевірку.

29.6. Dashboard

Критерій Очікуваний результат
AC-18 Керівник відкриває dashboard. Він бачить товари, замовлення, ціни, залишки, помилки.
AC-19 Є помилки синхронізації. Вони підсвічуються червоним.
AC-20 Є товари без мапінгу. Вони підсвічуються помаранчевим.
AC-21 Є нові замовлення. Вони підсвічуються жовтим.

30. MVP

До MVP входить:

  • створення інтеграції Horoshop;
  • перевірка підключення;
  • синхронізація категорій або мапінг категорій;
  • синхронізація товарів;
  • синхронізація цін;
  • синхронізація залишків;
  • імпорт замовлень;
  • імпорт клієнтів із замовлень;
  • оновлення статусів замовлень;
  • передача ТТН;
  • дедублікація;
  • retry-механізм;
  • журнал подій;
  • dashboard API;
  • unit-тести;
  • mock Horoshop client.

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

  • повна підтримка всіх API-методів Horoshop;
  • складна SEO-оптимізація товарів;
  • автоматичне створення маркетингових акцій;
  • складний UI керування каталогом;
  • інтеграція з усіма маркетплейсами;
  • автоматичне виправлення товарних даних;
  • ML-мапінг категорій і характеристик.

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

Етап 1. Аналіз API Horoshop

  • отримати доступ до API;
  • створити API login/password в адмінпанелі;
  • перевірити base_url;
  • перевірити тестовий запит;
  • визначити методи товарів;
  • визначити методи замовлень;
  • визначити методи статусів;
  • визначити методи цін і залишків;
  • визначити обмеження API.

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

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

Етап 3. Horoshop Client

  • реалізувати call_api;
  • реалізувати check_connection;
  • реалізувати get_orders;
  • реалізувати update_order_status;
  • реалізувати create_or_update_product;
  • реалізувати update_price;
  • реалізувати update_stock;
  • реалізувати обробку помилок.

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

  • реалізувати Product Mapper;
  • реалізувати Category Mapper;
  • реалізувати Attribute Mapper;
  • реалізувати валідацію;
  • реалізувати Product Sync Worker.

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

  • реалізувати Price Engine;
  • реалізувати Stock Engine;
  • реалізувати чергу оновлення;
  • реалізувати історію змін.

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

  • реалізувати Order Import Worker;
  • реалізувати дедублікацію;
  • реалізувати створення замовлення в K2 ERP;
  • реалізувати створення клієнта;
  • реалізувати резервування товарів.

Етап 7. Статуси та доставка

  • реалізувати мапінг статусів;
  • реалізувати Status Export Worker;
  • реалізувати передачу ТТН;
  • реалізувати журнал статусів.

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

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

Етап 9. Production hardening

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

32. Ризики

Ризик Опис Як зменшити
Невірні API-доступи Інтеграція не працюватиме. Check-connection і alert адміністратору.
Зміна API Методи або поля можуть змінитись. Версіонування клієнта і contract-тести.
Дублювання замовлень Повторний імпорт може створити дубль. Unique constraint по external_order_id + site_id.
Продаж відсутнього товару Залишки не оновились вчасно. Високий пріоритет Stock Sync.
Некоректний товар Товар не публікується. Валідація і статус NEEDS_CORRECTION.
Незамаплений статус Статус не передається. Таблиця status_mappings і ручна перевірка.
Недоступність API Синхронізація зупинена. Retry, queue, dashboard помилок.
Персональні дані в логах Ризик витоку даних. Маскування телефону/email.

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

  1. Чи K2 ERP є головним джерелом товарів?
  2. Чи потрібно створювати категорії в Horoshop автоматично?
  3. Чи потрібно імпортувати категорії з Horoshop?
  4. Які поля товару обов'язкові для MVP?
  5. Чи є модифікації / варіанти товарів?
  6. Чи потрібно синхронізувати фото?
  7. Чи потрібно синхронізувати SEO-поля?
  8. Чи потрібно синхронізувати акційні ціни?
  9. Чи потрібно синхронізувати декілька складів?
  10. Чи потрібно приховувати товар при нульовому залишку?
  11. Як часто імпортувати замовлення?
  12. Як часто оновлювати ціни?
  13. Як часто оновлювати залишки?
  14. Чи потрібно передавати ТТН у Horoshop?
  15. Чи потрібно підтримувати кілька сайтів Horoshop?
  16. Які статуси Horoshop потрібно замапити?
  17. Які типи оплат і доставок потрібно підтримати?

34. Джерела

  • Офіційна документація Horoshop API.
  • Центр допомоги Horoshop.
  • Сторінка Horoshop API.
  • Документація K2 ERP щодо товарів, залишків, цін і замовлень.
  • Технічні вимоги конкретного сайту Horoshop.

35. Див. також