| id
|
uuid
|
-
|
created_at
|
timestamp
|
Python-сервіс синхронізує локальний статус.; |-
|
Відкриття зміни
|
Вони підсвічуються червоним.; | Довідник tax_group і валідація.; Очікуваний результат
<div style="border-left: 6px solid #1565c0; background: #e3f2fd; padding: 12px 16px; margin: 16px 0;">
=== 8.4.; Чек повернення ===
<pre>
=== 19.1.; Створення чека ===
!;== 17.; Модель даних ==
* створити FastAPI-проєкт;
* налаштувати PostgreSQL;
* створити моделі інтеграції, кас, змін, чеків;
* налаштувати Alembic;
* реалізувати healthcheck.;
class CheckboxClient:
"unit": "шт"
1.; Очікуваний результат
allow_offline_mode: bool = False
except Exception as exc:
{| class="wikitable"
!;== 26.; Етапи реалізації ==
POST /api/v1/fiscal/checkbox/receipts/{receipt_id}/sync-status
"external_order_id": command.external_order_id,
<pre>
!; | style="background:#f3e5f5;" | Спеціальні операції
|-
| Службові операції
| Кількість внесень і винесень готівки.; |-
| shift_id
| uuid
| Зміна.; | style="background:#bbdefb;" | Блакитний
|-
| Відкрита
| OPENED
| Можна фіскалізувати чеки.; # Чи потрібна супровід змішаних оплат?; |-
| items
| array
| Позиції, які повертаються.; # Чи потрібна супровід службового внесення / винесення готівки?; Worker перевіряє зміну.; |-
| cash_register_id
| uuid
| Каса.; | style="background:#ef9a9a;" | Критично
|-
| Повернення
| Кількість чеків повернення.; У межах цього ТЗ ключовий сценарій.; Колір
=== 8.7.; Закриття зміни ===
|-
| id
| uuid
| Внутрішній ID чека.;<pre>
* реалізувати замовник 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;
* реалізувати отримання візуалізації;
* реалізувати обробку помилок.; # Чи потрібна інтеграційні функціональні можливості з POS-терміналами?; Тип
=== Етап 5.; Повернення ===
== 24. Acceptance Criteria ==
9.; |}
!; |-
| api_token
| secret
| Так
| Токен авторизації.; shift.raw_response = response.raw_payload
Перед фіскалізацією платформа повинна перевірити:
=== 17.2. cash_registers ===
</div>
Сценарії:
=== 18.9.; Відкриття зміни ===
{
pass
validation_service.validate_receipt(command)
</pre>
== 22.; Безпека ==
=== Етап 3.; Checkbox Client ===
"quantity": 2000,
платформа повинна підтримувати створення чека повернення.; |-
| AC-21
| є собою помилки фіскалізації.; |-
| RefundLimitError
| Сума повернення перевищує доступний залишок.; |-
| FiscalApiError
| API повернув помилку.; Параметр
</pre>
=== 24.4.; Зміни ===
</div>
v
Логічний endpoint:
db.commit()
!; |-
| created_at
| timestamp
| Дата створення.; Колір
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
<syntaxhighlight lang="python">
!; |-
| Shift Service
| Відкриття, контроль і закриття змін.; |-
| Офлайн-відкриття
| Дозволяється тільки за окремим налаштуванням і правилами Checkbox.; |-
| Checkbox API
| REST API для інтеграції з eCommerce / ERP / CRM / POS.; | style="background:#ef9a9a;" | Червоний
|-
| Потребує повтору
| NEEDS_RETRY
| Можна повторити відправку.; |-
| customer
| object
| інформаційні дані покупця.; |}
!; характеристика
<pre>
Retry застосовується для:
=== 24.2.; Чеки ===
!;=== 12.1.; Загальна схема ===
* додати rate limiting;
* додати alerting;
* додати retry policy;
* додати dead letter queue;
* додати моніторинг;
* додати резервне копіювання.; |-
| Відправка в API
| endpoint, час, request_id.; | Check-connection і сповіщення адміністратора.; Дія
|-
| AC-10
| користувач системи створює повернення.; | платформа блокує операцію.; Сума
if current_shift:
receipt.qr_code = status_response.qr_code
<pre>
!; | платформа формує Z-звіт.; ERP / CRM / сайт отримує статус.; |}
}
pass
== 25. MVP ==
=== 18.2.; Перевірка підключення ===
def check_connection(self) -> "ConnectionStatus":
|-
| id
| uuid
| ID події.; Статус
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
POST /api/v1/fiscal/checkbox/shifts/{shift_id}/close
=== 18.7.; Синхронізація статусу чека ===
До першої версії не входить:
!; Коментар
* акаунт у Checkbox;
* зареєстрованого торговця;
* торгову точку;
* зареєстровану касу / ПРРО;
* касира;
* спосіб підпису чеків;
* доступ до API;
* токен авторизації;
* license key каси;
* назву інтеграції для заголовка X-Client-Name;
* версію інтеграції для заголовка X-Client-Version;
* тестове середовище або тестову касу, якщо доступно;
* перелік кас, які будуть використовуватись;
* перелік касирів;
* правила відкриття і закриття зміни;
* правила формування чеків;
* правила повернень;
* формат оплати;
* формат товарних позицій;
* формат податкових ставок;
* вимоги до відправки електронного чека покупцю.; | style="background:#fff9c4;" | Жовтий
|-
| Відкривається
| OPENING
| Виконується відкриття зміни.; |-
| Refund Receipt
| Чек повернення.;=== Етап 2.; конфігурація інтеграції ===
|-
| Ручне відкриття
| користувач системи або адміністратор відкриває зміну.; |}
shift = shift_repository.create(
'''Критично істотно:''' чек повернення повинен бути пов'язаний із первинним чеком.; Статус / номер / посилання / візуалізація
CHECKBOX_TIMEOUT_SECONDS=30
!; # Чи потрібна супровід декількох юридичних осіб?; # Чи потрібно автономно відкривати зміну?; |-
| payload
| jsonb
| Технічні інформаційні дані.; |-
| Невірні суми
| Сума товарів не відповідає оплатам.; |-
| name
| varchar
| Назва товару або послуги.; Показник
def open_shift(self, payload: "OpenShiftPayload") -> "ShiftResponse":
def get_receipt_qrcode(self, receipt_id: str) -> bytes:
def get_receipt_status(self, receipt_id: str) -> "ReceiptStatusResponse":
!; },
from datetime import datetime, timezone
v
},
POST /api/v1/fiscal/checkbox/integrations
=== 17.4. fiscal_receipts ===
=== Етап 9.; Production hardening ===
|-
| integration_name
| string
| Так
| Назва інтеграції.; Каса
"external_payment_id": command.external_payment_id,
=== Етап 6.; Службові операції ===
До MVP не входить:
"cash_register_id": cash_register.id,
__TOC__
"payment_id": "PAY-123456"
entity_type="receipt",
<pre>
payload={"external_order_id": command.external_order_id},
payload={
платформа повинна підтримувати отримання проміжного X-звіту без закриття зміни.; |-
| fiscalized_at
| timestamp
| Дата фіскалізації.; Очікуваний результат
=== 19.3.; Відкриття зміни ===
"quantity": 1000,
!; Checkbox API
{| class="wikitable"
!; | style="background:#fff9c4;" | Жовтий
|-
| Відправляється
| SENDING
| Виконується API-запит.; | style="background:#eeeeee;" | Сірий
|-
| Очікує фіскалізації
| PENDING
| Чек у черзі на відправку.; Тип
=== 13.1.; Призначення ===
== 14.; Валідація чека ==
Метою задачі є собою створення Python-сервісу для інтеграції з ПРРО Checkbox з метою автоматизації фіскалізації продажів, повернень, службових операцій і касових змін.; |-
| auto_close_shift
| boolean
| Ні
| автономно закривати зміну за розкладом.; |-
| Фізичні магазини
| Через Checkbox Kasa Manager або інший фронт-агент.; Тип
Логічні endpoint-и Python-сервісу:
entity_id=receipt.id,
POST /api/v1/fiscal/checkbox/shifts/open
=== 18.10.; Закриття зміни ===
!; Помилка
{| class="wikitable"
],
"name": "Доставка",
</div>
=== 17.7. fiscal_events ===
{| class="wikitable"
</pre>
x_client_name: str
Мінімальні інформаційні дані:
платформа повинна підтримувати службові касові операції:
* прийом замовлень, продажів або оплат із зовнішньої системи;
* створення фіскального чека продажу;
* створення чека повернення;
* створення службового внесення готівки;
* створення службового винесення готівки;
* контроль відкриття касової зміни;
* контроль закриття касової зміни;
* формування X-звіту;
* формування Z-звіту;
* отримання статусів чеків;
* отримання статусів змін;
* збереження фіскальних номерів;
* збереження посилання або візуалізації чека;
* отримання HTML / PNG / TXT / QR-візуалізації чека, якщо потрібно;
* відправку електронного чека покупцю, якщо підтримується налаштуваннями;
* журналювання всіх API-запитів;
* повторну обробку помилкових операцій;
* захист від дублювання чеків;
* передачу статусів назад в ERP / CRM / сайт / POS.; |-
| Refund Service
| Створення чеків повернення.; |-
| z_report_number
| varchar
| Номер Z-звіту.; актуалізація ERP / CRM / POS
!; Дія системи
response = checkbox_client.open_shift(payload)
</div>
!; |-
| x_client_version
| string
| Так
| реліз інтеграції для заголовка X-Client-Version.; |-
| status
| varchar
| Активна, неактивна, помилка.; Що зберігати
|-
| Підходить для
| Хмарних ERP, CRM, інтернет-магазинів, SaaS-систем.; Призначення
{| class="wikitable"
CHECKBOX_DEFAULT_CASH_REGISTER_ID=cash-register-001
pass
|-
| id
| uuid
| ID оплати.; |-
| Service Receipt Service
| Службове внесення та винесення готівки.; |}
POST /api/v1/fiscal/checkbox/receipts
== 3.; Джерела інтеграції ==
"amount": 57000,
</div>
retry_backoff_seconds: int = 5
* службове внесення готівки;
* службове винесення готівки.; v
v
|-
| Створення чека
| external_order_id, сума, каса, касир.; |-
| receipt_id
| uuid
| ID чека.;== 23.; Логування та аудит ==
</pre>
POST /api/v1/fiscal/checkbox/service-receipts
if receipt.status == "FISCALIZED":
</pre>
'''Технічний стек:''' Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker.; | Він бачить кількість чеків, помилок, повернень, службових операцій і незакритих змін.; |-
| allow_offline_mode
| boolean
| Ні
| Чи дозволена офлайн-робота.; |-
| Помилка фіскалізації
| код помилки, повідомлення, raw-відповідь.; | Заборонити повернення.; |}
=== 17.6. fiscal_payments ===
!; Поле
},
CHECKBOX_ALLOW_OFFLINE_MODE=false
<div style="border-left: 6px solid #6a1b9a; background: #f3e5f5; padding: 12px 16px; margin: 16px 0;">
"total_amount": 57000,
=== 12.2.; Основні компоненти Python-сервісу ===
* наявність external_order_id;
* наявність idempotency_key;
* відсутність уже фіскалізованого чека по цьому external_order_id;
* наявність каси;
* наявність license key;
* наявність касира;
* наявність відкритої зміни або можливість її відкрити;
* наявність хоча б однієї позиції;
* коректність кількості;
* коректність ціни;
* коректність суми рядка;
* відповідність total_amount сумі товарів і оплат;
* коректність типу оплати;
* коректність податкових груп;
* коректність email або телефону покупця, якщо чек потрібно відправити;
* коректність формату UUID для операцій, які вимагають UUID.; |-
| currency
| varchar
| Валюта.; |-
| Service Receipt
| Службове внесення або винесення готівки.; |-
| ДПС
| Кінцевий отримувач фіскальних даних через ПРРО.; |-
| Status Sync Worker
| актуалізація статусів чеків і змін.; |-
| X Report
| Проміжний звіт без закриття зміни.; | Черга, статуси API.; 2.; Поле
<pre>
!; характеристика
return current_shift
платформа повинна підтримувати відкриття касової зміни.; | Зупинити інтеграцію, повідомити адміністратора.; # Чи потрібен QR-code у внутрішній системі?; Подія
* реалізувати відкриття зміни;
* реалізувати закриття зміни;
* реалізувати X-звіт;
* реалізувати контроль незакритих змін.; |-
| cash_register_id
| string
| Каса.; | style="background:#e3f2fd;" | Інформаційний
|-
| Фіскалізовано
| Кількість успішних чеків.; |-
| ERP / CRM / сайт / POS
| Джерело продажів, повернень, оплат і даних покупця.;</div>
{
"name": "Іван Петренко",
* перевірити відкриту зміну;
* перевірити незавершені чеки;
* сформувати Z-звіт;
* зберегти результат;
* змінити статус зміни на Closed;
* записати подію в журнал.; |-
| discount_amount
| integer
| Знижка в копійках.; №
"amount": 50000,
{| class="wikitable"
</pre>
Приклад змінних середовища:
!; |-
| original_fiscal_number
| string
| Фіскальний номер первинного чека.; |-
| Повторна обробка
| хто запустив, коли, результат.; | style="background:#c8e6c9;" | Зелений
|-
| Помилка фіскалізації
| FISCALIZATION_ERROR
| Виникла помилка при фіскалізації.;</div>
!; | Dashboard, список чеків, касові зміни.; |-
| Помилки токена
| Токен змінено або відкликано.; |-
| payments
| array
| Оплати.; | style="background:#c8e6c9;" | Зелений
|-
| Закривається
| CLOSING
| Виконується закриття зміни.; |-
| style="background:#bbdefb;" | Блакитний
| #bbdefb
| операційна дія виконується або в роботі.; Валідація, дедублікація, черга
!; |-
| API Layer
| REST API для прийому продажів, повернень, службових операцій, команд зміни.; |-
| z_report_id
| varchar
| ID Z-звіту.; Обов'язковість
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
{| class="wikitable"
!; | style="background:#eeeeee;" | Сірий
|-
| Створюється
| CREATED
| Створено запит на відкриття зміни.;</pre>
}
pass
!;<pre>
* реалізувати dashboard API;
* реалізувати журнал подій;
* реалізувати фільтри;
* реалізувати експорт, якщо потрібно.; default_license_key: str | None = None
</pre>
!; |-
| amount
| integer
| Сума в копійках.; |-
| idempotency_key
| string
| Ключ дедублікації.; Ключ
}
платформа повинна підтримувати синхронізацію статусу чека з Checkbox.; Поле
"raw_request": command.model_dump(),
receipt.error_message = str(exc)
!; |-
| Shift
| Касова зміна.; | style="background:#bbdefb;" | Блакитний
|-
| Фіскалізовано
| FISCALIZED
| Чек успішно фіскалізовано.; '''Критично істотно:''' інтеграційні функціональні можливості з ПРРО не повинна втрачати чеки.; |-
| cashier_id
| string
| Ні
| ID касира за замовчуванням.; |}
class CheckboxSettings(BaseSettings):
21.1.; Основні KPIreceipt.status = "FISCALIZED"
{
| AC-17
|
-
|
external_payment_id
|
varchar
|
-
|
Незакрита зміна
|
Касир або платформа не закрили зміну.; payload = receipt_mapper.to_checkbox_sell_payload(receipt, shift)
28.; Відкриті питання
21.; Dashboard керівника
| ; {
CHECKBOX_DEFAULT_CASHIER_ID=cashier-001
щоб контролювати фіскалізацію, помилки, повернення і незакриті зміни.; Тип
- timeout;
- тимчасової недоступності API;
- HTTP 429;
- HTTP 500;
- HTTP 502;
- HTTP 503;
- HTTP 504;
- мережевих помилок;
- тимчасових помилок статусу.; | Draft, Cancelled, Closed.; |}
|
-
|
Завантаження візуалізації чека
|
Низький
|
Не блокує фіскалізацію.; Де застосовується
"cashier_id": cashier_id,
if existing:
ERP / CRM / Website / POS
POST /api/v1/fiscal/checkbox/receipts/{receipt_id}/sync-status
щоб не втратити продаж.; характеристика
cashier_id: str,
Логічний endpoint:
17.1. fiscal_integrations
; Час
)
8.1.; конфігурація інтеграції
18.4.; Створення чека повернення
платформа повинна логувати:
|
-
|
Fiscal Status
|
Статус фіскалізації.; HTML
POST /api/v1/fiscal/checkbox/service-receipts
db: "Session",
До MVP входить:
entity_type="shift",
|
-
|
Єдиний dashboard
|
Керівник бачить усі чеки, каси, статуси й помилки в одному місці.; характеристика
],
Checkbox Client — це Python-клас або пакет, який інкапсулює роботу з Checkbox API.; |-
|
Особистий кабінет Checkbox
|
Керування торговими точками, касами, касирами.; )
|
;
) -> "FiscalShift":
я хочу передати інформацію про оплату в Python-сервіс,
5.; |-
| Обмеження
|
Idempotency key, receipt_uuid і дедублікація.; Компонент
| 10:42
|
Каса 1
|
ORDER-123
|
570.00
|
Помилка
|
Timeout API
|
Повторити
|
| 11:05
|
Каса 2
|
ORDER-124
|
1200.00
|
Потребує повтору
|
Тимчасова помилка
|
Повторити
|
| 12:10
|
Каса 3
|
SHIFT-55
|
-
|
Зміна відкрита
|
Не закрито Z-звіт
|
Закрити зміну
|
db=db,
|
-
|
amount
|
integer
|
-
|
Перевірка перед чеком
|
Якщо зміна вже відкрита, повторно не відкривати.;
finally:
entity_id=receipt.id,
7.5.; Повторна обробка
19.2.; Worker фіскалізації
|
| Checkbox
|
-
|
event_type
|
varchar
|
-
|
idempotency_key
|
varchar
|
-
|
reason
|
string
|
-
|
Червоний
|
#ef9a9a
|
Помилка або критична ситуація.; характеристика
"provider": "liqpay",
POST /api/v1/fiscal/checkbox/shifts/{shift_id}/close
pass
|
; Пріоритет
shift.external_shift_id = response.id
| Не відкрита
|
CLOSED
|
-
|
CashRegisterError
|
-
|
entity_type
|
varchar
|
receipt, shift, integration.; Замовлення
- зберігання токенів тільки у secret storage або в зашифрованому вигляді;
- зберігання license key тільки у secret storage або в зашифрованому вигляді;
- заборону логування токенів;
- маскування персональних даних покупців;
- обмеження доступу до чеків;
- контроль доступу до повернень;
- окремі права на закриття зміни;
- окремі права на службове винесення готівки;
- журнал усіх дій;
- HTTPS для API-запитів;
- перевірку SSL;
- обмеження повторних запитів;
- захист від дублювання чеків.; |-
|
external_shift_id
|
varchar
|
-
|
fiscal_operation_type
|
string
|
sale.; характеристика
"status": "CREATED",
|
; інформаційні дані проходять валідацію.; Параметр
POST /api/v1/fiscal/checkbox/integrations/{integration_id}/check-connection
GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/html
GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/qrcode
| id
|
uuid
|
ID позиції.; Якщо зміна не відкрита і auto_open_shift = true, worker відкриває зміну.;=== 18.6.; Отримання чека ===
return existing
payload={"receipt_id": str(receipt.id)},
платформа повинна підтримувати закриття касової зміни та формування Z-звіту.; | Черга чеків, pending-операції.; істотно: для інтеграції з Checkbox комфортно зберігати суми в копійках, щоб уникати помилок округлення у фінансових операціях.; |-
|
name
|
varchar
|
Заблокувати офлайн-операцію та повідомити адміністратора.; |-
|
Checkbox Client
|
style="background:#bbdefb;" | Блакитний
|
| Створено в Checkbox
|
CREATED_IN_CHECKBOX
|
Retry, незавершені операції.; |}
verify_ssl: bool = True
|
;
8.11.; Відправка чека покупцю
return receipt
status_response = checkbox_client.get_receipt_status(response.id)
Варіант 1.; 5.1.; WebAPI для eCommerceCHECKBOX_API_TOKEN=********
Етап 1.; Базова структура сервісу"tax_group": "NO_VAT",
| -
|
Основні операції
|
Фіскалізація чеків, робота касира, контроль зміни.; Сценарій
x_client_version: str
pass
def create_x_report(self, shift_id: str) -> "XReportResponse":
Мінімальні інформаційні дані:
18.5.; Службове внесення / винесення
| -
|
total_amount
|
integer
|
Загальна сума в копійках.; Поле
|
; !; Тип
payload = {
я хочу фіксувати службове внесення або винесення готівки,
)
!; |-
| currency
| string
| Валюта.; | Refund, сторно, коригування.; |-
| Receipt
| Фіскальний чек продажу.; |-
| provider
| varchar
| LiqPay, WayForPay, Mono, terminal тощо.; |-
| closed_at
| timestamp
| Дата закриття.; |-
| updated_at
| timestamp
| Дата актуалізація.; |-
| Обмеження
| Потрібна інсталяція й супровід агентів.; |-
| Конфлікт фронт-агентів
| По одній касі одночасно працюють різні інтеграції.; | Чек переходить у NEEDS_RETRY.; |-
| entity_id
| uuid
| ID сутності.; Поле
* реалізувати чек повернення;
* перевірити доступний залишок повернення;
* зв'язати повернення з первинним чеком.; Поле
POST /api/v1/fiscal/checkbox/shifts/{shift_id}/x-report
ДПС
pass
!; |-
| AC-3
| Токен неправильний.; receipt = receipt_repository.get_by_id(db, receipt_id)
* реалізувати створення інтеграції;
* реалізувати зберігання токена;
* реалізувати зберігання license key;
* реалізувати check-connection;
* реалізувати права доступу.; Worker викликає Checkbox API.; "cashier_id": "cashier-001",
* повноцінний POS-інтерфейс касира;
* власна реалізація ПРРО без Checkbox;
* самостійна реєстрація ПРРО в ДПС через Python-сервіс;
* власний компонент КЕП;
* інтеграційні функціональні можливості з усіма еквайрингами;
* складний UI для касира;
* заміна кабінету Checkbox;
* повна офлайн-робота без окремого погодженого сценарію.; |-
| allow_offline_mode
| boolean
| Чи дозволений офлайн.;== 18.; API Python-сервісу ==
* реалізувати службове внесення;
* реалізувати службове винесення;
* реалізувати права доступу до службових операцій;
* реалізувати аудит.; |-
| Успішна фіскалізація
| fiscal_number, fiscal_url, дата.; |-
| Службова операційна дія
| тип, сума, каса, касир.; Поле
"total_amount": command.total_amount,
=== Етап 4.; Чеки ===
def create_service_receipt(self, payload: "ServiceReceiptPayload") -> "ReceiptResponse":
def create_fiscal_receipt(command: "CreateReceiptCommand", db: "Session") -> "FiscalReceipt":
!; |-
| total_amount
| integer
| Загальна сума чека в копійках.; |-
| cash_register_id
| uuid
| Каса.;<pre>
я хочу бачити, чи відкрита касова зміна,
'''Заборонено:''' зберігати API token, license key, ключі, паролі касирів або інші секрети у коді, Git-репозиторії, відкритих логах або frontend-змінних.; платформа не повинна дозволяти створювати повернення на суму більшу, ніж залишок доступний до повернення.; |}
from uuid import UUID, uuid4
!; | Черга, retry, статус NEEDS_RETRY.; |-
| reason
| string
| Коментар або причина.; POST /api/v1/fiscal/checkbox/receipts/{receipt_id}/retry
=== 8.6.; Відкриття зміни ===
=== 16.1.; Логіка черги ===
Приклад hash:
data={
Python-сервіс, який функціонує з API Checkbox виступає ключовою рисою '''істотно:''' Checkbox має декілька сценаріїв роботи: WebAPI для eCommerce, Checkbox Kasa Manager для retail/POS-сценаріїв, мобільний застосунок та кабінет.; Статус
cash_register_id=receipt.cash_register_id,
Як адміністратор каси,
=== 7.6.; Контроль керівника ===
receipt.fiscalized_at = datetime.now(timezone.utc)
!; |-
| Deduplication Service
| Захищає від повторної фіскалізації одного продажу.; |-
| name
| varchar
| Назва каси.; | Чек отримує статус FISCALIZED.; | платформа створює service receipt.; | style="background:#bbdefb;" | Блакитний
|-
| Закрита
| CLOSED_WITH_Z_REPORT
| Зміна закрита із Z-звітом.; характеристика
def create_sell_receipt(self, payload: "SellReceiptPayload") -> "ReceiptResponse":
"status": "PENDING",
!; | Вони підсвічуються помаранчевим.; |-
| x_client_version
| varchar
| реліз інтеграції.; |-
| external_payment_id
| varchar
| ID оплати в платіжній системі.; |-
| cashier_id
| string
| Касир.; |-
| is_active
| boolean
| Так
| Ознака активності інтеграції.; характеристика
!; |-
| old_status
| varchar
| Попередній статус.; | style="background:#c8e6c9;" | Норма
|-
| Очікують
| Чеки в черзі.; receipt.status = "FISCALIZATION_ERROR"
"external_order_id": "ORDER-2026-000123",
щоб касові операції були відображені в системі.; щоб він автономно створив фіскальний чек у Checkbox.; характеристика
"phone": "+380501112233"
!; характеристика
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
!; |-
| OfflineModeError
| Помилка офлайн-режиму або перевищення лімітів.; |-
| fiscal_number
| varchar
| Фіскальний номер ПРРО, якщо доступний.; | має змогу використовуватись у локальних інтеграціях.; |-
| AC-9
| API повертає тимчасову помилку.; |-
| переважні аспекти
| Пряме API, зручна автоматизація процесів, можливість працювати з чергою.; |-
| idempotency_key
| Унікальний ключ запиту.; |-
| Службове внесення / винесення
| Середній
| Касова технічна операційна дія.; | style="background:#ffcc80;" | Потрібна дія
|}
!; |-
| Receipt Service
| Створення чеків продажу.; # Чи дозволяється офлайн-режим?; Як зменшити
[[Категорія:Checkbox]]
!; |-
| AC-6
| Checkbox повертає успіх.; |-
| API Event
| Технічна подія інтеграції.; |-
| Python-сервіс
| Інтеграційний шар між ERP / сайтом / CRM / POS та Checkbox.; Критерій
"price": 25000,
=== 8.10.; Отримання візуалізації чека ===
)
<syntaxhighlight lang="python">
== 1.; Мета ==
'''Критично істотно:''' якщо зміна відкривається через API, потрібно уникати паралельних дій через інші фронт-агенти по тій самій касі, щоб не отримати неконсистентні стани, помилкові звіти або конфлікти в роботі каси.; !; |-
| created_at
| timestamp
| Дата створення.; |-
| raw_response
| jsonb
| Відповідь.; | Python-сервіс напряму з ДПС у MVP не функціонує.; |-
| Втрата чека
| API недоступне під час продажу.; |-
| Повернення
| первинний чек, сума, причина.; |-
| idempotency_key
| string
| Ключ захисту від дублювання.; |-
| Cashier
| Касир, від імені якого виконується операційна дія.; |-
| receipt_type
| varchar
| sale, refund, service.; |-
| style="background:#ffcc80;" | Помаранчевий
| #ffcc80
| Потрібна дія або повтор.; Ризик
<pre>
[[Категорія:Інтеграції]]
|-
| Дублювання чеків
| Повторний запит має змогу створити другий чек.; |-
| License Key
| Ключ ліцензії каси, який застосовується в запитах до API.; | У БД зберігається fiscal_number.; №
|
| 7.; характеристика
!; | застосовується для конфігурація.; |-
| receipt_id
| uuid
| ID чека.; |-
| organization_id
| varchar
| Організація.; |}
event_type="RECEIPT_SENT_TO_CHECKBOX",
cash_register_id=cash_register.id,
=== Варіант 2.; 5.2.; Checkbox Kasa Manager === застосовують, коли потрібно для retail/POS-сценаріїв, коли касовий вузол має локальний агент.; !; |-
| current_shift_id
| uuid
| Поточна зміна.; Критерій
shift = shift_service.ensure_open_shift(
db=db,
receipt.status = "CREATED_IN_CHECKBOX"
16.2.; Пріоритети задач
sha256(external_order_id + total_amount + payment_id + cash_register_id)
POST /api/v1/fiscal/checkbox/refund-receipts
data={
|
; Поле
receipt.error_message = str(exc)
|
}
fiscal_queue.enqueue(
|
-
|
cash_register_id
|
string
|
Каса / ПРРО.; Тип задачі
я хочу бачити dashboard по касах і чеках,
Як оператор або ERP,
db.commit()
GET /api/v1/fiscal/checkbox/receipts/{receipt_id}/text
shift.status = response.status
4.; Передумови
"idempotency_key": "ORDER-2026-000123-PAY-123456",
"status": receipt.status,
|
платформа повертає успішний або помилковий статус.; | ключовий канал для Python-сервісу.; response = checkbox_client.create_sell_receipt(payload)
"price": 7000,
До області задачі входить:
!; | style="background:#c8e6c9;" | Зелений
|-
| Помилка
| ERROR
| Помилка відкриття або закриття зміни.; v
!; |-
| payment_type
| varchar
| CASH, CARD, ONLINE, MIXED.; pass
Логічний endpoint:
!; | платформа блокує операцію.; |-
| send_receipt_to_customer
| boolean
| Ні
| Відправляти чек покупцю.; |-
| Закриття зміни
| Критичний
| Не можна залишати зміну незакритою.; * реалізувати створення чеків;
* реалізувати валідацію;
* реалізувати дедублікацію;
* реалізувати чергу;
* реалізувати worker фіскалізації.; |-
| style="background:#fff9c4;" | Жовтий
| #fff9c4
| Очікування або попередження.; |-
| cash_register_id
| string
| Так
| ID каси / ПРРО у локальній системі.; Checkbox Adapter
current_shift = shift_repository.get_current_open_shift(
}
|-
| original_receipt_id
| uuid
| Внутрішній ID первинного чека.; | платформа створює чек повернення.; | як ілюстрація K2 ERP або інша платформа.; |-
| style="background:#eeeeee;" | Сірий
| #eeeeee
| Неактивно або скасовано.; |}
"amount": 7000,
== 30.; Див.; додатково ==
)
api_token: str
POST /api/v1/fiscal/checkbox/receipts
|-
| id
| uuid
| ID зміни.; # Які типи оплат підтримуються?; | платформа показує AuthError і не виконує фіскалізацію.;[[Категорія:K2 ERP]]
* повноцінний POS UI;
* власний ПРРО;
* інтеграційні функціональні можливості з усіма еквайрингами;
* складна аналітичні інструменти;
* автоматична реєстрація ПРРО в ДПС;
* повна супровід офлайн-режиму;
* повна супровід всіх нестандартних податкових сценаріїв.; |}
== 5.; Варіанти інтеграції ==
Мінімальні інформаційні дані:
=== Етап 7.; Зміни та звіти ===
Як касир або адміністратор,
},
=== 17.5. fiscal_receipt_items ===
<pre>
)
'''Критично істотно:''' повторний запит із тим самим idempotency_key або receipt_uuid не повинен створити другий фіскальний чек.; def close_shift(self, shift_id: str) -> "ZReportResponse":
Якщо конфігурація Checkbox або інтеграції підтримують електронну відправку чека, Python-сервіс повинен передавати email або телефон покупця.; |-
| integration_id
| uuid
| ID інтеграції.; |-
| opened_at
| timestamp
| Дата відкриття.; |-
| receipt_hash
| Hash товарів, сум, оплат і замовлення.; |-
| api_token_encrypted
| text
| Зашифрований токен.; |-
| status
| varchar
| Статус чека.; |}
!; |}
== 27.; Ризики ==
"currency": "UAH"
audit_logger.log(
task_name="fiscalize_checkbox_receipt",
</syntaxhighlight>
def create_refund_receipt(self, payload: "RefundReceiptPayload") -> "ReceiptResponse":
|-
| AC-1
| Адміністратор створює інтеграцію Checkbox.; |}
=== Етап 8.; Dashboard та аудит ===
{| class="wikitable"
!; |-
| Закриття зміни
| Z-звіт, час, результат.; |-
| status
| varchar
| CREATED, OPENED, CLOSED, ERROR тощо.; |-
| Receipt Item
| Товарна або послугова позиція в чеку.; {| class="wikitable"
!; | style="background:#bbdefb;" | Контроль
|-
| Незакриті зміни
| Каси з відкритими змінами.; def get_receipt_text(self, receipt_id: str) -> str:
Python Fiscal Service
|-
| Чеків створено
| Загальна кількість чеків за період.; |-
| external_refund_id
| string
| ID повернення у зовнішній системі.; Фіскальний результат
{| class="wikitable"
|
|
-
|
AC-16
|
class="wikitable"
2.; Область сфера застосування
Python-сервіс підтримує роботу централізований обліковий облік чеків, але різні торгові точки можуть використовувати різні канали.; |-
|
Dashboard API
|
}
"tax_group": "VAT_20",
13.3.; Конфігурація клієнта
20.; Обробка помилок
Python-сервіс повинен приймати інформаційні дані продажу та створювати фіскальний чек.; Значення
receipt.status = "SENDING"
cash_register_id: UUID,
Канали:
|
-
|
is_active
|
boolean
|
-
|
fiscal_number
|
varchar
|
Фіскальний номер.; Він повинен повернути результат уже створеної операції.; Значення
db.commit()
29.; Джерела
db.commit()
6.; Основні сутності
- HTML;
- PNG;
- TXT;
- QR-code.; Критерій
!; |-
| provider
| varchar
| checkbox.; |}
Кожна операційна дія продажу, повернення, відкриття зміни, закриття зміни, службове внесення / винесення готівки та помилка фіскалізації повинні мати внутрішній ID, статус, журнал подій і можливість безпечного повтору без створення дубля.; |-
| AC-19
| Сума службової операції некоректна.;=== 21.2.; Приклад dashboard ===
!; характеристика
[[Категорія:ПРРО]]
db=db,
=== 18.1.; Створення інтеграції ===
== 13. Checkbox Client ==
!; Тип
Python Fiscal Service
|-
| external_order_id
| string
| ID замовлення у зовнішній системі.; | Dashboard, нагадування, авто-закриття за правилом.; Задача додається в чергу.; | style="background:#f3e5f5;" | Фіолетовий
|}
{| class="wikitable"
audit_logger.log(
4.; | платформа створює service receipt з відповідним напрямком суми.; |-
| external_payment_id
| Додатковий ключ від платіжної системи.; |-
| Зміна налаштувань
| користувач системи, старі та нові параметри.; Результат зберігається в БД.; |-
| base_url
| string
| Так
| Базова адреса API Checkbox.; |-
| Автоматичне відкриття
| платформа відкриває зміну перед першим чеком.; характеристика
{| class="wikitable"
pass
return shift
!; CHECKBOX_X_CLIENT_VERSION=1.0.0
<pre>
!;=== 18.8.; Повторна фіскалізація ===
* Python API для прийому продажів;
* замовник інтеграції з Checkbox API;
* супровід фіскалізації чеків продажу;
* супровід повернень;
* супровід службового внесення та винесення готівки;
* відкриття та закриття змін;
* збереження чеків;
* збереження статусів;
* журнал помилок;
* retry-механізм;
* dashboard / API для контролю;
* інтеграційні функціональні можливості з внутрішньою системою.; | Python-сервіс створює чек зі статусом PENDING.; !; характеристика
{| class="wikitable"
"payments": [
Як адміністратор,
!; |-
| items
| array
| Позиції чека.; |}
=== 7.2.; Повернення ===
CHECKBOX_DEFAULT_LICENSE_KEY=********
* створення інтеграції Checkbox;
* перевірка підключення;
* збереження token і license key;
* створення чека продажу;
* створення чека повернення;
* службове внесення / винесення готівки;
* валідація чеків;
* дедублікація;
* черга фіскалізації;
* відкриття зміни;
* закриття зміни;
* отримання статусу чека;
* отримання статусу зміни;
* збереження fiscal_number;
* журнал подій;
* retry-механізм;
* dashboard API;
* базові unit-тести;
* mock API для інтеграційних тестів.; |-
| idempotency_key
| string
| Ключ захисту від дублювання повернення.; !; Фіскалізація через ПРРО
entity_type="receipt",
v
|
| 5.; |-
| qr_code
| text
| QR або інформаційні дані QR, якщо доступні.; |-
| Основні операції
| Створення чеків, повернень, службових операцій, отримання статусів, робота зі змінами.; |-
| переважні аспекти
| Зручніше для касового вузла, retail-логіки, локальної роботи.; |-
| AuthError
| Невірний API token або відсутній доступ.; | Зберегти raw-відповідь, перевести в NEEDS_RETRY або ERROR.; # Чи потрібна супровід часткових повернень?; характеристика
щоб коректно відобразити повернення коштів покупцю.; # Чи потрібен dashboard у UI, чи тільки API?; | Помилки фіскалізації, незакрита зміна.; | ключовий зовнішній сервіс інтеграції.; Поле
POST /api/v1/fiscal/checkbox/refund-receipts
я хочу створити чек повернення,
{| class="wikitable"
entity_id=shift.id,
!; | Первинний чек отримує ознаку повного або часткового повернення.; | платформа блокує операції по касі.; |-
| Validation Layer
| Перевіряє товари, суми, оплати, податки, касу, касира.; |-
| sku
| varchar
| Артикул.; |-
| receipt_uuid
| uuid
| UUID чека, який передається в Checkbox.; Тип
!; |-
| TimeoutError
| Перевищено час очікування.; |-
| AC-4
| License key неправильний.; # Чи потрібна інтеграційні функціональні можливості з K2 ERP?; | Другий чек не створюється.; |-
| x_client_name
| varchar
| Назва інтеграції.;<pre>
!; # Чи потрібна супровід локального друку чеків?; Код
|
| 4.; |-
| AC-12
| Повернення успішне.; |-
| quantity
| integer
| Кількість у мінімальних одиницях, якщо застосовується масштабування.; | Вмикати тільки після окремого погодження.; характеристика
def get_shift_status(self, shift_id: str) -> "ShiftStatusResponse":
"id": str(shift.id)
* email;
* SMS;
* месенджер, якщо підтримується налаштуваннями;
* посилання на чек через зовнішню систему.; | style="background:#ffcc80;" | Помаранчевий
|-
| Скасовано
| CANCELLED
| Операцію скасовано.; |-
| cashier_id
| varchar
| Касир.; Колір
"receipt_uuid": uuid4(),
Формати:
existing = receipt_repository.get_by_idempotency_key(
Як керівник,
|-
| operation_type
| enum
| cash_in або cash_out.; | платформа попереджає перед закриттям зміни.; |-
| raw_response
| jsonb
| Відповідь API.; |-
| value
| integer
| Сума в копійках.; | Повернути існуючий чек.; Тип помилки
|-
| id
| uuid
| ID інтеграції.; |-
| Audit Logger
| Журнал API-запитів, відповідей, помилок і змін статусів.; Критерій
"checkbox_receipt_id": response.id,
{{SEO
|title=Технічне завдання: Інтеграція ПРРО Checkbox для Python
|description=Технічне завдання на реалізацію Python-сервісу для інтеграції з ПРРО Checkbox: фіскалізація чеків, відкриття і закриття змін, повернення, службові операції, X/Z-звіти, статуси, помилки, API-клієнт, черги та журналювання.
|keywords=Python, Checkbox, ПРРО, API Checkbox, фіскалізація чеків, каса, програмний РРО, FastAPI, інтеграція, технічне завдання, K2 ERP
}}
timeout_seconds: int = 30
<pre>
receipt = receipt_repository.create(
!; |-
| AC-18
| користувач системи створює службове винесення.; | Заборонити змішування сценаріїв для однієї каси.; API приймає запит на створення чека.; |-
| external_cash_register_id
| varchar
| ID каси у Checkbox або локальній системі.; Продаж / оплата / повернення
платформа повинна забезпечити:
=== 13.2.; Основні методи ===
|
| 2.; Тип
!; |-
| Синхронізація статусів
| Середній
| має змогу виконуватись фоново.; | style="background:#ef9a9a;" | Червоний
|}
=== 17.3. fiscal_shifts ===
"fiscal_operation_type": "sale",
=== 24.6. Dashboard ===
base_url: str
платформа повинна:
=== 8.5.; Службове внесення та винесення готівки ===
|-
| style="background:#c8e6c9;" | Зелений
| #c8e6c9
| Успішно: чек фіскалізовано, зміна відкрита або закрита коректно.; | Валідація перед фіскалізацією.; |-
| fiscal_url
| varchar
| Посилання на чек, якщо доступне.; )
pass
"type": "CARD",
=== 8.3.; Приклад запиту на чек продажу ===
def fiscalize_checkbox_receipt(receipt_id: UUID, db: "Session") -> None:
v
|
-
|
tax_group
|
varchar
|
style="background:#eeeeee;" | Сірий
|
| Повернення створено
|
REFUNDED
|
-
|
default_tax_group
|
string
|
Ні
|
Податкова група за замовчуванням.; №
24.5.; Службові операції
ERP / CRM / Website / POS
7.; db=db,
7. User Story
Логічний endpoint Python-сервісу:
|
| Онлайн-продажі
|
-
|
Повернення
|
Високий
|
-
|
new_status
|
varchar
|
Заборонити фіскалізацію.; №
9.; Статуси чеків
except TemporaryFiscalError as exc:
8.; |-
| AC-7
|
Реалізується в межах цього ТЗ.; Сутність
|
; "sku": "DELIVERY",
idempotency_key=command.idempotency_key,
def get_receipt_html(self, receipt_id: str) -> str:
event_type="RECEIPT_QUEUED",
20.1.; Типи помилок
8.9.; Отримання статусу чека
receipt.status = "NEEDS_RETRY"
8.2.; Створення чека продажу11.; Єдина логіка кольорів
|
|
|
|
|
|
|
|
|
|
|