ORD 1.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ORD-1.7.0/ORD/__init__.py +6 -0
- ORD-1.7.0/ORD/ord_cash.py +168 -0
- ORD-1.7.0/ORD/ord_core.py +214 -0
- ORD-1.7.0/ORD/ord_fn.py +326 -0
- ORD-1.7.0/ORD/ord_receipt.py +381 -0
- ORD-1.7.0/ORD/ord_setting.py +86 -0
- ORD-1.7.0/ORD/ord_shift.py +69 -0
- ORD-1.7.0/ORD/test/ORD_test.py +12 -0
- ORD-1.7.0/ORD/test/__init__.py +0 -0
- ORD-1.7.0/ORD.egg-info/PKG-INFO +11 -0
- ORD-1.7.0/ORD.egg-info/SOURCES.txt +16 -0
- ORD-1.7.0/ORD.egg-info/dependency_links.txt +1 -0
- ORD-1.7.0/ORD.egg-info/top_level.txt +1 -0
- ORD-1.7.0/PKG-INFO +11 -0
- ORD-1.7.0/README.md +2 -0
- ORD-1.7.0/setup.cfg +4 -0
- ORD-1.7.0/setup.py +19 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
from libfptr10 import IFptr
|
|
2
|
+
from .ord_core import Core
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cash:
|
|
6
|
+
shift_stage = {
|
|
7
|
+
0: "CLOSED",
|
|
8
|
+
1: "OPENED",
|
|
9
|
+
2: "EXPIRED"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
fn_state = {
|
|
13
|
+
0: "FNS_INITIAL",
|
|
14
|
+
1: "FNS_CONFIGURED",
|
|
15
|
+
3: "FNS_FISCAL_MODE",
|
|
16
|
+
7: "FNS_POSTFISCAL_MODE",
|
|
17
|
+
15: "FNS_ACCESS_ARCHIVE"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def __init__(self, core):
|
|
21
|
+
self.core = core
|
|
22
|
+
if self.core.is_opened() == 0:
|
|
23
|
+
if not self.core.open_connect():
|
|
24
|
+
return None
|
|
25
|
+
self.fptr = core.fptr
|
|
26
|
+
|
|
27
|
+
def get_cash_info(self):
|
|
28
|
+
"""
|
|
29
|
+
Получение информации о ККТ
|
|
30
|
+
|
|
31
|
+
:returns: cash_info
|
|
32
|
+
:rtype: dict
|
|
33
|
+
"""
|
|
34
|
+
cash_info = {
|
|
35
|
+
"fnNo": "",
|
|
36
|
+
"fnVersion": "",
|
|
37
|
+
"fnCountDocInShift": "",
|
|
38
|
+
"serialNo": "",
|
|
39
|
+
"modelName": "",
|
|
40
|
+
"modelId": "",
|
|
41
|
+
"firmwareVersion": "",
|
|
42
|
+
"vendorName": "АТОЛ",
|
|
43
|
+
"shiftNumber": "",
|
|
44
|
+
"shiftState": "",
|
|
45
|
+
"shiftDateTime": "",
|
|
46
|
+
"taxModes": "",
|
|
47
|
+
"ffdVersion": ""
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_STATUS)
|
|
51
|
+
self.fptr.queryData()
|
|
52
|
+
|
|
53
|
+
serial_no = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_SERIAL_NUMBER)
|
|
54
|
+
model_name = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_MODEL_NAME)
|
|
55
|
+
model_id = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_MODEL)
|
|
56
|
+
|
|
57
|
+
cash_info.update({"serialNo": serial_no})
|
|
58
|
+
cash_info.update({"modelName": model_name})
|
|
59
|
+
cash_info.update({"modelId": model_id})
|
|
60
|
+
|
|
61
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_UNIT_VERSION)
|
|
62
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_UNIT_TYPE, IFptr.LIBFPTR_UT_FIRMWARE)
|
|
63
|
+
self.fptr.queryData()
|
|
64
|
+
|
|
65
|
+
firmware_version = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_UNIT_VERSION)
|
|
66
|
+
cash_info.update({"firmwareVersion": firmware_version})
|
|
67
|
+
|
|
68
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_SHIFT_STATE)
|
|
69
|
+
self.fptr.queryData()
|
|
70
|
+
|
|
71
|
+
shift_state = self.shift_stage.get(self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_SHIFT_STATE))
|
|
72
|
+
shift_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_SHIFT_NUMBER)
|
|
73
|
+
shift_date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
|
|
74
|
+
|
|
75
|
+
cash_info.update({"shiftState": shift_state})
|
|
76
|
+
cash_info.update({"shiftNumber": shift_number})
|
|
77
|
+
cash_info.update({"shiftDateTime": shift_date_time.strftime("%Y-%m-%d %H:%M:%S")})
|
|
78
|
+
|
|
79
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_FN_INFO)
|
|
80
|
+
self.fptr.fnQueryData()
|
|
81
|
+
|
|
82
|
+
fn_serial = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_SERIAL_NUMBER)
|
|
83
|
+
fn_version = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_FN_VERSION)
|
|
84
|
+
|
|
85
|
+
cash_info.update({"fnNo": fn_serial})
|
|
86
|
+
cash_info.update({"fnVersion": fn_version.strip()})
|
|
87
|
+
|
|
88
|
+
return cash_info
|
|
89
|
+
|
|
90
|
+
def get_uptime_cash(self):
|
|
91
|
+
"""
|
|
92
|
+
Запрос времени работы ККТ
|
|
93
|
+
:returns: uptime
|
|
94
|
+
:rtype: int
|
|
95
|
+
"""
|
|
96
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_DEVICE_UPTIME)
|
|
97
|
+
self.fptr.queryData()
|
|
98
|
+
|
|
99
|
+
uptime = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DEVICE_UPTIME)
|
|
100
|
+
|
|
101
|
+
return uptime
|
|
102
|
+
|
|
103
|
+
def cash_registration(self):
|
|
104
|
+
"""
|
|
105
|
+
Регистрация кассы
|
|
106
|
+
|
|
107
|
+
Расчет регистрационного номера для МГМ
|
|
108
|
+
ВХОД:
|
|
109
|
+
1) порядковый номер зарегистрированного ККТ (дополняется лидирующими нулями до длины в 10 символов, используется ascii-коды в кодировке CP866);
|
|
110
|
+
2) ИНН пользователя ККТ (дополняется лидирующими нулями до длины в 12 символов, используется ascii-коды в кодировке CP866);
|
|
111
|
+
3) заводской номер ККТ (дополняется лидирующими нулями до длины в 20 символов, используется ascii-коды в кодировке CP866);
|
|
112
|
+
|
|
113
|
+
ВЫХОД:
|
|
114
|
+
1) вычисляется значение по алгоритму расчета контрольной суммы CRC16-CCITT
|
|
115
|
+
2) значение переводится в десятичную систему счислений
|
|
116
|
+
3) дополняется лидирующими нулями до длины строки в 6 символов
|
|
117
|
+
|
|
118
|
+
Пример:
|
|
119
|
+
порядковый номер зарегистрированного ККТ 0000000001
|
|
120
|
+
ИНН пользователя ККТ 770123456789
|
|
121
|
+
заводской номер ККТ 00000000000123456789
|
|
122
|
+
|
|
123
|
+
Вычисления:
|
|
124
|
+
1) CRC16-CCITT(000000000177012345678900000000000123456789) = 492D (hex)
|
|
125
|
+
2) 492D (hex) = 18733 (dec)
|
|
126
|
+
3) 018733
|
|
127
|
+
|
|
128
|
+
РНМ ККТ равен 0000000001018733
|
|
129
|
+
|
|
130
|
+
:return:
|
|
131
|
+
"""
|
|
132
|
+
status = False
|
|
133
|
+
|
|
134
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_OPERATION_TYPE, IFptr.LIBFPTR_FNOP_REGISTRATION)
|
|
135
|
+
|
|
136
|
+
self.fptr.setParam(1060, "nalog.ru")
|
|
137
|
+
|
|
138
|
+
self.fptr.setParam(1009, "127051, г. Москва, Петровский б-р, 21")
|
|
139
|
+
self.fptr.setParam(1018, "9705112246")
|
|
140
|
+
self.fptr.setParam(1048, "ООО \"БШ СТОР\"")
|
|
141
|
+
self.fptr.setParam(1062, IFptr.LIBFPTR_TT_OSN)
|
|
142
|
+
self.fptr.setParam(1117, "volodya@brandshop.ru")
|
|
143
|
+
self.fptr.setParam(1057, IFptr.LIBFPTR_AT_NONE)
|
|
144
|
+
|
|
145
|
+
self.fptr.setParam(1187, "https://brandshop.ru")
|
|
146
|
+
self.fptr.setParam(1037, "0000000001030584")
|
|
147
|
+
self.fptr.setParam(1209, IFptr.LIBFPTR_FFD_UNKNOWN)
|
|
148
|
+
self.fptr.setParam(1001, False)
|
|
149
|
+
self.fptr.setParam(1002, False)
|
|
150
|
+
self.fptr.setParam(1056, False)
|
|
151
|
+
self.fptr.setParam(1108, True)
|
|
152
|
+
self.fptr.setParam(1109, False)
|
|
153
|
+
self.fptr.setParam(1110, False)
|
|
154
|
+
self.fptr.setParam(1126, False)
|
|
155
|
+
self.fptr.setParam(1193, False)
|
|
156
|
+
|
|
157
|
+
self.fptr.setParam(1221, False)
|
|
158
|
+
|
|
159
|
+
self.fptr.setParam(1017, "9715260691")
|
|
160
|
+
self.fptr.setParam(1046, "ООО ПС СТ")
|
|
161
|
+
|
|
162
|
+
if self.fptr.fnOperation() < 0:
|
|
163
|
+
self.core._error_log()
|
|
164
|
+
else:
|
|
165
|
+
self.core._check_document_close()
|
|
166
|
+
status = True
|
|
167
|
+
|
|
168
|
+
return status
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
from libfptr10 import IFptr
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SingletonMeta(type):
|
|
5
|
+
"""
|
|
6
|
+
В Python класс Одиночка можно реализовать по-разному. Возможные способы
|
|
7
|
+
включают себя базовый класс, декоратор, метакласс. Мы воспользуемся
|
|
8
|
+
метаклассом, поскольку он лучше всего подходит для этой цели.
|
|
9
|
+
"""
|
|
10
|
+
_instances = {}
|
|
11
|
+
|
|
12
|
+
def __call__(cls, *args, **kwargs):
|
|
13
|
+
if cls not in cls._instances:
|
|
14
|
+
cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
|
|
15
|
+
return cls._instances[cls]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Core(metaclass=SingletonMeta):
|
|
19
|
+
debug = False
|
|
20
|
+
casher_info = {
|
|
21
|
+
"name": "СИС. АДМИНИСТРАТОР",
|
|
22
|
+
"inn": ""
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
"""
|
|
27
|
+
Инициализация драйвера:
|
|
28
|
+
Настройка драйвера
|
|
29
|
+
"""
|
|
30
|
+
self.fptr = IFptr("")
|
|
31
|
+
|
|
32
|
+
self.version = self.fptr.version()
|
|
33
|
+
|
|
34
|
+
settings = {
|
|
35
|
+
IFptr.LIBFPTR_SETTING_MODEL: IFptr.LIBFPTR_MODEL_ATOL_AUTO,
|
|
36
|
+
IFptr.LIBFPTR_SETTING_PORT: IFptr.LIBFPTR_PORT_USB,
|
|
37
|
+
IFptr.LIBFPTR_SETTING_USB_DEVICE_PATH: "auto",
|
|
38
|
+
IFptr.LIBFPTR_SETTING_OFD_CHANNEL: IFptr.LIBFPTR_OFD_CHANNEL_AUTO
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
self.fptr.setSettings(settings)
|
|
42
|
+
|
|
43
|
+
def _set_casher(self):
|
|
44
|
+
"""
|
|
45
|
+
Регистрация кассира
|
|
46
|
+
|
|
47
|
+
Рекомендуется вызывать данный метод перед каждой
|
|
48
|
+
фискальной операцией (открытие чека, печать отчета, ...).
|
|
49
|
+
:return: status
|
|
50
|
+
:rtype: bool
|
|
51
|
+
"""
|
|
52
|
+
status = False
|
|
53
|
+
|
|
54
|
+
self.fptr.setParam(1021, self.casher_info.get("name"))
|
|
55
|
+
self.fptr.setParam(1203, self.casher_info.get("inn"))
|
|
56
|
+
|
|
57
|
+
if self.fptr.operatorLogin() < 0:
|
|
58
|
+
self._error_log()
|
|
59
|
+
else:
|
|
60
|
+
status = True
|
|
61
|
+
|
|
62
|
+
return status
|
|
63
|
+
|
|
64
|
+
def open_connect(self):
|
|
65
|
+
"""
|
|
66
|
+
Открытие соединение с кассой
|
|
67
|
+
:returns: status
|
|
68
|
+
:rtype: bool
|
|
69
|
+
"""
|
|
70
|
+
status = False
|
|
71
|
+
if self.fptr.open() < 0:
|
|
72
|
+
self._error_log()
|
|
73
|
+
else:
|
|
74
|
+
status = True
|
|
75
|
+
|
|
76
|
+
return status
|
|
77
|
+
|
|
78
|
+
def close_connect(self):
|
|
79
|
+
"""
|
|
80
|
+
Закрытие соединения с кассой
|
|
81
|
+
:returns: status
|
|
82
|
+
:rtype: bool
|
|
83
|
+
"""
|
|
84
|
+
status = False
|
|
85
|
+
if self.fptr.close() < 0:
|
|
86
|
+
self._error_log()
|
|
87
|
+
else:
|
|
88
|
+
status = True
|
|
89
|
+
|
|
90
|
+
return status
|
|
91
|
+
|
|
92
|
+
def is_opened(self):
|
|
93
|
+
"""
|
|
94
|
+
Получение состояния соединения с кассой
|
|
95
|
+
Результат метода не отражает текущее состояние подключения - если с ККТ
|
|
96
|
+
была разорвана связь, то метод все также будет возвращать true, но методы,
|
|
97
|
+
выполняющие какие-либо операции над ККТ,
|
|
98
|
+
будут возвращать ошибку LIBFPTR_ERROR_NO_CONNECTION
|
|
99
|
+
:returns: self.fptr.isOpened()
|
|
100
|
+
:rtype: int
|
|
101
|
+
"""
|
|
102
|
+
return self.fptr.isOpened()
|
|
103
|
+
|
|
104
|
+
def get_version_driver(self):
|
|
105
|
+
"""
|
|
106
|
+
Получение версии драйвера
|
|
107
|
+
:returns: self.version
|
|
108
|
+
:rtype: str
|
|
109
|
+
"""
|
|
110
|
+
return self.version
|
|
111
|
+
|
|
112
|
+
def get_current_datetime(self):
|
|
113
|
+
"""
|
|
114
|
+
Текущие дата и время ККТ
|
|
115
|
+
:returns: date_time
|
|
116
|
+
:rtype: str
|
|
117
|
+
"""
|
|
118
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_DATE_TIME)
|
|
119
|
+
self.fptr.queryData()
|
|
120
|
+
|
|
121
|
+
date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME).strftime("%Y-%m-%d %H:%M:%S")
|
|
122
|
+
|
|
123
|
+
return date_time
|
|
124
|
+
|
|
125
|
+
def get_setting(self):
|
|
126
|
+
"""
|
|
127
|
+
Получение настроек кассы
|
|
128
|
+
:returns: setting_cash
|
|
129
|
+
:rtype: dict
|
|
130
|
+
"""
|
|
131
|
+
setting_cash = self.fptr.getSettings()
|
|
132
|
+
|
|
133
|
+
return setting_cash
|
|
134
|
+
|
|
135
|
+
def _check_document_close(self):
|
|
136
|
+
"""
|
|
137
|
+
Проверка закрытия документа
|
|
138
|
+
|
|
139
|
+
В ряде ситуаций (окончание бумаги, потеря связи с
|
|
140
|
+
ККТ в момент регистрации документа) состояние документа остается неизвестным.
|
|
141
|
+
Он может закрыться в ФН (что является необратимой операцией), но не напечататься на чековой ленте.
|
|
142
|
+
Данный метод сверяет счетчики ККТ с сохраненными до закрытия документа копиями и вычисляет,
|
|
143
|
+
закрылся ли он, а также проверяет состояние печати документа.
|
|
144
|
+
:returns: status
|
|
145
|
+
:rtype: bool
|
|
146
|
+
"""
|
|
147
|
+
status = True
|
|
148
|
+
|
|
149
|
+
while self.fptr.checkDocumentClosed() < 0:
|
|
150
|
+
# Не удалось проверить состояние документа.
|
|
151
|
+
# Вывести пользователю текст ошибки, попросить
|
|
152
|
+
# устранить неполадку и повторить запрос
|
|
153
|
+
self._error_log()
|
|
154
|
+
status = False
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
# if not self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_DOCUMENT_CLOSED):
|
|
158
|
+
# # Документ не закрылся.
|
|
159
|
+
# # Требуется его отменить (если это чек) и сформировать заново
|
|
160
|
+
# self.fptr.cancelReceipt()
|
|
161
|
+
# return status
|
|
162
|
+
|
|
163
|
+
if not self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_DOCUMENT_PRINTED):
|
|
164
|
+
# Можно сразу вызвать метод допечатывания документа,
|
|
165
|
+
# он завершится с ошибкой, если это невозможно
|
|
166
|
+
while self.fptr.continuePrint() < 0:
|
|
167
|
+
# Если не удалось допечатать документ,
|
|
168
|
+
# показать пользователю ошибку и попробовать еще раз.
|
|
169
|
+
self._error_log()
|
|
170
|
+
status = False
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
return status
|
|
174
|
+
|
|
175
|
+
def reboot(self):
|
|
176
|
+
"""
|
|
177
|
+
Перезагрузка ККТ
|
|
178
|
+
:return:
|
|
179
|
+
"""
|
|
180
|
+
status = False
|
|
181
|
+
|
|
182
|
+
if self.fptr.deviceReboot() < 0:
|
|
183
|
+
self._error_log()
|
|
184
|
+
else:
|
|
185
|
+
status = True
|
|
186
|
+
|
|
187
|
+
return status
|
|
188
|
+
|
|
189
|
+
def _error_log(self):
|
|
190
|
+
"""
|
|
191
|
+
Логирование ошибок
|
|
192
|
+
Каждый метод драйвера возвращает индикатор результата выполнения.
|
|
193
|
+
Этот индикатор может принимать значения 0 и -1.
|
|
194
|
+
В случае, если индикатор не равен 0, выполнение метода завершилось с ошибкой и
|
|
195
|
+
есть возможность получить подробности о ней.
|
|
196
|
+
Для этого у драйвера можно запросить код последней ошибки (метод errorCode()) и
|
|
197
|
+
её текстовое описание (метод errorDescription()).
|
|
198
|
+
Драйвер хранит информацию об ошибке до следующего вызова метода - после него информация об ошибке обновляется.
|
|
199
|
+
Для явного сброса информации о последней ошибки нужно использовать метод resetError().
|
|
200
|
+
"""
|
|
201
|
+
error_msg = "{} [{}]".format(self.fptr.errorCode(), self.fptr.errorDescription())
|
|
202
|
+
self.fptr.logWrite("FiscalPrinter", IFptr.LIBFPTR_LOG_ERROR, error_msg)
|
|
203
|
+
|
|
204
|
+
def info_log(self, msg):
|
|
205
|
+
"""
|
|
206
|
+
Логирование нотификаций
|
|
207
|
+
:param msg:
|
|
208
|
+
:return:
|
|
209
|
+
"""
|
|
210
|
+
self.fptr.logWrite("FiscalPrinter", IFptr.LIBFPTR_LOG_INFO, msg)
|
|
211
|
+
|
|
212
|
+
def __del__(self):
|
|
213
|
+
if self.is_opened() == 1:
|
|
214
|
+
self.close_connect()
|
ORD-1.7.0/ORD/ord_fn.py
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
from libfptr10 import IFptr
|
|
2
|
+
from .ord_core import Core
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Fn:
|
|
6
|
+
fn_state = {
|
|
7
|
+
0: "FNS_INITIAL",
|
|
8
|
+
1: "FNS_CONFIGURED",
|
|
9
|
+
3: "FNS_FISCAL_MODE",
|
|
10
|
+
7: "FNS_POSTFISCAL_MODE",
|
|
11
|
+
15: "FNS_ACCESS_ARCHIVE"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
ffd_version = {
|
|
15
|
+
0: "FFD_UNKNOWN",
|
|
16
|
+
100: "FFD_1_0",
|
|
17
|
+
105: "FFD_1_0_5",
|
|
18
|
+
110: "FFD_1_1",
|
|
19
|
+
120: "FFD_1_2"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
tax_mode = {
|
|
23
|
+
1: "OSN",
|
|
24
|
+
2: "USN_INCOME",
|
|
25
|
+
4: "USN_INCOME_OUTCOME",
|
|
26
|
+
16: "ESN",
|
|
27
|
+
32: "PATENT",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
receipt_type = {
|
|
31
|
+
0: "CLOSED",
|
|
32
|
+
1: "SELL",
|
|
33
|
+
2: "SELL_RETURN",
|
|
34
|
+
7: "SELL_CORRECTION",
|
|
35
|
+
8: "SELL_RETURN_CORRECTION",
|
|
36
|
+
4: "BUY",
|
|
37
|
+
5: "BUY_RETURN",
|
|
38
|
+
9: "BUY_CORRECTION",
|
|
39
|
+
10: "BUY_RETURN_CORRECTION"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
doc_type = {
|
|
43
|
+
1: "REGISTRATION",
|
|
44
|
+
2: "OPEN_SHIFT",
|
|
45
|
+
3: "RECEIPT",
|
|
46
|
+
4: "BSO",
|
|
47
|
+
5: "CLOSE_SHIFT",
|
|
48
|
+
6: "CLOSE_FN",
|
|
49
|
+
7: "OPERATOR_CONFIRMATION",
|
|
50
|
+
11: "REREGISTRATION",
|
|
51
|
+
21: "EXCHANGE_STATUS",
|
|
52
|
+
31: "CORRECTION",
|
|
53
|
+
41: "BSO_CORRECTION"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
def __init__(self, core):
|
|
57
|
+
self.core = core
|
|
58
|
+
if self.core.is_opened() == 0:
|
|
59
|
+
if not self.core.open_connect():
|
|
60
|
+
return None
|
|
61
|
+
self.fptr = core.fptr
|
|
62
|
+
|
|
63
|
+
def get_status_fn(self):
|
|
64
|
+
"""
|
|
65
|
+
Получение статуса фискального накопителя
|
|
66
|
+
:return: fn_state
|
|
67
|
+
:rtype: str
|
|
68
|
+
"""
|
|
69
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_FN_INFO)
|
|
70
|
+
self.fptr.fnQueryData()
|
|
71
|
+
|
|
72
|
+
fn_state = self.fn_state.get(self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FN_STATE))
|
|
73
|
+
|
|
74
|
+
return fn_state
|
|
75
|
+
|
|
76
|
+
def get_info_last_receipt(self):
|
|
77
|
+
"""
|
|
78
|
+
Запрос информации о последнем чеке
|
|
79
|
+
:return: last_receipt_info
|
|
80
|
+
:rtype: dict
|
|
81
|
+
"""
|
|
82
|
+
last_receipt_info = {
|
|
83
|
+
"receipt_number": "",
|
|
84
|
+
"receipt_type": "",
|
|
85
|
+
"receipt_sum": "",
|
|
86
|
+
"fiscal_sign": "",
|
|
87
|
+
"date_time": ""
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_LAST_RECEIPT)
|
|
91
|
+
self.fptr.fnQueryData()
|
|
92
|
+
|
|
93
|
+
receipt_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
|
|
94
|
+
last_receipt_info.update({"receipt_number": receipt_number})
|
|
95
|
+
|
|
96
|
+
receipt_type = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_RECEIPT_TYPE)
|
|
97
|
+
last_receipt_info.update({"receipt_type": self.receipt_type.get(receipt_type)})
|
|
98
|
+
|
|
99
|
+
receipt_sum = self.fptr.getParamDouble(IFptr.LIBFPTR_PARAM_RECEIPT_SUM)
|
|
100
|
+
last_receipt_info.update({"receipt_sum": receipt_sum})
|
|
101
|
+
|
|
102
|
+
fiscal_sign = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_FISCAL_SIGN)
|
|
103
|
+
last_receipt_info.update({"fiscal_sign": fiscal_sign})
|
|
104
|
+
|
|
105
|
+
date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
|
|
106
|
+
last_receipt_info.update({"date_time": date_time.strftime("%Y-%m-%d %H:%M:%S")})
|
|
107
|
+
|
|
108
|
+
return last_receipt_info
|
|
109
|
+
|
|
110
|
+
def get_info_last_doc(self):
|
|
111
|
+
"""
|
|
112
|
+
Запрос информации о последнем фискальном документе
|
|
113
|
+
:return: last_doc_info
|
|
114
|
+
:rtype: dict
|
|
115
|
+
"""
|
|
116
|
+
last_doc_info = {
|
|
117
|
+
"document_number": "",
|
|
118
|
+
"receipt_type": "",
|
|
119
|
+
"fiscal_sign": "",
|
|
120
|
+
"date_time": ""
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_LAST_DOCUMENT)
|
|
124
|
+
self.fptr.fnQueryData()
|
|
125
|
+
|
|
126
|
+
document_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
|
|
127
|
+
last_doc_info.update({"document_number": document_number})
|
|
128
|
+
|
|
129
|
+
receipt_type = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_RECEIPT_TYPE)
|
|
130
|
+
last_doc_info.update({"receipt_type": self.receipt_type.get(receipt_type)})
|
|
131
|
+
|
|
132
|
+
fiscal_sign = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_FISCAL_SIGN)
|
|
133
|
+
last_doc_info.update({"fiscal_sign": fiscal_sign})
|
|
134
|
+
|
|
135
|
+
date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
|
|
136
|
+
last_doc_info.update({"date_time": date_time.strftime("%Y-%m-%d %H:%M:%S")})
|
|
137
|
+
|
|
138
|
+
return last_doc_info
|
|
139
|
+
|
|
140
|
+
def get_version_ffd(self):
|
|
141
|
+
"""
|
|
142
|
+
Запрос версий ФФД
|
|
143
|
+
:return:version_ffd
|
|
144
|
+
:rtype:dict
|
|
145
|
+
"""
|
|
146
|
+
version_ffd = {
|
|
147
|
+
"device_ffd_version": "",
|
|
148
|
+
"fn_ffd_version": "",
|
|
149
|
+
"max_fn_ffd_version": "",
|
|
150
|
+
"ffd_version": "",
|
|
151
|
+
"max_ffd_version": "",
|
|
152
|
+
"min_ffd_version": ""
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_FFD_VERSIONS)
|
|
156
|
+
self.fptr.fnQueryData()
|
|
157
|
+
|
|
158
|
+
device_ffd_version = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DEVICE_FFD_VERSION)
|
|
159
|
+
version_ffd.update({"device_ffd_version": self.ffd_version.get(device_ffd_version)})
|
|
160
|
+
|
|
161
|
+
fn_ffd_version = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FN_FFD_VERSION)
|
|
162
|
+
version_ffd.update({"fn_ffd_version": self.ffd_version.get(fn_ffd_version)})
|
|
163
|
+
|
|
164
|
+
max_fn_ffd_version = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FN_MAX_FFD_VERSION)
|
|
165
|
+
version_ffd.update({"max_fn_ffd_version": self.ffd_version.get(max_fn_ffd_version)})
|
|
166
|
+
|
|
167
|
+
ffd_version = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FFD_VERSION)
|
|
168
|
+
version_ffd.update({"ffd_version": self.ffd_version.get(ffd_version)})
|
|
169
|
+
|
|
170
|
+
max_ffd_version = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DEVICE_MAX_FFD_VERSION)
|
|
171
|
+
version_ffd.update({"max_ffd_version": self.ffd_version.get(max_ffd_version)})
|
|
172
|
+
|
|
173
|
+
min_ffd_version = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DEVICE_MIN_FFD_VERSION)
|
|
174
|
+
version_ffd.update({"document_number": self.ffd_version.get(min_ffd_version)})
|
|
175
|
+
|
|
176
|
+
return version_ffd
|
|
177
|
+
|
|
178
|
+
def get_info_doc(self, number_doc):
|
|
179
|
+
"""
|
|
180
|
+
Запрос информации о документе
|
|
181
|
+
:return: info_doc
|
|
182
|
+
:rtype: dict
|
|
183
|
+
"""
|
|
184
|
+
info_doc = {
|
|
185
|
+
"document_type": "",
|
|
186
|
+
"document_number": "",
|
|
187
|
+
"has_ofd_ticket": "",
|
|
188
|
+
"date_time": "",
|
|
189
|
+
"fiscal_sign": ""
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_DOCUMENT_BY_NUMBER)
|
|
193
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER, number_doc)
|
|
194
|
+
self.fptr.fnQueryData()
|
|
195
|
+
|
|
196
|
+
document_type = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FN_DOCUMENT_TYPE)
|
|
197
|
+
info_doc.update({"document_type": self.doc_type.get(document_type)})
|
|
198
|
+
|
|
199
|
+
document_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
|
|
200
|
+
info_doc.update({"document_number": document_number})
|
|
201
|
+
|
|
202
|
+
has_ofd_ticket = self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_HAS_OFD_TICKET)
|
|
203
|
+
info_doc.update({"has_ofd_ticket": has_ofd_ticket})
|
|
204
|
+
|
|
205
|
+
fiscal_sign = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_FISCAL_SIGN)
|
|
206
|
+
info_doc.update({"fiscal_sign": fiscal_sign})
|
|
207
|
+
|
|
208
|
+
date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
|
|
209
|
+
info_doc.update({"date_time": date_time.strftime("%Y-%m-%d %H:%M:%S")})
|
|
210
|
+
|
|
211
|
+
return info_doc
|
|
212
|
+
|
|
213
|
+
def get_ticket_ofd(self, number_doc):
|
|
214
|
+
"""
|
|
215
|
+
Запрос квитанции ОФД
|
|
216
|
+
:return: ticket_ofd
|
|
217
|
+
:rtype:
|
|
218
|
+
"""
|
|
219
|
+
ticket_ofd = {
|
|
220
|
+
"document_number": "",
|
|
221
|
+
"date_time": "",
|
|
222
|
+
"ofd_fiscal_sign": "",
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_TICKET_BY_DOC_NUMBER)
|
|
226
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER, number_doc)
|
|
227
|
+
self.fptr.fnQueryData()
|
|
228
|
+
|
|
229
|
+
document_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
|
|
230
|
+
ticket_ofd.update({"document_number": document_number})
|
|
231
|
+
|
|
232
|
+
date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
|
|
233
|
+
ticket_ofd.update({"date_time": date_time.strftime("%Y-%m-%d %H:%M:%S")})
|
|
234
|
+
|
|
235
|
+
ofd_fiscal_sign = self.fptr.getParamByteArray(IFptr.LIBFPTR_PARAM_OFD_FISCAL_SIGN)
|
|
236
|
+
ticket_ofd.update({"ofd_fiscal_sign": ofd_fiscal_sign})
|
|
237
|
+
|
|
238
|
+
return ticket_ofd
|
|
239
|
+
|
|
240
|
+
def get_fn_error(self):
|
|
241
|
+
"""
|
|
242
|
+
Запрос ошибок ФН и ОФД
|
|
243
|
+
:return:
|
|
244
|
+
"""
|
|
245
|
+
fn_error_info = {
|
|
246
|
+
"network": {
|
|
247
|
+
"error": "",
|
|
248
|
+
"error_text": ""
|
|
249
|
+
},
|
|
250
|
+
"ofd": {
|
|
251
|
+
"error": "",
|
|
252
|
+
"error_text": ""
|
|
253
|
+
},
|
|
254
|
+
"fn": {
|
|
255
|
+
"error": "",
|
|
256
|
+
"error_text": ""
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_ERRORS)
|
|
261
|
+
self.fptr.fnQueryData()
|
|
262
|
+
|
|
263
|
+
network_error = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_NETWORK_ERROR)
|
|
264
|
+
network_error_text = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_NETWORK_ERROR_TEXT)
|
|
265
|
+
|
|
266
|
+
network = fn_error_info.get("network")
|
|
267
|
+
network.update({"error": network_error})
|
|
268
|
+
network.update({"error_text": network_error_text})
|
|
269
|
+
|
|
270
|
+
ofd_error = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_OFD_ERROR)
|
|
271
|
+
ofd_error_text = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_OFD_ERROR_TEXT)
|
|
272
|
+
|
|
273
|
+
ofd = fn_error_info.get("ofd")
|
|
274
|
+
ofd.update({"error": ofd_error})
|
|
275
|
+
ofd.update({"error_text": ofd_error_text})
|
|
276
|
+
|
|
277
|
+
fn_error = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FN_ERROR)
|
|
278
|
+
fn_error_text = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_FN_ERROR_TEXT)
|
|
279
|
+
|
|
280
|
+
fn = fn_error_info.get("fn")
|
|
281
|
+
fn.update({"error": fn_error})
|
|
282
|
+
fn.update({"error_text": fn_error_text})
|
|
283
|
+
|
|
284
|
+
return fn_error_info
|
|
285
|
+
|
|
286
|
+
def get_exchange_status(self):
|
|
287
|
+
"""
|
|
288
|
+
Запрос статуса информационного обмена
|
|
289
|
+
:return:
|
|
290
|
+
"""
|
|
291
|
+
fn_exchange_info = {
|
|
292
|
+
"exchange_status": "",
|
|
293
|
+
"unsent_count": "",
|
|
294
|
+
"first_unsent_number": "",
|
|
295
|
+
"ofd_message_read": "",
|
|
296
|
+
"date_time": "",
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_OFD_EXCHANGE_STATUS)
|
|
300
|
+
self.fptr.fnQueryData()
|
|
301
|
+
|
|
302
|
+
exchange_status = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_OFD_EXCHANGE_STATUS)
|
|
303
|
+
unsent_count = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENTS_COUNT)
|
|
304
|
+
first_unsent_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
|
|
305
|
+
ofd_message_read = self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_OFD_MESSAGE_READ)
|
|
306
|
+
date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
|
|
307
|
+
|
|
308
|
+
fn_exchange_info.update({"exchange_status": exchange_status})
|
|
309
|
+
fn_exchange_info.update({"unsent_count": unsent_count})
|
|
310
|
+
fn_exchange_info.update({"first_unsent_number": first_unsent_number})
|
|
311
|
+
fn_exchange_info.update({"ofd_message_read": ofd_message_read})
|
|
312
|
+
fn_exchange_info.update({"date_time": date_time.strftime("%Y-%m-%d %H:%M:%S")})
|
|
313
|
+
|
|
314
|
+
return fn_exchange_info
|
|
315
|
+
|
|
316
|
+
def get_registration_number(self):
|
|
317
|
+
"""
|
|
318
|
+
Запрос РНМ
|
|
319
|
+
:return:registrationNumber
|
|
320
|
+
"""
|
|
321
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_REG_INFO)
|
|
322
|
+
self.fptr.fnQueryData()
|
|
323
|
+
|
|
324
|
+
registration_number = self.fptr.getParamString(1037)
|
|
325
|
+
|
|
326
|
+
return registration_number
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
from libfptr10 import IFptr
|
|
2
|
+
from .ord_core import Core
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Receipt:
|
|
6
|
+
"""
|
|
7
|
+
Формирование чека состоит из следующих операций:
|
|
8
|
+
|
|
9
|
+
открытие чека и передача реквизитов чека
|
|
10
|
+
регистрация позиций, печать нефискальных данных (текст, штрихкоды, изображения)
|
|
11
|
+
регистрация итога (необязательный пункт - если регистрацию итога не провести, он автоматически расчитается из суммы всех позиций)
|
|
12
|
+
регистрация налогов на чек (необязательный пункт - налоги могут быть подтянуты из позиций и суммированы)
|
|
13
|
+
регистрация оплат
|
|
14
|
+
закрытие чека
|
|
15
|
+
проверка состояния чека
|
|
16
|
+
|
|
17
|
+
Пример:
|
|
18
|
+
{
|
|
19
|
+
"document":{
|
|
20
|
+
"id":"ofd_605df0bed5d8a",
|
|
21
|
+
"checkoutDateTime":"2021-03-26T17:33:34+03:00",
|
|
22
|
+
"docNum":"197452540",
|
|
23
|
+
"docType":"SALE",
|
|
24
|
+
"printReceipt":false,
|
|
25
|
+
"responseURL":null,
|
|
26
|
+
"email":"volodya@brandshop.ru",
|
|
27
|
+
"inventPositions":[
|
|
28
|
+
{
|
|
29
|
+
"name":"Сланцы adidas Originals YEEZY Foam Runner Moon Gray/Moon Gray/Moon Gray",
|
|
30
|
+
"price":6990,
|
|
31
|
+
"quantity":"1",
|
|
32
|
+
"vatTag":1102,
|
|
33
|
+
"discSum":0,
|
|
34
|
+
"nomenclatureCode":"44 4D 03 B2 3C AF 78 CB 70 25 63 33 35 6F 7A 52 79 2C 72 3F 7A"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name":"Самовывоз",
|
|
38
|
+
"price":"0.0000",
|
|
39
|
+
"quantity":"1",
|
|
40
|
+
"vatTag":1102,
|
|
41
|
+
"discSum":0,
|
|
42
|
+
"nomenclatureCode":null
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"moneyPositions":[
|
|
46
|
+
{
|
|
47
|
+
"paymentType":"CARD",
|
|
48
|
+
"sum":6990
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
tax_mode = {
|
|
56
|
+
"OSN": 1,
|
|
57
|
+
"USN_INCOME": 2,
|
|
58
|
+
"USN_INCOME_OUTCOME": 4,
|
|
59
|
+
"ESN": 16,
|
|
60
|
+
"PATENT": 32,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
def __init__(self, core):
|
|
64
|
+
self.core = core
|
|
65
|
+
if self.core.is_opened() == 0:
|
|
66
|
+
if not self.core.open_connect():
|
|
67
|
+
return None
|
|
68
|
+
self.fptr = core.fptr
|
|
69
|
+
|
|
70
|
+
def open_receipt(self, receipt_data):
|
|
71
|
+
"""
|
|
72
|
+
Открытие чека и передача реквизитов чека
|
|
73
|
+
Тип чека (LIBFPTR_PARAM_RECEIPT_TYPE) может принимать следующие значения:
|
|
74
|
+
LIBFPTR_RT_SELL - чек прихода (продажи)
|
|
75
|
+
LIBFPTR_RT_SELL_RETURN - чек возврата прихода (продажи)
|
|
76
|
+
LIBFPTR_RT_SELL_CORRECTION - чек коррекции прихода
|
|
77
|
+
LIBFPTR_RT_SELL_RETURN_CORRECTION - чек коррекции возврата прихода
|
|
78
|
+
LIBFPTR_RT_BUY - чек расхода (покупки)
|
|
79
|
+
LIBFPTR_RT_BUY_RETURN - чек возврата расхода (покупки)
|
|
80
|
+
LIBFPTR_RT_BUY_CORRECTION - чек коррекции расхода
|
|
81
|
+
LIBFPTR_RT_BUY_RETURN_CORRECTION - чек коррекции возврата расхода
|
|
82
|
+
|
|
83
|
+
Чтобы чек не печатался (электронный чек), нужно установить
|
|
84
|
+
параметру LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY значение true.
|
|
85
|
+
|
|
86
|
+
"id":"ofd_605df0bed5d8a",
|
|
87
|
+
"checkoutDateTime":"2021-03-26T17:33:34+03:00",
|
|
88
|
+
"docNum":"197452540",
|
|
89
|
+
"docType":"SALE",
|
|
90
|
+
"printReceipt":false,
|
|
91
|
+
"responseURL":null,
|
|
92
|
+
"email":"volodya@brandshop.ru",
|
|
93
|
+
"taxMode": "OSN"
|
|
94
|
+
"""
|
|
95
|
+
status = False
|
|
96
|
+
|
|
97
|
+
if not self.core._set_casher():
|
|
98
|
+
return status
|
|
99
|
+
|
|
100
|
+
receipt_type = receipt_data.get("docType")
|
|
101
|
+
receipt_print = receipt_data.get("printReceipt")
|
|
102
|
+
receipt_email = receipt_data.get("email")
|
|
103
|
+
receipt_tax_mode = self.tax_mode.get(receipt_data.get("taxMode"))
|
|
104
|
+
|
|
105
|
+
if receipt_type == "SALE":
|
|
106
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECEIPT_TYPE, IFptr.LIBFPTR_RT_SELL)
|
|
107
|
+
elif receipt_type == "RETURN":
|
|
108
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECEIPT_TYPE, IFptr.LIBFPTR_RT_SELL_RETURN)
|
|
109
|
+
else:
|
|
110
|
+
return status
|
|
111
|
+
|
|
112
|
+
if receipt_print:
|
|
113
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY, False)
|
|
114
|
+
else:
|
|
115
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY, True)
|
|
116
|
+
|
|
117
|
+
self.fptr.setParam(1008, receipt_email)
|
|
118
|
+
self.fptr.setParam(1055, receipt_tax_mode)
|
|
119
|
+
|
|
120
|
+
if self.fptr.openReceipt() < 0:
|
|
121
|
+
self.core._error_log()
|
|
122
|
+
else:
|
|
123
|
+
status = True
|
|
124
|
+
|
|
125
|
+
return status
|
|
126
|
+
|
|
127
|
+
def cancel_receipt(self):
|
|
128
|
+
"""
|
|
129
|
+
Отмена чека
|
|
130
|
+
:return: status
|
|
131
|
+
:rtype: bool
|
|
132
|
+
"""
|
|
133
|
+
status = False
|
|
134
|
+
|
|
135
|
+
if self.fptr.cancelReceipt() < 0:
|
|
136
|
+
self.core._error_log()
|
|
137
|
+
else:
|
|
138
|
+
status = True
|
|
139
|
+
|
|
140
|
+
return status
|
|
141
|
+
|
|
142
|
+
def receipt_registration(self, product):
|
|
143
|
+
"""
|
|
144
|
+
Регистрация позиции
|
|
145
|
+
Тип налога (LIBFPTR_PARAM_TAX_TYPE) может принимать следующие значения:
|
|
146
|
+
|
|
147
|
+
LIBFPTR_TAX_DEPARTMENT - тип, привязанный к секции товара
|
|
148
|
+
LIBFPTR_TAX_VAT10 - НДС 10%
|
|
149
|
+
LIBFPTR_TAX_VAT110 - НДС расчитанный 10/110
|
|
150
|
+
LIBFPTR_TAX_VAT0 - НДС 0%
|
|
151
|
+
LIBFPTR_TAX_NO - не облагается
|
|
152
|
+
LIBFPTR_TAX_VAT20 - НДС 20%
|
|
153
|
+
LIBFPTR_TAX_VAT120 - НДС раcчитанный 20/120
|
|
154
|
+
|
|
155
|
+
1102 Сумма НДС чека по ставке 20% double
|
|
156
|
+
1103 Сумма НДС чека по ставке 10% double
|
|
157
|
+
1104 Сумма расчёта по чеку с НДС по ставке 0% double
|
|
158
|
+
1105 Сумма расчёта по чека без НДС double
|
|
159
|
+
1106 Сумма НДС чека по расч. ставке 20/120 double
|
|
160
|
+
1107 Сумма НДС чека по расч. ставке 10/110 double
|
|
161
|
+
|
|
162
|
+
"inventPositions":[
|
|
163
|
+
{
|
|
164
|
+
"name":"Сланцы adidas Originals YEEZY Foam Runner Moon Gray/Moon Gray/Moon Gray",
|
|
165
|
+
"price":6990,
|
|
166
|
+
"quantity":"1",
|
|
167
|
+
"vatTag":1102,
|
|
168
|
+
"discSum":0,
|
|
169
|
+
"nomenclatureCode":"44 4D 03 B2 3C AF 78 CB 70 25 63 33 35 6F 7A 52 79 2C 72 3F 7A"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name":"Самовывоз",
|
|
173
|
+
"price":"0.0000",
|
|
174
|
+
"quantity":"1",
|
|
175
|
+
"vatTag":1102,
|
|
176
|
+
"discSum":0,
|
|
177
|
+
"nomenclatureCode":null
|
|
178
|
+
}
|
|
179
|
+
],
|
|
180
|
+
:return: status
|
|
181
|
+
:rtype: bool
|
|
182
|
+
"""
|
|
183
|
+
status = False
|
|
184
|
+
|
|
185
|
+
product_name = product.get("name")
|
|
186
|
+
product_price = product.get("price")
|
|
187
|
+
product_quantity = product.get("quantity")
|
|
188
|
+
product_tax = product.get("vatTag")
|
|
189
|
+
product_nomenclature_code = product.get("nomenclatureCode")
|
|
190
|
+
product_code_check = product.get("codeCheck")
|
|
191
|
+
product_disc_sum = product.get("discSum")
|
|
192
|
+
|
|
193
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_COMMODITY_NAME, product_name)
|
|
194
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_PRICE, product_price)
|
|
195
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_QUANTITY, product_quantity)
|
|
196
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT20)
|
|
197
|
+
|
|
198
|
+
if product_nomenclature_code:
|
|
199
|
+
# Запускаем проверку КМ
|
|
200
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE, product_nomenclature_code)
|
|
201
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE_STATUS, 2)
|
|
202
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0)
|
|
203
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MEASUREMENT_UNIT, IFptr.LIBFPTR_IU_PIECE)
|
|
204
|
+
self.fptr.beginMarkingCodeValidation()
|
|
205
|
+
|
|
206
|
+
# Дожидаемся окончания проверки и запоминаем результат
|
|
207
|
+
while True:
|
|
208
|
+
self.fptr.getMarkingCodeValidationStatus()
|
|
209
|
+
if self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_MARKING_CODE_VALIDATION_READY):
|
|
210
|
+
break
|
|
211
|
+
|
|
212
|
+
validation_result = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT)
|
|
213
|
+
|
|
214
|
+
# Подтверждаем реализацию товара с указанным КМ
|
|
215
|
+
self.fptr.acceptMarkingCode()
|
|
216
|
+
|
|
217
|
+
# Результат проверки разрешительного режима кода маркировки(Регистрация позиции с отраслевым
|
|
218
|
+
# реквизитом предмета расчета (тег 1260, ФФД 1.2))
|
|
219
|
+
self.fptr.setParam(1262, '030')
|
|
220
|
+
self.fptr.setParam(1263, '21.11.2023')
|
|
221
|
+
self.fptr.setParam(1264, '1944')
|
|
222
|
+
self.fptr.setParam(1265, product_code_check)
|
|
223
|
+
self.fptr.utilFormTlv()
|
|
224
|
+
industry_info = self.fptr.getParamByteArray(IFptr.LIBFPTR_PARAM_TAG_VALUE)
|
|
225
|
+
self.fptr.setParam(1260, industry_info)
|
|
226
|
+
|
|
227
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_COMMODITY_NAME, product_name)
|
|
228
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_PRICE, product_price)
|
|
229
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_QUANTITY, product_quantity)
|
|
230
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT20)
|
|
231
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT, validation_result)
|
|
232
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE, product_nomenclature_code)
|
|
233
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE_STATUS, 2)
|
|
234
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0)
|
|
235
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MEASUREMENT_UNIT, IFptr.LIBFPTR_IU_PIECE)
|
|
236
|
+
else:
|
|
237
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_MEASUREMENT_UNIT, IFptr.LIBFPTR_IU_PIECE)
|
|
238
|
+
|
|
239
|
+
if product_disc_sum > 0:
|
|
240
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_INFO_DISCOUNT_SUM, product_disc_sum)
|
|
241
|
+
|
|
242
|
+
if self.fptr.registration() < 0:
|
|
243
|
+
self.core._error_log()
|
|
244
|
+
else:
|
|
245
|
+
status = True
|
|
246
|
+
|
|
247
|
+
return status
|
|
248
|
+
|
|
249
|
+
def receipt_payment(self, money_position):
|
|
250
|
+
"""
|
|
251
|
+
Регистрация оплаты
|
|
252
|
+
|
|
253
|
+
Способ расчета (LIBFPTR_PARAM_PAYMENT_TYPE) может принимать следующие значения:
|
|
254
|
+
LIBFPTR_PT_CASH - наличными
|
|
255
|
+
LIBFPTR_PT_ELECTRONICALLY - безналичными
|
|
256
|
+
LIBFPTR_PT_PREPAID - предварительная оплата (аванс)
|
|
257
|
+
LIBFPTR_PT_CREDIT - последующая оплата (кредит)
|
|
258
|
+
LIBFPTR_PT_OTHER - иная форма оплаты (встречное предоставление)
|
|
259
|
+
LIBFPTR_PT_6 - способ расчета №6
|
|
260
|
+
LIBFPTR_PT_7 - способ расчета №7
|
|
261
|
+
LIBFPTR_PT_8 - способ расчета №8
|
|
262
|
+
LIBFPTR_PT_9 - способ расчета №9
|
|
263
|
+
LIBFPTR_PT_10 - способ расчета №10
|
|
264
|
+
|
|
265
|
+
Пример:
|
|
266
|
+
"moneyPositions": {
|
|
267
|
+
"paymentType": "CARD",
|
|
268
|
+
"sum": 46.8
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
:return: status
|
|
272
|
+
:rtype: bool
|
|
273
|
+
"""
|
|
274
|
+
status = False
|
|
275
|
+
|
|
276
|
+
sum = money_position.get("sum")
|
|
277
|
+
|
|
278
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_PAYMENT_TYPE, IFptr.LIBFPTR_PT_ELECTRONICALLY)
|
|
279
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_PAYMENT_SUM, sum)
|
|
280
|
+
|
|
281
|
+
if self.fptr.payment() < 0:
|
|
282
|
+
self.core._error_log()
|
|
283
|
+
else:
|
|
284
|
+
status = True
|
|
285
|
+
|
|
286
|
+
return status
|
|
287
|
+
|
|
288
|
+
def receipt_tax(self, product_tax, money_position):
|
|
289
|
+
"""
|
|
290
|
+
Регистрация налога на чек
|
|
291
|
+
|
|
292
|
+
Как выделить НДС?
|
|
293
|
+
Если у Вас под рукой не окажется интернета и надо будет выделить НДС - запомните этот простой алгоритм.
|
|
294
|
+
Чтобы выделить НДС из суммы, нужно разделить сумму на 1+НДС (т.е. если НДС 18%, то разделить нужно на 1.18),
|
|
295
|
+
вычесть из полученного исходную сумму, умножить на -1 и округлить до копеек в ближайшую сторону.
|
|
296
|
+
Если вы делаете это на калькуляторе, то последние два действия легко выполнить в уме.
|
|
297
|
+
|
|
298
|
+
Как начислить НДС?
|
|
299
|
+
Начислить НДС еще проще. Если ставка НДС 18%, то умножьте сумму без НДС на 0.18
|
|
300
|
+
и вы получите сумму налога, а умножив на 1.18 вы получите сумму с учетом налога.
|
|
301
|
+
|
|
302
|
+
:return: status
|
|
303
|
+
:rtype: bool
|
|
304
|
+
"""
|
|
305
|
+
status = False
|
|
306
|
+
|
|
307
|
+
sum = money_position.get("sum")
|
|
308
|
+
|
|
309
|
+
if product_tax == 1102:
|
|
310
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT20)
|
|
311
|
+
koef = 1.2
|
|
312
|
+
elif product_tax == 1103:
|
|
313
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT10)
|
|
314
|
+
koef = 1.1
|
|
315
|
+
elif product_tax == 1104:
|
|
316
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT0)
|
|
317
|
+
koef = 1
|
|
318
|
+
elif product_tax == 1105:
|
|
319
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_NO)
|
|
320
|
+
koef = 1
|
|
321
|
+
elif product_tax == 1106:
|
|
322
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT120)
|
|
323
|
+
koef = 1
|
|
324
|
+
elif product_tax == 1107:
|
|
325
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT110)
|
|
326
|
+
koef = 1
|
|
327
|
+
else:
|
|
328
|
+
return status
|
|
329
|
+
|
|
330
|
+
tax_sum = round(-1 * (sum * koef - sum), 2)
|
|
331
|
+
|
|
332
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_SUM, tax_sum)
|
|
333
|
+
|
|
334
|
+
if self.fptr.receiptTax() < 0:
|
|
335
|
+
self.core._error_log()
|
|
336
|
+
else:
|
|
337
|
+
status = True
|
|
338
|
+
|
|
339
|
+
return status
|
|
340
|
+
|
|
341
|
+
def receipt_total(self, money_position):
|
|
342
|
+
"""
|
|
343
|
+
Регистрация итога на чек
|
|
344
|
+
|
|
345
|
+
"moneyPositions":[
|
|
346
|
+
{
|
|
347
|
+
"paymentType":"CARD",
|
|
348
|
+
"sum":6990
|
|
349
|
+
}
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
:return: status
|
|
353
|
+
:rtype: bool
|
|
354
|
+
"""
|
|
355
|
+
status = False
|
|
356
|
+
|
|
357
|
+
sum = money_position.get("sum")
|
|
358
|
+
|
|
359
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_SUM, sum)
|
|
360
|
+
|
|
361
|
+
if self.fptr.receiptTotal() < 0:
|
|
362
|
+
self.core._error_log()
|
|
363
|
+
else:
|
|
364
|
+
status = True
|
|
365
|
+
|
|
366
|
+
return status
|
|
367
|
+
|
|
368
|
+
def receipt_close(self):
|
|
369
|
+
"""
|
|
370
|
+
Закрытие чека
|
|
371
|
+
:return: status
|
|
372
|
+
:rtype: bool
|
|
373
|
+
"""
|
|
374
|
+
status = False
|
|
375
|
+
|
|
376
|
+
if self.fptr.closeReceipt() < 0:
|
|
377
|
+
self.core._error_log()
|
|
378
|
+
else:
|
|
379
|
+
status = True
|
|
380
|
+
|
|
381
|
+
return status
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from libfptr10 import IFptr
|
|
2
|
+
from .ord_core import Core
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Setting(Core):
|
|
6
|
+
|
|
7
|
+
def __init__(self, core):
|
|
8
|
+
self.core = core
|
|
9
|
+
if self.core.is_opened() == 0:
|
|
10
|
+
if not self.core.open_connect():
|
|
11
|
+
return None
|
|
12
|
+
self.fptr = core.fptr
|
|
13
|
+
|
|
14
|
+
def init_setting(self):
|
|
15
|
+
"""
|
|
16
|
+
Инициализация системных таблиц
|
|
17
|
+
:returns: status
|
|
18
|
+
:rtype: bool
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
status = False
|
|
22
|
+
|
|
23
|
+
if self.fptr.initSettings() < 0:
|
|
24
|
+
self._error_log()
|
|
25
|
+
else:
|
|
26
|
+
status = True
|
|
27
|
+
|
|
28
|
+
return status
|
|
29
|
+
|
|
30
|
+
def get_device_setting_by_id(self, id_setting, type_setting):
|
|
31
|
+
"""
|
|
32
|
+
Чтение настройки кассы
|
|
33
|
+
:param id_setting:
|
|
34
|
+
:param type_setting
|
|
35
|
+
:return: setting_value
|
|
36
|
+
:rtype: bool, int, str
|
|
37
|
+
"""
|
|
38
|
+
setting_value = False
|
|
39
|
+
|
|
40
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_SETTING_ID, id_setting)
|
|
41
|
+
self.fptr.readDeviceSetting()
|
|
42
|
+
|
|
43
|
+
if type_setting == "int":
|
|
44
|
+
setting_value = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_SETTING_VALUE)
|
|
45
|
+
if type_setting == "string":
|
|
46
|
+
setting_value = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_SETTING_VALUE)
|
|
47
|
+
|
|
48
|
+
return setting_value
|
|
49
|
+
|
|
50
|
+
def set_device_setting_by_id(self, id_setting, value_setting):
|
|
51
|
+
"""
|
|
52
|
+
Запись настройки кассы
|
|
53
|
+
:param id_setting:
|
|
54
|
+
:param value_setting:
|
|
55
|
+
:return status
|
|
56
|
+
:rtype bool
|
|
57
|
+
"""
|
|
58
|
+
status = False
|
|
59
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_SETTING_ID, id_setting)
|
|
60
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_SETTING_VALUE, value_setting)
|
|
61
|
+
|
|
62
|
+
if self.fptr.writeDeviceSetting() < 0:
|
|
63
|
+
self._error_log()
|
|
64
|
+
else:
|
|
65
|
+
status = True
|
|
66
|
+
|
|
67
|
+
return status
|
|
68
|
+
|
|
69
|
+
def commit_setting(self):
|
|
70
|
+
"""
|
|
71
|
+
Сохранение настроек
|
|
72
|
+
:returns: status
|
|
73
|
+
:rtype: bool
|
|
74
|
+
"""
|
|
75
|
+
status = False
|
|
76
|
+
|
|
77
|
+
if self.fptr.commitSettings() < 0:
|
|
78
|
+
self._error_log()
|
|
79
|
+
else:
|
|
80
|
+
status = True
|
|
81
|
+
|
|
82
|
+
return status
|
|
83
|
+
|
|
84
|
+
def __del__(self):
|
|
85
|
+
if self.is_opened() == 1:
|
|
86
|
+
self.close_connect()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from libfptr10 import IFptr
|
|
2
|
+
from .ord_core import Core
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Shift:
|
|
6
|
+
|
|
7
|
+
def __init__(self, core):
|
|
8
|
+
self.core = core
|
|
9
|
+
if self.core.is_opened() == 0:
|
|
10
|
+
if not self.core.open_connect():
|
|
11
|
+
return None
|
|
12
|
+
self.fptr = core.fptr
|
|
13
|
+
|
|
14
|
+
def open_shift(self):
|
|
15
|
+
"""
|
|
16
|
+
Открытие смены
|
|
17
|
+
|
|
18
|
+
Открывать смену необязательно, т.к. она будет открыта первой фискальной операцией автоматически.
|
|
19
|
+
На некоторых ККТ возможно отключить печать отчета об открытии смены
|
|
20
|
+
с помощью установки параметра LIBFPTR_PARAM_REPORT_ELECTRONICALLY в true.
|
|
21
|
+
Если ККТ не поддерживает такой функционал, параметр будет проигнорирован и отчет будет напечатан.
|
|
22
|
+
:returns: status
|
|
23
|
+
:rtype: bool
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
status = False
|
|
27
|
+
|
|
28
|
+
if not self.core._set_casher():
|
|
29
|
+
return status
|
|
30
|
+
|
|
31
|
+
if self.fptr.openShift() < 0:
|
|
32
|
+
self.core._error_log()
|
|
33
|
+
else:
|
|
34
|
+
self.core._check_document_close()
|
|
35
|
+
status = True
|
|
36
|
+
|
|
37
|
+
return status
|
|
38
|
+
|
|
39
|
+
def close_shift(self):
|
|
40
|
+
"""
|
|
41
|
+
Закрытие смены
|
|
42
|
+
|
|
43
|
+
Автоматически может напечататься так же и Z-отчет.
|
|
44
|
+
На некоторых ККТ возможно отключить печать отчета о закрытии смены с помощью установки
|
|
45
|
+
параметра LIBFPTR_PARAM_REPORT_ELECTRONICALLY в true.
|
|
46
|
+
Если ККТ не поддерживает такой функционал, параметр будет
|
|
47
|
+
проигнорирован и отчет будет напечатан.
|
|
48
|
+
:returns: status
|
|
49
|
+
:rtype: bool
|
|
50
|
+
"""
|
|
51
|
+
status = False
|
|
52
|
+
|
|
53
|
+
if not self.core._set_casher():
|
|
54
|
+
return status
|
|
55
|
+
|
|
56
|
+
self.fptr.setParam(IFptr.LIBFPTR_PARAM_REPORT_TYPE, IFptr.LIBFPTR_RT_CLOSE_SHIFT)
|
|
57
|
+
|
|
58
|
+
if self.fptr.report() < 0:
|
|
59
|
+
self.core._error_log()
|
|
60
|
+
else:
|
|
61
|
+
self.core._check_document_close()
|
|
62
|
+
status = True
|
|
63
|
+
|
|
64
|
+
return status
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# def __del__(self):
|
|
68
|
+
# if core.is_opened() == 1:
|
|
69
|
+
# self.close_connect()
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ORD
|
|
3
|
+
Version: 1.7.0
|
|
4
|
+
Summary: Module for working with the ATOL cash register driver
|
|
5
|
+
Home-page: https://brandshop.ru
|
|
6
|
+
Author: Vladimir Smirnov
|
|
7
|
+
Author-email: volodya@brandshop.ru
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
Модуль для работы с драйвером кассы АТОЛ
|
|
11
|
+
===========
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.cfg
|
|
3
|
+
setup.py
|
|
4
|
+
ORD/__init__.py
|
|
5
|
+
ORD/ord_cash.py
|
|
6
|
+
ORD/ord_core.py
|
|
7
|
+
ORD/ord_fn.py
|
|
8
|
+
ORD/ord_receipt.py
|
|
9
|
+
ORD/ord_setting.py
|
|
10
|
+
ORD/ord_shift.py
|
|
11
|
+
ORD.egg-info/PKG-INFO
|
|
12
|
+
ORD.egg-info/SOURCES.txt
|
|
13
|
+
ORD.egg-info/dependency_links.txt
|
|
14
|
+
ORD.egg-info/top_level.txt
|
|
15
|
+
ORD/test/ORD_test.py
|
|
16
|
+
ORD/test/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ORD
|
ORD-1.7.0/PKG-INFO
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ORD
|
|
3
|
+
Version: 1.7.0
|
|
4
|
+
Summary: Module for working with the ATOL cash register driver
|
|
5
|
+
Home-page: https://brandshop.ru
|
|
6
|
+
Author: Vladimir Smirnov
|
|
7
|
+
Author-email: volodya@brandshop.ru
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
Модуль для работы с драйвером кассы АТОЛ
|
|
11
|
+
===========
|
ORD-1.7.0/README.md
ADDED
ORD-1.7.0/setup.cfg
ADDED
ORD-1.7.0/setup.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
from io import open
|
|
3
|
+
|
|
4
|
+
def read(filename):
|
|
5
|
+
"""Прочитаем наш README.md для того, чтобы установить большое описание."""
|
|
6
|
+
with open(filename, "r", encoding="utf-8") as file:
|
|
7
|
+
return file.read()
|
|
8
|
+
|
|
9
|
+
setup(
|
|
10
|
+
name='ORD',
|
|
11
|
+
version='1.7.0',
|
|
12
|
+
author='Vladimir Smirnov',
|
|
13
|
+
author_email='volodya@brandshop.ru',
|
|
14
|
+
description='Module for working with the ATOL cash register driver',
|
|
15
|
+
url='https://brandshop.ru',
|
|
16
|
+
long_description=read("README.md"),
|
|
17
|
+
long_description_content_type="text/markdown",
|
|
18
|
+
packages=find_packages(),
|
|
19
|
+
)
|