Module for working with the ATOL cash register driver
Project description
ORD — Python-клиент драйвера АТОЛ libfptr10
Тонкая обёртка над libfptr10 (драйвер ККТ АТОЛ v10.10.x) для типовых
кассовых сценариев: открытие/закрытие смены, регистрация чека продажи и
возврата, чтение состояния ФН и ОФД-обмена, регистрация ККТ, чтение и
запись device settings.
Используется в backend-проекте online-receipt/online-api (Flask + Celery)
для фискализации чеков на физических кассах АТОЛ 30Ф, ATOL Sigma и
совместимых моделях.
- Текущая версия:
1.11.0 - PyPI:
pip install ORD - Источник истины: GitLab
online-receipt/online-receipt-driver(этот репо) - Зеркало: GitHub
brandshopru/online-receipt-driver - Стек: Python 3.6+,
libfptr10>=10.10.0 - Лицензия: проприетарная, ООО «БШ СТОР» (brandshop.ru)
1. Установка
pip install ORD==1.11.0
Зависимость от libfptr10 (Python wrapper) ставится отдельно из дистрибутива
АТОЛ kit (fptr10-rpc-server*.deb + wrappers/python/libfptr10.py).
Минимальные системные требования:
- Python >=3.6 (3.6 в EOL, рекомендуется 3.8+)
libfptr10.sov10.10.x в/lib64/илиLD_LIBRARY_PATH- USB-устройство ATOL (
Vendor:Product 2912:0005) либо TCP/IP подключение - При работе через
atol-grpc-service— gRPC мост на127.0.0.1:4041/:4042
2. Архитектура
2.1. Структура
ORD/
├── __init__.py # public-экспорт классов
├── ord_core.py # Core (Singleton, IFptr wrapper)
├── ord_cash.py # Cash (state ККТ, регистрация)
├── ord_fn.py # Fn (ФН-операции, ОФД-обмен)
├── ord_receipt.py # Receipt (чек: open/registration/payment/close)
├── ord_shift.py # Shift (open/close смены)
├── ord_setting.py # Setting (device settings R/W)
└── exceptions.py # OrdError, OrdTimeoutError (§6.8 + §6.9, c 1.11.0)
2.2. Класс Core (Singleton)
Core — единая точка инициализации IFptr. Реализован как Singleton через
метакласс SingletonMeta с потокобезопасным threading.Lock. На процесс
гарантированно один экземпляр.
Дефолтные settings при Core():
| Параметр libfptr10 | Значение |
|---|---|
LIBFPTR_SETTING_MODEL |
LIBFPTR_MODEL_ATOL_AUTO (автоопределение) |
LIBFPTR_SETTING_PORT |
LIBFPTR_PORT_USB |
LIBFPTR_SETTING_USB_DEVICE_PATH |
"auto" |
LIBFPTR_SETTING_OFD_CHANNEL |
LIBFPTR_OFD_CHANNEL_AUTO |
LIBFPTR_SETTING_AUTO_TIME_SYNC |
True |
LIBFPTR_SETTING_AUTO_TIME_SYNC_TIME |
15 (секунд) |
Instance-level state Core.casher_info (c 1.10.0):
core = Core(path="", casher_name="Иванов И.И.", casher_inn="500100732259")
# или сменить runtime:
core.set_casher("Петров П.П.", inn="...")
Используется в _set_casher() перед каждой фискальной операцией
(setParam(1021, name), setParam(1203, inn), operatorLogin()). Если
casher_name пуст — operatorLogin пропускается (logon оператора
не происходит, чек/смена пишутся без тегов 1021/1203).
Жизненный цикл соединения:
__init__создаётIFptrinstance, читает версию, применяет settingsopen_connect()→fptr.open()— реальный коннект к ККТclose_connect()→fptr.close()__del__авто-закрывает еслиis_opened() == 1
2.3. Доменные классы
Cash, Fn, Receipt, Shift, Setting — потребители Core. Все принимают
один Core-экземпляр в конструктор и сохраняют self.fptr = core.fptr. Если
соединение закрыто, конструктор автоматически вызывает core.open_connect().
from ORD.ord_core import Core
from ORD.ord_receipt import Receipt
from ORD.ord_fn import Fn
core = Core() # Singleton
core.open_connect()
fn = Fn(core)
receipt = Receipt(core)
# ...
core.close_connect()
3. Типовой жизненный цикл чека
Псевдокод реального флоу из online-api/jobs/handlers.py:
core = Core()
core.open_connect()
# 1. Открыть смену (необязательно — первая фискальная операция откроет автоматически)
Shift(core).open_shift()
# 2. Открыть чек
receipt = Receipt(core)
receipt.open_receipt({
"docType": "SALE", # или "RETURN"
"printReceipt": False, # электронный
"email": "client@example.com",
"taxMode": "OSN", # OSN / USN_INCOME / ...
})
# 3. Регистрация каждой позиции
receipt.receipt_registration({
"name": "Кроссовки Nike",
"price": 10000,
"quantity": "1",
"vatTag": 1102, # 1102 — Сумма НДС по ставке 20%
"vat": 22, # ставка 22 → LIBFPTR_TAX_VAT22
"discSum": 0,
"nomenclatureCode": "0104680001234567...", # КМ Data Matrix, опционально
"codeCheck": "UUID=...&Time=...", # результат ПИоТ-проверки, опционально
})
# 4. Оплата
receipt.receipt_payment({"paymentType": "CARD", "sum": 10000})
# paymentType резолвится через Receipt.payment_type → LIBFPTR_PT_* (с 1.8.26.1)
# 5. Закрытие чека → ФН → ОФД
receipt.receipt_close()
# 6. Получить фискальные реквизиты
last = Fn(core).get_info_last_doc()
# → {"document_number": 123, "fiscal_sign": "1234567890", "date_time": "..."}
Закрытие смены (Z-отчёт): Shift(core).close_shift().
4. API Reference
4.1. Core
| Метод | Возврат | Назначение |
|---|---|---|
Core(path: str = '') |
— | Singleton-инициализация IFptr с дефолтными settings |
open_connect() |
bool |
fptr.open() — коннект к ККТ |
close_connect() |
bool |
fptr.close() |
is_opened() |
int |
0/1, см. §5.1 — не отражает реальное состояние |
get_version_driver() |
str |
версия libfptr10 |
get_current_datetime() |
str |
"%Y-%m-%d %H:%M:%S" от ККТ |
get_setting() |
dict |
текущие device settings |
reboot() |
bool |
fptr.deviceReboot() |
_set_casher() |
bool |
оператор тег 1021 + 1203 + operatorLogin() (приватный) |
_check_document_close() |
bool |
проверка checkDocumentClosed, допечатка (приватный) |
_error_log() |
— | пишет errorCode + errorDescription в журнал libfptr10 |
info_log(msg: str) |
— | пишет INFO в журнал libfptr10 |
4.2. Cash
| Метод | Возврат | Назначение |
|---|---|---|
Cash(core) |
— | Конструктор; авто-open_connect если закрыто |
get_cash_info() |
dict |
13 полей: модель, ФН, версия прошивки, состояние смены, ФФД |
get_cash_info_v2() |
dict |
31 поле: всё из v1 + флаги принтера/бумаги/ФН/блокировок |
get_uptime_cash() |
int |
секунды непрерывной работы ККТ |
cash_registration() |
bool |
Регистрация ККТ (МГМ). Хардкод реквизитов brandshop, см. §5.2 |
shift_stage mapping: 0→CLOSED, 1→OPENED, 2→EXPIRED.
4.3. Fn
| Метод | Возврат | Назначение |
|---|---|---|
Fn(core) |
— | Конструктор |
get_status_fn() |
str |
FNS_INITIAL/CONFIGURED/FISCAL_MODE/POSTFISCAL_MODE/ACCESS_ARCHIVE |
get_info_last_receipt() |
dict |
номер, тип, сумма, ФПД, datetime последнего чека |
get_info_last_doc() |
dict |
то же для последнего фискального документа |
get_version_ffd() |
dict |
device/fn/min/max версии ФФД (есть баг ключа, см. §5.8) |
get_info_doc(number_doc) |
dict |
тип, номер, ФПД, datetime, has_ofd_ticket для номера ФД |
get_ticket_ofd(number_doc) |
dict |
номер, datetime, OFD ФПД (bytearray) квитанции от ОФД |
get_ofd_document_by_number(n) |
list[dict] |
TLV-структуры ФД (tag_number, tag_name, tag_type, tag_value) |
get_fn_error() |
dict |
network / ofd / fn ошибки и их тексты |
get_exchange_status() |
dict |
статус ОФД-обмена, кол-во неотправленных |
get_registration_number() |
str |
РНМ ККТ (тег 1037) |
4.4. Receipt
| Метод | Возврат | Назначение |
|---|---|---|
Receipt(core) |
— | Конструктор |
open_receipt(receipt_data) |
bool |
Открытие чека (см. ниже) |
cancel_receipt() |
bool |
fptr.cancelReceipt() — отмена незакрытого чека |
receipt_registration(product) |
bool |
Регистрация одной позиции |
receipt_payment(money_position) |
bool |
Оплата (paymentType через Receipt.payment_type) |
receipt_total(money_position) |
bool |
Регистрация итога (необязательно) |
receipt_close() |
bool |
fptr.closeReceipt() → запись в ФН |
open_receipt(receipt_data) ожидает:
| Ключ | Тип | Значения |
|---|---|---|
docType |
str | см. Receipt.receipt_type: SALE/RETURN, SALE_CORRECTION/RETURN_CORRECTION, BUY/BUY_RETURN, BUY_CORRECTION/BUY_RETURN_CORRECTION |
printReceipt |
bool | False → electronic чек (LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY=True) |
email |
str | тег 1008 — email клиента |
taxMode |
str | OSN/USN_INCOME/USN_INCOME_OUTCOME/ESN/PATENT |
Жёстко устанавливается тег 1125=1 («признак расчёта в интернете») — это
hard-coded для интернет-магазина brandshop.
receipt_registration(product) ожидает:
| Ключ | Тип | Назначение |
|---|---|---|
name |
str | LIBFPTR_PARAM_COMMODITY_NAME |
price |
int/float | LIBFPTR_PARAM_PRICE |
quantity |
str | LIBFPTR_PARAM_QUANTITY |
vat |
int | см. Receipt.vat_type: 0/5/7/10/20/22 + расчётные 5/105, 7/107, 10/110, 20/120, 22/122 + "NO" (без НДС) |
discSum |
int | LIBFPTR_PARAM_INFO_DISCOUNT_SUM (если > 0) |
nomenclatureCode |
str / None | КМ Data Matrix; запускает beginMarkingCodeValidation + polling + acceptMarkingCode |
codeCheck |
str / None | tag 1265 от ПИоТ; собирает TLV-тег 1260 (отраслевой реквизит предмета расчёта) |
vatTag |
int | поле в payload, но не используется в коде |
Цепочка libfptr10 для маркированного товара (упрощённо):
setParam(MARKING_CODE, km)
setParam(MARKING_CODE_STATUS, 2)
setParam(MARKING_PROCESSING_MODE, 0)
setParam(MEASUREMENT_UNIT, IU_PIECE)
beginMarkingCodeValidation()
while not getParamBool(MARKING_CODE_VALIDATION_READY):
getMarkingCodeValidationStatus()
validation_result = getParamInt(MARKING_CODE_ONLINE_VALIDATION_RESULT)
acceptMarkingCode()
# Если есть codeCheck (tag 1265 от ПИоТ) — формируется TLV-тег 1260.
# С 1.10.0 значения 1262/1263/1264 параметризованы через product['industry']:
setParam(1262, industry['mode']) # режим обработки (например, '030')
setParam(1263, industry['date']) # дата НПА (например, '21.11.2023')
setParam(1264, industry['num']) # номер НПА (например, '1944')
setParam(1265, codeCheck)
utilFormTlv() → tag 1260 TLV
setParam(1260, tlv)
setParam(1212, 33) # признак предмета расчёта: маркированный товар + услуга
4.5. Shift
| Метод | Возврат | Назначение |
|---|---|---|
Shift(core) |
— | Конструктор |
open_shift() |
bool |
_set_casher() → fptr.openShift() → проверка закрытия |
close_shift() |
bool |
_set_casher() → report(LIBFPTR_RT_CLOSE_SHIFT) → Z-отчёт |
4.6. Setting
| Метод | Возврат | Назначение |
|---|---|---|
Setting(core) |
— | Конструктор (composition, не наследуется от Core) |
init_setting() |
bool |
fptr.initSettings() |
get_device_setting_by_id(id, type) |
bool/int/str |
Чтение настройки ККТ (type ∈ int/string) |
set_device_setting_by_id(id, value) |
bool |
Запись настройки |
commit_setting() |
bool |
fptr.commitSettings() |
5. Известные ограничения и hidden behavior
5.1. Core.is_opened() не отражает реальное состояние
Из docstring: «Результат метода не отражает текущее состояние подключения —
если с ККТ была разорвана связь, то метод всё также будет возвращать true».
Это особенность libfptr10.isOpened() — она проверяет только локальный флаг
сессии. Реально упало соединение или нет — узнаётся только на первом
вызове, который вернёт LIBFPTR_ERROR_NO_CONNECTION.
5.2. Хардкод бизнес-данных — устранён в 1.9.0 и 1.10.0
Раньше в коде были захардкожены бизнес-значения:
Cash.cash_registration()— ИНН/адрес/ОФД brandshop. Параметризовано в 1.9.0 (registration_data: dict).Receipt.receipt_registration()для маркированных товаров — теги 1262/1263/1264 ='030' / '21.11.2023' / '1944'. Параметризовано в 1.10.0 (полеindustryв payload позиции).Core.casher_infoclass-level"СИС. АДМИНИСТРАТОР". Параметризовано в 1.10.0:Core(casher_name, casher_inn)+Core.set_casher(name, inn). Дефолт пустой →_set_casher()пропускаетoperatorLogin.
5.3. Setting наследуется от Core — исправлено в 1.10.0
Setting наследуется от CoreРаньше class Setting(Core) + одновременно self.core = core — двойственная связь, бьётся с SingletonMeta. С 1.10.0 — чистая композиция: class Setting: с делегированием логирования через self.core._error_log(). См. §6.6.
5.4. cash_registration пишет в FN
Метод реально вызывает fptr.fnOperation() с LIBFPTR_FNOP_REGISTRATION —
это необратимая операция перерегистрации ФН. Использовать только для
первоначальной активации новой ККТ или замены ФН, никогда не дёргать в
тестах. Логирования предупреждения нет.
5.5. casher_info class-level
Реквизиты кассира (name, inn) — это class-level переменная Core,
а не instance. Это значит, что изменение из одного места приложения
повлияет на все будущие вызовы _set_casher(). Для multi-tenant сценариев
(несколько касс в одном процессе) — баг.
5.6. Молчаливая обработка ошибок
Все методы возвращают False при ошибке libfptr10 и пишут описание через
logWrite. Никаких исключений. Это удобно для batch-обработки чеков, но
затрудняет отладку — приходится парсить логи libfptr10 (/var/log/...) и
коррелировать с приложением. См. §6.8.
5.7. _check_document_close infinite loop
Цикл while self.fptr.checkDocumentClosed() < 0: ... без timeout. Если ККТ
отвалилась (LIBFPTR_ERROR_NO_CONNECTION) — поток зависнет навсегда.
Аналогично для while self.fptr.continuePrint() < 0. См. §6.9.
5.8. get_version_ffd баг ключа
В строке 334 ord_fn.py:
version_ffd.update({"document_number": self.ffd_version.get(min_ffd_version)})
Ключ должен быть "min_ffd_version", а не "document_number". Опечатка
скрывает значение min_ffd_version в возвращаемом dict.
6. Задачи на доработку (TODO)
Сделанные задачи:
- ✅ §6.1 paymentType маппинг — в
1.8.26.1(Receipt.payment_typedict) - ✅ §6.2 VAT mapping — в
1.8.27.0(Receipt.vat_typedict, 0/5/7/10/20/22 + расчётные + NO) - ✅ §6.3 docType коррекции и расход — в
1.8.27.0(Receipt.receipt_typedict с 8 типами) - ✅ §6.4 Cash.cash_registration параметризация — в
1.9.0. Принимаетregistration_data: dict(inn/address/org_name/email/place/reg_number/ofd_inn/ofd_name + tax_system/agent_type/ffd_version/tax_site/flags). Breaking change: дефолтов brandshop больше нет, ValueError при отсутствии обязательных полей. - ✅ §6.5 Параметризация отраслевого реквизита (тег 1260) — в
1.10.0.Receipt.receipt_registrationпринимает полеindustry({mode, date, num}для тегов 1262/1263/1264). Breaking change: при наличииcodeCheckблокindustryобязателен, иначе ValueError. - ✅ §6.6
Setting(Core)→Setting— в1.10.0. Убрано наследование от Core, теперь composition (self.core._error_log()), убран__del__(Setting не владеет соединением). - ✅ §6.7
casher_infoinstance-level — в1.10.0.Core(path, casher_name='', casher_inn='')+ методCore.set_casher(name, inn=''). Класс-атрибут с brandshop-хардкодом удалён. Backward-compat: при пустомcasher_nameметод_set_casherпропускаетoperatorLogin(фискальные операции работают без logon оператора). - ✅ §6.8 Опциональные исключения — в
1.11.0.Core(..., raise_on_error=True)поднимаетOrdError(code, description, method)вместо тихогоreturn False. HelperCore._handle_error(method)объединяет log + raise/return. Дефолтraise_on_error=False— backward compatible. - ✅ §6.9 Timeout в
_check_document_close— в1.11.0. Бесконечныеwhile ... < 0: continueзаменены на deadline-loop с параметромtimeout: float = 30.0. При превышении —OrdTimeoutError(всегда, независимо отraise_on_error). - ✅ §6.10 Тесты — в
1.11.0. Структураtests/unit/*.pyс 17 unit-тестами (Core/Receipt/Cash, ~70% покрытия публичного API).libfptr10.IFptrподменяется MagicMock'ом в conftest.py — тесты идут без реальной кассы. Dev-зависимости вrequirements-dev.txt. Integration-тесты против реальной АТОЛ 30Ф — отдельным этапом (см. §6.11+).
6.8. Опциональные исключения вместо False — done в 1.11.0
FalseПриоритет: P2.
Добавить параметр Core(raise_on_error=True). При активации все методы
поднимают OrdError(error_code, error_description) вместо return False.
Сохранить дефолт False для обратной совместимости. Это даст:
- Stacktrace в логах приложения
- Возможность
except OrdErrorдля конкретных кодов libfptr10 - Прекращение «тихих фейлов» когда
Falseигнорируется вызывающим кодом
6.9. Timeout в _check_document_close / continuePrint — done в 1.11.0
_check_document_close / continuePrintПриоритет: P1.
Бесконечные while ... < 0: continue без выхода. Заменить на:
import time
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
if self.fptr.checkDocumentClosed() >= 0:
break
self._error_log()
time.sleep(0.5)
else:
raise OrdTimeoutError(...)
6.10. Тесты — done в 1.11.0
Приоритет: P0.
ORD/test/ORD_test.py сейчас 207 байт (пустой шаблон). Добавить:
- Unit-тесты с моком
IFptr— каждый метод проверяет правильность setParam-цепочки (без реальной кассы). Минимум 30 тестов. - Integration-тесты против реальной АТОЛ 30Ф (cashdev,
172.16.0.7) — реальные пробития чеков, чтение ФН. Маркер@pytest.mark.real_kkt, skip-by-default. - Покрытие минимум 70%.
Использовать pytest + pytest-mock. Сейчас вообще нет покрытия.
6.11. pyproject.toml вместо setup.py
Приоритет: P2.
Перейти на PEP 517 build (pyproject.toml + setuptools.build_meta).
Убрать setup.py+setup.cfg, перенести метаданные:
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "ORD"
version = "1.11.0"
description = "Python client for ATOL libfptr10 fiscal printer driver"
authors = [{name = "Vladimir Smirnov", email = "volodya@brandshop.ru"}]
readme = "README.md"
license = {text = "Proprietary"}
requires-python = ">=3.8"
dependencies = [] # libfptr10 ставится отдельно
[project.urls]
Repository = "https://brandshop.gitlab.yandexcloud.net/online-receipt/online-receipt-driver"
Mirror = "https://github.com/brandshopru/online-receipt-driver"
6.12. Type hints
Приоритет: P3.
Сейчас код без аннотаций. Добавить:
- Возвращаемые типы у всех публичных методов
TypedDictилиdataclassдля словарей-результатов (CashInfo,FnDocInfo,OfdExchangeStatus, ...)- Конкретные перечисления для
docType,paymentType,taxModeчерезenum.StrEnum(Python 3.11) илиLiteral[...]
6.13. Обновить минимальную версию Python: 3.6 → 3.8+
Приоритет: P2.
Python 3.6 в EOL с 23 декабря 2021. На cashdev сейчас стоит 3.6.8.
Согласовать миграцию: 3.8 или 3.10 как минимум. Это снимет ограничения
mock-3.0.5 / pytest-6.2.5 в проекте-потребителе online-api.
6.14. CI/CD в GitLab
Приоритет: P1.
Добавить .gitlab-ci.yml:
- lint —
ruff check ORD/+mypy ORD/ - test —
pytest tests/(безreal_kktмаркера) - build —
python -m build→ артефактыdist/*.whl + *.tar.gz - publish — на tag запускать
twine upload dist/* -u __token__ -p $PYPI_TOKEN - mirror — push на GitHub после успешного релиза в master
6.15. CHANGELOG.md
Приоритет: P2.
Сейчас отсутствует. Восстановить ретроспективно (по тэгам 1.6.x — 1.8.x) и продолжать в формате Keep a Changelog.
6.16. Контекст-менеджеры
Приоритет: P3.
Поддержать with Core() as core: (__enter__/__exit__). Гарантирует
закрытие коннекта даже при exception между open и close. Сейчас полагается
на __del__, который не вызывается при kill -9.
6.17. Thread-safety guarantee
Приоритет: P2.
SingletonMeta потокобезопасен на создание. Но операции над одним
fptr — нет: setParam → queryData → getParam — это «stateful цепочка», и
если две задачи параллельно зовут разные методы, состояние перемешается.
Опции:
- Документировать «один процесс, один поток» как требование
- Добавить
Core._operation_lock = threading.Lock()и оборачивать им каждый публичный метод - Сделать
Coreper-thread (threading.local)
6.18. AutoTimeSyncTime: 15 секунд избыточно
Приоритет: P3.
LIBFPTR_SETTING_AUTO_TIME_SYNC_TIME = 15 означает синк раз в 15 секунд —
это нагружает ФН без необходимости. ФНС требует синхронизацию раз в
сутки. Поставить 3600 (раз в час) или 86400 (раз в сутки).
6.19. Логирование в стандартный logging
Приоритет: P2.
Сейчас _error_log/info_log пишут через fptr.logWrite — внутренний
журнал libfptr10. Добавить параллельно вывод в стандартный
logging.getLogger("ORD") чтобы интегрироваться с системным логированием
приложения.
6.20. Документация кода
Приоритет: P3.
Docstrings есть, но в смешанном стиле (русский комментарий с английским
именем параметров, иногда отсутствие :param:/:return:). Привести к
единому формату (Google или Numpy style).
6.21. Исправить опечатку cancel_reciept.py
Приоритет: P3.
Файл в корне репо называется cancel_reciept.py (reciept → receipt).
Переименовать.
6.22. Удалить артефакты из .gitignore
Приоритет: P3.
ORD.egg-info/, build/, dist/, __pycache__/, venv/ сейчас
неотслеживаемые, но не добавлены в .gitignore. Добавить.
7. Версионирование и релизы
Используется semver: MAJOR.MINOR.PATCH[.HOTFIX].
MAJOR— несовместимое API изменениеMINOR— новый функционал, обратно совместимыйPATCH— багфиксы
Процесс релиза:
- Внести изменения в feature-ветке
- Merge в
masterпосле ревью - Bump версии в
setup.py(потом — вpyproject.toml) - Поставить tag:
git tag X.Y.Z && git push origin --tags - Сборка:
python -m build - Публикация:
twine upload dist/* - После §6.14 — CI делает всё начиная с tag автоматически
Текущая ситуация (на 2026-06-25):
| Источник | Версия master |
|---|---|
Локально (IdeaProjects/online-receipt-driver) |
1.8.26.0 |
| GitLab origin (master) | 1.8.26.0 |
| GitHub зеркало (master) | 1.8.26.0 |
| PyPI ORD | 1.8.26.0 |
Production: online-api/venv на cashdev |
1.8.26.0 |
Все источники синхронизированы.
История версий:
1.8.x— текущая линия (НДС 22%, AutoTimeSync, разрешительный режим 030)1.6.x(веткаlegacy-1.6.xв GitLab) — заброшенная ветка с устаревшим API, оставлена для исторической справкиdenis— старая ветка экспериментов, не мерджена
8. Тестирование
До настоящего момента тесты для ORD делались только в проекте-потребителе
online-api (см. online-api/tests/unit/test_piot_client_mock.py,
tests/e2e/test_fn_real.py). Прогон против реальной АТОЛ 30Ф на cashdev:
ssh volodya@cashdev 'cd /var/www/api/current && \
./venv/bin/pytest tests/e2e/ -m e2e -v'
После §6.10 тесты переедут в этот репо.
9. Контакты
- Автор: Vladimir Smirnov (volodya@brandshop.ru)
- Баги/MR: GitLab
online-receipt/online-receipt-driver
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ord-1.11.0.tar.gz.
File metadata
- Download URL: ord-1.11.0.tar.gz
- Upload date:
- Size: 41.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5cce1a8d4a6d48cd82a2f2e3c7a32356739e87d8f620103bf1d8cc59e9ef924
|
|
| MD5 |
0bf0eeb1b6a6c93afd298d0d03f14d67
|
|
| BLAKE2b-256 |
12748045da29c16f29cbf2d0f2f6625d4fb4c08c060b362a063389109d0d68a7
|
File details
Details for the file ord-1.11.0-py3-none-any.whl.
File metadata
- Download URL: ord-1.11.0-py3-none-any.whl
- Upload date:
- Size: 37.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e5946eaf58139fb2c18659bc31372a2f5af0a7f63c422552986c105f79f7d99
|
|
| MD5 |
a5c81b242acba49c5cb7a386d2ec303d
|
|
| BLAKE2b-256 |
f33d3c1f46b7c8309f9645163c0dfdcb78db53721b05c7046be38eb50b7f4467
|