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

Інтеграція РРО в Python через загальну бібліотеку для різних РРО

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

На касовому ПК запускається Python RRO Agent. Python-сервіс повинен працювати з драйвером ArtSoft, а не напряму з ДПС. Характеристика

def get_device_status(self, device_id: str) -> dict:

class ArtSoftRROSettings(BaseSettings):

def service_cash_out(self, device_id: str, amount: float, comment: str | None = None) -> "ServiceOperationResponse":
"device_id": "rro-store-001",

|- | external_order_id | string | ID замовлення у K2 ERP / POS. SEO-опис


import ctypes

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

Етап 7. Production hardening

! Ризик

v

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

! @abstractmethod

if self.dll is None:

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

index.php?title=Категорія:ArtSoft

3. |-
| status
| varchar
| Статус.<pre>

 return {"raw": result}

! |-
| RRO Agent
| Локальний Python-сервіс, який керує драйвером. |-
| style="background:#eeeeee;" | Сірий
| #eeeeee
| Неактивно або скасовано. |-
| AC-13
| Повернення часткове. | платформа повертає READY або конкретну помилку. Перевірити доступність драйвера. |-
| external_order_id
| varchar
| ID замовлення.
def check_driver(self) -> dict:
  • придбати або отримати демо-версію ArtSoft Універсального драйвера;
  • отримати документацію розробника;
  • визначити сценарій інтеграції: OLE, DLL, service;
  • перевірити підтримувані моделі РРО;
  • перевірити версію драйвера;
  • перевірити тестовий РРО або емулятор. |-

| Доступ до DLL | ctypes або cffi. SEO-опис

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

ole_progid: str | None = None
def get_status(self, device_id: str) -> "RROStatus":

Python Agent повинен уміти перевіряти:

22.10. Повторити чек

result = self.driver.OpenShift(device_id, cashier_id)

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

щоб не розробляти окрему Python-інтеграцію для кожної моделі. |- | error_code | varchar | Код помилки. |- | new_status | varchar | Новий статус. Краще використовувати локальний Python Agent біля РРО, а K2 ERP функціонує з ним через API. | style="background:#c8e6c9;" | Зелений |- | Помилка драйвера | DRIVER_ERROR | ArtSoft-драйвер повернув помилку. Тип

index.php?title=Категорія:Технічні завдання

Це дозволить: def print_refund_receipt(self, device_id: str, payload: "RefundReceiptPayload") -> "ReceiptResponse": я хочу створити чек повернення, критично: значення OLE ProgID, назви DLL, назви функцій і параметри команд потрібно брати з офіційної документації ArtSoft до конкретної версії драйвера. Тип
- status varchar class="wikitable"

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

Етап 6. Dashboard і синхронізація

9.1. конфігурація драйвера

"unit": "послуга"

критично: ArtSoft-драйвер призначений для спрощення роботи з фіскальними реєстраторами: замість реалізації протоколу кожного РРО Python-інтеграція повинна викликати високорівневі команди драйвера. | Чернетка, зміна закрита. Як касир,

  • створити FastAPI-сервіс;
  • реалізувати healthcheck;
  • реалізувати локальну БД;
  • реалізувати модель драйвера;
  • реалізувати модель РРО;
  • реалізувати логування. Статус
pass
self.connect()

3. |-

ArtSoft Driver style="background:#ef9a9a;" | Червоний
Невідомий результат UNKNOWN_RESULT - Жовтий #fff9c4 - Shift - PaperOutError - fiscal_number varchar - AC-20 Виносити інтеграцію в локальний Windows Agent. |- entity_id uuid ID сутності.=== 9.9. X-звіт ===

Endpoint:

РРО закриває зміну. |- total_amount numeric - Чек повернення Високий Фінансова операційна дія. Потрібно мати офіційну документацію ArtSoft щодо DLL API, типів параметрів, кодування рядків, кодів помилок і 32/64-bit сумісності. Поле

6. Це потрібно врахувати в експлуатації та оновленнях production-середовища. | РРО доступний у списку пристроїв. №

24.3. Проблемні операції

def ensure_connected(self) -> None:
Друкується чек повернення. платформа повинна обмежувати доступ до цієї дії та логувати, хто її виконав. # Чи потрібно програмувати товари в РРО? |- оновлення версій - Нефіскальний друк Низький Не блокує продажі та реалізація. Критерій Відкрити зміну, якщо дозволено. |- Відкриття зміни - status varchar - Сценарій використання Перевести чек у CONNECTION_ERROR. | платформа переводить чек у MANUAL_REVIEW. ! |- Чек повернення - AC-12 Python функціонує через перевірені команди драйвера. |- is_active boolean Так style="background:#ef9a9a;" | Критично
Помилки РРО - Фіолетовий #f3e5f5 Повернення, ручна перевірка або спеціальна операційна дія. SEO-опис
v
pass

POST /api/v1/rro/artsoft/reports/z

def service_cash_in(self, device_id: str, amount: float, comment: str | None = None) -> "ServiceOperationResponse":

9.10. Z-звіт

Ключі дедублікації: До MVP входить:

Як касир або адміністратор,

'''Ознайомтесь з документацією від розробника універсального драйвера РРО:''' [[Керівництво програміста "АртСофт - Універсальний драйвер фіскальних реєстраторів для України"]]
ДПС
Параметр

2. Область сценарії використання

integration_name string Так - X-звіт Середній - Бордовий #b71c1c Невідомий результат або ризик дублювання фіскального чека. SEO-опис

17.2. Пріоритети

AC-11 Касир створює повернення. pass
  • реалізувати cash_in;
  • реалізувати cash_out;
  • реалізувати права доступу;
  • реалізувати аудит. | style="background:#bbdefb;" | Блакитний
Друкується PRINTING РРО виконує друк. я хочу відкрити зміну на РРО,
"provider": "terminal",
float(payment ["amount"]),

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

ARTSOFT_LOG_RAW_COMMANDS=true

index.php?title=Категорія:POS

- Driver Command Помилка РРО, драйвер недоступний, фіскальна помилка. | Python функціонує з єдиним високорівневим драйвером. |}
- Локальна БД style="background:#ffcc80;" | Помаранчевий
Помилка фіскальної пам'яті FISCAL_MEMORY_ERROR }

13.3. Методи Python RRO Client

18. Абстрактна модель драйвера

item.get("department", 1),
Тестове середовище і regression-тести. | РРО переходить у стан SHIFT_OPEN. Очікуваний результат

8. User Story

Фізичний РРО

}

21.1. fiscal_driver_integrations

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

service_url: str | None = None
"quantity": 1,
ArtSoft випускає оновлення версій драйвера. |- event_type varchar - connection_port string Ні COM/USB/мережевий порт, якщо потрібен. Колір
float(item ["quantity"]), style="background:#ef9a9a;" | Червоний
Немає паперу PAPER_OUT Потрібно замінити рулон. Якщо РРО або ArtSoft-драйвер має критичну помилку, чек не повинен переходити в статус «Фіскалізовано». Перевірити підключення до РРО. Значення
10:42 РРО #001 ORDER-123 570.00 Помилка драйвера ArtSoft недоступний Перевірити драйвер
11:05 РРО #001 ORDER-124 1200.00 Потребує повтору Немає паперу Замінити папір і повторити
12:10 РРО #002 SHIFT-55 - Зміна відкрита Не закрито Z-звіт Закрити зміну
12:30 РРО #003 ORDER-125 700.00 Ручна перевірка Невідомо, чи чек надруковано Перевірити на РРО
result = self.dll.OpenShift(

1. Мета

  • доступ до локального агента тільки з дозволених IP або через токен;
  • HTTPS або локальну захищену мережу;
  • авторизацію запитів від K2 ERP / POS;
  • розмежування прав: продаж, повернення, X-звіт, Z-звіт, службові операції;
  • журнал дій користувачів;
  • захист від дублювання чеків;
  • заборону прямого доступу до драйвера з кількох процесів;
  • шифрування конфігурацій, якщо містять чутливі інформаційні дані;
  • маскування персональних даних покупців у логах;
  • блокування небезпечних повторів для статусу UNKNOWN_RESULT. |-
Фізичний РРО Конкретна модель фіскального реєстратора. Високорівневі команди до РРО

ARTSOFT_OLE_PROGID=ArtSoft.Driver.Placeholder

13. Python RRO Agent

5. Тип
result = self.driver.GetDriverStatus()
Сутність - old_status varchar Старий статус. SEO-опис
pass
"sku": "SKU-001",

8.1. Продаж

критично: назви методів у прикладі виступає як умовними. |-

Python RRO Agent платформа зменшує доступний залишок до повернення. |- Логи Не відправляти в драйвер. # Які типи оплат підтримуються: готівка, картка, змішана оплата? |}

24.1. Основні KPI

POST /api/v1/rro/artsoft/service-operation
v
"total_amount": 570.00,
def x_report(self, device_id: str) -> dict:
pass driver_connection_type: str = "OLE_COM"
SEO-опис
return {"raw": result}
POST /api/v1/rro/artsoft/reports/x "external_order_id": "ORDER-2026-000123",
- driver_provider string Так - customer object інформаційні дані покупця, якщо потрібні. device_id.encode("utf-8"),
def open_shift(self, device_id: str, cashier_id: str) -> "ShiftResponse":
return {"raw": result}
v
"items": [

Рекомендована технічна архітектура: локальний Python RRO Agent встановлюється на касовому ПК або POS-вузлі, функціонує з ArtSoft-драйвером і приймає команди від K2 ERP через HTTP API або локальну чергу. |}

self.ensure_connected()
for payment in receipt ["payments"]:
style="background:#f3e5f5;" | Фіолетовий
"operation_type": "CASH_IN",
import win32com.client

}

"type": "CARD",
"comment": "Службове внесення на початок зміни",
Готовий READY РРО і драйвер готові до роботи. Критерій
self.dll.OpenShift.argtypes = [c_char_p, c_char_p]
pass
Реальні назви методів, параметри та коди відповідей потрібно взяти з актуальної документації ArtSoft. Передача фіскальних даних каналами РРО style="background:#eeeeee;" | Сірий
Очікує друку PENDING Чек у черзі на друк. * приймати HTTP-запити від K2 ERP / POS;
  • керувати ArtSoft-драйвером;
  • виконувати друк чеків;
  • повертати статуси;
  • зберігати локальний журнал;
  • працювати навіть при тимчасовій недоступності центральної системи, якщо це дозволено сценарієм;
  • синхронізувати результати з центральною БД. ARTSOFT_RETRY_COUNT=2

20. Приклад ArtSoft DLL Adapter


Endpoint:
</syntaxhighlight>
{| class="wikitable"
=== 22.4. Відкриття зміни ===
<pre>
{| class="wikitable"
== 29. Етапи реалізації ==
Він повинен:
 def refund_receipt(self, device_id: str, receipt: dict) -> dict:

 result = self.driver.GetDeviceStatus(device_id)
 )
== 28. MVP ==

! |-
| Refund Receipt
| Чек повернення. ! Результат зберігається локально. SEO-опис

Python викликає об'єкти драйвера через COM/OLE. |-
| cashier_id
| string
| Касир. |-
| AC-6
| РРО не підключений. {| class="wikitable"

<syntaxhighlight lang="json">
GET /api/v1/health


 "tax_group": "NO_VAT",
 @abstractmethod
[[index.php?title=Категорія:Фіскальні реєстратори]]
! |-
| RRO Error
| Помилка пристрою, драйвера або з'єднання. |-
| Dashboard
| Центральний контроль чеків, змін і помилок. |-
| integration_id
| uuid
| ID інтеграції ArtSoft. | Критична помилка, заборонити друк. |-
| fiscal_number
| string
| Так
| Фіскальний номер РРО. | style="background:#f3e5f5;" | Фіолетовий
|-
| Скасовано
| CANCELLED
| Операцію скасовано до друку. |-
| payments
| array
| Сума повернення. |}

{| class="wikitable"
Логіка:
! |-
| Дублювання чеків
| Повторний запит здатна надрукувати другий чек. |}

 def service_cash_out(self, device_id: str, amount: float, comment: str | None = None) -> dict:

 def check_connection(self, device_id: str) -> "RROStatus":

== 23. Обробка помилок ==

ArtSoft Універсальний драйвер реєстраторів потрібен для того, щоб не писати окрему інтеграцію під кожну модель РРО.<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
</div>
Як POS або K2 ERP, 
 @abstractmethod
 pass
<pre>
Покупець / чекова стрічка
=== 13.2. Рекомендований стек агента ===
! )

* уже фіскалізованого чека;
* повернення понад доступну суму;
* некоректної суми;
* помилки фіскальної пам'яті;
* невідомого стану, коли неможливо визначити, чи чек уже надруковано. :contentReference [oaicite:1]{index=1}
! |-
| RefundLimitError
| Повернення перевищує доступну суму. Якщо потрібно — відкриває зміну. Технологія
! |-
| Z Report
| Звіт із закриттям зміни. ! У K2 ERP або локальному агенті повинна бути картка інтеграції ArtSoft. # Чи потрібно друкувати QR-код у чеку? | style="background:#ef9a9a;" | Червоний
|-
| Помилка з'єднання
| CONNECTION_ERROR
| Немає зв'язку з РРО або драйвером. |-
| raw_close_response
| jsonb/text
| Відповідь закриття. |}

=== Варіант 2. 5.2. Через DLL ===

# Який саме API надає ArtSoft у вашій ліцензії: OLE, DLL, локальний сервіс чи інший механізм? |-
| Інтеграційний шар
| DLL / OLE / інший програмний інтерфейс згідно з документацією ArtSoft. |-
| connection_type
| varchar
| OLE_COM, DLL, SERVICE. |-
| Мова
| Python 3.11+
|-
| API
| FastAPI
|-
| Доступ до COM/OLE
| pywin32 або comtypes. |-
| Різні моделі РРО
| Моделі можуть мати різні обмеження. |-
| Черга
| SQLite queue / Redis / RQ. |-
| sku
| varchar
| Артикул. | Dashboard, список чеків, статус РРО. SEO-опис

{| class="wikitable"

! POST /api/v1/rro/artsoft/reports/x

 self.ensure_connected()
=== 22.7. Чек продажу ===

 ],
! Критерій

=== Етап 4. Чеки ===
 @abstractmethod
 pass
{| class="wikitable"

! SEO-опис
 pass
{| class="wikitable"
=== 22.9. Службова операційна дія ===

 "cashier_id": "cashier-001",

 )
'''Критично критично:''' чек повернення не повинен перевищувати залишок по первинному чеку. "price": 70.00,

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

! |-
| Складно підтримувати різні моделі РРО. | style="background:#fff9c4;" | Жовтий
|-
| Відправляється в драйвер
| SENDING_TO_DRIVER
| Команда передається в ArtSoft-драйвер. |-
| external_payment_id
| varchar
| ID оплати. | Повернути існуючий результат. | style="background:#c8e6c9;" | Зелений
|-
| Драйвер недоступний
| DRIVER_UNAVAILABLE
| Python не здатна підключитися до ArtSoft-драйвера. |-
| price
| numeric
| Ціна. |-
| Python-бібліотеки
| pywin32 або comtypes. |-
| AC-10
| Повторний запит має той самий idempotency_key. POST /api/v1/rro/artsoft/receipts/{receipt_id}/retry
! | Перевести в MANUAL_REVIEW. | style="background:#ffcc80;" | Потрібна дія
|-
| РРО не підключені
| Пристрої без зв'язку. | Таблиця можливостей device_capabilities. Поле
! Тип
 pass
! Worker друкує чек через ArtSoft. Дія системи
id uuid - device_model string Так - AC-16 - current_shift_id uuid - AC-2 }
pass
платформа блокує операцію. SEO-опис - error_message text Повідомлення помилки.

Приклад `.env`:
Метою задачі виступає як створення універсального Python-рішення для роботи з різними фізичними РРО через ArtSoft Універсальний драйвер реєстраторів. | Статус оновлюється з коментарем і записом в аудит. |-
| print_qr
| boolean
| Чи друкувати QR-код. Що зберігати

<pre>

5. |-
| style="background:#ffcc80;" | Помаранчевий
| #ffcc80
| Потрібна дія користувача. Перевірити, чи зміна вже відкрита. Замовлення
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
 "department": 1,
Призначення:
|-
| AC-4
| Адміністратор додає РРО. # Які моделі РРО потрібно підтримати в MVP? |-
| Важко оновлювати логіку під нові форми чеків. |-
| конкурентні переваги
| Менше залежності від прямого COM/DLL-коду в бізнес-сервісі. |}

[[index.php?title=Категорія:Python]]

 def check_driver(self) -> "DriverStatus":
 "idempotency_key": "CASH-IN-2026-05-07-001"
 self.driver.OpenReceipt(device_id, "SALE")

{| class="wikitable"
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
</syntaxhighlight>

=== 17.1. Логіка черги ===

 ],

 "device_id": "rro-store-001",
GET /api/v1/rro/artsoft/devices/{device_id}/status
Локальний endpoint:
 timeout_seconds: int = 30
4. |-
| fiscal_number
| varchar
| Фіскальний номер або номер чека, якщо доступний. :contentReference [oaicite:2]{index=2}
! Колір
<pre>
=== 23.1. Типи помилок ===

4. 5. Час

я хочу передати продаж у Python RRO Agent, Критично критично: перед друком фіскального чека агент повинен перевірити готовність РРО. Компонент

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

def __init__(self, ole_progid: str):

Варіант 1. 5.1. Через OLE / COM-інтерфейс

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

MVP: реалізувати інтеграцію Python не з конкретним РРО забезпечується через Рекомендовано; так само реалізовано а з ArtSoft-драйвером як із єдиним абстрактним шаром для всіх підтримуваних реєстраторів. | РРО друкує X-звіт без закриття зміни. |-

provider varchar - external_payment_id - AC-5 style="background:#f3e5f5;" | Контроль
Помилки драйвера - Упаковка - cashier_id string Ні } self.ensure_connected() - технічна підтримка моделей Чек друкується і переходить у FISCALIZED. |- Червоний #ef9a9a style="background:#ffcc80;" | Помаранчевий
Відкрита кришка COVER_OPEN - allow_service_operations boolean Так - DeviceConnectionError - Помилка драйвера UNKNOWN_RESULT. |- - device_id string ID РРО. # Чи потрібно запускати Python Agent як Windows Service? Критерій
! Результат синхронізується з центральною системою. |-
| device_id
| uuid
| РРО. |-
| Службова операційна дія
| Тип, сума, касир. Поле
 return {"raw": result}
POST /api/v1/rro/artsoft/receipts/sale
|-
| RRO Device
| Фізичний фіскальний реєстратор. |-
| AC-17
| Зміна не закрита наприкінці дня. Очікуваний результат
! | Заборонити операцію. 

}
=== 9.3. Перевірка стану РРО ===
</div>
== 19. Приклад ArtSoft OLE Adapter ==
|-
| id
| uuid
| ID позиції. |}

</div>

=== 22.2. Перевірка стану драйвера ===

{| class="wikitable"
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
 auto_open_shift: bool = True
|-
| Підходить для
| Windows-сценаріїв, де доступна DLL-бібліотека. |}

Типи:

 self.driver = None

* локальний Python RRO Agent;
* конфігурація ArtSoft-драйвера;
* конфігурація декількох РРО;
* перевірка стану драйвера;
* перевірка стану РРО;
* відкриття зміни;
* друк чека продажу;
* друк чека повернення;
* службове внесення / винесення;
* X-звіт;
* Z-звіт;
* локальна БД чеків;
* дедублікація;
* журнал команд і відповідей;
* базовий dashboard API;
* обробка помилок драйвера, РРО, паперу, зміни;
* retry для безпечних ситуацій;
* MANUAL_REVIEW для невідомого результату. |}

! |}

{| class="wikitable"

 self.connect()

! K2 ERP / POS / CRM / Website

! |-
| discount_amount
| numeric
| Знижка. |-
| Повторна операційна дія
| Хто запустив, причина, результат. |-
| raw_open_response
| jsonb/text
| Відповідь відкриття. {| class="wikitable"
8. # Чи виступає як доступ до емулятора фіскального реєстратора? №
 return {"raw": result}
 def get_device_status(self, device_id: str) -> dict:
! def check_driver(self) -> dict:
<syntaxhighlight lang="python">
=== Етап 1. Аналіз ArtSoft-драйвера ===
<pre>
=== 8.2. Повернення ===
</div>
== 32. Джерела ==
 self.dll.OpenShift.restype = c_char_p
виконати команду відкриття зміни через драйвер виступає ключовою рисою 6. Критерій
! |-
| idempotency_key
| базовий ключ повторного запиту. 7. |}

 allow_service_operations: bool = True

<pre>

я хочу бачити помилки РРО та драйвера, 

 return {"raw": result}

* замінити ArtSoft на інший драйвер у майбутньому;
* тестувати бізнес-логіку без фізичного РРО;
* використовувати mock-драйвер;
* підтримувати декілька реалізацій: ArtSoft OLE, ArtSoft DLL, ArtSoft Service;
* не прив'язувати K2 ERP до конкретного драйвера. |-
| shift_id
| uuid
| Зміна. | style="background:#eeeeee;" | Сірий
|-
| Заблоковано
| BLOCKED
| Робота неможлива. ! | style="background:#c8e6c9;" | Зелений
|-
| Зміна закрита
| SHIFT_CLOSED
| Перед продажем потрібно відкрити зміну. |-
| idempotency_key
| string
| Ключ захисту від дублювання. Поле
 def open_shift(self, device_id: str, cashier_id: str) -> dict:

[[index.php?title=Категорія:K2 ERP]]

! |-
| CoverOpenError
| Кришка відкрита. |-
| Обмеження
| Потребує Windows, встановленого драйвера та коректної COM-реєстрації. POST /api/v1/rro/artsoft/receipts/sale

'''Критично критично:''' Z-звіт виступає як операцією закриття зміни. Тип
! Поле
 if self.driver is None:

 result = self.driver.XReport(device_id)
 float(item ["price"]),
! Перевірити відкриту зміну. |-
| z_report_number
| varchar
| Номер Z-звіту. | Зупинити друк, чек лишити в NEEDS_RETRY. SEO-опис

! |-
| items
| array
| Позиції чека. |-
| AC-18
| Після збою результат чека невідомий. | Черга чеків, очікування друку. SEO-опис
<pre>

 result = self.driver.ZReport(device_id)
! Python Agent виконує валідацію. Тип
 @abstractmethod
POST /api/v1/rro/artsoft/shifts/open
До MVP не входить:
 "sku": "DELIVERY",
</pre>
 pass
! |-
| Fiscal Receipt
| Фіскальний чек продажу. | style="background:#c8e6c9;" | Норма
|-
| Повернення
| Кількість чеків повернення. |-
| artsoft_device_id
| string
| Так
| Ідентифікатор або номер пристрою в ArtSoft-драйвері. Значення
! | Другий чек не друкується. Пріоритет

{| class="wikitable"

=== 13.1. Призначення ===
2.</div>
 "name": "Доставка",
|-
| id
| uuid
| ID пристрою. def print_non_fiscal_text(self, device_id: str, lines: list [str]) -> "PrintResponse":

ARTSOFT_DLL_PATH=C:\ArtSoft\Driver\driver.dll

{| class="wikitable"
 @abstractmethod
 @abstractmethod

=== Етап 3. Драйверний шар ===

from ctypes import c_char_p, c_double

=== Варіант 3. 5.3. Через локальний ArtSoft-сервіс / агент ===
{| class="wikitable"
== 9. Функціональні вимоги ==
 def print_sale_receipt(self, device_id: str, payload: "SaleReceiptPayload") -> "ReceiptResponse":
|-
| ValidationError
| Некоректні інформаційні дані чека. |-
| AC-8
| Драйвер і РРО готові. Подія
<syntaxhighlight lang="python">
|-
| id
| uuid
| ID чека. |-
| Основне призначення
| Надати високорівневі команди для роботи з РРО без реалізації протоколу кожної моделі. # На якій ОС працюватиме касовий ПК: Windows чи Linux? | style="background:#ef9a9a;" | Червоний
|-
| Зміна відкрита
| SHIFT_OPEN
| Можна друкувати фіскальні чеки. # Чи буде один РРО на декілька касирів? Показник
=== 22.6. X-звіт ===
== 27. Acceptance Criteria ==

 dll_path: str | None = None

! |-
| Z-звіт
| Час, номер звіту, результат. |-
| department
| integer
| Відділ. я хочу підключати різні моделі РРО через один драйвер, 

* реалізувати sale receipt;
* реалізувати refund receipt;
* реалізувати валідацію;
* реалізувати дедублікацію;
* реалізувати чергу друку. Поле
=== 21.4. rro_receipts ===

=== Варіант 4. 5.4. Локальний Python RRO Agent + K2 ERP API ===

10. Зберегти номер і результат Z-звіту. | Перевести чек у DRIVER_ERROR або NEEDS_RETRY. Коментар Як керівник або адміністратор,

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

self.ensure_connected()

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

3.=== 24.2. Приклад dashboard ===

self.ole_progid = ole_progid

1. | style="background:#ffcc80;" | Потрібна дія

Ручна перевірка }

Central Fiscal API

<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">
{{SEO
|title=Технічне завдання: Інтеграція РРО в Python через ArtSoft Універсальний драйвер реєстраторів
|description=Технічне завдання на реалізацію Python-сервісу для інтеграції з різними фізичними РРО через ArtSoft Універсальний драйвер реєстраторів: чеки продажу, повернення, службові операції, X/Z-звіти, зміни, статуси, помилки, драйверний адаптер, черги та журналювання.
|keywords=Python, РРО, ArtSoft, універсальний драйвер реєстраторів, фіскальний реєстратор, каса, POS, FastAPI, K2 ERP, фіскальний чек, Z-звіт, X-звіт, OLE, DLL, Linux, Windows
}}
'''Рекомендована схема для K2 ERP:''' K2 ERP не повинна напряму керувати драйвером на касовому ПК. |-
| X Report
| Проміжний звіт без закриття зміни. |}

=== 23.2. Retry-логіка ===

 self.ensure_connected()

* тимчасової втрати зв'язку;
* тимчасової недоступності драйвера;
* timeout;
* очікування готовності РРО;
* відновлення після відсутності паперу, якщо чек не був завершений. №
8. | Статус PAPER_OUT, повтор після заміни паперу. Черга, журнал, дедублікація
! №
== 25. Безпека ==
щоб коректно повернути кошти покупцю та відобразити операцію в РРО. №
{| class="wikitable"
Локальний endpoint:

 device_id,

== 30. Ризики ==

 log_raw_commands: bool = True
Деякі сторонні описи ArtSoft-драйвера вказують підтримку Windows 7+ і Linux, а так само наявність вбудованого емулятора фіскального реєстратора; ці функції ERP потрібно підтвердити на конкретній ліцензії та версії драйвера перед проєктуванням production-схеми. |-
| Service Operation
| Службове внесення або винесення. |}

POST /api/v1/rro/artsoft/shifts/open

GET /api/v1/rro/artsoft/events?date_from=2026-05-01&date_to=2026-05-07

 "amount": 500.00,
 "payments": [
 cashier_id.encode("utf-8"),
інтеграційні функції ERP призначена для:
! Код

! Endpoint:
 self.ensure_connected()
|-
| Чек продажу
| Високий
| Основна операційна дія. def close_shift(self, device_id: str) -> dict:
 "amount": 70.00,
! | Чек переходить у NEEDS_RETRY або RRO_ERROR. 5. На сторінці ArtSoft окремо вказано, що компанія-користувач випускає оновлення версій універсального драйвера для підтримки нових версій реєстраторів і нової друкованої форми чека. Закрити локальну зміну. 7. HTML
 def connect(self) -> None:

33. Див. так само

Критично критично: це інтеграційні функції ERP з фізичними РРО через проміжний драйвер, а не ПРРО типу Checkbox або Вчасно.Каса.

27.1. Підключення драйвера

  • фізичних магазинів;
  • аптек;
  • кафе, барів, ресторанів;
  • кіосків;
  • торгових точок із декількома РРО;
  • торговельних мереж;
  • POS-вузлів;
  • підприємств, які використовують різні моделі фіскальних реєстраторів;
  • компаній, які хочуть мати один Python-інтерфейс для різних РРО. | Отримати документацію ArtSoft до початку розробки. |-
raw_response text/jsonb style="background:#ef9a9a;" | Червоний
- amount numeric - ole_progid string Ні style="background:#ef9a9a;" | Червоний
Помилка РРО RRO_ERROR - Python-бібліотеки }

22.3. Перевірка стану РРО

payment ["type"],

щоб агент через ArtSoft-драйвер надрукував і фіскалізував чек на підключеному РРО. # Чи потрібно програмувати податкові ставки з Python? |-

is_active boolean Так - AC-3 - DriverUnavailableError ArtSoft-драйвер недоступний. Статус
v

8. Колір

SEO-опис

Управлінський результат: керівник повинен бачити, скільки чеків надруковано, скільки повернень виконано, які зміни відкриті, які Z-звіти сформовані, які РРО мають помилки зв'язку або потребують уваги. SEO-опис

Тип
device_name string Так Назва РРО. Обов'язковість

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

def connect(self) -> None:

class ArtSoftDllFiscalDriver(FiscalDriver):

# Назва методу залежить від документації ArtSoft. |-
tax_profile_id string Ні - error_message text - driver_version varchar реліз системи драйвера. SEO-опис

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

original_receipt_id uuid - X-звіт Час, РРО, відповідь. Поле
def __init__(self, dll_path: str):
Перевірка драйвера }
"tax_group": "VAT_20",
"department": 2,

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

9. |-

ArtSoft Driver Універсальний драйвер реєстраторів.</syntaxhighlight>
"name": "Товар 1",
"unit": "шт"

22.5. Закриття зміни / Z-звіт

Критично критично: повторний запит із тим самим idempotency_key не повинен друкувати другий фіскальний чек. рішення для бізнесу через ArtSoft

  • реалізувати dashboard API;
  • реалізувати список помилок;
  • реалізувати синхронізацію з K2 ERP;
  • реалізувати експорт журналу, якщо потрібно. Критерій

21.6. rro_events

id uuid ID події. Статус
self.dll = None
def check_driver(self) -> dict:

14. Приклад конфігурації

}
self.ensure_connected()
  • чи встановлено ArtSoft-драйвер;
  • чи доступний драйверний інтерфейс;
  • чи підключений РРО;
  • чи доступний порт;
  • чи виступає як папір;
  • чи відкрита кришка;
  • чи виступає як помилки живлення;
  • чи виступає як зв'язок із фіскальним модулем;
  • чи відкрита зміна;
  • чи не заблокований РРО;
  • чи не переповнена пам'ять;
  • чи коректно встановлена дата і час;
  • чи готовий РРО до друку чека. |}
item ["tax_group"],
"payment_id": "PAY-123456"
- artsoft_device_id varchar ID пристрою у драйвері. Параметр
@abstractmethod

Приклад: GET /api/v1/rro/artsoft/driver/status Головна ідея: розробити Python-сервіс або Python-адаптер, який дає можливість K2 ERP / POS / CRM / обліковій системі працювати з різними фізичними РРО через ArtSoft Універсальний драйвер реєстраторів, не реалізовуючи окремий низькорівневий протокол для кожної моделі РРО. РРО

- receipt_hash class="wikitable"
"amount": 570.00,
Тип рішення для бізнесу - payload jsonb/text інформаційні дані події. SEO-опис
"price": 250.00,
Зелений #c8e6c9 Успішна операційна дія або нормальний стан. Очікуваний результат

18.2. Інтерфейс FiscalDriver

- auto_open_shift boolean Так - service_url varchar - idempotency_key varchar Ключ дедублікації. POST /api/v1/rro/artsoft/receipts/refund
"amount": 1000.00,
self.dll_path = dll_path
}

21.5. rro_receipt_items

Healthcheck, monitoring, auto-restart. SEO-опис
"idempotency_key": "ORDER-2026-000123-PAY-123456",
{| class="wikitable"
<pre>
</div>
! |-
| Z-звіт
| Критичний
| Закриття зміни. |-
| created_at
| timestamp
| Дата події. рішення для бізнесу повинно забезпечити:

* отримати проміжний звіт без закриття зміни;
* перевірити обороти;
* перевірити стан каси;
* показати керівнику поточні підсумки. |-
| Обмеження
| Потрібні точні сигнатури функцій, типи параметрів, коди відповідей і правила 32/64-bit сумісності. |-
| printed_at
| timestamp
| Дата друку.== 31. Відкриті питання ==
2. # Чи потрібна інтеграційні функції ERP з банківським POS-терміналом? | Refund, manual review, службові операції. | Цю низькорівневу логіку бере на себе драйвер. |-
| device_id
| uuid
| ID РРО. Стан
|-
| Кожен РРО має власний протокол обміну.</div>

 pass
=== 27.5. Зміни та звіти ===

</div>
</pre>

ARTSOFT_TIMEOUT_SECONDS=30
 self.ensure_connected()

6. Повернути результат у K2 ERP / POS. ! |-
| log_raw_commands
| boolean
| Так
| Чи зберігати технічні команди і відповіді. Колір
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
<pre>
 retry_backoff_seconds: int = 3
|-
| Чеків за день
| Кількість чеків продажу. |-
| FiscalMemoryError
| Помилка фіскальної пам'яті. SEO-опис

! Логіка:
{
{| class="wikitable"
Якщо ArtSoft надає сервісний режим або локальний серверний компонент, Python здатна працювати з ним через локальний API або файловий/черговий обмін. | style="background:#ef9a9a;" | Критично
|-
| Потребують повтору
| Чеки у NEEDS_RETRY. Він функціонує з ArtSoft-драйвером і приймає команди від K2 ERP. Сума
 retry_count: int = 2
1. | платформа повертає READY або помилку пристрою. |-
| style="background:#bbdefb;" | Блакитний
| #bbdefb
| операційна дія виконується. * Тестовий емулятор фіскального реєстратора, якщо доступний. |-
| payments
| array
| Оплати. |-
| raw_command
| text/jsonb
| Команда до драйвера. Перевірити незавершені чеки. Тип

<pre>

</div>
 def sale_receipt(self, device_id: str, receipt: dict) -> dict:
! |-
| receipt_id
| uuid
| ID чека. Поле
</pre>
<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">

 self.dll = ctypes.WinDLL(self.dll_path)
from pydantic_settings import BaseSettings

! |-
| Невідомий стан після збою
| Невідомо, чи чек надрукований. |-
| Службове внесення / винесення
| Середній
| Касова операційна дія. SEO-опис
|-
| K2 ERP / POS
| Створює продаж або повернення. Перевірити доступність ArtSoft-драйвера. |}

ARTSOFT_DRIVER_CONNECTION_TYPE=OLE_COM

</pre>

== 4. Технічні особливості ArtSoft-драйвера ==

<pre>

 self.driver.Payment(
{| class="wikitable"
=== 27.2. Підключення РРО ===
|-
| Підходить для
| Windows POS, касових робочих місць. # Чи потрібно інтегрувати агент із K2 ERP? |-
| Потрібно реалізовувати контрольні суми, пакети, таймаути, коди помилок. |-
| driver_connection_type
| enum
| Так
| OLE_COM, DLL, SERVICE, OTHER. * реалізувати FiscalDriver interface;
* реалізувати ArtSoftOleFiscalDriver або ArtSoftDllFiscalDriver;
* реалізувати check_driver;
* реалізувати check_device;
* реалізувати open_shift;
* реалізувати X/Z-звіти. | Узгодити bitness Python і драйвера. result = self.dll.GetDeviceStatus(device_id.encode("utf-8"))
</pre>

Local Python RRO Agent
Приклад:
[[index.php?title=Категорія:РРО]]

 }

 def open_shift(self, device_id: str, cashier_id: str) -> dict:
== 22. API Python Agent ==


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

21.2. rro_devices

Як адміністратор,

 def open_shift(self, device_id: str, cashier_id: str) -> dict:
== 6. Загальна технічна архітектура ==

<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">

 device_id,
 pass
Кожен фізичний РРО повинен мати окрему картку. |-
| tax_group
| varchar
| Податкова група. |-
| opened_at
| timestamp
| Дата відкриття. |-
| service_url
| string
| Ні
| URL локального сервісу, якщо застосовують, коли потрібно сервісний режим. |-
| Перевірка РРО
| Статус, помилки, час. KPI
=== 18.1. Навіщо потрібна абстракція ===
<div style="border-left: 6px solid #6a1b9a; background: #f3e5f5; padding: 12px 16px; margin: 16px 0;">
== 11. Статуси РРО та драйвера ==
! Тип
 def close_shift(self, device_id: str) -> "ZReportResponse":
 "print_qr": true

=== Етап 2. Локальний Python Agent ===

! |-
| Чек продажу
| Замовлення, сума, позиції, статус. |-
| конкурентні переваги
| Прямі виклики бібліотеки. Код
! |-
| ole_progid
| varchar
| ProgID OLE.<pre>

* повна технічна підтримка всіх моделей РРО без тестування;
* автоматичне програмування усієї номенклатури;
* повний POS UI;
* власна фіскальна логіка замість РРО;
* складна офлайн-синхронізація;
* заміна ArtSoft-драйвера власним протоколом;
* технічна підтримка Linux, якщо фактичний сценарій інтеграції використовує Windows-only OLE/DLL. ! |-
| driver_version
| string
| Так
| реліз системи ArtSoft-драйвера. | style="background:#ef9a9a;" | Критично
|}

 return {"raw": result}

 pass
! Помилка
Retry дозволений для:

! | Черга, друк, передача команди. # Чи потрібно відкривати грошову скриньку? |-
| cashier_id
| varchar
| Касир. | style="background:#b71c1c; color:#ffffff;" | Бордовий
|-
| Потребує повтору
| NEEDS_RETRY
| Операцію можна повторити. |-
| Cashier
| Касир, від імені якого виконується операційна дія.<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">

щоб оперативно реагувати на проблеми з папером, зв'язком, портом, драйвером або фіскалізацією. |-
| is_active
| boolean
| Активність. Як зменшити
! |-
| Несумісність 32/64-bit
| Python, DLL і драйвер можуть мати різну архітектуру. Проблема без універсального драйвера

! |-
| DuplicateReceiptError
| Чек уже надруковано. Перевірити стан касира. | платформа показує DEVICE_DISCONNECTED червоним кольором. |}

 pass

Як касир, 

<div style="border-left: 6px solid #1565c0; background: #e3f2fd; padding: 12px 16px; margin: 16px 0;">
 def sale_receipt(self, device_id: str, receipt: dict) -> dict:
4. |-
| device_serial_number
| string
| Так
| Серійний номер пристрою. |-
| DriverCallError
| Помилка виклику OLE/DLL. |-
| closed_at
| timestamp
| Дата закриття. Перевірити доступність Python Agent. | Автоматичний retry заблокований. def x_report(self, device_id: str) -> dict:

== 16. Дедублікація ==
=== 22.11. Отримати журнал подій ===
! |-
| entity_type
| varchar
| driver, device, shift, receipt. # Як опрацьовувати ситуацію, коли результат друку невідомий? Якщо зміна не відкрита. |-
| AC-9
| Немає паперу. POST /api/v1/rro/artsoft/service-operation

=== 22.1. Перевірка стану агента ===

7. |-
| default_timeout_seconds
| integer
| Так
| Таймаут команди до драйвера. |-
| name
| varchar
| Назва товару. Worker перевіряє стан РРО. POS / K2 ERP надсилає запит на чек. |-
| quantity
| numeric
| Кількість. Передати результат у K2 ERP. Для часткових повернень платформа повинна вести залишок доступної до повернення суми та кількості. |-
| reason
| string
| Причина повернення. |-
| Python-підхід
| HTTP, TCP, файли обміну або інший механізм згідно з документацією. |-
| dll_path
| varchar
| Шлях до DLL. |-
| оновлення версій драйвера
| оновлення версій здатна змінити поведінку команд. |-
| dll_path
| string
| Ні
| Шлях до DLL, якщо застосовується для DLL. |-
| status
| varchar
| OPEN, CLOSED, ERROR. Друк і фіскалізація чека

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

- конкурентні переваги - Driver Response - total_amount decimal - Драйвер недоступний ArtSoft не запущений або неправильно встановлений. pass 1. |-
external_refund_id string - idempotency_key string Ключ захисту від дублювання. Дія

from abc import ABC, abstractmethod я хочу сформувати Z-звіт, POST /api/v1/rro/artsoft/reports/z

27.6. Ручна перевірка

AC-14 Dashboard показує помаранчеве попередження.=== 8.6. Контроль помилок ===

21.3. rro_shifts

pass
return {"raw": result}
result = self.driver.CloseReceipt(device_id)
pass
- UnknownResultError }

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

def get_device_status(self, device_id: str) -> dict:

{

@abstractmethod

Python RRO Agent — це локальний сервіс, який встановлюється на касовий ПК і має доступ до ArtSoft-драйвера та фізичного РРО. Ключ

allow_refunds: bool = True

3. Чому застосовується для ArtSoft-драйвер

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

item ["name"],
<pre>
|-
| CASH_IN
| Службове внесення готівки. Обов'язковість
 self.driver = win32com.client.Dispatch(self.ole_progid)
 },
|-
| Чеків за день
| 384
| style="background:#e3f2fd;" | інформаційні матеріали
|-
| Фіскалізовано
| 378
| style="background:#c8e6c9;" | Норма
|-
| Повернення
| 9
| style="background:#f3e5f5;" | Контроль
|-
| Помилки драйвера
| 2
| style="background:#ef9a9a;" | Критично
|-
| Помилки РРО
| 4
| style="background:#ef9a9a;" | Критично
|-
| Потребують повтору
| 3
| style="background:#ffcc80;" | Потрібна дія
|-
| Ручна перевірка
| 1
| style="background:#b71c1c; color:#ffffff;" | Високий ризик
|-
| Незакриті зміни
| 1
| style="background:#ffcc80;" | Потрібна дія
|}

class FiscalDriver(ABC):

</pre>
</pre>
! SEO-опис

щоб закрити касову зміну. |}

index.php?title=Категорія:Інтеграції

Endpoint:

def close_shift(self, device_id: str) -> dict:

9.5. Чек продажу

"quantity": 2,
AC-7 POS передає продаж.=== 9.7. Чек повернення ===
{
external_order_id ID замовлення у зовнішній системі. SEO-опис Idempotency key, локальна БД, журнал статусів. | технічна підтримка моделей централізується на стороні драйвера. COM/OLE/DLL або інший API ArtSoft
for item in receipt ["items"]:
4. Параметр

9.2. конфігурація РРО

sha256(external_order_id + total_amount + payment_id + device_serial_number)

- Немає паперу - AC-15 } щоб мати можливість друкувати фіскальні чеки. SEO-опис

Мінімальні інформаційні дані:

  • підключення Python-сервісу до ArtSoft-драйвера;
  • роботу з різними моделями РРО через єдиний програмний інтерфейс;
  • перевірку стану РРО;
  • відкриття касової зміни;
  • друк і фіскалізацію чека продажу;
  • друк і фіскалізацію чека повернення;
  • службове внесення готівки;
  • службове винесення готівки;
  • формування X-звіту;
  • формування Z-звіту;
  • друк нефіскального тексту, якщо підтримується;
  • контроль помилок РРО;
  • журналювання команд і відповідей;
  • захист від дублювання чеків;
  • повторну обробку технічних помилок;
  • інтеграцію з K2 ERP / POS / CRM / сайтом. | Немає паперу, кришка, повтор. |-
items array Позиції, які повертаються. Тип задачі

27.3. Продаж

def print_x_report(self, device_id: str) -> "XReportResponse":

2. |-

Драйвер функціонує тільки на Windows - receipt_type varchar style="background:#bbdefb;" | Блакитний
Фіскалізовано FISCALIZED Зупинити друк, показати помаранчевий статус. POST /api/v1/rro/artsoft/receipts/refund
Перед відправкою на ArtSoft-драйвер платформа повинна перевірити:
ARTSOFT_AUTO_OPEN_SHIFT=true
</syntaxhighlight>
|-
| Немає документації до API драйвера
| Без документації неможливо коректно викликати OLE/DLL. |}

! Тип
<pre>


{| class="wikitable"
 {
 result = self.dll.GetDriverStatus()
Python викликає функції DLL через `ctypes` або `cffi`. Компонент
'''Критично критично:''' DLL-інтеграція без точних сигнатур функцій небезпечна. | інтеграційні функції ERP зберігається в системі. * Інструкції до конкретних моделей РРО. |-
| serial_number
| varchar
| Серійний номер. Продаж / повернення / службова операційна дія
 self.ensure_connected()
 {
 |
 | 2. | Python Agent створює чек у статусі PENDING. |-
| ShiftClosedError
| Зміна закрита. |-
| Ручна перевірка
| Хто перевірив, що встановив, коментар.<syntaxhighlight lang="python">
'''Критично критично:''' якщо після збою неможливо визначити, чи чек був надрукований, платформа повинна перевести операцію в статус MANUAL_REVIEW, а не автоматизовано друкувати повторно. Тип
|-
| Чернетка
| DRAFT
| Чек створено в Python-сервісі, але не відправлено на драйвер. Очікуваний результат

class ArtSoftRROClient:

Навіть якщо застосовується для ArtSoft як єдина бібліотека, в Python-коді потрібно зробити власний інтерфейс `FiscalDriver`. |-
| Обмеження
| Потрібно підтвердити підтримку такого режиму в ArtSoft. |-
| is_active
| boolean
| Активність. |-
| CASH_OUT
| Службове винесення готівки. Поле
! | style="background:#ffcc80;" | Помаранчевий
|-
| Ручна перевірка
| MANUAL_REVIEW
| Потрібна перевірка касиром або адміністратором. Очікуваний результат

class ArtSoftOleFiscalDriver(FiscalDriver):

* наявність external_order_id;
* наявність idempotency_key;
* відсутність уже фіскалізованого чека з таким ключем;
* активний РРО;
* доступність драйвера;
* доступність конкретного пристрою;
* наявність відкритої зміни або можливість її відкрити;
* готовність РРО;
* наявність паперу;
* відсутність критичних помилок;
* наявність хоча б однієї позиції;
* коректність кількості;
* коректність ціни;
* коректність суми рядка;
* відповідність total_amount сумі товарів і оплат;
* коректність типу оплати;
* коректність податкових груп;
* довжину назви товару;
* наявність відділу, якщо він обов'язковий;
* коректність QR-коду, якщо він друкується. |-
| unit
| varchar
| Одиниця. | style="background:#b71c1c; color:#ffffff;" | Високий ризик
|-
| Незакриті зміни
| Відкриті зміни без Z-звіту. # Чи потрібен централізований dashboard по декількох торгових точках? * Документація OLE/DLL API ArtSoft. Очікуваний результат
! |-
| model
| varchar
| Модель РРО. Де застосовується для

 # Сигнатури функцій потрібно задати згідно з документацією ArtSoft. | MANUAL_REVIEW замість автоматичного повтору. |-
| AC-19
| Чек у MANUAL_REVIEW. | Записати raw-помилку, повідомити адміністратора. Перевірити підключення до РРО.</div>

! Тип
 def ensure_connected(self) -> None:
{| class="wikitable"
|-
| id
| uuid
| ID зміни. |}

== 17. Черга друку ==

 pass

! ! | style="background:#ef9a9a;" | Червоний
|-
| РРО не підключений
| DEVICE_DISCONNECTED
| Немає зв'язку з пристроєм. | style="background:#e3f2fd;" | інформаційні матеріали
|-
| Фіскалізовано
| Кількість успішних чеків. | style="background:#eeeeee;" | Сірий
|-
| Повернення
| REFUNDED
| По чеку створено повне або часткове повернення. |-
| original_fiscal_number
| string
| Фіскальний номер первинного чека, якщо доступний. * Список підтримуваних моделей ArtSoft. |-
| AC-1
| Адміністратор налаштовує ArtSoft-драйвер. | платформа показує DRIVER_UNAVAILABLE червоним кольором. Поле
ArtSoft Універсальний драйвер реєстраторів
 |
 | 3. # Нижче наведено тільки архітектурний приклад. "cashier_id": "cashier-001",

* реалізувати Windows Service;
* додати моніторинг агента;
* додати auto-restart;
* додати резервне копіювання локальної БД;
* додати alerting;
* протестувати типові помилки РРО;
* протестувати оновлення версій ArtSoft-драйвера. v
|-
| Підходить для
| POS-вузлів, де драйвер функціонує як окремий сервіс.

Мінімальні інформаційні дані:

self.driver.Sale(
return {"raw": result}
def service_cash_in(self, device_id: str, amount: float, comment: str | None = None) -> dict:

8.3. Робота з різними моделями РРО