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

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

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

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

!; | style="background:#ef9a9a;" | Червоний |}

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

я хочу один раз вести товар у K2 ERP, Retry заборонений для:

db.commit()

!; |- | Price Engine | Формує ціну по правилах.; |- | ValidationError | Некоректний товар або замовлення.; |- | Attribute Mapper | Мапить характеристики.; # Чи потрібно імпортувати замовлення з Prom?; |- | k2_order_id | uuid | ID замовлення K2 ERP.; |}

13.4. Hotline Client

Управлінський результат: менеджер і керівник повинні бачити, які товари синхронізовані, які мають помилки, які замовлення отримані, які ціни та залишки передані, які товари не пройшли модерацію, які фіди сформовані, які ставки Hotline активні та які канали продажів дають результат.; |- | marketplace | varchar | PROM, ROZETKA, HOTLINE.; Показник

payload=response,

Як керівник,

if not validation_result.is_valid:

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

pass
async def import_orders(self, filters: dict) -> list [dict]:
mp_product.status = "SYNC_ERROR"

платформа повинна не допускати дублювання товарів і замовлень.; |- | Зміна ціни | Стара ціна, нова ціна, канал.; ключовий тип інтеграції |- | Чернетка | DRAFT | Товар створений у K2 ERP, але ще не готовий до передачі.; № !; | Потрібно звірити актуальний API продавця.; | API-токени керуються в кабінеті компанії.; |- | errors_count | integer | Кількість помилок.; | style="background:#fff9c4;" | Жовтий |- | Опубліковано | PUBLISHED | Товар доступний покупцям.; |}

@abstractmethod

!; Тип

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

</category>
audit_logger.log(
db.commit()

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

Критично істотно: товар без категорії, фото, ціни або обов'язкових характеристик не повинен автономно передаватись у канали.; | платформа передає новий залишок.; Основні сценарії

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

POST /api/v1/marketplaces/prices/sync |- | marketplace | Джерело замовлення.; Worker передає товар через API або додає у фід.; |- | marketplace_status | varchar | Оригінальний статус.; |- | Token недійсний | API не функціонує.; |}

20.2. marketplace_products

!; |- | external_order_id | string | ID замовлення в маркетплейсі.;== 15.; Приклад запиту на синхронізацію товару ==

v
)

!; | Заблокувати синхронізацію ціни.; |- | description | text | характеристика.; |- | Некоректний XML | Hotline не прийме фід.; !; |- | customer_name | string | ПІБ покупця.; !; |- | raw_payload | jsonb | інформаційні дані замовлення.; | Черги, API-запити, статуси обробки.; :contentReference [oaicite:2]{index=2}

Python Sync Workers

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

|- | На модерації | MODERATION | Товар очікує перевірки маркетплейса.; |- | category_id | string | Категорія K2 ERP.; Тип помилки

8.1.; конфігурація інтеграції

self.api_token = api_token

Python-сервіс повинен: !; |- | base_url | varchar | URL API.; @abstractmethod

  • неправильного API token;
  • помилок категорії;
  • помилок характеристик;
  • товару без фото;
  • товару без ціни;
  • дубліката замовлення;
  • відхиленого товару без виправлення даних.; | style="background:#bbdefb;" | Блакитний

|- | Синхронізується | SYNCING | Виконується API-запит або генерація фіду.; Очікуваний результат

@abstractmethod

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

"total_amount": order_payload.get("total_amount"),

POST /api/v1/marketplaces/stocks/sync !; |- | style="background:#fff9c4;" | Жовтий | #fff9c4 | Очікування дії або модерації.; |- | marketplace | varchar | PROM або ROZETKA.; №

k2_order = k2_order_service.create_from_marketplace(order_payload)

12.; технічна архітектура рішення для бізнесу

Зміна API - Помилки категорій Товари не проходять модерацію.; Статус
external_order_id=external_order_id,
<vendor>Example</vendor>
marketplace enum UNKNOWN_STATUS і ручний мапінг.; |- marketplace varchar - Prom Adapter Робота з API Prom.ua.; характеристика


Див.; 33.; додатково

}

<item>

створює його в K2 ERP виступає ключовою рисою 3.; {| class="wikitable"

external_order_id = order_payload ["external_order_id"]
- Червоний #ef9a9a Критична помилка або відхилення.; характеристика
pass
sku string - AC-21 - sync_products_enabled boolean Синхронізація товарів.;
"sku": "SKU-001",

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

- idempotency_key - marketplace_category_id string - customer_phone string Мапінг категорій і dashboard проблем.; POST /api/v1/marketplaces/orders/{order_id}/update-status

K2 ERP / Dashboard / Менеджери

; * отримати Prom API token;
  • отримати Rozetka API credentials;
  • отримати Hotline feed specs;
  • отримати Hotline bid API token, якщо потрібно;
  • перевірити тестові запити;
  • визначити список категорій;
  • визначити правила мапінгу.; Критерій
- file_id uuid - Order - Feed XML/YML/CSV-фід для Hotline або Rozetka.; характеристика
Зелений #c8e6c9 Успішно: синхронізовано, опубліковано, імпортовано, виконано.; K2 ERP отримує статус.; Тип

1.; Мета

pass
"category_id": "phones",

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

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

Заблокувати передачу товару.; |- error_message text - AC-10 - feed_public_url string Ні Вони підсвічуються червоним.; |- AC-3 Адміністратор створює інтеграцію Hotline.; Вони підсвічуються помаранчевим.; |- AC-15 - AC-8 Повернути існуюче замовлення.; Критерій

"raw_payload": order_payload,
1.; |-
marketplace enum Так - AC-17 У товарі некоректний XML-символ.; характеристика
API Layer інтеграційні функціональні можливості зберігається і проходить check_connection.; |- format varchar XML, YML, CSV.; Стан
db=db,

async def import_marketplace_orders(marketplace: str, db: "Session") -> None:

pass

async def sync_product_to_marketplaces(product_id: str, channels: list [str], db: "Session") -> None: 5.; | style="background:#ef9a9a;" | Критично

Нові замовлення style="background:#c8e6c9;" | Зелений
Комплектується PROCESSING - sync_products_enabled boolean Так Чи синхронізувати товари.; Поле
!; |-
| password_encrypted
| text
| Зашифрований password.; | style="background:#c8e6c9;" | Норма
|-
| Проблемні фіди
| Помилки XML/YML.; |-
| entity_id
| uuid
| ID сутності.; Prom та Rozetka мають API для продавців, а Hotline у базовому сценарії функціонує через товарні фіди, вимоги до прайсів і окремий API керування ставками.; | API error, rejected, sync error.; KPI
  • визначити активні канали для товару;
  • застосувати правила націнки;
  • застосувати промо-ціну, якщо є собою;
  • застосувати мінімальну ціну;
  • сформувати зміну ціни;
  • передати зміну в Prom;
  • передати зміну в Rozetka;
  • оновити XML/YML-фід Hotline;
  • зберегти історію зміни ціни.;=== 27.3.; Ціни та залишки ===
  • timeout;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасової недоступності API;
  • тимчасової помилки імпорту замовлень;
  • тимчасової помилки актуалізація ціни;
  • тимчасової помилки актуалізація залишку;
  • тимчасової помилки генерації фіду.; |-
Bid Ставка Hotline по товарній пропозиції.; Критерій

from abc import ABC, abstractmethod

4.; |-

AttributeMappingError - marketplace_product_id ID товару в каналі.; Канал
marketplace_order_repository.create(
async def update_stock(self, external_product_id: str, stock: dict) -> dict:

щоб товари були актуальні за ціною, наявністю і характеристиками.; |-

AC-20 - актуалізація ставок Hotline Середній - sync_stocks_enabled boolean Синхронізація залишків.; характеристика

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

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

Активні товари - sync_stocks_enabled boolean Так Чи синхронізувати залишки.; Задача

7.1.; Товари

},
product = product_repository.get_by_id(db, product_id)
existing = marketplace_order_repository.get_by_external_id(
async def get_bids(self) -> list [dict]:

Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker, XML/YML generator.; | style="background:#fff9c4;" | Жовтий

Потребує виправлення NEEDS_CORRECTION Не вистачає фото, категорії, характеристик або опису.;=== 14.1.; Створення інтеграції ===
pass

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

class RozetkaClient(MarketplaceClient):

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

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

)

щоб вона автономно оновилась у всіх підключених каналах.; |-

created_at timestamp style="background:#eeeeee;" | Сірий
Помилка ERROR - Продаж відсутнього товару }
"rozetka": "rozetka-category-id",

27.5. Hotline

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

Як маркетолог,

- ApiError API повернув помилку.; Назва
v
!; |-
| Order Status
| Статус замовлення.; Обов'язковість

<syntaxhighlight lang="python">
!; | Статус стає SYNCED або PUBLISHED.; "customer_name": order_payload.get("customer_name"),

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

!; актуалізація K2 ERP
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
GET /api/v1/marketplaces/dashboard?date_from=2026-05-01&date_to=2026-05-31
class MarketplaceClient(ABC):

{| class="wikitable"

 @abstractmethod
{| class="wikitable"
!; !; !; | external_order_id + marketplace unique constraint.; |-
| external_order_id
| ID замовлення в маркетплейсі.; Де застосовується
=== 24.1.; Основні KPI ===
!; | Архів, hidden, cancelled.; :contentReference [oaicite:1]{index=1}
|-
| integration_name
| string
| Так
| Назва інтеграції.; | style="background:#c8e6c9;" | Норма
|-
| На модерації
| Товари очікують перевірки.; |-
| DuplicateOrderError
| Замовлення вже імпортовано.; |-
| AC-13
| Rozetka має нове замовлення.; | Ручна перевірка, нестандартний фід.; Коментар

* повна супровід всіх API-методів Prom;
* повна супровід всіх API-методів Rozetka;
* повна автоматизація процесів модерації;
* автоматичне виправлення характеристик;
* складна аналітичні інструменти реклами;
* повна інтеграційні функціональні можливості з кабінетами маркетплейсів;
* ML-мапінг категорій;
* автоматичне створення рекламних кампаній.; характеристика
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
!; | Замовлення переходить у NEEDS_REVIEW.; # Як часто оновлювати залишки?; Товари, ціни, залишки, статуси
 )
 async def update_price(self, external_product_id: str, price: dict) -> dict:
 |
 | 2.; характеристика
 entity_type="product",
{| class="wikitable"
|-
| AC-5
| Товар має всі обов'язкові поля.; характеристика
!; Якщо товар не знайдено  статус NEEDS_REVIEW.; |-
| customer_email
| string
| Email.; |-
| Marketplace Product
| Товар у конкретному каналі.; | Це більше price-comparison / рекламний канал, ніж класичний marketplace.; | Dashboard, список товарів, список замовлень.; Перевіряє external_order_id.; |-
| Audit Logger
| Запити, відповіді, помилки, статуси.; !; |-
| external_order_id
| varchar
| ID замовлення в каналі.; async def update_bid(self, offer_id: str, bid_value: int) -> dict:

* централізовану картку інтеграції по кожному каналу;
* синхронізацію товарів;
* синхронізацію цін;
* синхронізацію залишків;
* отримання замовлень;
* актуалізація статусів замовлень;
* передачу номерів ТТН / ЕН;
* генерацію товарних фідів;
* валідацію товарів перед передачею;
* контроль помилок API;
* контроль помилок фідів;
* журнал усіх запитів і відповідей;
* dashboard по маркетплейсах;
* захист від дублювання товарів і замовлень.; |-
| stock_quantity
| numeric
| Залишок.; !; | style="background:#ef9a9a;" | Критично
|}

 <firmId>12345</firmId>

 async def check_connection(self) -> dict:
!; | style="background:#bbdefb;" | Блакитний
|-
| Виконано
| COMPLETED
| Замовлення завершено.; |}

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

<syntaxhighlight lang="xml">
 task_name="sync_product_to_channel",
!; Подія

!; |-
| warranty
| string
| Гарантія.; Поле

!; Поле

 "channels": ["PROM", "ROZETKA", "HOTLINE"]
<pre>
!; характеристика

</div>
 return
 )
 "status": "IMPORTED",
!; | Attribute mapping і валідація.; |-
| marketplace
| varchar
| HOTLINE або ROZETKA.; POST /api/v1/marketplaces/hotline/feed/generate
 async def check_connection(self) -> dict:
{| class="wikitable"
 db=db,
 <categoryId>phones</categoryId>
 client = marketplace_client_factory.create(integration)
[[Категорія:K2 ERP]]
7.; |-
| total_amount
| numeric
| Сума замовлення.; # Чи потрібно автономно приховувати товари без залишку?; |-
| delivery_service
| string
| Нова пошта, Укрпошта тощо.; Очікуваний результат
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">

!; |-
| login
| secret
| Ні
| Логін, якщо потрібен.; Дія

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

Prom.ua / Rozetka / Hotline

[[Категорія:Інтеграції]]

 v

* доступ до кабінету продавця 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;
* правила мапінгу характеристик;
* правила округлення цін;
* правила синхронізації залишків;
* правила резервування товару після отримання замовлення;
* правила актуалізація статусів замовлень;
* правила передачі ТТН.; | Перевести в ручну перевірку.; |-
| Генерація фідів
| Середній
| Hotline / Rozetka feed.; |}

!; | Товар приховується або передається як недоступний за правилом.;</item>
{| class="wikitable"

!; | style="background:#fff9c4;" | Увага
|-
| Імпортовано замовлень
| Успішно створено в K2 ERP.; |-
| Hotline
| XML/YML/CSV/XLS/TXT фіди + API ставок
| Передача товарів через фід, контроль акцій, керування ставками.; |}
async def publish_feed(self, feed: bytes, filename: str) -> str:

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

- marketplace varchar - barcode - sku varchar Артикул.; №
payload=order_payload,

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

- api_token_encrypted text - product_id - last_synced_stock numeric Останній переданий залишок.; Код


14.12. Dashboard

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

"hotline": "hotline-category-code"

2.; Область сфера застосування

style="background:#ffcc80;" | Помаранчевий
Підтверджено CONFIRMED платформа показує AuthError і не виконує синхронізацію.; Тип POST /api/v1/marketplaces/integrations self.bid_api_token = bid_api_token

32.; Джерела

<guarantee>12 місяців</guarantee>

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

  • SKU заповнений;
  • назва заповнена;
  • характеристика заповнений;
  • категорія K2 ERP визначена;
  • категорія каналу замаплена;
  • бренд заповнений, якщо обов'язковий;
  • ціна більша за 0;
  • залишок не від'ємний;
  • фото доступні за URL;
  • характеристики заповнені;
  • штрихкод валідний, якщо потрібен;
  • гарантія заповнена, якщо потрібна;
  • товар не заборонений правилами каналу;
  • назва не містить HTML або службового сміття;
  • характеристика не містить заборонених тегів;
  • для Hotline є собою URL товару на сайті магазину;
  • для Rozetka є собою категорія й характеристики згідно з вимогами категорії;
  • для Prom є собою коректний статус публікації.; | Не публікувати фід.; | style="background:#e3f2fd;" | відомості
Синхронізовано - feed_public_url varchar інтеграційні функціональні можливості зберігається і проходить check_connection.; |- product_id uuid Заблокувати синхронізацію залишку.; |- attributes object - Дублювання замовлень - актуалізація ставки - Status Export Worker Передача статусів і ТТН.; # Чи потрібні окремі склади для залишків по каналах?; Колір

2.; |}

7. User Story

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

integration = integration_repository.get_active(db, marketplace)
 self.base_url = base_url
|-
| AC-1
| Адміністратор створює інтеграцію Prom.; |-
| Retry
| Хто або який worker запустив, причина, результат.; | Фід доступний за public URL.; self.username = username

* реалізувати order import workers;
* реалізувати дедублікацію;
* реалізувати створення замовлення в K2 ERP;
* реалізувати status export;
* реалізувати передачу ТТН.; |-
| style="background:#f3e5f5;" | Фіолетовий
| #f3e5f5
| Спеціальний або ручний сценарій.; характеристика
|-
| AC-19
| Керівник відкриває dashboard.; !; Поле
2.; Поле

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

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

sync_queue.enqueue(
;=== 13.3. Rozetka Client ===
  • реалізувати price engine;
  • реалізувати stock engine;
  • реалізувати чергу актуалізація;
  • реалізувати історію змін.; |-
Імпорт замовлення }

я хочу автономно формувати фід для Hotline,

@abstractmethod

K2 ERP передає нові ціни.; # Як часто імпортувати замовлення?; |-

AC-2 } ; я хочу, щоб залишки з K2 ERP автономно оновлювались на маркетплейсах,
pass
mp_product.raw_response = response

</syntaxhighlight>

24.2.; Приклад dashboard

Синхронізація товару - payment_type string style="background:#bbdefb;" | Блакитний
Імпортовано IMPORTED Замовлення створено в K2 ERP.; marketplace=marketplace,
<url>https://example.com/product/sku-001</url>
async def check_connection(self) -> dict:
  • формувати XML/YML-фід;
  • включати тільки активні товари;
  • передавати актуальні ціни;
  • передавати актуальні залишки;
  • передавати URL товару;
  • передавати фото;
  • передавати характеристики;
  • формувати фід акцій, якщо потрібно;
  • керувати ставками через API ставок, якщо підключено.; |-
status string Статус.;=== 19.1.; Логіка синхронізації товарів === Передати менеджеру каталогу.; |- base_url string Так - external_product_id varchar ID товару в каналі.; Пріоритет
)
; Ризик

я хочу змінити ціну в K2 ERP,

async def update_stock(self, external_product_id: str, stock: dict) -> dict:
"price": 12999.00,
if existing:
- old_price numeric Стара ціна, якщо є собою.; Критично істотно: інтеграційні функціональні можливості не повинна створювати дублікати товарів, замовлень або фідів.; Як зменшити
async def sync_product_to_channel(product_id: str, marketplace: str, db: "Session") -> None:

!; |-
| Hotline Feed Generator
| Генерація XML/YML/CSV-фідів Hotline.; Критерій
== 21.; Приклад Python-логіки ==
|-
| SKU-001
| Смартфон Example X
| Rozetka
| style="background:#ffcc80;" | Потребує виправлення
| Не замаплена характеристика «Пам'ять»
| Заповнити мапінг
|-
| SKU-002
| Навушники Example Air
| Prom
| style="background:#ef9a9a;" | Помилка
| Фото недоступне
| Перевірити URL фото
|-
| SKU-003
| Кавоварка Example
| Hotline
| style="background:#ef9a9a;" | Помилка фіду
| Некоректний XML-символ в описі
| Очистити характеристика
|}

'''Критично істотно:''' доступи до Prom, Rozetka і Hotline потрібно зберігати тільки в secret storage або в зашифрованому вигляді.; |-
| is_active
| boolean
| Так
| Ознака активності.; {

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

* отримати актуальний залишок;
* врахувати резерви;
* врахувати мінімальний страховий залишок;
* визначити доступну кількість для продажу;
* передати залишок у канали;
* приховати товар, якщо залишок 0;
* відновити товар, якщо залишок з'явився.; |-
| AC-14
| Замовлення вже імпортоване.; |-
| sync_prices_enabled
| boolean
| Синхронізація цін.; POST /api/v1/marketplaces/hotline/feed/publish
=== 14.9.; Генерація фіду Hotline ===
Python Marketplace Integration Service

 mp_product.error_message = str(exc)

'''істотно:''' Prom, Rozetka і Hotline мають різну логіку інтеграції.; | style="background:#ffcc80;" | Помаранчевий
|-
| Готовий до синхронізації
| READY_TO_SYNC
| Товар готовий до передачі.; # Який формат Hotline використовуємо: XML, YML, CSV?; |-
| Невідомий статус
| Канал повернув новий статус.;<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">

{| class="wikitable"
 async def sync_product(self, product: dict) -> dict:
 "stock_quantity": 12,
POST /api/v1/marketplaces/hotline/bids/update
=== 14.10.; Публікація фіду Hotline ===
інтеграційні функціональні можливості призначена для:
 async def update_order_status(self, external_order_id: str, status: dict) -> dict:
!; |-
| Помилка API
| Код, текст, raw-відповідь.; Статус

 new_status="SYNCED",

* регулярно отримувати нові замовлення;
* перевіряти, чи замовлення вже імпортовано;
* створювати замовлення в K2 ERP;
* створювати покупця або прив'язувати до існуючого;
* створювати резерв товарів;
* зберігати джерело замовлення;
* зберігати external_order_id;
* передавати статус обробки назад у маркетплейс.; 
<price>
 "https://example.com/images/sku-001-1.jpg",

 "color": "Black",

 "product_id": product_id,

 mp_product.last_synced_stock = product.available_stock

* Prom.ua;
* Rozetka Marketplace;
* Hotline.; Коментар
== 10.; Статуси замовлень ==

!; Компонент
 pass

<pre>
[[Категорія:API]]

5.; # Чи потрібна повна синхронізація товарів у Prom через API?; # Який формат фіду Rozetka потрібен?; |-
| ImageError
| Фото недоступне або некоректне.; | style="background:#bbdefb;" | Блакитний
|-
| Передано
| SYNCED
| Товар передано в канал.; | Високий пріоритет stock sync.; | Передати менеджеру каталогу.; !; характеристика

</pre>

</pre>
=== 20.3. marketplace_orders ===
!; Rozetka

{| class="wikitable"

=== 8.2.; Товар для синхронізації ===
{| class="wikitable"
=== 27.2.; Товари ===
 "marketplace": channel,

 product = product_repository.get_by_id(db, product_id)
 pass

щоб він автономно передавався в Prom, Rozetka і Hotline.; |-
| актуалізація цін
| Високий
| Впливає на маржу.; Заборонено зберігати API token, логіни, паролі або auth token у коді, Git, frontend-змінних або відкритих логах.; |-
| product_hash
| Hash назви, ціни, залишку, характеристик.; | style="background:#eeeeee;" | Сірий
|}

{| class="wikitable"

== 20.; Модель даних ==
!; |-
| API Event
| Подія інтеграції.; Ключ

 )

</pre>
 <items>
 v
 @abstractmethod
 "marketplace_status": order_payload.get("status"),
 <category>
<pre>
 product_status_service.set_status(
!; характеристика
!; Для кожного активного каналу створюється sync task.; |-
| status
| varchar
| Статус синхронізації.; я хочу бачити продажі та реалізація, помилки, статуси товарів і ефективність каналів, 

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

* отримувати товари з K2 ERP;
* перевіряти обов'язкові поля;
* мапити категорії;
* мапити характеристики;
* формувати характеристика;
* перевіряти фото;
* формувати ціну;
* формувати залишок;
* передавати товар у Prom / Rozetka через API або фід;
* включати товар у фід Hotline;
* зберігати зовнішні ID товарів.;<date>2026-05-07 12:00</date>
=== 7.2.; Ціни ===
{| class="wikitable"
</price>
<pre>
!;<categories>
{| class="wikitable"
=== 14.6.; актуалізація залишків ===
!; | платформа передає нову ціну в канали.; |-
| marketplace_category_id
| varchar
| Категорія каналу.; Що зберігати
 "prom": "prom-category-ref",
!; |-
| Stock Rule
| Правило формування доступного залишку.; |-
| items
| array
| Товари замовлення.; Очікуваний результат
=== 14.4.; Масова синхронізація товарів ===

</pre>

!;== 25.; Безпека ==

 <firmName>Example Store</firmName>
</pre>
 db=db,

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

!; 

POST /api/v1/marketplaces/products/{product_id}/sync
 data={
<pre>

!; | style="background:#bbdefb;" | Блакитний
|-
| Відправлено
| SHIPPED
| Передано ТТН / ЕН.; | Зупинити інтеграцію, повідомити адміністратора.; |-
| last_synced_price
| numeric
| Остання передана ціна.; |-
| event_type
| varchar
| Тип події.; # Як часто оновлювати ціни?; |-
| barcode
| string
| Штрихкод.; !; Prom API / Rozetka API / Hotline Feed + Bids API
!; |-
| external_product_id
| string
| ID товару в маркетплейсі.; |-
| Синхронізація товарів
| Середній
| Каталог.; |-
| delivery_address
| text
| Адреса або відділення.; | style="background:#fff9c4;" | Увага
|-
| Відхилено
| Товари відхилені каналом.; |-
| generated_at
| timestamp
| Дата генерації.; |-
| style="background:#ffcc80;" | Помаранчевий
| #ffcc80
| Потрібна дія менеджера.; |-
| order_number
| varchar
| Номер.; | Він передається в активні канали.; | Зберегти raw-відповідь.; | Check-connection і alert адміністратору.;=== 13.2. Prom Client ===

 <name>Смартфони</name>

Prom і Rozetka можуть бути джерелами замовлень.; Rozetka Marketplace має API для інтеграції продавців: офіційна довідка описує API як набір інструментів для інтеграції системи продавця з ROZETKA Маркетплейс, а API-документація вказує можливість роботи із замовленнями, товарами, листуванням і контролем процесів.; |-
| актуалізація залишків
| Критичний
| Захищає від продажу відсутнього товару.; Якщо все коректно  статус IMPORTED.; # Чи потрібно імпортувати замовлення з Rozetka?; |-
| CategoryMappingError
| Не знайдено категорію каналу.; |-
| price
| numeric
| Базова ціна.;<syntaxhighlight lang="json">

 <id>K2-PRODUCT-000123</id>

щоб не продавати товар, якого немає.; |-
| products_count
| integer
| Кількість товарів.; Сутність

== 13. Marketplace Client Interface ==

* створення інтеграцій Prom, Rozetka, Hotline;
* перевірка підключення;
* мапінг категорій;
* мапінг характеристик;
* синхронізація товарів;
* синхронізація цін;
* синхронізація залишків;
* імпорт замовлень з Prom;
* імпорт замовлень з Rozetka;
* актуалізація статусів замовлень;
* передача ТТН;
* генерація Hotline XML/YML-фіду;
* публікація фіду за URL;
* базове керування ставками Hotline, якщо є собою token;
* дедублікація;
* retry-механізм;
* журнал подій;
* dashboard API;
* unit-тести;
* mock clients для Prom/Rozetka/Hotline.; |-
| brand
| string
| Бренд.; |-
| public_url
| varchar
| URL фіду.; |-
| Order Import Worker
| Імпорт замовлень.; |-
| Price Rule
| Правило формування ціни.;</pre>

 client = marketplace_client_factory.create(integration)
{| class="wikitable"

!; |}

 "images": [

 ],

== 4.; Передумови ==
=== 14.5.; актуалізація цін ===
 </categories>

 <description>характеристика товару</description>
mp_product.status = "SYNCING"
async def update_price(self, external_product_id: str, price: dict) -> dict:
errors=validation_result.errors,
- total_amount numeric - Product Validator - created_at timestamp - name varchar Назва.; Замовлення, статуси, модерація, фіди
__TOC__
 |
 | 5.; |-
| password
| secret
| Ні
| Пароль, якщо потрібен.; | платформа формує тестовий фід або перевіряє конфігурація.; |-
| is_active
| boolean
| Активність.; | Воно імпортується в K2 ERP.; Код
 async def generate_product_feed(self, products: list [dict], format: str = "xml") -> bytes:
 pass

 <id>phones</id>

POST /api/v1/marketplaces/products/sync-batch
=== 20.5. marketplace_events ===
 <stock>В наявності</stock>

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

 pass
=== 14.7.; Імпорт замовлень ===
=== 13.1.; Загальний інтерфейс ===

!; marketplace_order_repository.create_error_record(

* реалізувати dashboard API;
* реалізувати список проблемних товарів;
* реалізувати список проблемних замовлень;
* реалізувати список помилок фідів;
* реалізувати експорт, якщо потрібно.; # Чи потрібно передавати ТТН Нової пошти / Укрпошти?; Колір
=== Етап 9.; Production hardening ===
 |
 | 4.; HTML
 "barcode": "4820000000000",

!; |-
| Генерація фіду
| Канал, формат, кількість товарів, помилки.;== 23.; Retry-логіка ==
=== 19.3.; Пріоритети задач ===

!;</syntaxhighlight>
Retry дозволений для:
 validation_result = product_validator.validate(product)

== 27. Acceptance Criteria ==
 for order_payload in orders:
== 26.; Логування та аудит ==

 try:
</syntaxhighlight>
=== 5.5.; актуалізація статусів замовлень ===

 orders = await client.import_orders(filters={"status": "new"})
 "memory": "128GB",
 event_type="PRODUCT_SYNCED",

=== 7.3.; Залишки ===
=== 27.1.; Інтеграції ===
=== 20.1. marketplace_integrations ===
Hotline офіційно описує вимоги до товарних фідів, зокрема Hotline XML і YML, а додатково має API для керування ставками по пропозиціях магазину.; |-
| api_token
| secret
| Ні
| Token для API.; | Версіонування клієнтів і contract-тести.; |-
| raw_response
| jsonb
| Відповідь API.; pass

* додати rate limiting;
* додати retry policy;
* додати dead letter queue;
* додати alerting;
* додати моніторинг;
* додати резервне копіювання;
* додати безпечне зберігання secret-ів.; |-
| name
| string
| Назва.; |-
| Feed Publisher
| Публікація фідів за публічним URL.; |}

<pre>

=== 19.2.; Логіка імпорту замовлень ===
!;</syntaxhighlight>
 db=db,
=== Етап 4.; Товари ===
== 28. MVP ==
|-
| id
| uuid
| ID запису.; |-
| customer_name
| varchar
| Покупець.; |-
| Rozetka
| Seller API + товарний фід
| Замовлення через API, товари/ціни/залишки через API або XML-фід залежно від сценарію.; |-
| Attribute Mapping
| Мапінг характеристик.; | style="background:#c8e6c9;" | Зелений
|-
| Потребує перевірки
| NEEDS_REVIEW
| Не знайдено товар, клієнта або адресу.; | style="background:#ef9a9a;" | Червоний
|-
| Помилка синхронізації
| SYNC_ERROR
| API або фід повернув помилку.; Результат зберігається.; |}

6.; |-
| Category Mapper
| Мапить категорії K2 ERP до категорій каналів.; Тип
 "description": "характеристика товару без HTML-помилок та заборонених символів.",
class HotlineClient:
 marketplace=marketplace,
|-
| Нове
| NEW
| Замовлення отримано з маркетплейса.; | style="background:#eeeeee;" | Сірий
|-
| Очікує валідації
| PENDING_VALIDATION
| Товар очікує перевірки.; |}

</div>

 integration = integration_repository.get_active(db, marketplace)
 mp_product.status = "SYNCED"
 "customer_phone": order_payload.get("customer_phone"),
Як комерційний менеджер, 
|-
| id
| uuid
| ID фіду.; |-
| style="background:#eeeeee;" | Сірий
| #eeeeee
| Чернетка, приховано, скасовано або архів.; |-
| Зміна залишку
| Старий залишок, новий залишок, канал.; |-
| order_date
| datetime
| Дата замовлення.; Він повинен потрапляти в статус NEEDS_CORRECTION.; |-
| style="background:#bbdefb;" | Блакитний
| #bbdefb
| операційна дія виконується або інформаційні дані в процесі передачі.; |-
| updated_at
| timestamp
| Дата актуалізація.; Дія системи
 pass
 marketplace=marketplace,
=== 14.11.; актуалізація ставок Hotline ===
Prom.ua офіційно має публічне API для віддаленого керування даними в кабінеті компанії, а API-токени можна керувати в кабінеті компанії у розділі налаштувань.; | Помилки валідації, невідомі товари, retry.; |-
| sync_prices_enabled
| boolean
| Так
| Чи синхронізувати ціни.; |-
| PriceError
| Ціна некоректна.; |}

{| class="wikitable"

 <priceRUAH>12999</priceRUAH>

</div>
except Exception as exc:

<pre>
{| class="wikitable"
K2 ERP є собою джерелом операційних статусів.; Prom

!; # Чи потрібно керувати ставками Hotline?; pass

3.; |-
| order_number
| Номер замовлення.;<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">
Marketplace Adapters

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

 "order_number": order_payload.get("order_number"),
POST /api/v1/marketplaces/integrations/{integration_id}/check-connection
 pass

<pre>

!; |-
| FeedGenerationError
| Помилка генерації XML/YML.; Призначення
POST /api/v1/marketplaces/orders/import
 },
щоб обробляти їх в єдиній системі.; |-
| Hotline Bid Client
| API керування ставками Hotline.; Колір
 marketplace=marketplace,
<div style="border-left: 6px solid #1565c0; background: #e3f2fd; padding: 12px 16px; margin: 16px 0;">
 pass
 "product_id": "K2-PRODUCT-000123",
[[Категорія:Rozetka]]
 async def sync_product(self, product: dict) -> dict:
 pass
== 8.; Функціональні вимоги ==
 self.feed_storage_url = feed_storage_url
 product_id=product_id,
 async def update_stock(self, external_product_id: str, stock: dict) -> dict:
=== 18.2.; Дедублікація замовлень ===
 db.commit()
 v

 mp_product.last_synced_price = product.price
 payload = marketplace_mapper.to_payload(product, marketplace)
 entity_id=mp_product.id,
== 29.; Етапи реалізації ==
 <image>https://example.com/images/sku-001-1.jpg</image>
{| class="wikitable"
== 18.; Дедублікація ==
 "warranty": "12 місяців"

 db=db,
<div style="border-left: 6px solid #6a1b9a; background: #f3e5f5; padding: 12px 16px; margin: 16px 0;">

 try:

Сервіс повинен забезпечити:
 error=str(exc),
=== 5.6.; Hotline як фід і канал просування ===
 async def sync_product(self, product: dict) -> dict:
|-
| AuthError
| Невірний token, login або password.; |-
| payload
| jsonb
| Технічні інформаційні дані.; |-
| UnknownStatusError
| Канал повернув невідомий статус.; |-
| customer_phone
| varchar
| Телефон.; | Модерація, нові замовлення, очікування.; | Він переходить у NEEDS_CORRECTION.; Очікуваний результат

До MVP входить:

K2 ERP передає залишки по складах.; | style="background:#c8e6c9;" | Зелений
|-
| Скасовано
| CANCELLED
| Замовлення скасовано.; | XML validation перед публікацією.; Канал
=== 27.4.; Замовлення ===
Як менеджер товарного каталогу, 
!; |-
| актуалізація статусів замовлень
| Високий
| Впливає на клієнтський досвід.; |}

class PromClient(MarketplaceClient):

Перед передачею товару платформа повинна перевірити:
{{DISPLAYTITLE:Технічне завдання: Інтеграція з Prom, Rozetka, Hotline для Python}}
!; | Дубль не створюється.; |-
| актуалізація статусу
| Старий статус, новий статус, канал.; |}

 <name>Смартфон Example X 128GB</name>

# Чи K2 ERP є собою головним джерелом товарів?; |-
| delivery_service
| varchar
| Служба доставки.; |-
| feed_type
| varchar
| products, actions, prices.; |-
| StockError
| Залишок некоректний.; |-
| AC-6
| Товар не має фото.; :contentReference [oaicite:3]{index=3}

=== 14.8.; актуалізація статусу замовлення ===

</div>
 continue
 async def update_order_status(self, external_order_id: str, status: dict) -> dict:
<syntaxhighlight lang="python">
== 11.; Єдина логіка кольорів ==

 mp_product.external_product_id = response.get("external_product_id")
4.; Критерій
<syntaxhighlight lang="python">

!; Значення

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

 self.password = password

 self.token = token
!; |}

{| class="wikitable"

!; Поле
 pass

 pass
=== 7.6.; Dashboard керівника ===
!; Валідація, мапінг, черги, дедублікація
 "marketplace_categories": {
 "attributes": {
 |
 | 3.;
"name": "Смартфон Example X 128GB",

істотно: структура XML вище є собою прикладом.; # Чи потрібно оновлювати статуси замовлень у маркетплейсах?; |-

entity_type varchar Він бачить товари, замовлення, фіди, помилки по Prom/Rozetka/Hotline.; |}

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

Як складський облік,

},
pass
AC-9 }
=== 5.1.; Передача товарів ===
!;=== 14.3.; Синхронізація товару ===
=== 5.4.; Отримання замовлень ===
 finally:
 response = await client.sync_product(payload)
|-
| id
| uuid
| ID інтеграції.; |-
| Rozetka Adapter
| Робота з API Rozetka.;=== 18.1.; Дедублікація товарів ===

=== Етап 1.; Аналіз API та вимог ===
 external_order_id=external_order_id,
=== 27.6. Dashboard ===
</pre>
!; * отримувати статус із K2 ERP;
* мапити статус у статус маркетплейса;
* передавати статус у Prom / Rozetka;
* передавати номер ТТН / ЕН;
* зберігати історію статусів;
* логувати помилки актуалізація.; |-
| AC-18
| користувач системи оновлює ставку Hotline.; |-
| sync_orders_enabled
| boolean
| Так
| Чи імпортувати замовлення.; Статус K2 ERP
!; я хочу отримувати замовлення з Prom і Rozetka в K2 ERP, 
[[Категорія:Hotline]]
|-
| AC-16
| платформа генерує Hotline XML.; |-
| AC-11
| Залишок став 0.; |-
| tracking_number
| varchar
| ТТН / ЕН.; |}

 def __init__(self, base_url: str, api_token: str):

<pre>
 "external_order_id": external_order_id,
{| class="wikitable"
 )
|-
| AC-12
| Prom має нове замовлення.; | style="background:#c8e6c9;" | Норма
|-
| Фіди сформовані
| XML/YML-фіди згенеровані.; |}

!; Якщо замовлення нове.; |-
| order_number
| string
| Номер замовлення.; Ключ
 payload={
=== 5.3.; Синхронізація залишків ===
Python-сервіс повинен:
[[Категорія:Prom.ua]]

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

is_active boolean Перевести в NEEDS_CORRECTION / NEEDS_REVIEW.; |- images array }
pass

Етап 3.; Marketplace Adapters

SKU-001

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

20.4. marketplace_feeds

id uuid - AC-4 Token неправильний.; характеристика

Як менеджер продажів,

</items>
{{SEO


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

pass
pass

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

product_id=product.id,

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

"marketplace": marketplace,
status="NEEDS_CORRECTION",
; Помилка
def __init__(self, base_url: str, username: str | None = None, password: str | None = None, token: str | None = None):
pass
; Товар проходить валідацію.; Тип ; характеристика
  • реалізувати PromClient;
  • реалізувати RozetkaClient;
  • реалізувати HotlineFeedGenerator;
  • реалізувати HotlineBidClient;
  • реалізувати client factory;
  • реалізувати обробку помилок.; |-
AC-7 style="background:#fff9c4;" | Жовтий
Імпортується IMPORTING Створюється в K2 ERP.; !; !; Колір

платформа повинна логувати:

mp_product = marketplace_product_repository.get_or_create(

платформа повинна забезпечити:

; Python-сервіс отримує подію.;

* реалізувати XML/YML generator;
* реалізувати валідацію XML;
* реалізувати публікацію файлу;
* реалізувати журнал генерацій;
* реалізувати фід акцій, якщо потрібно.; | Воно імпортується в K2 ERP.; Production-фід потрібно формувати за актуальною специфікацією Hotline XML або YML.;</div>

* реалізувати product mapper;
* реалізувати category mapper;
* реалізувати attribute mapper;
* реалізувати валідацію;
* реалізувати sync workers.; Тип
 },
|-
| sku
| ключовий артикул.; Worker регулярно запитує нові замовлення Prom / Rozetka.; |-
| Product
| Товар у K2 ERP.; №
== 9.; Статуси товарів ==

!; SKU
|-
| Prom.ua
| Public API
| Товари, замовлення, статуси, ціни, залишки.; # Чи Rozetka товари приймає через API, фід або змішано?; |-
| sync_orders_enabled
| boolean
| Імпорт замовлень.; |-
| old_status
| varchar
| Старий статус.; |-
| Stock Engine
| Формує доступний залишок.; |-
| Помилки характеристик
| Rozetka часто потребує точних характеристик категорій.; |}

K2 ERP є собою головним джерелом товарів.; async def authenticate(self) -> dict:

!; Тип
 "brand": "Example",
|-
| id
| uuid
| ID події.; !; |-
| status
| varchar
| Статус генерації.; | style="background:#ef9a9a;" | Критично
|-
| Помилки синхронізації
| Товари або замовлення з помилками.; |-
| new_status
| varchar
| Новий статус.; характеристика
 def __init__(self, feed_storage_url: str, bid_api_token: str | None = None):
== 30.; Ризики ==

</syntaxhighlight>

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

except Exception as exc:
"k2_order_id": k2_order.id,
self.base_url = base_url

7.5. Hotline

; Очікуваний результат
!; |-
| status
| varchar
| Статус K2 ERP.; async def update_price(self, external_product_id: str, price: dict) -> dict:

щоб контролювати якість інтеграції.;== 24.; Dashboard керівника ==

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

1.; | Фід не публікується або товар виключається за правилом.; |-

Dashboard API - Category Mapping Мапінг категорій K2 ERP до категорій каналу.; Очікуваний результат
pass
"old_price": 13999.00,
async def generate_action_feed(self, actions: list [dict]) -> bytes:
Marketplace Integration style="background:#c8e6c9;" | Зелений
Відхилено REJECTED style="background:#ef9a9a;" | Червоний
Приховано HIDDEN Товар приховано через залишок, правило або вручну.; Призначення
"https://example.com/images/sku-001-2.jpg"
Імпорт замовлень Критичний Впливає на продажі та реалізація.; Hotline