| Імпортовано замовлень
|
Замовлення створені в K2 ERP. Якщо замовлення нове — створює його в K2 ERP. Код
синхронізації товарів забезпечується через Головна ідея: розробити Python-сервіс, який інтегрує K2 ERP / CRM / WMS з інтернет-магазином на платформі Horoshop / Хорошоп; так само реалізовано категорій, характеристик, цін, залишків, клієнтів, замовлень, статусів, оплат, доставок і журналу помилок. | K2 ERP / WMS
|
Критичний бізнес-процес. №
continue
Як адміністратор,
orders = response.get("orders", [])
Етап 1. Аналіз API Horoshop
error=str(exc),
3. №
)
"customer_name": order_payload.get("customer", {}).get("name"),
db.commit()
pass
5. |-
|
AC-16
|
-
|
оновлення версій цін
|
Високий
|
-
|
AC-6
|
-
|
Недоступність API
|
Синхронізація зупинена. function="orders/get/",
- реалізувати мапінг статусів;
- реалізувати Status Export Worker;
- реалізувати передачу ТТН;
- реалізувати журнал статусів. | K2 ERP
|
-
|
Status Export Worker
|
Передає статуси назад у Horoshop. sku=product.sku,
Етап 7. Статуси та доставка
- отримати доступ до API;
- створити API login/password в адмінпанелі;
- перевірити base_url;
- перевірити тестовий запит;
- визначити методи товарів;
- визначити методи замовлень;
- визначити методи статусів;
- визначити методи цін і залишків;
- визначити обмеження API. |-
|
Horoshop Product
|
Товар на сайті Horoshop.=== 5.3. оновлення версій залишків ===
self.base_url = base_url.rstrip("/")
критично: назви методів Python-клієнта виступає як внутрішньою абстракцією. | Unique constraint по external_order_id + site_id.
|
-
|
sku
|
varchar
|
}
|
Пріоритет
Критично критично: товар без SKU, категорії, ціни або головного фото не повинен автоматизовано передаватися в Horoshop. SEO-опис
{
|
Draft, hidden, cancelled. db=db,
1. |}
return data
15.7. оновлення версій залишків
17. Приклад замовлення з Horoshop
POST /api/v1/horoshop/orders/{order_id}/update-status
</syntaxhighlight>
|
-
|
product_hash
|
Hash назви, опису, ціни, залишку, характеристик. Напрям
def __init__(self, base_url: str, api_login: str, api_password: str, timeout_seconds: int = 30):
|
Тип
15.8. Імпорт замовлень
pass
def get_customers(self, filters: dict) -> "CustomerListResponse":
available_stock = stock_engine.calculate_available_stock(
|
-
|
Attribute
|
Валідація і статус NEEDS_CORRECTION. | Horoshop
|
Замовлення створюються покупцями на сайті. external_order_id = str(order_payload ["id"])
|
-
|
k2_product_id
|
uuid
|
Заблокувати синхронізацію залишку. |-
|
horoshop_status
|
varchar
|
-
|
Зміна залишку
|
-
|
Статуси замовлень
|
K2 ERP → Horoshop
|
K2 ERP
|
Статус стає SYNCED. |-
|
product_hash
|
varchar
|
-
|
Ціни
|
K2 ERP → Horoshop
|
K2 ERP
|
Актуальні ціни на сайті.
- підключення до Horoshop API;
- перевірку доступності API;
- синхронізацію категорій;
- синхронізацію товарів;
- синхронізацію модифікацій / варіантів товарів;
- синхронізацію характеристик;
- синхронізацію фото;
- синхронізацію цін;
- синхронізацію знижок і акцій, якщо підтримується API;
- синхронізацію залишків;
- імпорт замовлень;
- імпорт клієнтів;
- оновлення версій статусів замовлень;
- передачу ТТН / ЕН у замовлення;
- синхронізацію оплат і доставок;
- журналювання API-запитів;
- контроль помилок;
- dashboard для менеджерів і керівника. |-
|
Product Image
|
-
|
AC-3
|
інтеграційні функції ERP зберігається в системі. |-
|
last_synced_stock
|
numeric
|
Останній переданий залишок. Сутність
"comment": order.manager_comment,
|
}
def get_orders(self, filters: dict) -> "OrderListResponse":
14. Конфігурація клієнта
21. Черги синхронізації
28. Логування та аудит
)
|
| Скасовано
|
CANCELLED
|
Високий пріоритет Stock Sync. |}
"phone": "+380671112233",
|
-
|
Order
|
-
|
Order Item
|
-
|
sync_prices_enabled
|
boolean
|
-
|
Зміна ціни
|
-
|
Доставка
|
Передача служби доставки, адреси, ТТН. ! Критерій
- отримати залишок із K2 ERP або WMS;
- врахувати резерви;
- врахувати мінімальний страховий залишок;
- сформувати доступний залишок для сайту;
- передати залишок у Horoshop;
- приховати товар, якщо залишок 0, якщо це передбачено правилами;
- відновити товар, якщо залишок з'явився. |-
|
site_domain
|
varchar
|
Домен сайту. * timeout;
- HTTP 429;
- HTTP 500;
- HTTP 502;
- HTTP 503;
- HTTP 504;
- тимчасової недоступності API;
- тимчасової помилки імпорту замовлень;
- тимчасової помилки оновлення версій ціни;
- тимчасової помилки оновлення версій залишку;
- тимчасової помилки оновлення версій статусу. |-
|
horoshop_category_id
|
varchar
|
Категорія Horoshop. SEO-опис
product = product_repository.get_by_id(db, product_id)
Це відповідає офіційній документації Horoshop API, де вказано, що шлюз має формат `http(s)://<DOMAIN>/api/`, а функції передаються через адресний рядок. |-
|
Залишки
|
K2 ERP/WMS → Horoshop
|
K2 ERP / WMS
|
Актуальна наявність. :contentReference [oaicite:2]{index=2}
def call_api(self, function: str, payload: dict | None = None) -> dict:
</syntaxhighlight>
hs_product.status = "SYNC_ERROR"
function="catalog/update_stock/",
| style="background:#eeeeee;" | Сірий
|
| Помилка
|
ERROR
|
-
|
Блакитний
|
#bbdefb
|
style="background:#ef9a9a;" | Критично
|
| Оновлено цін
|
-
|
AC-20
|
платформа передає нову ціну в Horoshop. "date_from": sync_state_repository.get_last_order_sync_date(db),
=== 29.6. Dashboard ===
</pre>
! Товари, ціни, залишки, статуси
Перед створенням замовлення в K2 ERP платформа повинна перевірити:
HOROSHOP_TIMEOUT_SECONDS=30
|
| 2. | Товар приховується або позначається як недоступний за правилом. |-
| delivery_service
| varchar
| Служба доставки. | K2 ERP або Horoshop
| Визначається правилами проєкту. |-
| created_at
| timestamp
| Дата створення. |-
| quantity
| numeric
| Кількість. Значення
інтеграційні функції ERP призначена для:
я хочу отримувати замовлення з Horoshop у K2 ERP,
=== 21.1. Логіка синхронізації товарів ===
! №
{| class="wikitable"
</pre>
! ! |-
| raw_payload
| jsonb
| інформаційні дані замовлення. |-
| API Event
| Технічна подія інтеграції. Створюється задача Product Sync. |-
| style="background:#f3e5f5;" | Фіолетовий
| #f3e5f5
| Ручна перевірка або нестандартний сценарій. |-
| AC-7
| Товар успішно передано. Подія
! |-
| Product
| Товар у K2 ERP. K2 ERP змінює товар. Статус K2 ERP
HOROSHOP_RETRY_BACKOFF_SECONDS=5
"price": 12999.00,
{| class="wikitable"
! Стан
response = await client.call_api(
! Призначення
timeout_seconds: int = 30
)
k2_product_id=product.id,
7. | style="background:#bbdefb;" | Блакитний
|-
| Синхронізується
| SYNCING
| Виконується API-запит до Horoshop. Компонент
6. |-
| total_amount
| numeric
| Сума. Поле
</pre>
Retry заборонений для:
product_status_service.set_status(
! SEO-опис
! Дата
! |-
| Оплата
| Статус і тип оплати. # Які типи оплат і доставок потрібно підтримати? |-
| Order Mapper
| Перетворює замовлення Horoshop у формат K2 ERP. API-запити виконуються до шлюзу:
}
== 26. Dashboard керівника ==
integration = horoshop_integration_repository.get_active(db)
{| class="wikitable"
4. "price": 12999.00,
payload=payload,
|-
| Товари
| Створення та оновлення версій товарів на Horoshop. def check_connection(self) -> "ConnectionStatus":
)
Order Import Worker
=== 15.2. Перевірка підключення ===
=== 23.5. оновлення версій статусу замовлення ===
v
=== 5.2. оновлення версій цін ===
Python-сервіс повинен:
! |-
| Клієнти
| Horoshop → K2 ERP
| Horoshop
| Створення клієнтів із замовлень. Перевіряє external_order_id. |-
| Замовлення
| Horoshop → K2 ERP
| Horoshop
| Обробка продажів. Колір
self.api_login = api_login
! | style="background:#c8e6c9;" | Норма
|-
| Потребують перевірки
| Замовлення з невідомими товарами або даними. |-
| Помилка API
| Код, текст, raw-відповідь без секретів. payload=payload,
платформа повинна підтримувати:
client = horoshop_client_factory.create(integration)
data = response.json()
</pre>
=== 13.1. Призначення ===
{| class="wikitable"
* отримати товар із K2 ERP;
* перевірити обов'язкові поля;
* визначити категорію;
* підготувати назву;
* підготувати SEO-опис;
* підготувати характеристики;
* підготувати фото;
* підготувати ціну;
* підготувати залишок;
* створити або оновити товар у Horoshop;
* зберегти external_product_id;
* записати результат у журнал. | ТТН передається в Horoshop. |-
| style="background:#ef9a9a;" | Червоний
| #ef9a9a
| Критична помилка. Тип
! |-
| customer_phone
| varchar
| Телефон. |-
| Customer
| Покупець. Точну схему передачі login/password, token або session потрібно звірити з актуальною документацією Horoshop API для конкретного методу. Критерій
|-
| API Layer
| REST API для команд із K2 ERP. |
| 5. |-
| payment_status
| varchar
| Статус оплати. щоб вони автоматизовано з'являлися та оновлювалися на сайті Horoshop. |-
| order_number
| Номер замовлення. SEO-опис
"external_order_id": external_order_id,
{| class="wikitable"
* SKU заповнений;
* назва заповнена;
* SEO-опис заповнений;
* категорія визначена;
* категорія Horoshop замаплена;
* ціна більша за 0;
* залишок не від'ємний;
* фото доступні;
* головне фото визначене;
* характеристики заповнені;
* бренд заповнений, якщо потрібен;
* штрихкод валідний, якщо застосовується для;
* товар не дублюється за SKU;
* товар не дублюється за external_product_id;
* текст опису не містить небезпечного HTML;
* активність товару відповідає правилам публікації. Поле
</pre>
! |-
| Stock
| Залишок товару.=== Етап 9. Production hardening ===
Приклад `.env`:
! За потреби оновлює статус у Horoshop.=== 29.5. Статуси та ТТН ===
payload=payload,
"name": "Іван Петренко",
=== Етап 6. Замовлення ===
{| class="wikitable"
external_order_id=external_order_id,
pass
"images": [
<syntaxhighlight lang="python">
"product_id": "K2-PRODUCT-000123",
class HoroshopClient:
== 34. Джерела ==
{| class="wikitable"
</pre>
! |-
| horoshop_product_id
| varchar
| ID товару Horoshop. |-
| Залишки
| оновлення версій доступної кількості. |-
| style="background:#eeeeee;" | Сірий
| #eeeeee
| Чернетка, приховано, скасовано або архів. | Retry, dashboard warning. SEO-опис
<pre>
! | style="background:#fff9c4;" | Жовтий
|-
| Потребує виправлення
| NEEDS_CORRECTION
| Не вистачає категорії, ціни, фото, опису або характеристик. |-
| style="background:#ffcc80;" | Помаранчевий
| #ffcc80
| Потрібна дія менеджера. | style="background:#c8e6c9;" | Норма
|-
| Нові замовлення
| Нові замовлення з Horoshop. class HoroshopSettings(BaseSettings):
=== 15.6. оновлення версій цін ===
</pre>
horoshop_order_repository.create(
! | style="background:#bbdefb;" | Блакитний
|-
| Виконано
| COMPLETED
| Замовлення завершено. |-
| entity_id
| uuid
| ID сутності. | Retry, queue, dashboard помилок. | style="background:#ef9a9a;" | Критично
|}
Python Horoshop Integration Service
щоб оперативно знаходити технічні помилки інтеграції. |}
! SEO-опис
retry_backoff_seconds: int = 5
=== 15.9. оновлення версій статусу замовлення ===
! SKU
* додати rate limiting;
* додати retry policy;
* додати dead letter queue;
* додати alerting;
* додати моніторинг;
* додати резервне копіювання;
* додати безпечне зберігання secret-ів. |-
| Audit Logger
| Запити, відповіді, помилки, статуси. Валідація, мапінг, черги, дедублікація
== 2. Область сценарії використання ==
db.commit()
|
| 3. Очікуваний результат
POST /api/v1/horoshop/prices/sync
|-
| AC-18
| Керівник відкриває dashboard. |}
я хочу бачити dashboard інтеграції,
# Чи K2 ERP виступає як головним джерелом товарів? |-
| Order Import Worker
| Імпортує замовлення. |-
| Синхронізація категорій
| Низький
| Довідник. pass
! # Чи потрібно синхронізувати фото? Де застосовується для
! Замовлення
<syntaxhighlight lang="python">
try:
product_id=product.id,
<pre>
{| class="wikitable"
hs_product.last_synced_price = product.price
)
<pre>
db=db,
<pre>
k2_status=order.status,
hs_product.error_message = str(exc)
<syntaxhighlight lang="python">
"external_order_id": "HS-ORDER-000123",
"payment_type": order_payload.get("payment", {}).get("type"),
== 1. Мета ==
POST /api/v1/horoshop/orders/import
{| class="wikitable"
=== 15.1. Створення інтеграції ===
<pre>
щоб контролювати помилки, продажі та реалізація, синхронізацію товарів і проблемні замовлення. | style="background:#eeeeee;" | Сірий
|-
| Очікує валідації
| PENDING_VALIDATION
| Товар очікує перевірки. # Чи потрібно синхронізувати акційні ціни?=== 22.7. horoshop_events ===
pass
|-
| AuthError
| Невірний API login або password. # Які поля товару обов'язкові для MVP?== 5. Основні бізнес-сценарії ==
|-
| style="background:#c8e6c9;" | Зелений
| #c8e6c9
| Успішно: синхронізовано, опубліковано, імпортовано, виконано. |-
| Передача ТТН
| Номер замовлення, ТТН, служба доставки. Назва
pass
* external_order_id;
* номер замовлення;
* дату замовлення;
* телефон покупця;
* список товарів;
* SKU кожного товару;
* кількість;
* ціну;
* суму;
* тип оплати;
* статус оплати;
* тип доставки;
* адресу або відділення;
* чи не імпортоване замовлення раніше;
* чи існують товари в K2 ERP;
* чи достатньо залишку для резервування. Критерій
! |-
| PriceError
| Некоректна ціна. |-
| Product Sync Worker
| Передає товари. |-
| ValidationError
| Некоректний товар або замовлення. HTML
if not validation_result.is_valid:
! | Check-connection і alert адміністратору. |}
! |-
| AC-10
| Залишок став 0. |-
| sync_orders_enabled
| boolean
| Імпорт замовлень. |}
=== Етап 4. Товари ===
! Очікуваний результат
Для реалізації задачі необхідно отримати:
</div>
! | style="background:#c8e6c9;" | Зелений
|-
| Опубліковано
| PUBLISHED
| Товар доступний на сайті. Поле
Функції API викликаються через URL:
Перед передачею товару в Horoshop платформа повинна перевірити:
"is_active": true
== 32. Ризики ==
"attributes": {
{| class="wikitable"
}
{| class="wikitable"
=== 12.1. Загальна схема ===
POST /api/v1/horoshop/categories/sync
=== 29.3. Ціни та залишки ===
pass
=== 22.2. horoshop_products ===
! Він повинен потрапляти у статус NEEDS_CORRECTION. |-
| error_message
| text
| Остання помилка. Джерело
)
async with httpx.AsyncClient(timeout=self.timeout_seconds) as client:
7. | Маскування телефону/email. |-
| Category Mapper
| Мапить категорії. # Чи потрібно синхронізувати декілька складів? |-
| idempotency_key
| Ключ повторної обробки. |-
| ConnectionError
| API Horoshop недоступне. |}
)
! |}
"warranty": "12 місяців"
async def sync_stock_to_horoshop(product_id: str, db: "Session") -> None:
},
6. | Версіонування клієнта і contract-тести.<pre>
* створити FastAPI-проєкт;
* налаштувати PostgreSQL;
* створити моделі інтеграцій, товарів, замовлень, мапінгів, подій;
* налаштувати Alembic;
* реалізувати healthcheck. | Дубль не створюється. Джерело істини
raise HoroshopApiError(str(data))
=== 23.2. Синхронізація товару ===
=== 5.6. Обмін клієнтами ===
</pre>
|-
| SKU-001
| Смартфон Example X
| style="background:#ffcc80;" | Потребує виправлення
| Не замаплена категорія
| Заповнити мапінг
|-
| SKU-002
| Навушники Example Air
| style="background:#ef9a9a;" | Помилка
| Фото недоступне
| Перевірити URL фото
|-
| SKU-003
| Кавоварка Example
| style="background:#ffcc80;" | Потребує виправлення
| Немає ціни
| Заповнити ціну
|}
response = await client.post(url, json=request_payload)
response=response,
Інтернет-магазин Horoshop
"barcode": "4820000000000",
<pre>
"total_amount": 12999.00,
{| class="wikitable"
def update_order_status(self, order_id: str, payload: dict) -> "OrderStatusResponse":
|-
| 07.05.2026
| HS-ORDER-001
| Іван Петренко
| style="background:#ffcc80;" | Потребує перевірки
| Не знайдено SKU
| Прив'язати товар
|-
| 07.05.2026
| HS-ORDER-002
| Олена Сидоренко
| style="background:#ef9a9a;" | Помилка
| Не створено клієнта
| Перевірити телефон/email
|-
| 07.05.2026
| HS-ORDER-003
| ТОВ «Альфа»
| style="background:#ffcc80;" | Потребує перевірки
| Невідомий тип доставки
| Заповнити мапінг доставки
|}
== 31. Етапи реалізації ==
</pre>
* зберігання API login/password тільки у secret storage;
* заборону логування паролів;
* HTTPS для всіх API-запитів;
* перевірку SSL;
* рольову модель доступу;
* окремі права на синхронізацію товарів;
* окремі права на зміну цін;
* окремі права на зміну залишків;
* окремі права на імпорт замовлень;
* окремі права на оновлення версій статусів;
* журнал усіх дій;
* маскування персональних даних покупців;
* захист від дублювання замовлень;
* контроль доступу до raw API payload. | K2 ERP
| ERP керує виконанням замовлень. |-
| Horoshop Client
| Python-клієнт для Horoshop API.<syntaxhighlight lang="python">
== 12. технічна архітектура рішення для бізнесу ==
[[Категорія:WMS]]
'''Критично критично:''' інтеграційні функції ERP не повинна створювати дублікати товарів. |-
| direction
| varchar
| IMPORT або EXPORT. |-
| delivery_address
| text
| Адреса доставки. client = horoshop_client_factory.create(integration)
{{DISPLAYTITLE:Технічне завдання: Інтеграція з Horoshop / Хорошоп для Python}}
status="NEEDS_CORRECTION",
"amount": 12999.00
error=str(exc),
|-
| Перевірка підключення
| URL, результат, час, без пароля. Статус
errors=validation_result.errors,
! Worker передає залишок у Horoshop. |-
| k2_status
| varchar
| Статус K2 ERP. |-
| оновлення версій статусів замовлень
| Високий
| Впливає на клієнтський досвід. db=db,
|-
| AC-1
| Адміністратор створює інтеграцію Horoshop. |-
| horoshop_site_id
| ID сайту, якщо магазинів декілька. | API-запити, черги, обробка. Колір
! |-
| AC-17
| Статус не замаплений. |-
| event_type
| varchar
| Тип події. | K2 ERP / служби доставки
| Нова пошта, Укрпошта тощо. # Чи потрібно передавати ТТН у Horoshop? SEO-опис
=== 7.4. Керівник ===
</pre>
__TOC__
<pre>
2. Задача
"city": "Київ",
horoshop_status = status_mapping_repository.map_k2_to_horoshop(
! * Сторінка Horoshop API. |}
POST /api/v1/horoshop/products/{product_id}/sync
audit_logger.log(
Як менеджер товарного каталогу,
== 23. Приклад Python-логіки ==
"service": "nova_poshta",
|-
| id
| uuid
| ID замовлення. SEO-опис
! |-
| ImageError
| Фото недоступне. №
|-
| Імпорт замовлень
| Критичний
| Впливає на продажі та реалізація. | Він переходить у NEEDS_CORRECTION. |-
| style="background:#fff9c4;" | Жовтий
| #fff9c4
| Очікування дії або оплати. | Заблокувати передачу товару. Критерій
new_status="SYNCED",
{| class="wikitable"
Коли ціна змінюється в K2 ERP, Python-сервіс повинен:
</syntaxhighlight>
|
-
|
AC-13
|
-
|
created_at
|
timestamp
|
Дата створення. Тип помилки
[[Категорія:CRM]]
|-
| id
| uuid
| ID інтеграції. Worker регулярно запитує нові замовлення Horoshop.[[Категорія:Python]]
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
v
* отримати статус замовлення з K2 ERP;
* замапити його у статус Horoshop;
* передати статус у Horoshop;
* передати ТТН / ЕН, якщо виступає як;
* передати коментар менеджера, якщо підтримується;
* записати подію в журнал. Показник
entity_type="order",
"order_id": hs_order.external_order_id,
== 30. MVP ==
],
! Призначення
! |-
| k2_product_id
| ID товару в K2 ERP. | платформа передає новий залишок. Коментар
я хочу бачити журнал API-запитів,
db=db,
== 3. Основні функції ERP інтеграції ==
"sku": "SKU-001",
"order_number": "000123",
verify_ssl: bool = True
</syntaxhighlight>
"status": "paid",
GET /api/v1/horoshop/dashboard?date_from=2026-05-01&date_to=2026-05-31
{
=== 7.3. Менеджер продажів ===
)
product = product_repository.get_by_id(db, product_id)
if existing:
=== 29.2. Товари ===
K2 ERP виступає як головним джерелом операційного статусу. |-
| is_active
| boolean
| Активність. |-
| AC-19
| виступає як помилки синхронізації. |}
HOROSHOP_LANGUAGE=ua
event_type="HOROSHOP_PRODUCT_SYNCED",
api_login: str
{| class="wikitable"
|
| 1. Якщо товар не знайдено — статус NEEDS_REVIEW.== 29. Acceptance Criteria ==
}
|-
| Чернетка
| DRAFT
| Товар створений у K2 ERP, але ще не готовий до передачі. | style="background:#bbdefb;" | Блакитний
|-
| Синхронізовано
| SYNCED
| Товар успішно передано або оновлено. |-
| is_active
| boolean
| Активність. request_payload ["password"] = self.api_password
* неправильного API login/password;
* товару без SKU;
* товару без категорії;
* товару без ціни;
* товару без фото;
* незамапленого статусу;
* дубліката замовлення;
* помилки бізнес-логіки K2 ERP. |-
| payload
| jsonb
| Технічні інформаційні дані. | style="background:#fff9c4;" | Жовтий
|-
| Оплачено
| PAID
| Оплата отримана. 4. # Чи потрібно створювати категорії в Horoshop автоматизовано? |-
| status
| varchar
| Статус синхронізації. * Центр допомоги Horoshop. Призначення
try:
! |-
| Товари
| K2 ERP → Horoshop
| K2 ERP
| Публікація каталогу. Окремо варто відзначити клієнтів або замовлень. |-
| status
| varchar
| Статус K2 ERP. function="catalog/import/",
</syntaxhighlight>
=== 15.10. Передача ТТН / ЕН ===
"description": "SEO-опис товару для сайту.",
[[Категорія:Технічні завдання]]
<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">
[[Категорія:API]]
! |-
| sync_statuses_enabled
| boolean
| оновлення версій статусів. |-
| Характеристики
| Передача атрибутів товарів. №
"payment_status": order_payload.get("payment", {}).get("status"),
"email": "client@example.com"
4. * Документація K2 ERP щодо товарів, залишків, цін і замовлень. |}
! | Він не передається і показується менеджеру. | style="background:#e3f2fd;" | інформаційні матеріали
|-
| Синхронізовано товарів
| Товари успішно передані. |}
K2 ERP / CRM / WMS
5. Worker викликає Horoshop API. |-
| AC-12
| Замовлення вже імпортоване. Колір
validation_result = product_validator.validate(product)
"comment": "Зателефонувати перед відправкою",
|-
| Horoshop Integration
| конфігурація підключення до конкретного сайту. SEO-опис
integration = horoshop_integration_repository.get_active(db)
=== Етап 5. Ціни та залишки ===
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
== 24. Обробка помилок ==
{| class="wikitable"
Коли змінюється залишок на складі, Python-сервіс повинен:
pass
15.5. Масова синхронізація товарів
12.2. Основні компоненти Python-сервісу
stock=available_stock,
def update_product_price(self, product_id: str, payload: dict) -> "PriceResponse":
10. Статуси замовлень
if response.status_code >= 400:
19. Валідація замовлень
},
Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker. |-
|
name
|
varchar
|
Замовлення потрапляє в ручну перевірку. |-
|
AC-14
|
-
|
Category
|
Dashboard, товари, замовлення. |-
|
k2_category_id
|
varchar
|
Manual review. |-
|
DuplicateOrderError
|
-
|
Продаж відсутнього товару
|
Зупинити інтеграцію, повідомити адміністратора. |-
|
horoshop_product_id
|
style="background:#c8e6c9;" | Норма
|
| Оновлено залишків
|
-
|
last_synced_price
|
numeric
|
-
|
Dashboard API
|
інформаційні дані для контролю інтеграції. },
"total_amount": order_payload.get("total"),
=== 21.3. Логіка імпорту замовлень ===
"order_number": order_payload.get("number"),
)
"order_date": "2026-05-07T12:10:00+03:00",
=== 5.4. Імпорт замовлень ===
HOROSHOP_API_PASSWORD=********
</div>
Retry дозволений для:
1. |-
| horoshop_category_id
| varchar
| Категорія Horoshop. | NEEDS_CORRECTION / NEEDS_REVIEW. |-
| Категорії
| Синхронізація структури каталогу. "status": "IMPORTED",
Як комірник або WMS,
! Як менеджер продажів,
except Exception as exc:
* інтернет-магазинів на Horoshop;
* компаній, які ведуть обліковий облік у K2 ERP;
* компаній, які мають CRM і хочуть імпортувати замовлення з сайту;
* складів, які мають оновлювати залишки на сайті;
* менеджерів продажів;
* e-commerce відділів;
* компаній із кількома інтернет-магазинами;
* компаній, які продають через сайт і маркетплейси одночасно. # Чи потрібно підтримувати кілька сайтів Horoshop? |-
| Price Engine
| Формує ціни для сайту. |-
| Ціни
| оновлення версій базових, акційних, роздрібних цін. | style="background:#ffcc80;" | Помаранчевий
|-
| Готовий до синхронізації
| READY_TO_SYNC
| Товар можна передавати. |-
| Delivery
| Доставка. |-
| ТТН / ЕН
| K2 ERP → Horoshop
| K2 ERP / доставка
| Інформування покупця про доставку. |-
| base_url
| varchar
| URL API. |}
k2_product_id=product.id,
"items": [
== 7. User Story ==
import httpx
{| class="wikitable"
|-
| AC-4
| Товар має всі обов'язкові поля. |-
| Персональні інформаційні дані в логах
| Ризик витоку даних.</syntaxhighlight>
"delivery": {
HOROSHOP_RETRY_COUNT=3
client = horoshop_client_factory.create(integration)
"brand": "Example",
|-
| sku
| базовий артикул. |-
| sku
| varchar
| Артикул.=== 21.4. Пріоритети задач ===
{| class="wikitable"
def create_or_update_product(self, payload: dict) -> "ProductResponse":
"amount": 12999.00
payload = {
def update_product_stock(self, product_id: str, payload: dict) -> "StockResponse":
!</div>
order = k2_order_repository.get_by_id(db, k2_order_id)
|-
| AC-8
| У K2 ERP змінилась ціна. # Чи потрібно синхронізувати SEO-поля? |-
| Attribute Mapper
| Мапить характеристики. |}
=== 5.5. оновлення версій статусу замовлення ===
event_type="HOROSHOP_ORDER_STATUS_EXPORTED",
db=db,
Див. 35. так само
|
Що зберігати
7.2. складський облік
"color": "Black",
payload=order_payload,
hs_product.status = "SYNCING"
13. Horoshop API Client
1. |-
|
payment_type
|
varchar
|
Тип оплати. Статус
horoshop_product_repository.set_sync_error(
Етап 2. Базовий Python-сервіс
23.1. Базовий Horoshop Client
22.6. horoshop_status_mappings
15.3. Синхронізація категорій
v
|
SEO-опис
26.2. Приклад dashboard
|
Імпорт у K2 ERP
11. Єдина логіка кольорівPOST /api/v1/horoshop/integrations
HOROSHOP_BASE_URL=https://example.com/api/
k2_product_id=product.id,
| -
|
updated_at
|
timestamp
|
}
6. Напрям
"customer": {
for order_payload in orders:
client = horoshop_client_factory.create(integration)
|
K2 ERP
|
style="background:#ef9a9a;" | Червоний
|
|
# Як часто оновлювати залишки?
- реалізувати call_api;
- реалізувати check_connection;
- реалізувати get_orders;
- реалізувати update_order_status;
- реалізувати create_or_update_product;
- реалізувати update_price;
- реалізувати update_stock;
- реалізувати обробку помилок. |-
|
updated_at
|
timestamp
|
-
|
customer_name
|
varchar
|
Покупець. Причина
payload=response,
horoshop_product_repository.update_stock_sync_result(
7.5. Адміністратор
|
-
|
entity_type
|
varchar
|
-
|
old_status
|
varchar
|
-
|
оновлення версій залишків
|
Критичний
|
-
|
оновлення версій статусу
|
Старий статус, новий статус. Кожен товар, замовлення, клієнт ERP, зміна ціни, залишку, статусу і API-запит повинні мати внутрішній ID, external_id, журнал подій і захист від повторної обробки.
|
Очікуваний результат
pass
pass
response = await client.call_api(
v
},
=== 23.4. оновлення версій залишку ===
! Заборонено зберігати їх у коді, Git, frontend-змінних або відкритих логах. | Він бачить товари, замовлення, ціни, залишки, помилки. # Чи потрібно приховувати товар при нульовому залишку? Враховуються резерви та страховий залишок. |-
| tracking_number
| varchar
| ТТН / ЕН. |-
| price
| numeric
| Ціна. | style="background:#ffcc80;" | Помаранчевий
|-
| Підтверджено
| CONFIRMED
| Менеджер підтвердив замовлення. |-
| AC-5
| Товар не має SKU. |-
| AC-2
| Адміністратор перевіряє підключення. Ключ
"customer_email": order_payload.get("customer", {}).get("email"),
payload={
"horoshop_status": order_payload.get("status"),
"horoshop_category_id": "h-category-001",
'''Управлінський результат:''' менеджер і керівник повинні бачити, які товари синхронізовані з Horoshop, які мають помилки, які замовлення імпортовані, які статуси передані, які залишки не оновились, які товари не мають фото, категорії або характеристик. |-
| order_number
| varchar
| Номер замовлення. Як зменшити
async def export_order_status_to_horoshop(k2_order_id: str, db: "Session") -> None:
"customer_phone": order_payload.get("customer", {}).get("phone"),
db=db,
"old_price": 13999.00,
|-
| Невірні API-доступи
| інтеграційні функції ERP не працюватиме. №
== 22. Модель даних ==
=== 26.4. Проблемні замовлення ===
"tracking_number": order.tracking_number,
! Очікуваний результат
from pydantic_settings import BaseSettings
== 25. Retry-логіка ==
<pre>
entity_id=hs_order.id,
платформа повинна логувати:
! Поле
! |-
| created_at
| timestamp
| Дата. SEO-опис
{| class="wikitable"
Python-сервіс повинен:
"status": horoshop_status,
'''Критично критично:''' логін і пароль API Horoshop потрібно зберігати тільки у secret storage або в зашифрованому вигляді. | Статус стає IMPORTED.<pre>
* реалізувати dashboard API;
* реалізувати список проблемних товарів;
* реалізувати список проблемних замовлень;
* реалізувати список помилок API;
* реалізувати експорт, якщо потрібно. | style="background:#ffcc80;" | Потрібна дія
|-
| Помилки API
| Технічні помилки інтеграції. |-
| Product Variant
| Варіант / модифікація товару. | Він передається в Horoshop. | Horoshop / K2 ERP
| Залежить від бізнес-логіки. Поле
retry_count: int = 3
"https://example.com/images/sku-001-2.jpg"
== 33. Відкриті питання ==
)
POST /api/v1/horoshop/stocks/sync
entity_id=hs_product.id,
},
! Ризик
"delivery_service": order_payload.get("delivery", {}).get("service"),
== 16. Приклад запиту на синхронізацію товару ==
pass
{| class="wikitable"
response = await client.call_api(
=== 26.1. Основні KPI ===
}
2.=== 23.3. Імпорт замовлень ===
|-
| AC-15
| K2 ERP змінила статус замовлення. | Передати менеджеру каталогу. Тип
=== 29.1. інтеграційні функції ERP ===
"quantity": available_stock,
! |-
| UnknownStatusError
| Статус не замаплений. SEO-опис
Horoshop API Client — це Python-клас або пакет, який інкапсулює роботу з API конкретного сайту Horoshop. warehouse_id=product.default_warehouse_id,
response = await client.call_api(
| -
|
api_password_encrypted
|
text
|
style="background:#c8e6c9;" | Зелений
|
| Комплектується
|
PROCESSING
|
-
|
k2_order_id
|
uuid
|
-
|
barcode
|
Таблиця status_mappings і ручна перевірка. Значення
</syntaxhighlight>
if not hs_order:
"sku": product.sku,
Сервіс повинен забезпечити:
raise HoroshopApiError(response.text)
return
| style="background:#fff9c4;" | Жовтий
|
| Імпортується
|
IMPORTING
|
-
|
AttributeMappingError
|
-
|
CategoryMappingError
|
}
26.3. Проблемні товари
|
Очікуваний результат
|
| Категорії
|
K2 ERP → Horoshop або Horoshop → K2 ERP
|
Залежить від проєкту
|
Єдина структура каталогу.
{
"k2_order_id": k2_order.id,
|
Дія системи
6. Основні сутності
data={
7.1. Менеджер товарного каталогу
request_payload ["login"] = self.api_login
я хочу вести товари в K2 ERP,
|
| Нове
|
NEW
|
Замовлення отримано з Horoshop. api_password: str
except Exception as exc:
|
Повернути існуюче замовлення. |-
|
api_login_encrypted
|
text
|
-
|
Синхронізація товарів
|
Середній
|
-
|
external_order_id
|
ID замовлення Horoshop. Як керівник,
|
Перевести в ручну перевірку. horoshop_order_repository.create_error_record(
- повна технічна підтримка всіх API-методів Horoshop;
- складна SEO-оптимізація товарів;
- автоматичне створення маркетингових акцій;
- складний UI керування каталогом;
- інтеграційні функції ERP з усіма маркетплейсами;
- автоматичне виправлення товарних даних;
- ML-мапінг категорій і характеристик. Статус
щоб покупці не замовляли товар, якого немає. ! {| class="wikitable"
Horoshop API Client
я хочу, щоб залишки автоматизовано оновлювалися на сайті,
def authenticate(self) -> "AuthResult":
}
|
клієнт ERP
|
=== 29.4. Замовлення ===
22.3. horoshop_orders
integration = horoshop_integration_repository.get_active(db)
! Дія
Python-сервіс повинен:
"name": "Смартфон Example X 128GB",
[[Категорія:E-commerce]]
! Код
! external_order_id=external_order_id,
* реалізувати Product Mapper;
* реалізувати Category Mapper;
* реалізувати Attribute Mapper;
* реалізувати валідацію;
* реалізувати Product Sync Worker. |-
| Retry
| Причина, кількість спроб, результат. | Помилки мапінгу, неповні товари, review. K2 ERP / Dashboard / Менеджери
* реалізувати Price Engine;
* реалізувати Stock Engine;
* реалізувати чергу оновлення версій;
* реалізувати історію змін. |-
| order_id
| uuid
| Замовлення. Товар проходить валідацію. # Чи потрібно імпортувати категорії з Horoshop? Результат записується в журнал. | style="background:#c8e6c9;" | Норма
|-
| Помилки товарів
| Товари з помилками валідації або API. | style="background:#eeeeee;" | Сірий
|-
| Помилка синхронізації
| SYNC_ERROR
| API повернув помилку або товар не передано. | style="background:#ef9a9a;" | Червоний
|}
=== Етап 8. Dashboard та аудит ===
=== 22.4. horoshop_order_items ===
{| class="wikitable"
)
K2 ERP виступає як головним джерелом товарного каталогу. |-
| Синхронізація товару
| SKU, статус, відповідь API. SEO-опис
existing = horoshop_order_repository.get_by_external_id(
url = f"{self.base_url}/{function.strip('/')}/"
request_payload = payload or {}
integration = horoshop_integration_repository.get_active(db)
20.1. Дедублікація товарівДо MVP входить:
| -
|
StockError
|
style="background:#c8e6c9;" | Зелений
|
| Відправлено
|
SHIPPED
|
-
|
external_order_id
|
varchar
|
API error, sync error. | style="background:#bbdefb;" | Блакитний
|
| Очікує оплати
|
WAITING_PAYMENT
|
style="background:#bbdefb;" | Блакитний
|
| Імпортовано
|
IMPORTED
|
Передати менеджеру каталогу. Поле
)
product_id=product_id,
|
Помилка
<syntaxhighlight lang="json">
db.commit()
щоб опрацьовувати всі продажі та реалізація в єдиній системі. Критерій
"category_id": "phones",
|
| id
|
uuid
|
-
|
AC-9
|
У K2 ERP змінився залишок. HTTP/HTTPS API Horoshop
async def call_api(self, function: str, payload: dict | None = None) -> dict:
entity_type="product",
|
|
}
5.1. Передача товарів з K2 ERP у Horoshop
hs_product.status = "SYNCED"
22.1. horoshop_integrations
20. Дедублікація
function="orders/update_status/",
|
| id
|
uuid
|
-
|
k2_product_id
|
uuid
|
ID товару K2 ERP. Критерій
finally:
hs_product.last_synced_stock = product.available_stock
hs_product.horoshop_product_id = response.get("product_id") or hs_product.horoshop_product_id
SEO title: Технічне завдання: Інтеграція з Horoshop / Хорошоп для Python
SEO keywords: Python, Horoshop, Хорошоп, Horoshop API, Хорошоп API, інтеграція інтернет-магазину, K2 ERP, CRM, WMS, товари, замовлення, ціни, залишки, FastAPI, ecommerce
</noinclude>
{{SEO
Шаблон для службового SEO-опису сторінки.
}}
4. Передумови15. API Python-сервісуasync def sync_product_to_horoshop(product_id: str, db: "Session") -> None:
| -
|
name
|
varchar
|
-
|
raw_response
|
jsonb
|
Відповідь API.== 8. Напрями синхронізації ==
"warehouse": "Відділення №1",
|
| Активні товари
|
12 450
|
інформаційні матеріали
|
| Синхронізовано
|
12 100
|
Норма
|
| Потребують виправлення
|
180
|
Потрібна дія
|
| Помилки синхронізації
|
24
|
Критично
|
| Оновлено цін сьогодні
|
820
|
Норма
|
| Оновлено залишків сьогодні
|
1 540
|
Норма
|
| Нові замовлення
|
42
|
Увага
|
| Імпортовано замовлень
|
39
|
Норма
|
| Замовлення на перевірці
|
3
|
Потрібна дія
|
)
)
|
-
|
customer_email
|
varchar
|
Email. async def import_horoshop_orders(db: "Session") -> None:
<syntaxhighlight lang="python">
Horoshop виступає як джерелом замовлень, які створюють покупці на сайті. |-
|
Незамаплений статус
|
платформа повертає успішний або помилковий статус. |-
|
Створення клієнта
|
Замовлення переходить у NEEDS_REVIEW. |}
"raw_payload": order_payload,
<syntaxhighlight lang="json">
"memory": "128GB",
hs_product = horoshop_product_repository.get_or_create(
|
| id
|
uuid
|
Воно імпортується в K2 ERP. SEO-опис
9. Статуси товарів
20.2. Дедублікація замовлень
def create_or_update_category(self, payload: dict) -> "CategoryResponse":
15.11. Dashboard
|
Нові замовлення, очікування оплати. K2 ERP отримує статус. |}
3. Тому для кожного сайту потрібно зберігати власний base_url, логін, пароль, статус інтеграції, правила синхронізації та технічний журнал.
|
|
|
|
|