| Відкрита кришка
|
COVER_OPEN
|
-
|
raw_command
|
text/jsonb
|
-
|
Дублювання чеків
|
class="wikitable"
</syntaxhighlight>
def get_status(self) -> dict:
12.2.; Рекомендований стек агента19.1.; Абстрактний інтерфейс драйвераdef print_refund_receipt(self, payload: "RefundReceiptPayload") -> "ReceiptResponse":
Endpoint:
8.6.; Чек поверненняself.serial = None
- підключення до РРО через USB, RS232 або драйвер;
- роботу через OLE/DLL-бібліотеку виробника або прямий протокол обміну;
- перевірку стану РРО;
- відкриття касової зміни;
- друк і фіскалізацію чека продажу;
- друк і фіскалізацію чека повернення;
- службове внесення готівки;
- службове винесення готівки;
- формування X-звіту;
- формування Z-звіту;
- друк нефіскального тексту, якщо підтримується;
- програмування товарів, податкових груп, касирів — якщо потрібно;
- контроль помилок РРО;
- журналювання команд і відповідей;
- захист від дублювання чеків;
- повторну обробку технічних помилок;
- інтеграцію з K2 ERP / POS / CRM / сайтом.; |-
| Акумулятор
|
-
|
status
|
varchar
|
-
|
Чек повернення
|
Первинний чек, сума, причина.; №
def open_shift(self, cashier_id: str) -> "ShiftResponse":
!; |-
| model
| varchar
| MINI_FP54_01.; | Dashboard, нагадування, блок попереджень.; Чек потрапляє в чергу друку.; Worker перевіряє стан РРО.; | style="background:#fff9c4;" | Жовтий
|-
| Відправляється на РРО
| SENDING_TO_RRO
| Команда передається в драйвер або COM-порт.; | Зупинити друк, показати помаранчевий статус.; Статус
POST /api/v1/rro/receipts/sale
'''Управлінський результат:''' керівник повинен бачити, скільки чеків надруковано, скільки повернень виконано, які зміни відкриті, які Z-звіти сформовані, які РРО мають помилки зв'язку або потребують уваги.; Колір
Логіка:
<syntaxhighlight lang="python">
connection_type: str = "OLE_DLL"
POST /api/v1/rro/receipts/{receipt_id}/retry
return {"raw": result}
{| class="wikitable"
платформа повинна не допускати дублювання чеків.; | РРО закриває зміну.; Python Agent повинен уміти перевіряти:
POST /api/v1/rro/reports/x
"print_qr": true
<pre>
self.device.Sale(
!; Час
1.;== 6.; Основні сутності ==
for payment in receipt ["payments"]:
!; # Чи потрібно інтегрувати агент із K2 ERP?; |-
| style="background:#bbdefb;" | Блакитний
| #bbdefb
| операційна дія виконується.; OLE/DLL або Serial Protocol
=== 16.2.; Пріоритети ===
def open_shift(self, cashier_id: str) -> dict:
|
| 4.; |-
| is_active
| boolean
| Активність.; Поле
!; | style="background:#ffcc80;" | Потрібна дія
|-
| Незакриті зміни
| Відкриті зміни без Z-звіту.; |}
!; Реальні назви методів, параметри та коди відповідей потрібно взяти з актуального керівництва програміста / OLE-сервера виробника.; # Чи потрібен централізований dashboard по декількох торгових точках?; * ПЗ Uniq Commander.; Призначення
}
"type": "CARD",
|-
| id
| uuid
| ID зміни.; Що зберігати
<pre>
Ключі дедублікації:
import win32com.client
=== 21.3.; Проблемні операції ===
!; |}
!; |-
| Підключення до ПК
| USB, RS232.; | Другий чек не друкується.; |-
| ConnectionError
| Немає зв'язку з РРО.; |-
| Відкриття зміни
| Касир, час, відповідь РРО.; Дія
result = self.device.CloseReceipt()
|-
| Чек продажу
| Високий
| Основна операційна дія.; ERP надсилає йому HTTP-запити.; | Критична помилка, заборонити друк.; |-
| ShiftClosedError
| Зміна закрита.; |}
"cashier_id": "cashier-001",
<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">
* тимчасової втрати зв'язку;
* зайнятого COM-порту;
* timeout;
* тимчасової помилки драйвера;
* очікування готовності РРО;
* відновлення після відсутності паперу, якщо чек не був завершений.; №
{{SEO
|title=Технічне завдання: Інтеграція РРО МІНІ-ФП54.01 для Python
|description=Технічне завдання на реалізацію Python-сервісу для інтеграції з фізичним фіскальним реєстратором МІНІ-ФП54.01: продажі, повернення, відкриття та закриття зміни, X/Z-звіти, службове внесення/винесення, драйвер, COM/OLE/DLL, USB/RS232, черги, статуси та журналювання.
|keywords=Python, РРО, МІНІ-ФП54.01, MINI-FP54.01, фіскальний реєстратор, Юнісістем, USB, RS232, OLE, DLL, FastAPI, POS, K2 ERP, фіскальний чек, Z-звіт, X-звіт
}}
!; def __init__(self, ole_progid: str):
=== 24.4.; Зміни та звіти ===
=== Етап 7.; Production hardening ===
<syntaxhighlight lang="json">
return {"raw": response.hex()}
{| class="wikitable"
</div>
command = b"X_REPORT_COMMAND_PLACEHOLDER"
=== 7.1.; Продаж ===
!; Параметр
{| class="wikitable"
1.; |}
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
pass
!; self.serial.write(command)
"unit": "послуга"
=== Варіант 3.; 4.3.; Локальний Python Agent + ERP API ===
</div>
"department": 1,
log_raw_commands: bool = True
Central Fiscal API
!;== 2.; Область сфера застосування ==
== 12. Python RRO Agent ==
self.device = None
виконати команду відкриття зміни виступає ключовою рисою 4.; Перевірити підключення до РРО.; | Refund, службові операції.; | Черга чеків, очікування друку.; {| class="wikitable"
return {"raw": result}
я хочу сформувати Z-звіт,
pass
def x_report(self) -> dict:
!; |-
| original_fiscal_number
| string
| Фіскальний номер первинного чека, якщо доступний.; Код
|-
| AC-15
| Керівник відкриває dashboard.; Критерій
=== 18.2.; Перевірка стану РРО ===
|-
| ValidationError
| Некоректні інформаційні дані чека.; |-
| entity_id
| uuid
| ID сутності.; |}
def get_status(self) -> "RROStatus":
Як касир,
"tax_group": "NO_VAT",
port=self.port,
!; |-
| cashier_id
| string
| Ні
| Касир за замовчуванням.; |-
| CASH_OUT
| Службове винесення готівки.; |}
!; # Чи потрібна локальна БД на касовому ПК?; |}
<pre>
pass
'''Критично істотно:''' якщо після збою неможливо визначити, чи чек був надрукований, платформа повинна перевести операцію в статус MANUAL_REVIEW, а не автономно друкувати повторно.;== 29.; Джерела ==
* приймати HTTP-запити від K2 ERP / POS;
* керувати РРО;
* виконувати друк чеків;
* повертати статуси;
* зберігати локальний журнал;
* працювати навіть при тимчасовій недоступності центральної системи, якщо це дозволено сценарієм;
* синхронізувати результати з центральною БД.; | style="background:#eeeeee;" | Сірий
|-
| Очікує друку
| PENDING
| Чек у черзі на друк.; # Чи потрібно програмувати податкові ставки з Python?; Перевірити, чи зміна вже відкрита.; |-
| error_message
| text
| Помилка.; |-
| Немає паперу
| Чек не має змогу бути надрукований.; Тип
Retry дозволений для:
{
=== 4.1.; Варіант 1.; Через OLE/DLL-бібліотеку виробника ===
|-
| Підходить для
| Windows POS, касових робочих місць, локальної інтеграції.; |-
| external_order_id
| varchar
| ID замовлення.; характеристика
== 23.; Логування та аудит ==
pass
pass
5.; |-
| DuplicateReceiptError
| Чек уже надруковано.; def get_status(self) -> dict:
"idempotency_key": "ORDER-2026-000123-PAY-123456",
{| class="wikitable"
"amount": 70.00,
[[Категорія:МІНІ-ФП54.01]]
щоб коректно повернути кошти покупцю та відобразити операцію в РРО.; |}
pass
{| class="wikitable"
!; * [[Python]]
* [[FastAPI]]
* [[K2 ERP]]
* [[РРО]]
* [[Фіскальний реєстратор]]
* [[МІНІ-ФП54.01]]
* [[Фіскальний чек]]
* [[Касова зміна]]
* [[Z-звіт]]
* [[X-звіт]]
* [[POS]]
* [[USB]]
* [[RS232]]
* [[OLE]]
* [[DLL]]
* [[COM-порт]]
v
!; | Повторити після паузи або заблокувати чергу.; Поле
{| class="wikitable"
@abstractmethod
|
| 1.; Ризик
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
щоб агент надрукував і фіскалізував чек на МІНІ-ФП54.01.; |-
| items
| array
| Позиції чека.; характеристика
== 20.; Обробка помилок ==
платформа повинна логувати:
"amount": 570.00,
!; |}
!; Значення
retry_backoff_seconds: int = 3
=== 18.4.; Закриття зміни / Z-звіт ===
def close_shift(self) -> "ZReportResponse":
5.; Для serial-інтеграції обов'язково потрібен офіційно затверджений протокол обміну з точним форматом команд, відповідей, кодування та контрольних сум.; Локальний endpoint:
=== 24.3.; Повернення ===
def sale_receipt(self, receipt: dict) -> dict:
|
; РРО
def open_shift(self, cashier_id: str) -> dict:
щоб мати можливість друкувати фіскальні чеки.; {| class="wikitable"
pass
pass
|
; Очікуваний результат
item ["tax_group"],
pass
|
| Готовий
|
READY
|
}
@abstractmethod
def service_cash_out(self, amount: float, comment: str | None = None) -> "ServiceOperationResponse":
істотно: для МІНІ-ФП54.01 виробник надає USB-драйвер, OLE/DLL-бібліотеку для фіскальних реєстраторів, інструкції та документи щодо протоколу обміну.; Поле
|
-
|
Python-підхід
|
Перевести чек у CONNECTION_ERROR або NEEDS_RETRY.; Тип
|
; Тип задачі
v
{
Python взаємодіє з OLE/COM або DLL-бібліотекою, яку надає виробник.; |-
|
device_id
|
uuid
|
-
|
Грошова скринька
|
style="background:#eeeeee;" | Сірий
|
| Повернення
|
REFUNDED
|
-
|
items
|
array
|
-
|
new_status
|
varchar
|
style="background:#ef9a9a;" | Червоний
|
| Потребує повтору
|
NEEDS_RETRY
|
Операцію можна повторити.; Показник
16.1.; Логіка черги
POST /api/v1/rro/service-operation
def close_shift(self) -> dict:
Мінімальні інформаційні дані:
MINI_FP54_CONNECTION_TYPE=OLE_DLL
18.1.; Перевірка стану агента
return {"raw": result}
|
;
|
| AC-8
|
платформа показує DISCONNECTED червоним кольором.; | Повернути існуючий результат.; |-
|
AC-10
|
-
|
DriverError
|
Помилка OLE/DLL/драйвера.; Поле
Критично істотно: Z-звіт є собою операцією закриття зміни.;=== 12.3.; Методи Python RRO Client ===
- реалізувати dashboard API;
- реалізувати список помилок;
- реалізувати синхронізацію з K2 ERP;
- реалізувати експорт журналу, якщо потрібно.; | style="background:#ef9a9a;" | Червоний
|
| Помилка з'єднання
|
CONNECTION_ERROR
|
-
|
Cashier
|
Касир, від імені якого виконується операційна дія.;
|
| RRO Device
|
Фізичний фіскальний реєстратор МІНІ-ФП54.01.; Передача даних до ДПС самим РРО
def x_report(self) -> dict:
|
-
|
raw_close_response
|
jsonb/text
|
Друкується чек повернення.;== 7. User Story ==
=== Етап 4.; Чеки ===
!; Виконати команду формування Z-звіту.; | Зупинити друк, чек лишити в NEEDS_RETRY.; |-
| auto_open_shift
| boolean
| Так
| автономно відкривати зміну перед першим чеком.; |-
| AC-9
| Сума повернення перевищує продаж.; характеристика
</div>
Local Python RRO Agent
"operation_type": "CASH_IN",
{| class="wikitable"
!; | style="background:#ffcc80;" | Помаранчевий
|-
| Скасовано
| CANCELLED
| Операцію скасовано до друку.; |}
"tax_group": "VAT_20",
Endpoint:
pass
|-
| AC-11
| Касир відкриває зміну.; | Використовувати OLE/DLL або отримати документацію виробника.;== 9.; Статуси чеків ==
self.device = win32com.client.Dispatch(self.ole_progid)
"sku": "DELIVERY",
sha256(external_order_id + total_amount + payment_id + device_serial_number)
MINI_FP54_TIMEOUT_SECONDS=30
MINI_FP54_BAUD_RATE=115200
'''Рекомендована схема для K2 ERP:''' K2 ERP не повинна напряму керувати COM-портом.; Колір
<pre>
=== 17.2. rro_shifts ===
def print_non_fiscal_text(self, lines: list [str]) -> "PrintResponse":
</pre>
=== 20.2.; Retry-логіка ===
"quantity": 2,
'''Критично істотно:''' чек повернення не повинен перевищувати залишок по первинному чеку.; |-
| receipt_id
| uuid
| ID чека.; | Чек друкується і переходить у FISCALIZED.; {| class="wikitable"
{| class="wikitable"
=== 21.2.; Приклад dashboard ===
=== Етап 1.; Аналіз драйвера та протоколу ===
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
я хочу відкрити зміну на РРО,
!; return {"raw": response.hex()}
=== 12.1.; Призначення ===
== 4.; Варіанти інтеграції Python з РРО ==
|-
| Перевірка РРО
| Статус, помилки, час.; Тип
7.; Він повинен повернути результат уже виконаної операції.; характеристика
class MiniFP54Client:
!; |-
| PaperOutError
| Немає паперу.; |-
| переважні аспекти
| Використання офіційної бібліотеки виробника.; # Чи буде декілька РРО на одному ПК?; |-
| price
| numeric
| Ціна.; |-
| com_port
| string
| Ні
| як ілюстрація COM3.; Передати результат у K2 ERP.; def connect(self) -> None:
def sale_receipt(self, receipt: dict) -> dict:
=== 24.1.; Підключення ===
!;== 11.; Єдина логіка кольорів ==
],
* фізичних магазинів;
* аптек;
* кафе, барів, ресторанів;
* кіосків;
* торгових точок із обмеженим простором;
* виїзної торгівлі;
* кур'єрської доставки;
* інтернет-магазинів із друком фіскального чека на фізичному РРО;
* POS-вузлів, де потрібна робота з реальним фіскальним реєстратором.; result = self.device.XReport()
!; |-
| FiscalMemoryError
| Помилка фіскальної пам'яті.; |}
pass
{| class="wikitable"
* чи підключений РРО;
* чи доступний порт;
* чи доступний драйвер/OLE/DLL;
* чи є собою папір;
* чи відкрита кришка;
* чи є собою помилки живлення;
* чи є собою зв'язок з ДПС через канали пристрою;
* чи відкрита зміна;
* чи не заблокований РРО;
* чи не переповнена пам'ять;
* чи коректно встановлена дата і час;
* чи готовий РРО до друку чека.; Параметр
</div>
!; Краще використовувати локальний Python Agent біля РРО, а K2 ERP функціонує з ним через API.; Закрити локальну зміну.; Результат зберігається локально.; # Які типи оплат підтримуються: готівка, картка, змішана оплата?; "payment_id": "PAY-123456"
@abstractmethod
[[Категорія:РРО]]
!; |-
| PortBusyError
| COM-порт зайнятий.; |-
| Службова операційна дія
| Тип, сума, касир.; |-
| Refund Receipt
| Чек повернення.;=== Етап 6.; Dashboard і синхронізація ===
* реалізувати sale receipt;
* реалізувати refund receipt;
* реалізувати валідацію;
* реалізувати дедублікацію;
* реалізувати чергу друку.; | платформа блокує операцію.; Пріоритет
!; Замовлення
Як керівник або адміністратор,
Типи:
def connect(self) -> None:
|
; Коментар
|
Dashboard, список чеків, статус РРО.; Python Agent виконує валідацію.; | Заборонити паралельний доступ.; |-
|
device_serial_number
|
string
|
Так
|
}
Retry заборонений для:
Мінімальні інформаційні дані:
self.device.Payment(payment ["type"], float(payment ["amount"]))
== 1.; Мета ==
=== 18.6.; Чек продажу ===
== 16.; Черга друку ==
"external_order_id": "ORDER-2026-000123",
|-
| Підходить для
| Глибокої інтеграції, Linux/Windows-сценаріїв, embedded POS.; |-
| com_port
| varchar
| COM-порт.; |-
| print_qr
| boolean
| Чи друкувати QR-код.; self.device.OpenReceipt(0)
* https://unisystem.ua/catalog/fiskalnye-registratory/fiskalnyj-registrator-mini-fp54-01/
* Інструкція з експлуатації МІНІ-ФП54.01.; характеристика
!; |-
| event_type
| varchar
| Тип події.; Статус
!; POST /api/v1/rro/service-operation
|-
| AC-4
| POS передає продаж.; # Чи потрібно програмувати товари в РРО?; Параметр
До MVP входить:
|
; Критерій
- отримати проміжний звіт без закриття зміни;
- перевірити обороти;
- перевірити стан каси;
- показати керівнику поточні підсумки.; Перевірити підключення до РРО.; # На якій ОС працюватиме касовий ПК: Windows чи Linux?; Критично істотно: перед друком фіскального чека агент повинен перевірити готовність РРО.; |-
|
Нефіскальний друк
|
Низький
|
-
|
current_shift_id
|
uuid
|
Поточна зміна.;
|
; Поле
|
; Стан
def service_cash_in(self, amount: float, comment: str | None = None) -> "ServiceOperationResponse":
K2 ERP / POS / CRM / Website
return {"raw": result}
}
|
Вони підсвічуються помаранчевим.; pass
я хочу створити чек повернення,
</div>
def __init__(self, port: str, baud_rate: int, timeout: int = 30):
def print_sale_receipt(self, payload: "SaleReceiptPayload") -> "ReceiptResponse":
command = b"STATUS_COMMAND_PLACEHOLDER"
from abc import ABC, abstractmethod
POST /api/v1/rro/reports/x
!; |-
| ole_progid
| varchar
| ProgID OLE.; характеристика
Він повинен:
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
class MiniFP54OleDriver(RRODriver):
2.; |-
| customer
| object
| інформаційні дані покупця, якщо потрібні.; |-
| payments
| array
| Оплати.; |-
| Передача даних у ДПС
| Через Ethernet або GSM/GPRS-модем.; |-
| payments
| array
| Сума повернення.; |-
| AC-2
| Python Agent перевіряє статус РРО.; |-
| baud_rate
| integer
| Ні
| Швидкість порту, якщо застосовують, коли потрібно serial.; POS / K2 ERP надсилає запит на чек.; |-
| z_report_number
| varchar
| Номер Z-звіту.; | style="background:#e3f2fd;" | відомості
|-
| Фіскалізовано
| Кількість успішних чеків.; |-
| error_message
| text
| Повідомлення помилки.; dll_path: str | None = None
item ["name"],
</pre>
МІНІ-ФП54.01
def print_x_report(self) -> "XReportResponse":
class MiniFP54SerialDriver(RRODriver):
== 14.; Валідація чека ==
if self.serial is None or not self.serial.is_open:
retry_count: int = 2
return response
class RRODriver(ABC):
"name": "Доставка",
</pre>
POST /api/v1/rro/reports/z
=== 20.1.; Типи помилок ===
!; |-
| allow_service_operations
| boolean
| Так
| Дозволити службове внесення/винесення.; | style="background:#ffcc80;" | Помаранчевий
|-
| Помилка фіскальної пам'яті
| FISCAL_MEMORY_ERROR
| Критична помилка.; Критерій
== 15.; Дедублікація ==
|-
| 10:42
| MINI-FP54.01 #001
| ORDER-123
| 570.00
| style="background:#ef9a9a;" | Помилка
| Немає зв'язку з COM-портом
| Перевірити підключення
|-
| 11:05
| MINI-FP54.01 #001
| ORDER-124
| 1200.00
| style="background:#ffcc80;" | Потребує повтору
| Немає паперу
| Замінити папір і повторити
|-
| 12:10
| MINI-FP54.01 #002
| SHIFT-55
| -
| style="background:#ffcc80;" | Зміна відкрита
| Не закрито Z-звіт
| Закрити зміну
|}
{| class="wikitable"
response = self.send_command(command)
* доступ до локального агента тільки з дозволених IP або через токен;
* HTTPS або локальну захищену мережу;
* авторизацію запитів від K2 ERP / POS;
* розмежування прав: продаж, повернення, X-звіт, Z-звіт, службові операції;
* журнал дій користувачів;
* захист від дублювання чеків;
* заборону прямого доступу до драйвера з кількох процесів;
* шифрування конфігурацій, якщо містять чутливі інформаційні дані;
* маскування персональних даних покупців у логах.; '''істотно:''' прямий протокол потрібно реалізовувати тільки після отримання актуальної документації виробника щодо команд, форматів пакетів, контрольних сум і відповідей РРО.; # Чи потрібна інтеграційні функціональні можливості з банківським POS-терміналом?; Тип
== 18. API Python Agent ==
!; self.connect()
9.; | Виносити інтеграцію в локальний Windows Agent.; | style="background:#f3e5f5;" | Фіолетовий
|}
== 22.; Безпека ==
[[Категорія:Технічні завдання]]
result = self.device.OpenShift(cashier_id)
!; '''Критично істотно:''' це інтеграційні функціональні можливості з фізичним РРО, а не з хмарним ПРРО.; |-
| quantity
| numeric
| Кількість.; |-
| name
| varchar
| Назва товару.; |-
| AC-14
| Зміна не закрита наприкінці дня.; |-
| ole_progid
| string
| Ні
| ProgID OLE-сервера, якщо застосовується OLE.; | РРО переходить у стан SHIFT_OPEN.; Поле
* наявність external_order_id;
* наявність idempotency_key;
* відсутність уже фіскалізованого чека з таким ключем;
* наявність відкритої зміни або можливість її відкрити;
* готовність РРО;
* наявність паперу;
* відсутність критичних помилок;
* наявність хоча б однієї позиції;
* коректність кількості;
* коректність ціни;
* коректність суми рядка;
* відповідність total_amount сумі товарів і оплат;
* коректність типу оплати;
* коректність податкових груп;
* довжину назви товару;
* довжину рядка чека;
* наявність відділу, якщо він обов'язковий;
* коректність QR-коду, якщо він друкується.; Якщо зміна не відкрита.; |-
| total_amount
| decimal
| Загальна сума.; |-
| RRO Agent
| Локальний Python-сервіс, який керує пристроєм.; |-
| idempotency_key
| string
| Ключ захисту від дублювання.; |-
| Невідомий стан після збою
| Невідомо, чи чек надрукований.; | Немає паперу, кришка, повтор.; # Чи потрібно запускати Python Agent як Windows Service?; # Тут наведено тільки архітектурний приклад.; |}
<pre>
=== 17.5. rro_events ===
POST /api/v1/rro/reports/z
"total_amount": 570.00,
!; |-
| idempotency_key
| ключовий ключ повторного запиту.; | style="background:#ef9a9a;" | Критично
|-
| Потребують повтору
| Чеки у NEEDS_RETRY.; |-
| style="background:#fff9c4;" | Жовтий
| #fff9c4
| Очікування або попередження.; |-
| style="background:#ef9a9a;" | Червоний
| #ef9a9a
| Критична помилка.; |-
| Bluetooth
| Опція.; |-
| cashier_id
| string
| Касир.; |-
| РРО МІНІ-ФП54.01
| Фізичний пристрій, підключений через USB/RS232.; |-
| AC-16
| є собою помилки РРО.;=== 8.5.; Приклад запиту на чек продажу ===
* реалізувати cash_in;
* реалізувати cash_out;
* реалізувати права доступу;
* реалізувати аудит.; |-
| Кількість касирів
| 32.; HTML
| Мова
|
Python 3.11+
|
| API
|
FastAPI
|
| Доступ до COM/OLE
|
pywin32 або comtypes
|
| Доступ до DLL
|
ctypes або cffi
|
| Доступ до COM-порту
|
pyserial
|
| Локальна БД
|
SQLite або PostgreSQL
|
| Черга
|
SQLite queue / Redis / RQ
|
| Логи
|
structlog / logging
|
| Упаковка
|
Windows Service / Docker для Linux-сценаріїв, якщо serial
|
|
; for item in receipt ["items"]:
def close_shift(self) -> dict:
"provider": "terminal",
self.baud_rate = baud_rate
|
-
|
Помаранчевий
|
#ffcc80
|
-
|
cashier_id
|
varchar
|
Касир.; Критерій
я хочу бачити помилки РРО,
|
; №
|
-
|
printed_at
|
timestamp
|
-
|
receipt_hash
|
Hash товарів, сум, оплат і каси.;
24. Acceptance Criteria
<pre>
=== 8.1.; конфігурація пристрою ===
</pre>
[[Категорія:Фіскальні реєстратори]]
{| class="wikitable"
{
!; |-
| Кількість товарів
| 16 384.; | Записати raw-помилку, повідомити адміністратора.; Очікуваний результат
command = b"OPEN_SHIFT_COMMAND_PLACEHOLDER"
4.; |}
[[Категорія:K2 ERP]]
== 19.; Приклад Python-логіки ==
{| class="wikitable"
[[Категорія:Інтеграції]]
6.; Помилка
self.port = port
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
{{DISPLAYTITLE:Технічне завдання: Інтеграція РРО МІНІ-ФП54.01 для Python}}
=== 8.3.; Відкриття зміни ===
!; {
'''істотно:''' назви методів OLE/DLL у прикладі є собою умовними.; Подія
!; |}
allow_refunds: bool = True
=== 17.1. rro_devices ===
2.; pass
self.ole_progid = ole_progid
=== 8.9.; Z-звіт ===
<pre>
Python-сервіс повинен працювати через драйвер, COM/OLE/DLL, протокол обміну, USB/RS232 або проміжний локальний агент.; # Чи потрібна офлайн-робота при недоступності центральної ERP?; |-
| payload
| jsonb/text
| інформаційні дані події.; |-
| AC-3
| РРО не підключений.; характеристика
|-
| Немає актуального протоколу
| Без документації неможливо безпечно реалізувати serial-інтеграцію.; платформа повинна забезпечити:
* реалізувати RRODriver interface;
* реалізувати MiniFP54OleDriver або MiniFP54SerialDriver;
* реалізувати check_status;
* реалізувати open_shift;
* реалізувати X/Z-звіти.; |-
| X-звіт
| Час, РРО, відповідь.; |-
| Shift
| Касова зміна.; |-
| RefundLimitError
| Повернення перевищує доступну суму.; | MANUAL_REVIEW замість автоматичного повтору.; | style="background:#ef9a9a;" | Червоний
|-
| Немає зв'язку з ДПС
| TAX_SERVER_CONNECTION_ERROR
| Пристрій не має змогу передати інформаційні дані.; |-
| discount_amount
| numeric
| Знижка.; '''Критично істотно:''' повторний запит із тим самим idempotency_key не повинен друкувати другий фіскальний чек.; Перед відправкою на РРО платформа повинна перевірити:
* створити FastAPI-сервіс;
* реалізувати healthcheck;
* реалізувати локальну БД;
* реалізувати модель пристрою;
* реалізувати логування.; | style="background:#c8e6c9;" | Зелений
|-
| Не підключений
| DISCONNECTED
| Немає зв'язку з пристроєм.; | платформа зменшує доступний залишок до повернення.; pass
інтеграційні функціональні можливості призначена для:
</div>
!; | style="background:#ef9a9a;" | Критично
|}
6.; 6.; Технологія
return {"raw": response.hex()}
2.; |-
| reason
| string
| Причина повернення.; Повернути результат у K2 ERP / POS.; Результат синхронізується з центральною системою.; |-
| amount
| numeric
| Сума.; |-
| opened_at
| timestamp
| Дата відкриття.; |-
| Обмеження
| Найчастіше потребує Windows, COM/OLE, драйверів і локального доступу до пристрою.; |-
| OLE/DLL функціонує тільки на Windows
| Обмеження для Linux-серверів.; !; Для часткових повернень платформа повинна вести залишок доступної до повернення суми та кількості.; |-
| Швидкість друку
| 8 рядків/с.; |}
'''Критично істотно:''' Ethernet і GSM/GPRS у цій моделі використовуються для передачі даних РРО до ДПС, але інтеграційні функціональні можливості з Python для команд друку чеків зазвичай потребує USB/RS232 або драйвера/OLE/DLL на локальному комп'ютері.; |-
| created_at
| timestamp
| Дата події.; характеристика
* повна реалізація всього протоколу обміну;
* автоматичне програмування всієї номенклатури;
* повний POS UI;
* власна фіскальна логіка замість РРО;
* складна офлайн-синхронізація;
* інтеграційні функціональні можливості з усіма моделями РРО;
* супровід Linux, якщо обрано OLE/DLL для Windows.; command = b"Z_REPORT_COMMAND_PLACEHOLDER"
</pre>
<pre>
v
pass
|-
| style="background:#c8e6c9;" | Зелений
| #c8e6c9
| Успішна операційна дія або нормальний стан.; |-
| fiscal_number
| varchar
| Фіскальний номер або номер чека, якщо доступний.; def service_cash_out(self, amount: float, comment: str | None = None) -> dict:
'''Рекомендована технічна архітектура:''' Python POS Adapter функціонує локально на комп'ютері касира або POS-вузлі, має доступ до USB/RS232/COM/OLE/DLL-драйвера та приймає команди від ERP через HTTP API або локальну чергу.; Очікуваний результат
@abstractmethod
=== 18.9.; Повторити чек ===
=== 8.4.; Чек продажу ===
</div>
ДПС
}
{| class="wikitable"
@abstractmethod
4.; Тип
5.; Дія системи
@abstractmethod
auto_open_shift: bool = True
У K2 ERP або локальному агенті повинна бути картка РРО.; Колір
я хочу передати продаж у Python Agent,
{| class="wikitable"
"payments": [
response = self.serial.read_until()
<pre>
Як касир,
== 5.; Загальна технічна архітектура ==
== Див.; 30.; додатково ==
</pre>
pass
!; | Чек переходить у NEEDS_RETRY або RRO_ERROR.; |-
| Z-звіт
| Критичний
| Закриття зміни.; характеристика
|-
| Тип пристрою
| Фізичний фіскальний реєстратор.; |-
| Dashboard
| Центральний контроль чеків, змін і помилок.; | Не відправляти на РРО.; | Python Agent створює чек у статусі PENDING.; |-
| raw_response
| text/jsonb
| Відповідь РРО.; характеристика
</div>
response = self.send_command(command)
На касовому ПК запускається локальний Python Agent, який функціонує з РРО.; |-
| RRO Response
| Відповідь пристрою.; !; Як зменшити
=== 24.5. Dashboard ===
!; # Чи потрібно відкривати грошову скриньку?; Тип
|
-
|
entity_type
|
varchar
|
device, shift, receipt.; Поле
27.; Ризики
"cashier_id": "cashier-001",
|
-
|
external_payment_id
|
varchar
|
-
|
переважні аспекти
|
class="wikitable"
POST /api/v1/rro/shifts/open
def check_connection(self) -> "RROStatus":
"sku": "SKU-001",
"department": 2,
allow_service_operations: bool = True
"quantity": 1,
17.; Модель даних
|
| Чеків за день
|
-
|
Ширина чекової стрічки
|
-
|
Контрольна стрічка
|
-
|
sku
|
varchar
|
Артикул.; Де застосовується
|
; Компонент
Особливості моделі МІНІ-ФП54.; 3.01
MINI_FP54_RETRY_COUNT=2
|
; Друк та фіскалізація чека
"items": [
8.; Функціональні вимоги
|
|
-
|
external_refund_id
|
string
|
style="background:#ffcc80;" | Потрібна дія
|
| РРО не підключені
|
}
<syntaxhighlight lang="python">
|
-
|
Помилка драйвера
|
Код, текст, raw-відповідь.; {
result = self.device.GetStatus()
Як POS або K2 ERP,
|-
| device_name
| string
| Так
| Назва РРО.; |-
| dll_path
| string
| Ні
| Шлях до DLL, якщо застосовується DLL.; |-
| idempotency_key
| string
| Ключ захисту від дублювання.; |-
| AC-5
| РРО готовий.; |-
| baud_rate
| integer
| Швидкість порту.; |-
| Друк QR / штрих-коду
| Підтримується.; | style="background:#ffcc80;" | Помаранчевий
|-
| Зміна відкрита
| SHIFT_OPEN
| Можна друкувати фіскальні чеки.; |-
| dll_path
| varchar
| Шлях до DLL.; # Чи потрібно друкувати QR-код у чеку?; * Зміни до протоколу обміну.; |-
| Не закрито зміну
| Касир забув зробити Z-звіт.; |-
| Service Operation
| Службове внесення або винесення.; |-
| connection_type
| enum
| Так
| OLE_DLL, SERIAL, USB_COM.; Очікуваний результат
!; |-
| AC-6
| Немає паперу.; baudrate=self.baud_rate,
MINI_FP54_LOG_RAW_COMMANDS=true
{| class="wikitable"
def close_shift(self) -> dict:
Призначення:
'''Заборонено:''' використовувати placeholder-команди в production.; ],
- завантажити інструкцію з експлуатації;
- завантажити зміни до протоколу обміну;
- завантажити OLE/DLL-бібліотеку;
- завантажити USB-драйвер;
- перевірити підключення РРО до ПК;
- визначити робочий сценарій: OLE/DLL або serial.; характеристика
Етап 5.; Службові операції
|
| id
|
uuid
|
Чернетка, зміна закрита.; |}
result = self.device.ZReport()
@abstractmethod
- локальний Python Agent;
- конфігурація підключення до МІНІ-ФП54.01;
- перевірка стану РРО;
- відкриття зміни;
- друк чека продажу;
- друк чека повернення;
- службове внесення / винесення;
- X-звіт;
- Z-звіт;
- локальна БД чеків;
- дедублікація;
- журнал команд і відповідей;
- базовий dashboard API;
- обробка помилок паперу, порту, драйвера, зміни;
- retry для безпечних ситуацій.; |-
|
raw_open_response
|
jsonb/text
|
-
|
Fiscal Receipt
|
Фіскальний чек продажу.; характеристика
GET /api/v1/rro/status
Endpoint:
<syntaxhighlight lang="python">
|
Пристрій зберігається в системі.; | Заборонити операцію.; |-
|
RRO Command
|
-
|
COM-порт зайнятий
|
Інший бізнес-процес використовує РРО.; * OLE/DLL-бібліотека виробника.; Значення / характеристика
10.; Статуси РРО
v
<pre>
=== 8.7.; Службове внесення / винесення ===
def get_status(self) -> dict:
com_port: str | None = "COM3"
рішення для бізнесу повинно забезпечити:
|
; характеристика
MINI_FP54_COM_PORT=COM3
[[Категорія:POS]]
=== 21.1.; Основні KPI ===
)
== 21.; Dashboard керівника ==
</div>
До MVP не входить:
# Назви методів залежать від документації OLE-сервера виробника.; def refund_receipt(self, receipt: dict) -> dict:
POST /api/v1/rro/receipts/refund
GET /api/v1/rro/events?date_from=2026-05-01&date_to=2026-05-07
;=== 8.8.; X-звіт ===
def x_report(self) -> dict:
3.; Тип
28.; Відкриті питання
POST /api/v1/rro/receipts/sale
Етап 3.; Драйверний шар
| ; характеристика
Рекомендовано для MVP: починати з OLE/DLL-бібліотеки виробника, якщо вона стабільно функціонує з моделлю МІНІ-ФП54.01 та підтримує роботу всі потрібні команди.; |-
|
department
|
integer
|
Відділ.; №
|
;=== 24.2.; Продаж ===
|
-
|
Чек продажу
|
Замовлення, сума, позиції, статус.; Зберегти номер і результат Z-звіту.; from pydantic_settings import BaseSettings
POST /api/v1/rro/shifts/open
|
-
|
Дисплей покупця
|
Вбудований 2x16.; характеристика
Python RRO Agent — це локальний сервіс, який встановлюється на касовий ПК і має доступ до РРО через USB/RS232/OLE/DLL.; Якщо РРО має критичну помилку, чек не повинен переходити в статус «Фіскалізовано».; |-
| unit
|
varchar
|
-
|
status
|
varchar
|
-
|
is_active
|
boolean
|
Так
|
Чи активний пристрій.; Обов'язковість
},
|
| id
|
uuid
|
-
|
Службове внесення / винесення
|
Середній
|
Касова операційна дія.; self.timeout = timeout
|
-
|
Обмеження
|
-
|
device_id
|
uuid
|
ID РРО.; №
|
| id
|
uuid
|
-
|
Сірий
|
#eeeeee
|
-
|
fiscal_number
|
varchar
|
}
# Який варіант інтеграції обираємо: OLE/DLL чи прямий serial-протокол?; | style="background:#c8e6c9;" | Норма
|
| Повернення
|
Кількість чеків повернення.; Локальний endpoint:
"price": 250.00,
18.10.; Отримати журнал подій
|
; Якщо потрібно — відкриває зміну.;
18.8.; Службова операційна дія
Приклад:
MINI_FP54_AUTO_OPEN_SHIFT=true
|
| Чеків за день
|
384
|
відомості
|
| Фіскалізовано
|
378
|
Норма
|
| Повернення
|
9
|
Контроль
|
| Помилки РРО
|
4
|
Критично
|
| Потребують повтору
|
3
|
Потрібна дія
|
| Незакриті зміни
|
1
|
Потрібна дія
|
item.get("department", 1),
pass
13.; Приклад конфігурації
3.; |}
"unit": "шт"
@abstractmethod
float(item ["quantity"]),
19.2.; Приклад OLE-драйвера
Endpoint:
|
; Тип
17.4. rro_receipt_items
1.; Поле
Приклад `.env`:
def open_shift(self, cashier_id: str) -> dict:
інтеграції ERP / POS / CRM / інтернет-магазину з фізичним фіскальним реєстратором МІНІ-ФП54.01 для друку та фіскалізації чеків забезпечується через Головна ідея: розробити Python-сервіс або Python-адаптер; додатково реалізовано повернень, службових операцій, відкриття і закриття змін.; Зберегти локальний статус.; |-
| receipt_type
|
varchar
|
style="background:#ef9a9a;" | Червоний
|
щоб закрити касову зміну.; | style="background:#bbdefb;" | Блакитний
|
| Фіскалізовано
|
FISCALIZED
|
-
|
RRO Error
|
-
|
status
|
varchar
|
}
return {"raw": result}
Варіант 2.; 4.2.; Через прямий протокол обміну RS232/USB-COM
Метою задачі є собою створення Python-рішення для інтеграції з фізичним фіскальним реєстратором МІНІ-ФП54.01.; | Вони підсвічуються червоним.; |-
|
Кількість відділів
|
64.; Логіка:
* реалізувати Windows Service;
* додати моніторинг агента;
* додати auto-restart;
* додати резервне копіювання локальної БД;
* додати alerting;
* протестувати типові помилки РРО.; |}
|
; Тип
|
Черга, друк, передача команди.; |-
|
old_status
|
varchar
|
Старий статус.; Очікуваний результат
7.2.; Повернення
GET /api/v1/health
response = self.send_command(command)
Як касир або адміністратор,
)
|
style="background:#f3e5f5;" | Контроль
|
| Помилки РРО
|
Кількість помилкових операцій.; Перевірити незавершені чеки.;=== 17.3. rro_receipts ===
|
; Тип
|
| K2 ERP / POS
|
Статус PAPER_OUT, повтор після заміни паперу.; Сума
|
-
|
AC-7
|
Повторний запит має той самий idempotency_key.; !; Критерій
7.5.; Контроль помилок
v
"comment": "Службове внесення на початок зміни",
|
-
|
AC-17
|
-
|
X-звіт
|
Середній
|
-
|
total_amount
|
numeric
|
-
|
external_order_id
|
Idempotency key, локальна БД, журнал статусів.; |-
|
Z-звіт
|
Час, номер звіту, результат.; характеристика
self.serial = serial.Serial(
|
style="background:#ef9a9a;" | Червоний
|
| Немає паперу
|
PAPER_OUT
|
платформа повертає READY або конкретну помилку.; |-
|
X Report
|
Проміжний звіт без закриття зміни.; Створюється локальний запис receipt зі статусом PENDING.; Сутність
|
| id
|
uuid
|
ID події.; KPI
class MiniFP54Settings(BaseSettings):
"amount": 1000.00,
|
| Чернетка
|
DRAFT
|
-
|
tax_profile_id
|
string
|
Ні
|
-
|
closed_at
|
timestamp
|
-
|
error_code
|
varchar
|
style="background:#c8e6c9;" | Зелений
|
| Помилка РРО
|
RRO_ERROR
|
Він бачить чеки, повернення, помилки, незакриті зміни.; return {"raw": response.hex()}
POST /api/v1/rro/receipts/refund
|
-
|
Повторна операційна дія
|
Хто запустив, причина, результат.; Статус
def service_cash_in(self, amount: float, comment: str | None = None) -> dict:
baud_rate: int = 115200
=== 7.4.; Закриття зміни ===
|
|
| |
|