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

Технічне завдання: інтеграція ПРРО Checkbox для Python

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


SEO title: Технічне завдання: Інтеграція ПРРО Checkbox для Python SEO description: Технічне завдання на реалізацію Python-сервісу для інтеграції з ПРРО Checkbox: фіскалізація чеків, відкриття і закриття змін, повернення, службові операції, X/Z-звіти, статуси, помилки, API-клієнт, черги та журналювання. SEO keywords: Python, Checkbox, ПРРО, API Checkbox, фіскалізація чеків, каса, програмний РРО, FastAPI, інтеграція, технічне завдання, K2 ERP Alternative to:



Головна ідея: розробити Python-сервіс, який інтегрує ERP / CRM / інтернет-магазин / POS-систему з ПРРО Checkbox для автоматичної фіскалізації чеків, контролю касових змін, повернень, службових операцій, статусів, помилок та відправки електронних чеків покупцям.

Критично важливо: інтеграція з ПРРО не повинна втрачати чеки. Кожна операція продажу, повернення, відкриття зміни, закриття зміни, службове внесення / винесення готівки та помилка фіскалізації повинні мати внутрішній ID, статус, журнал подій і можливість безпечного повтору без створення дубля.

Важливо: Checkbox має декілька сценаріїв роботи: WebAPI для eCommerce, Checkbox Kasa Manager для retail/POS-сценаріїв, мобільний застосунок та кабінет. У межах цього ТЗ основний сценарій — Python-сервіс, який працює з API Checkbox.

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

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

1. Мета

Метою задачі є створення Python-сервісу для інтеграції з ПРРО Checkbox з метою автоматизації фіскалізації продажів, повернень, службових операцій і касових змін.

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

  • прийом замовлень, продажів або оплат із зовнішньої системи;
  • створення фіскального чека продажу;
  • створення чека повернення;
  • створення службового внесення готівки;
  • створення службового винесення готівки;
  • контроль відкриття касової зміни;
  • контроль закриття касової зміни;
  • формування X-звіту;
  • формування Z-звіту;
  • отримання статусів чеків;
  • отримання статусів змін;
  • збереження фіскальних номерів;
  • збереження посилання або візуалізації чека;
  • отримання HTML / PNG / TXT / QR-візуалізації чека, якщо потрібно;
  • відправку електронного чека покупцю, якщо підтримується налаштуваннями;
  • журналювання всіх API-запитів;
  • повторну обробку помилкових операцій;
  • захист від дублювання чеків;
  • передачу статусів назад в ERP / CRM / сайт / POS.

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

Функціонал використовується для:

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

До області задачі входить:

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

До першої версії не входить:

  • повноцінний POS-інтерфейс касира;
  • власна реалізація ПРРО без Checkbox;
  • самостійна реєстрація ПРРО в ДПС через Python-сервіс;
  • власний модуль КЕП;
  • інтеграція з усіма еквайрингами;
  • складний UI для касира;
  • заміна кабінету Checkbox;
  • повна офлайн-робота без окремого погодженого сценарію.

3. Джерела інтеграції

Компонент Призначення Коментар
Checkbox ПРРО-сервіс для фіскалізації чеків. Основний зовнішній сервіс інтеграції.
Checkbox API REST API для інтеграції з eCommerce / ERP / CRM / POS. Основний канал для Python-сервісу.
Checkbox Kasa Manager Фронт-агент для retail/POS-сценаріїв. Може використовуватись у локальних інтеграціях.
Особистий кабінет Checkbox Керування торговими точками, касами, касирами. Використовується для налаштування.
Python-сервіс Інтеграційний шар між ERP / сайтом / CRM / POS та Checkbox. Реалізується в межах цього ТЗ.
ERP / CRM / сайт / POS Джерело продажів, повернень, оплат і даних покупця. Наприклад K2 ERP або інша система.
ДПС Кінцевий отримувач фіскальних даних через ПРРО. Python-сервіс напряму з ДПС у MVP не працює.

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

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

  • акаунт у Checkbox;
  • зареєстрованого торговця;
  • торгову точку;
  • зареєстровану касу / ПРРО;
  • касира;
  • спосіб підпису чеків;
  • доступ до API;
  • токен авторизації;
  • license key каси;
  • назву інтеграції для заголовка X-Client-Name;
  • версію інтеграції для заголовка X-Client-Version;
  • тестове середовище або тестову касу, якщо доступно;
  • перелік кас, які будуть використовуватись;
  • перелік касирів;
  • правила відкриття і закриття зміни;
  • правила формування чеків;
  • правила повернень;
  • формат оплати;
  • формат товарних позицій;
  • формат податкових ставок;
  • вимоги до відправки електронного чека покупцю.

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

5. Варіанти інтеграції

5.1. Варіант 1. WebAPI для eCommerce

Python-сервіс напряму викликає Checkbox API.

Параметр Опис
Підходить для Хмарних ERP, CRM, інтернет-магазинів, SaaS-систем.
Переваги Пряме API, зручна автоматизація, можливість працювати з чергою.
Обмеження Потрібен стабільний інтернет, коректне керування змінами та токенами.
Основні операції Створення чеків, повернень, службових операцій, отримання статусів, робота зі змінами.

5.2. Варіант 2. Checkbox Kasa Manager

Використовується для retail/POS-сценаріїв, коли касовий вузол має локальний агент.

Параметр Опис
Підходить для Фізичних магазинів, POS-систем, торгових точок.
Переваги Зручніше для касового вузла, retail-логіки, локальної роботи.
Обмеження Потрібна інсталяція й підтримка агентів.
Основні операції Фіскалізація чеків, робота касира, контроль зміни.

5.3. Варіант 3. Гібридна схема

Python-сервіс підтримує централізований облік чеків, але різні торгові точки можуть використовувати різні канали.

Сценарій Опис
Онлайн-продажі Через WebAPI.
Фізичні магазини Через Checkbox Kasa Manager або інший фронт-агент.
Загальна БД чеків Усі чеки зберігаються в єдиній БД Python-сервісу.
Єдиний dashboard Керівник бачить усі чеки, каси, статуси й помилки в одному місці.

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

Сутність Опис
Cash Register Каса / ПРРО, через яку фіскалізуються чеки.
Cashier Касир, від імені якого виконується операція.
License Key Ключ ліцензії каси, який використовується в запитах до API.
Shift Касова зміна.
Receipt Фіскальний чек продажу.
Refund Receipt Чек повернення.
Service Receipt Службове внесення або винесення готівки.
Receipt Item Товарна або послугова позиція в чеку.
Payment Оплата в чеку: готівка, картка, онлайн-еквайринг тощо.
Fiscal Status Статус фіскалізації.
X Report Проміжний звіт без закриття зміни.
Z Report Звіт із закриттям зміни.
API Event Технічна подія інтеграції.

7. User Story

7.1. Фіскалізація продажу

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

7.2. Повернення

Як оператор або ERP, я хочу створити чек повернення, щоб коректно відобразити повернення коштів покупцю.

7.3. Службове внесення / винесення

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

7.4. Контроль зміни

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

7.5. Повторна обробка

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

7.6. Контроль керівника

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

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

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

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

Поле Тип Обов'язковість Опис
integration_name string Так Назва інтеграції.
base_url string Так Базова адреса API Checkbox.
api_token secret Так Токен авторизації.
x_client_name string Так Назва інтеграції для заголовка X-Client-Name.
x_client_version string Так Версія інтеграції для заголовка X-Client-Version.
organization_id string Так Внутрішній ID організації.
cash_register_id string Так ID каси / ПРРО у локальній системі.
license_key secret Так License key каси.
cashier_id string Ні ID касира за замовчуванням.
default_tax_group string Ні Податкова група за замовчуванням.
auto_open_shift boolean Так Автоматично відкривати зміну перед першим чеком.
auto_close_shift boolean Ні Автоматично закривати зміну за розкладом.
send_receipt_to_customer boolean Ні Відправляти чек покупцю.
allow_offline_mode boolean Ні Чи дозволена офлайн-робота.
is_active boolean Так Ознака активності інтеграції.

8.2. Створення чека продажу

Python-сервіс повинен приймати дані продажу та створювати фіскальний чек.

Логічний endpoint Python-сервісу:

POST /api/v1/fiscal/checkbox/receipts

Мінімальні дані:

Поле Тип Опис
external_order_id string ID замовлення у зовнішній системі.
fiscal_operation_type string sale.
cash_register_id string Каса / ПРРО.
cashier_id string Касир.
customer object Дані покупця.
items array Позиції чека.
payments array Оплати.
total_amount integer Загальна сума чека в копійках.
currency string Валюта.
idempotency_key string Ключ захисту від дублювання.

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

8.3. Приклад запиту на чек продажу

{
  "external_order_id": "ORDER-2026-000123",
  "idempotency_key": "ORDER-2026-000123-PAY-123456",
  "fiscal_operation_type": "sale",
  "cash_register_id": "cash-register-001",
  "cashier_id": "cashier-001",
  "customer": {
    "name": "Іван Петренко",
    "email": "customer@example.com",
    "phone": "+380501112233"
  },
  "items": [
    {
      "name": "Товар 1",
      "sku": "SKU-001",
      "quantity": 2000,
      "price": 25000,
      "amount": 50000,
      "tax_group": "VAT_20",
      "unit": "шт"
    },
    {
      "name": "Доставка",
      "sku": "DELIVERY",
      "quantity": 1000,
      "price": 7000,
      "amount": 7000,
      "tax_group": "NO_VAT",
      "unit": "послуга"
    }
  ],
  "payments": [
    {
      "type": "CARD",
      "amount": 57000,
      "provider": "liqpay",
      "payment_id": "PAY-123456"
    }
  ],
  "total_amount": 57000,
  "currency": "UAH"
}

8.4. Чек повернення

Система повинна підтримувати створення чека повернення.

Логічний endpoint:

POST /api/v1/fiscal/checkbox/refund-receipts

Мінімальні дані:

Поле Тип Опис
original_receipt_id uuid Внутрішній ID первинного чека.
original_fiscal_number string Фіскальний номер первинного чека.
external_refund_id string ID повернення у зовнішній системі.
items array Позиції, які повертаються.
payments array Сума повернення.
reason string Причина повернення.
idempotency_key string Ключ захисту від дублювання повернення.

Критично важливо: чек повернення повинен бути пов'язаний із первинним чеком. Система не повинна дозволяти створювати повернення на суму більшу, ніж залишок доступний до повернення.

8.5. Службове внесення та винесення готівки

Система повинна підтримувати службові касові операції:

  • службове внесення готівки;
  • службове винесення готівки.

Логічний endpoint Python-сервісу:

POST /api/v1/fiscal/checkbox/service-receipts

Мінімальні дані:

Поле Тип Опис
operation_type enum cash_in або cash_out.
cash_register_id string Каса.
cashier_id string Касир.
value integer Сума в копійках.
reason string Коментар або причина.
idempotency_key string Ключ дедублікації.

8.6. Відкриття зміни

Система повинна підтримувати відкриття касової зміни.

Логічний endpoint:

POST /api/v1/fiscal/checkbox/shifts/open

Сценарії:

Сценарій Опис
Ручне відкриття Користувач або адміністратор відкриває зміну.
Автоматичне відкриття Система відкриває зміну перед першим чеком.
Перевірка перед чеком Якщо зміна вже відкрита, повторно не відкривати.
Офлайн-відкриття Дозволяється тільки за окремим налаштуванням і правилами Checkbox.

8.7. Закриття зміни

Система повинна підтримувати закриття касової зміни та формування Z-звіту.

Логічний endpoint:

POST /api/v1/fiscal/checkbox/shifts/{shift_id}/close

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

  • перевірити відкриту зміну;
  • перевірити незавершені чеки;
  • сформувати Z-звіт;
  • зберегти результат;
  • змінити статус зміни на Closed;
  • записати подію в журнал.

8.8. X-звіт

Система повинна підтримувати отримання проміжного X-звіту без закриття зміни.

POST /api/v1/fiscal/checkbox/shifts/{shift_id}/x-report

8.9. Отримання статусу чека

Система повинна підтримувати синхронізацію статусу чека з Checkbox.

POST /api/v1/fiscal/checkbox/receipts/{receipt_id}/sync-status

8.10. Отримання візуалізації чека

Система повинна підтримувати отримання візуалізації чека.

Формати:

  • HTML;
  • PNG;
  • TXT;
  • QR-code.

Логічні endpoint-и Python-сервісу:

GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/html
GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/png
GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/text
GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/qrcode

8.11. Відправка чека покупцю

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

Канали:

  • email;
  • SMS;
  • месенджер, якщо підтримується налаштуваннями;
  • посилання на чек через зовнішню систему.

9. Статуси чеків

Статус Код Опис Колір
Чернетка DRAFT Чек створено у Python-сервісі, але ще не відправлено. Сірий
Очікує фіскалізації PENDING Чек у черзі на відправку. Жовтий
Відправляється SENDING Виконується API-запит. Блакитний
Створено в Checkbox CREATED_IN_CHECKBOX Чек створено в Checkbox, очікується фінальний статус. Блакитний
Фіскалізовано FISCALIZED Чек успішно фіскалізовано. Зелений
Помилка фіскалізації FISCALIZATION_ERROR Виникла помилка при фіскалізації. Червоний
Потребує повтору NEEDS_RETRY Можна повторити відправку. Помаранчевий
Скасовано CANCELLED Операцію скасовано. Сірий
Повернення створено REFUNDED По чеку є повне або часткове повернення. Фіолетовий

10. Статуси зміни

Статус Код Опис Колір
Не відкрита CLOSED Зміна закрита або ще не відкривалась. Сірий
Створюється CREATED Створено запит на відкриття зміни. Жовтий
Відкривається OPENING Виконується відкриття зміни. Блакитний
Відкрита OPENED Можна фіскалізувати чеки. Зелений
Закривається CLOSING Виконується закриття зміни. Блакитний
Закрита CLOSED_WITH_Z_REPORT Зміна закрита із Z-звітом. Зелений
Помилка ERROR Помилка відкриття або закриття зміни. Червоний

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

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

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

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

ERP / CRM / Website / POS
        |
        | 1. Продаж / оплата / повернення
        v
Python Fiscal Service
        |
        | 2. Валідація, дедублікація, черга
        v
Checkbox Adapter
        |
        | 3. Checkbox API
        v
Checkbox
        |
        | 4. Фіскалізація через ПРРО
        v
ДПС
        |
        | 5. Фіскальний результат
        v
Checkbox
        |
        | 6. Статус / номер / посилання / візуалізація
        v
Python Fiscal Service
        |
        | 7. Оновлення ERP / CRM / POS
        v
ERP / CRM / Website / POS

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

Компонент Опис
API Layer REST API для прийому продажів, повернень, службових операцій, команд зміни.
Validation Layer Перевіряє товари, суми, оплати, податки, касу, касира.
Deduplication Service Захищає від повторної фіскалізації одного продажу.
Fiscal Queue Черга задач на фіскалізацію.
Checkbox Client Python-клієнт для Checkbox API.
Shift Service Відкриття, контроль і закриття змін.
Receipt Service Створення чеків продажу.
Refund Service Створення чеків повернення.
Service Receipt Service Службове внесення та винесення готівки.
Status Sync Worker Оновлення статусів чеків і змін.
Audit Logger Журнал API-запитів, відповідей, помилок і змін статусів.
Dashboard API Дані для керівника: чеки, зміни, помилки, обороти.

13. Checkbox Client

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

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

13.2. Основні методи

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

    def open_shift(self, payload: "OpenShiftPayload") -> "ShiftResponse":
        pass

    def close_shift(self, shift_id: str) -> "ZReportResponse":
        pass

    def create_x_report(self, shift_id: str) -> "XReportResponse":
        pass

    def create_sell_receipt(self, payload: "SellReceiptPayload") -> "ReceiptResponse":
        pass

    def create_refund_receipt(self, payload: "RefundReceiptPayload") -> "ReceiptResponse":
        pass

    def create_service_receipt(self, payload: "ServiceReceiptPayload") -> "ReceiptResponse":
        pass

    def get_receipt_status(self, receipt_id: str) -> "ReceiptStatusResponse":
        pass

    def get_shift_status(self, shift_id: str) -> "ShiftStatusResponse":
        pass

    def get_receipt_html(self, receipt_id: str) -> str:
        pass

    def get_receipt_png(self, receipt_id: str) -> bytes:
        pass

    def get_receipt_text(self, receipt_id: str) -> str:
        pass

    def get_receipt_qrcode(self, receipt_id: str) -> bytes:
        pass

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

from pydantic_settings import BaseSettings


class CheckboxSettings(BaseSettings):
    base_url: str
    api_token: str
    x_client_name: str
    x_client_version: str
    default_license_key: str | None = None
    default_cash_register_id: str | None = None
    default_cashier_id: str | None = None
    timeout_seconds: int = 30
    retry_count: int = 3
    retry_backoff_seconds: int = 5
    verify_ssl: bool = True
    allow_offline_mode: bool = False

Приклад змінних середовища:

CHECKBOX_BASE_URL=https://api.checkbox.ua
CHECKBOX_API_TOKEN=********
CHECKBOX_X_CLIENT_NAME=K2-ERP-Integration
CHECKBOX_X_CLIENT_VERSION=1.0.0
CHECKBOX_DEFAULT_LICENSE_KEY=********
CHECKBOX_DEFAULT_CASH_REGISTER_ID=cash-register-001
CHECKBOX_DEFAULT_CASHIER_ID=cashier-001
CHECKBOX_TIMEOUT_SECONDS=30
CHECKBOX_RETRY_COUNT=3
CHECKBOX_RETRY_BACKOFF_SECONDS=5
CHECKBOX_ALLOW_OFFLINE_MODE=false

Заборонено: зберігати API token, license key, ключі, паролі касирів або інші секрети у коді, Git-репозиторії, відкритих логах або frontend-змінних.

14. Валідація чека

Перед фіскалізацією система повинна перевірити:

  • наявність external_order_id;
  • наявність idempotency_key;
  • відсутність уже фіскалізованого чека по цьому external_order_id;
  • наявність каси;
  • наявність license key;
  • наявність касира;
  • наявність відкритої зміни або можливість її відкрити;
  • наявність хоча б однієї позиції;
  • коректність кількості;
  • коректність ціни;
  • коректність суми рядка;
  • відповідність total_amount сумі товарів і оплат;
  • коректність типу оплати;
  • коректність податкових груп;
  • коректність email або телефону покупця, якщо чек потрібно відправити;
  • коректність формату UUID для операцій, які вимагають UUID.

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

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

Ключі дедублікації:

Ключ Призначення
external_order_id Основний ключ від зовнішньої системи.
external_payment_id Додатковий ключ від платіжної системи.
idempotency_key Унікальний ключ запиту.
receipt_uuid UUID чека, який передається в Checkbox.
receipt_hash Hash товарів, сум, оплат і замовлення.

Приклад hash:

sha256(external_order_id + total_amount + payment_id + cash_register_id)

Критично важливо: повторний запит із тим самим idempotency_key або receipt_uuid не повинен створити другий фіскальний чек. Він повинен повернути результат уже створеної операції.

16. Черга фіскалізації

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

16.1. Логіка черги

1. API приймає запит на створення чека.
2. Дані проходять валідацію.
3. Створюється запис receipt зі статусом PENDING.
4. Задача додається в чергу.
5. Worker перевіряє зміну.
6. Якщо зміна не відкрита і auto_open_shift = true, worker відкриває зміну.
7. Worker викликає Checkbox API.
8. Результат зберігається в БД.
9. ERP / CRM / сайт отримує статус.

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

Тип задачі Пріоритет Коментар
Фіскалізація продажу Високий Основний бізнес-процес.
Повернення Високий Важлива фінансова операція.
Закриття зміни Критичний Не можна залишати зміну незакритою.
Службове внесення / винесення Середній Касова технічна операція.
Синхронізація статусів Середній Може виконуватись фоново.
Завантаження візуалізації чека Низький Не блокує фіскалізацію.

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

17.1. fiscal_integrations

Поле Тип Опис
id uuid ID інтеграції.
provider varchar checkbox.
name varchar Назва інтеграції.
base_url varchar URL API.
api_token_encrypted text Зашифрований токен.
x_client_name varchar Назва інтеграції.
x_client_version varchar Версія інтеграції.
organization_id varchar Організація.
allow_offline_mode boolean Чи дозволений офлайн.
is_active boolean Активність.
created_at timestamp Дата створення.
updated_at timestamp Дата оновлення.

17.2. cash_registers

Поле Тип Опис
id uuid Внутрішній ID каси.
integration_id uuid ID інтеграції.
external_cash_register_id varchar ID каси у Checkbox або локальній системі.
license_key_encrypted text Зашифрований license key.
name varchar Назва каси.
fiscal_number varchar Фіскальний номер ПРРО, якщо доступний.
status varchar Активна, неактивна, помилка.
current_shift_id uuid Поточна зміна.
is_active boolean Чи використовується.

17.3. fiscal_shifts

Поле Тип Опис
id uuid ID зміни.
cash_register_id uuid Каса.
cashier_id varchar Касир.
external_shift_id varchar ID зміни у Checkbox.
status varchar CREATED, OPENED, CLOSED, ERROR тощо.
opened_at timestamp Дата відкриття.
closed_at timestamp Дата закриття.
z_report_id varchar ID Z-звіту.
z_report_number varchar Номер Z-звіту.
raw_request jsonb Запит.
raw_response jsonb Відповідь.
error_message text Остання помилка.

17.4. fiscal_receipts

Поле Тип Опис
id uuid Внутрішній ID чека.
integration_id uuid ID інтеграції.
cash_register_id uuid Каса.
shift_id uuid Зміна.
receipt_uuid uuid UUID чека, який передається в Checkbox.
external_order_id varchar ID замовлення.
external_payment_id varchar ID оплати.
idempotency_key varchar Ключ дедублікації.
receipt_type varchar sale, refund, service.
status varchar Статус чека.
total_amount integer Загальна сума в копійках.
currency varchar Валюта.
fiscal_number varchar Фіскальний номер.
fiscal_url varchar Посилання на чек, якщо доступне.
qr_code text QR або дані QR, якщо доступні.
raw_request jsonb Запит до API.
raw_response jsonb Відповідь API.
error_message text Остання помилка.
created_at timestamp Дата створення.
fiscalized_at timestamp Дата фіскалізації.

17.5. fiscal_receipt_items

Поле Тип Опис
id uuid ID позиції.
receipt_id uuid ID чека.
name varchar Назва товару або послуги.
sku varchar Артикул.
quantity integer Кількість у мінімальних одиницях, якщо використовується масштабування.
unit varchar Одиниця виміру.
price integer Ціна в копійках.
amount integer Сума в копійках.
tax_group varchar Податкова група.
discount_amount integer Знижка в копійках.

17.6. fiscal_payments

Поле Тип Опис
id uuid ID оплати.
receipt_id uuid ID чека.
payment_type varchar CASH, CARD, ONLINE, MIXED.
provider varchar LiqPay, WayForPay, Mono, terminal тощо.
amount integer Сума оплати в копійках.
external_payment_id varchar ID оплати в платіжній системі.

17.7. fiscal_events

Поле Тип Опис
id uuid ID події.
entity_type varchar receipt, shift, integration.
entity_id uuid ID сутності.
event_type varchar Тип події.
old_status varchar Попередній статус.
new_status varchar Новий статус.
payload jsonb Технічні дані.
created_at timestamp Дата події.

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

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

POST /api/v1/fiscal/checkbox/integrations

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

POST /api/v1/fiscal/checkbox/integrations/{integration_id}/check-connection

18.3. Створення чека продажу

POST /api/v1/fiscal/checkbox/receipts

18.4. Створення чека повернення

POST /api/v1/fiscal/checkbox/refund-receipts

18.5. Службове внесення / винесення

POST /api/v1/fiscal/checkbox/service-receipts

18.6. Отримання чека

GET /api/v1/fiscal/checkbox/receipts/{receipt_id}

18.7. Синхронізація статусу чека

POST /api/v1/fiscal/checkbox/receipts/{receipt_id}/sync-status

18.8. Повторна фіскалізація

POST /api/v1/fiscal/checkbox/receipts/{receipt_id}/retry

18.9. Відкриття зміни

POST /api/v1/fiscal/checkbox/shifts/open

18.10. Закриття зміни

POST /api/v1/fiscal/checkbox/shifts/{shift_id}/close

18.11. X-звіт

POST /api/v1/fiscal/checkbox/shifts/{shift_id}/x-report

18.12. Dashboard

GET /api/v1/fiscal/checkbox/dashboard?date_from=2026-05-01&date_to=2026-05-07

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

19.1. Створення чека

from uuid import UUID, uuid4
from datetime import datetime, timezone


def create_fiscal_receipt(command: "CreateReceiptCommand", db: "Session") -> "FiscalReceipt":
    existing = receipt_repository.get_by_idempotency_key(
        db=db,
        idempotency_key=command.idempotency_key,
    )

    if existing:
        return existing

    validation_service.validate_receipt(command)

    receipt = receipt_repository.create(
        db=db,
        data={
            "receipt_uuid": uuid4(),
            "external_order_id": command.external_order_id,
            "external_payment_id": command.external_payment_id,
            "idempotency_key": command.idempotency_key,
            "receipt_type": "sale",
            "status": "PENDING",
            "total_amount": command.total_amount,
            "currency": command.currency,
            "raw_request": command.model_dump(),
        },
    )

    fiscal_queue.enqueue(
        task_name="fiscalize_checkbox_receipt",
        payload={"receipt_id": str(receipt.id)},
    )

    audit_logger.log(
        entity_type="receipt",
        entity_id=receipt.id,
        event_type="RECEIPT_QUEUED",
        payload={"external_order_id": command.external_order_id},
    )

    db.commit()
    return receipt

19.2. Worker фіскалізації

def fiscalize_checkbox_receipt(receipt_id: UUID, db: "Session") -> None:
    receipt = receipt_repository.get_by_id(db, receipt_id)

    if receipt.status == "FISCALIZED":
        return

    try:
        receipt.status = "SENDING"
        db.commit()

        shift = shift_service.ensure_open_shift(
            cash_register_id=receipt.cash_register_id,
            cashier_id=receipt.cashier_id,
            db=db,
        )

        payload = receipt_mapper.to_checkbox_sell_payload(receipt, shift)

        response = checkbox_client.create_sell_receipt(payload)

        receipt.status = "CREATED_IN_CHECKBOX"
        receipt.raw_response = response.raw_payload

        status_response = checkbox_client.get_receipt_status(response.id)

        if status_response.is_fiscalized:
            receipt.status = "FISCALIZED"
            receipt.fiscal_number = status_response.fiscal_number
            receipt.fiscal_url = status_response.fiscal_url
            receipt.qr_code = status_response.qr_code
            receipt.fiscalized_at = datetime.now(timezone.utc)

        audit_logger.log(
            entity_type="receipt",
            entity_id=receipt.id,
            event_type="RECEIPT_SENT_TO_CHECKBOX",
            payload={
                "checkbox_receipt_id": response.id,
                "status": receipt.status,
            },
        )

    except TemporaryFiscalError as exc:
        receipt.status = "NEEDS_RETRY"
        receipt.error_message = str(exc)

    except Exception as exc:
        receipt.status = "FISCALIZATION_ERROR"
        receipt.error_message = str(exc)

    finally:
        db.commit()

19.3. Відкриття зміни

def open_checkbox_shift(
    cash_register_id: UUID,
    cashier_id: str,
    db: "Session",
) -> "FiscalShift":
    cash_register = cash_register_repository.get_by_id(db, cash_register_id)

    current_shift = shift_repository.get_current_open_shift(
        db=db,
        cash_register_id=cash_register.id,
    )

    if current_shift:
        return current_shift

    shift = shift_repository.create(
        db=db,
        data={
            "cash_register_id": cash_register.id,
            "cashier_id": cashier_id,
            "status": "CREATED",
        },
    )

    payload = {
        "id": str(shift.id)
    }

    response = checkbox_client.open_shift(payload)

    shift.external_shift_id = response.id
    shift.status = response.status
    shift.raw_response = response.raw_payload

    audit_logger.log(
        entity_type="shift",
        entity_id=shift.id,
        event_type="SHIFT_OPEN_REQUESTED",
        payload={"checkbox_shift_id": response.id},
    )

    db.commit()
    return shift

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

20.1. Типи помилок

Тип помилки Опис Дія системи
ValidationError Некоректні дані чека. Не відправляти чек, повернути список помилок.
AuthError Невірний API token або відсутній доступ. Зупинити інтеграцію, повідомити адміністратора.
LicenseKeyError Невірний або відсутній license key. Заборонити операції по касі.
CashRegisterError Каса не знайдена або неактивна. Заборонити фіскалізацію.
ShiftError Помилка відкриття або закриття зміни. Записати помилку, дозволити повтор.
FiscalApiError API повернув помилку. Зберегти raw-відповідь, перевести в NEEDS_RETRY або ERROR.
TimeoutError Перевищено час очікування. Виконати retry.
DuplicateReceiptError Чек уже створено. Повернути існуючий чек.
RefundLimitError Сума повернення перевищує доступний залишок. Заборонити повернення.
OfflineModeError Помилка офлайн-режиму або перевищення лімітів. Заблокувати офлайн-операцію та повідомити адміністратора.

20.2. Retry-логіка

Retry застосовується для:

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

Retry не застосовується для:

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

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

21.1. Основні KPI

KPI Опис Колір
Чеків створено Загальна кількість чеків за період. Інформаційний
Фіскалізовано Кількість успішних чеків. Норма
Очікують Чеки в черзі. Увага
Помилки Чеки з помилкою. Критично
Повернення Кількість чеків повернення. Спеціальні операції
Службові операції Кількість внесень і винесень готівки. Контроль
Незакриті зміни Каси з відкритими змінами. Потрібна дія

21.2. Приклад dashboard

Показник Значення Стан
Чеків за день 1240 Інформація
Фіскалізовано 1218 Норма
Очікують у черзі 12 Увага
Помилки фіскалізації 7 Критично
Повернення 14 Контроль
Службові внесення / винесення 6 Контроль
Незакриті зміни 2 Потрібна дія

21.3. Список проблемних операцій

Час Каса Замовлення Сума Статус Помилка Дія
10:42 Каса 1 ORDER-123 570.00 Помилка Timeout API Повторити
11:05 Каса 2 ORDER-124 1200.00 Потребує повтору Тимчасова помилка Повторити
12:10 Каса 3 SHIFT-55 - Зміна відкрита Не закрито Z-звіт Закрити зміну

22. Безпека

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

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

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

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

Подія Що зберігати
Створення чека external_order_id, сума, каса, касир.
Відправка в API endpoint, час, request_id.
Успішна фіскалізація fiscal_number, fiscal_url, дата.
Помилка фіскалізації код помилки, повідомлення, raw-відповідь.
Повторна обробка хто запустив, коли, результат.
Повернення первинний чек, сума, причина.
Службова операція тип, сума, каса, касир.
Відкриття зміни каса, касир, час.
Закриття зміни Z-звіт, час, результат.
Зміна налаштувань користувач, старі та нові параметри.

24. Acceptance Criteria

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

Критерій Очікуваний результат
AC-1 Адміністратор створює інтеграцію Checkbox. Інтеграція зберігається в системі.
AC-2 Адміністратор перевіряє підключення. Система повертає успішний або помилковий статус.
AC-3 Токен неправильний. Система показує AuthError і не виконує фіскалізацію.
AC-4 License key неправильний. Система блокує операції по касі.

24.2. Чеки

Критерій Очікуваний результат
AC-5 ERP передає продаж. Python-сервіс створює чек зі статусом PENDING.
AC-6 Checkbox повертає успіх. Чек отримує статус FISCALIZED.
AC-7 Чек фіскалізовано. У БД зберігається fiscal_number.
AC-8 Повторний запит має той самий idempotency_key. Другий чек не створюється.
AC-9 API повертає тимчасову помилку. Чек переходить у NEEDS_RETRY.

24.3. Повернення

Критерій Очікуваний результат
AC-10 Користувач створює повернення. Система створює чек повернення.
AC-11 Сума повернення більша за суму продажу. Система блокує операцію.
AC-12 Повернення успішне. Первинний чек отримує ознаку повного або часткового повернення.

24.4. Зміни

Критерій Очікуваний результат
AC-13 Перед першим чеком зміна закрита. Система відкриває зміну, якщо auto_open_shift = true.
AC-14 Користувач закриває зміну. Система формує Z-звіт.
AC-15 Є незавершені чеки. Система попереджає перед закриттям зміни.
AC-16 Статус зміни змінився у Checkbox. Python-сервіс синхронізує локальний статус.

24.5. Службові операції

Критерій Очікуваний результат
AC-17 Користувач створює службове внесення. Система створює service receipt.
AC-18 Користувач створює службове винесення. Система створює service receipt з відповідним напрямком суми.
AC-19 Сума службової операції некоректна. Система блокує операцію.

24.6. Dashboard

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

25. MVP

До MVP входить:

  • створення інтеграції Checkbox;
  • перевірка підключення;
  • збереження token і license key;
  • створення чека продажу;
  • створення чека повернення;
  • службове внесення / винесення готівки;
  • валідація чеків;
  • дедублікація;
  • черга фіскалізації;
  • відкриття зміни;
  • закриття зміни;
  • отримання статусу чека;
  • отримання статусу зміни;
  • збереження fiscal_number;
  • журнал подій;
  • retry-механізм;
  • dashboard API;
  • базові unit-тести;
  • mock API для інтеграційних тестів.

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

  • повноцінний POS UI;
  • власний ПРРО;
  • інтеграція з усіма еквайрингами;
  • складна аналітика;
  • автоматична реєстрація ПРРО в ДПС;
  • повна підтримка офлайн-режиму;
  • повна підтримка всіх нестандартних податкових сценаріїв.

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

Етап 1. Базова структура сервісу

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

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

  • реалізувати створення інтеграції;
  • реалізувати зберігання токена;
  • реалізувати зберігання license key;
  • реалізувати check-connection;
  • реалізувати права доступу.

Етап 3. Checkbox Client

  • реалізувати клієнт API;
  • реалізувати авторизацію;
  • реалізувати заголовки X-Client-Name, X-Client-Version, X-License-Key;
  • реалізувати open_shift;
  • реалізувати close_shift;
  • реалізувати create_sell_receipt;
  • реалізувати create_refund_receipt;
  • реалізувати create_service_receipt;
  • реалізувати get_status;
  • реалізувати отримання візуалізації;
  • реалізувати обробку помилок.

Етап 4. Чеки

  • реалізувати створення чеків;
  • реалізувати валідацію;
  • реалізувати дедублікацію;
  • реалізувати чергу;
  • реалізувати worker фіскалізації.

Етап 5. Повернення

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

Етап 6. Службові операції

  • реалізувати службове внесення;
  • реалізувати службове винесення;
  • реалізувати права доступу до службових операцій;
  • реалізувати аудит.

Етап 7. Зміни та звіти

  • реалізувати відкриття зміни;
  • реалізувати закриття зміни;
  • реалізувати X-звіт;
  • реалізувати контроль незакритих змін.

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

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

Етап 9. Production hardening

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

27. Ризики

Ризик Опис Як зменшити
Дублювання чеків Повторний запит може створити другий чек. Idempotency key, receipt_uuid і дедублікація.
Втрата чека API недоступне під час продажу. Черга, retry, статус NEEDS_RETRY.
Незакрита зміна Касир або система не закрили зміну. Dashboard, нагадування, авто-закриття за правилом.
Невірні суми Сума товарів не відповідає оплатам. Валідація перед фіскалізацією.
Помилки токена Токен змінено або відкликано. Check-connection і сповіщення адміністратора.
Невірний license key Каса не може виконувати операції. Валідація налаштувань каси.
Невірна податкова група Товар передано з неправильним податком. Довідник tax_group і валідація.
Конфлікт фронт-агентів По одній касі одночасно працюють різні інтеграції. Заборонити змішування сценаріїв для однієї каси.
Офлайн-режим Є обмеження й додаткові правила для офлайн-операцій. Вмикати тільки після окремого погодження.

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

  1. Який сценарій інтеграції використовується: WebAPI, Checkbox Kasa Manager або гібрид?
  2. Чи потрібна підтримка локального друку чеків?
  3. Чи потрібно відправляти чек покупцю через email/SMS?
  4. Які типи оплат підтримуються?
  5. Які платіжні провайдери використовуються?
  6. Чи потрібна інтеграція з POS-терміналами?
  7. Чи потрібно автоматично відкривати зміну?
  8. Чи потрібно автоматично закривати зміну?
  9. Чи потрібна підтримка часткових повернень?
  10. Чи потрібна підтримка змішаних оплат?
  11. Чи потрібно зберігати HTML/PNG/TXT чека локально?
  12. Чи потрібен QR-code у внутрішній системі?
  13. Який SLA по фіскалізації?
  14. Чи потрібен dashboard у UI, чи тільки API?
  15. Чи потрібна інтеграція з K2 ERP?
  16. Які податкові групи товарів використовуються?
  17. Чи потрібна підтримка декількох юридичних осіб?
  18. Чи потрібна підтримка декількох торгових точок?
  19. Чи дозволяється офлайн-режим?
  20. Чи потрібна підтримка службового внесення / винесення готівки?

29. Джерела

30. Див. також