ORD 1.8.13__py3-none-any.whl

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/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ from .ord_core import Core
2
+ from .ord_shift import Shift
3
+ from .ord_receipt import Receipt
4
+ from .ord_cash import Cash
5
+ from .ord_fn import Fn
6
+ from .ord_setting import Setting
ORD/ord_cash.py ADDED
@@ -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
ORD/ord_core.py ADDED
@@ -0,0 +1,218 @@
1
+ import threading
2
+
3
+ from libfptr10 import IFptr
4
+
5
+
6
+ class SingletonMeta(type):
7
+ """
8
+ В Python класс Одиночка можно реализовать по-разному. Возможные способы
9
+ включают себя базовый класс, декоратор, метакласс. Мы воспользуемся
10
+ метаклассом, поскольку он лучше всего подходит для этой цели.
11
+ """
12
+ _instances = {}
13
+ _lock = threading.Lock()
14
+
15
+ def __call__(cls, *args, **kwargs):
16
+ if cls not in cls._instances:
17
+ with cls._lock:
18
+ if cls not in cls._instances:
19
+ cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
20
+ return cls._instances[cls]
21
+
22
+
23
+ class Core(metaclass=SingletonMeta):
24
+ casher_info = {
25
+ 'name': 'СИС. АДМИНИСТРАТОР',
26
+ 'inn': ''
27
+ }
28
+
29
+ def __init__(self, path: str = ''):
30
+ """
31
+ Инициализация драйвера:
32
+ Настройка драйвера
33
+ """
34
+ self.fptr = IFptr(path)
35
+
36
+ self.version = self.fptr.version()
37
+
38
+ settings = {
39
+ IFptr.LIBFPTR_SETTING_MODEL: IFptr.LIBFPTR_MODEL_ATOL_AUTO,
40
+ IFptr.LIBFPTR_SETTING_PORT: IFptr.LIBFPTR_PORT_USB,
41
+ IFptr.LIBFPTR_SETTING_USB_DEVICE_PATH: 'auto',
42
+ IFptr.LIBFPTR_SETTING_OFD_CHANNEL: IFptr.LIBFPTR_OFD_CHANNEL_AUTO
43
+ }
44
+
45
+ self.fptr.setSettings(settings)
46
+
47
+ def _set_casher(self):
48
+ """
49
+ Регистрация кассира
50
+
51
+ Рекомендуется вызывать данный метод перед каждой
52
+ фискальной операцией (открытие чека, печать отчета, ...).
53
+ :return: status
54
+ :rtype: bool
55
+ """
56
+ status = False
57
+
58
+ self.fptr.setParam(1021, self.casher_info.get('name'))
59
+ self.fptr.setParam(1203, self.casher_info.get('inn'))
60
+
61
+ if self.fptr.operatorLogin() < 0:
62
+ self._error_log()
63
+ else:
64
+ status = True
65
+
66
+ return status
67
+
68
+ def open_connect(self):
69
+ """
70
+ Открытие соединение с кассой
71
+ :returns: status
72
+ :rtype: bool
73
+ """
74
+ status = False
75
+ if self.fptr.open() < 0:
76
+ self._error_log()
77
+ else:
78
+ status = True
79
+
80
+ return status
81
+
82
+ def close_connect(self):
83
+ """
84
+ Закрытие соединения с кассой
85
+ :returns: status
86
+ :rtype: bool
87
+ """
88
+ status = False
89
+ if self.fptr.close() < 0:
90
+ self._error_log()
91
+ else:
92
+ status = True
93
+
94
+ return status
95
+
96
+ def is_opened(self):
97
+ """
98
+ Получение состояния соединения с кассой
99
+ Результат метода не отражает текущее состояние подключения - если с ККТ
100
+ была разорвана связь, то метод все также будет возвращать true, но методы,
101
+ выполняющие какие-либо операции над ККТ,
102
+ будут возвращать ошибку LIBFPTR_ERROR_NO_CONNECTION
103
+ :returns: self.fptr.isOpened()
104
+ :rtype: int
105
+ """
106
+ return self.fptr.isOpened()
107
+
108
+ def get_version_driver(self):
109
+ """
110
+ Получение версии драйвера
111
+ :returns: self.version
112
+ :rtype: str
113
+ """
114
+ return self.version
115
+
116
+ def get_current_datetime(self):
117
+ """
118
+ Текущие дата и время ККТ
119
+ :returns: date_time
120
+ :rtype: str
121
+ """
122
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_DATE_TIME)
123
+ self.fptr.queryData()
124
+
125
+ date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME).strftime('%Y-%m-%d %H:%M:%S')
126
+
127
+ return date_time
128
+
129
+ def get_setting(self):
130
+ """
131
+ Получение настроек кассы
132
+ :returns: setting_cash
133
+ :rtype: dict
134
+ """
135
+ setting_cash = self.fptr.getSettings()
136
+
137
+ return setting_cash
138
+
139
+ def _check_document_close(self):
140
+ """
141
+ Проверка закрытия документа
142
+
143
+ В ряде ситуаций (окончание бумаги, потеря связи с
144
+ ККТ в момент регистрации документа) состояние документа остается неизвестным.
145
+ Он может закрыться в ФН (что является необратимой операцией), но не напечататься на чековой ленте.
146
+ Данный метод сверяет счетчики ККТ с сохраненными до закрытия документа копиями и вычисляет,
147
+ закрылся ли он, а также проверяет состояние печати документа.
148
+ :returns: status
149
+ :rtype: bool
150
+ """
151
+ status = True
152
+
153
+ while self.fptr.checkDocumentClosed() < 0:
154
+ # Не удалось проверить состояние документа.
155
+ # Вывести пользователю текст ошибки, попросить
156
+ # устранить неполадку и повторить запрос
157
+ self._error_log()
158
+ status = False
159
+ continue
160
+
161
+ # if not self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_DOCUMENT_CLOSED):
162
+ # # Документ не закрылся.
163
+ # # Требуется его отменить (если это чек) и сформировать заново
164
+ # self.fptr.cancelReceipt()
165
+ # return status
166
+
167
+ if not self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_DOCUMENT_PRINTED):
168
+ # Можно сразу вызвать метод допечатывания документа,
169
+ # он завершится с ошибкой, если это невозможно
170
+ while self.fptr.continuePrint() < 0:
171
+ # Если не удалось допечатать документ,
172
+ # показать пользователю ошибку и попробовать еще раз.
173
+ self._error_log()
174
+ status = False
175
+ continue
176
+
177
+ return status
178
+
179
+ def reboot(self):
180
+ """
181
+ Перезагрузка ККТ
182
+ :return:
183
+ """
184
+ status = False
185
+
186
+ if self.fptr.deviceReboot() < 0:
187
+ self._error_log()
188
+ else:
189
+ status = True
190
+
191
+ return status
192
+
193
+ def _error_log(self):
194
+ """
195
+ Логирование ошибок
196
+ Каждый метод драйвера возвращает индикатор результата выполнения.
197
+ Этот индикатор может принимать значения 0 и -1.
198
+ В случае если индикатор неравен 0, выполнение метода завершилось с ошибкой и
199
+ есть возможность получить подробности о ней.
200
+ Для этого у драйвера можно запросить код последней ошибки (метод errorCode()) и
201
+ её текстовое описание (метод errorDescription()).
202
+ Драйвер хранит информацию об ошибке до следующего вызова метода - после него информация об ошибке обновляется.
203
+ Для явного сброса информации о последней ошибке нужно использовать метод resetError().
204
+ """
205
+ error_msg = '{} [{}]'.format(self.fptr.errorCode(), self.fptr.errorDescription())
206
+ self.fptr.logWrite("FiscalPrinter", IFptr.LIBFPTR_LOG_ERROR, error_msg)
207
+
208
+ def info_log(self, msg):
209
+ """
210
+ Логирование нотификаций
211
+ :param msg:
212
+ :return:
213
+ """
214
+ self.fptr.logWrite("FiscalPrinter", IFptr.LIBFPTR_LOG_INFO, msg)
215
+
216
+ def __del__(self):
217
+ if self.is_opened() == 1:
218
+ self.close_connect()
ORD/ord_fn.py ADDED
@@ -0,0 +1,359 @@
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_ofd_document_by_number(self, number_doc):
241
+ """
242
+ Метод чтения документа из ФН в виде TLV-структур
243
+ :param number_doc: номер документа
244
+ :return: array
245
+ """
246
+ tags = []
247
+
248
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECORDS_TYPE, IFptr.LIBFPTR_RT_FN_DOCUMENT_TLVS)
249
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER, number_doc)
250
+ self.fptr.beginReadRecords()
251
+ records_id = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_RECORDS_ID)
252
+
253
+ while self._readNextRecord(records_id) == IFptr.LIBFPTR_OK:
254
+ tag = {
255
+ "tag_value": self.fptr.getParamByteArray(IFptr.LIBFPTR_PARAM_TAG_VALUE),
256
+ "tag_number": self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_TAG_NUMBER),
257
+ "tag_name": self.fptr.getParamString(IFptr.LIBFPTR_PARAM_TAG_NAME),
258
+ "tag_type": self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_TAG_TYPE),
259
+ }
260
+ tags.append(tag)
261
+
262
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECORDS_ID, records_id)
263
+ self.fptr.endReadRecords()
264
+
265
+ return tags
266
+
267
+ def get_fn_error(self):
268
+ """
269
+ Запрос ошибок ФН и ОФД
270
+ :return:
271
+ """
272
+ fn_error_info = {
273
+ "network": {
274
+ "error": "",
275
+ "error_text": ""
276
+ },
277
+ "ofd": {
278
+ "error": "",
279
+ "error_text": ""
280
+ },
281
+ "fn": {
282
+ "error": "",
283
+ "error_text": ""
284
+ }
285
+ }
286
+
287
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_ERRORS)
288
+ self.fptr.fnQueryData()
289
+
290
+ network_error = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_NETWORK_ERROR)
291
+ network_error_text = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_NETWORK_ERROR_TEXT)
292
+
293
+ network = fn_error_info.get("network")
294
+ network.update({"error": network_error})
295
+ network.update({"error_text": network_error_text})
296
+
297
+ ofd_error = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_OFD_ERROR)
298
+ ofd_error_text = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_OFD_ERROR_TEXT)
299
+
300
+ ofd = fn_error_info.get("ofd")
301
+ ofd.update({"error": ofd_error})
302
+ ofd.update({"error_text": ofd_error_text})
303
+
304
+ fn_error = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_FN_ERROR)
305
+ fn_error_text = self.fptr.getParamString(IFptr.LIBFPTR_PARAM_FN_ERROR_TEXT)
306
+
307
+ fn = fn_error_info.get("fn")
308
+ fn.update({"error": fn_error})
309
+ fn.update({"error_text": fn_error_text})
310
+
311
+ return fn_error_info
312
+
313
+ def get_exchange_status(self):
314
+ """
315
+ Запрос статуса информационного обмена
316
+ :return:
317
+ """
318
+ fn_exchange_info = {
319
+ "exchange_status": "",
320
+ "unsent_count": "",
321
+ "first_unsent_number": "",
322
+ "ofd_message_read": "",
323
+ "date_time": "",
324
+ }
325
+
326
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_OFD_EXCHANGE_STATUS)
327
+ self.fptr.fnQueryData()
328
+
329
+ exchange_status = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_OFD_EXCHANGE_STATUS)
330
+ unsent_count = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENTS_COUNT)
331
+ first_unsent_number = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
332
+ ofd_message_read = self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_OFD_MESSAGE_READ)
333
+ date_time = self.fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
334
+
335
+ fn_exchange_info.update({"exchange_status": exchange_status})
336
+ fn_exchange_info.update({"unsent_count": unsent_count})
337
+ fn_exchange_info.update({"first_unsent_number": first_unsent_number})
338
+ fn_exchange_info.update({"ofd_message_read": ofd_message_read})
339
+ fn_exchange_info.update({"date_time": date_time.strftime("%Y-%m-%d %H:%M:%S")})
340
+
341
+ return fn_exchange_info
342
+
343
+ def get_registration_number(self):
344
+ """
345
+ Запрос РНМ
346
+ :return:registrationNumber
347
+ """
348
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_REG_INFO)
349
+ self.fptr.fnQueryData()
350
+
351
+ registration_number = self.fptr.getParamString(1037)
352
+
353
+ return registration_number
354
+
355
+ # Вспомогательная функция чтения следующей записи
356
+
357
+ def _readNextRecord(self, recordsID):
358
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_RECORDS_ID, recordsID)
359
+ return self.fptr.readNextRecord()
ORD/ord_receipt.py ADDED
@@ -0,0 +1,342 @@
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
+ self.fptr.setParam(1125, 1)
121
+
122
+ if self.fptr.openReceipt() < 0:
123
+ self.core._error_log()
124
+ else:
125
+ status = True
126
+
127
+ return status
128
+
129
+ def cancel_receipt(self):
130
+ """
131
+ Отмена чека
132
+ :return: status
133
+ :rtype: bool
134
+ """
135
+ status = False
136
+
137
+ if self.fptr.cancelReceipt() < 0:
138
+ self.core._error_log()
139
+ else:
140
+ status = True
141
+
142
+ return status
143
+
144
+ def receipt_registration(self, product):
145
+ """
146
+ Регистрация позиции
147
+ Тип налога (LIBFPTR_PARAM_TAX_TYPE) может принимать следующие значения:
148
+
149
+ LIBFPTR_TAX_VAT10 - НДС 10%;
150
+ LIBFPTR_TAX_VAT110 - НДС рассчитанный 10/110;
151
+ LIBFPTR_TAX_VAT0 - НДС 0%;
152
+ LIBFPTR_TAX_NO - не облагается;
153
+ LIBFPTR_TAX_VAT20 - НДС 20%;
154
+ LIBFPTR_TAX_VAT120 - НДС рассчитанный 20/120;
155
+ LIBFPTR_TAX_VAT5 - НДС 5%;
156
+ LIBFPTR_TAX_VAT105 - НДС рассчитанный 5/105;
157
+ LIBFPTR_TAX_VAT7 - НДС 7%;
158
+ LIBFPTR_TAX_VAT107 - НДС рассчитанный 7/107;
159
+ LIBFPTR_TAX_VAT22 - НДС 22%;
160
+ LIBFPTR_TAX_VAT122 - НДС рассчитанный 22/122.
161
+
162
+ 1102 Сумма НДС чека по ставке 20% double
163
+ 1103 Сумма НДС чека по ставке 10% double
164
+ 1104 Сумма расчёта по чеку с НДС по ставке 0% double
165
+ 1105 Сумма расчёта по чека без НДС double
166
+ 1106 Сумма НДС чека по расч. ставке 20/120 double
167
+ 1107 Сумма НДС чека по расч. ставке 10/110 double
168
+
169
+ "inventPositions":[
170
+ {
171
+ "name":"Сланцы adidas Originals YEEZY Foam Runner Moon Gray/Moon Gray/Moon Gray",
172
+ "price":6990,
173
+ "quantity":"1",
174
+ "vatTag":1102,
175
+ "discSum":0,
176
+ "nomenclatureCode":"44 4D 03 B2 3C AF 78 CB 70 25 63 33 35 6F 7A 52 79 2C 72 3F 7A"
177
+ },
178
+ {
179
+ "name":"Самовывоз",
180
+ "price":"0.0000",
181
+ "quantity":"1",
182
+ "vatTag":1102,
183
+ "discSum":0,
184
+ "nomenclatureCode":null
185
+ }
186
+ ],
187
+ :return: status
188
+ :rtype: bool
189
+ """
190
+ status = False
191
+
192
+ product_name = product.get("name")
193
+ product_price = product.get("price")
194
+ product_quantity = product.get("quantity")
195
+ # product_tax = product.get("vatTag")
196
+ product_nomenclature_code = product.get("nomenclatureCode")
197
+ product_code_check = product.get("codeCheck")
198
+ product_disc_sum = product.get("discSum")
199
+
200
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_COMMODITY_NAME, product_name)
201
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_PRICE, product_price)
202
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_QUANTITY, product_quantity)
203
+ # Для запроса суммы налога за чек необходимо вызвать метод queryData() с типом запроса LIBFPTR_PARAM_DATA_TYPE
204
+ # равным LIBFPTR_DT_RECEIPT_TAX_SUM и указать тип налога LIBFPTR_PARAM_TAX_TYPE.
205
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT22)
206
+
207
+ if product_nomenclature_code:
208
+ # Запускаем проверку КМ
209
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE, product_nomenclature_code)
210
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE_STATUS, 2)
211
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0)
212
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MEASUREMENT_UNIT, IFptr.LIBFPTR_IU_PIECE)
213
+ self.fptr.beginMarkingCodeValidation()
214
+
215
+ # Дожидаемся окончания проверки и запоминаем результат
216
+ while True:
217
+ self.fptr.getMarkingCodeValidationStatus()
218
+ if self.fptr.getParamBool(IFptr.LIBFPTR_PARAM_MARKING_CODE_VALIDATION_READY):
219
+ break
220
+
221
+ validation_result = self.fptr.getParamInt(IFptr.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT)
222
+
223
+ # Подтверждаем реализацию товара с указанным КМ
224
+ self.fptr.acceptMarkingCode()
225
+
226
+ # Результат проверки разрешительного режима кода маркировки(Регистрация позиции с отраслевым
227
+ # реквизитом предмета расчета (тег 1260, ФФД 1.2))
228
+ if product_code_check:
229
+ self.fptr.setParam(1262, '030')
230
+ self.fptr.setParam(1263, '21.11.2023')
231
+ self.fptr.setParam(1264, '1944')
232
+ self.fptr.setParam(1265, product_code_check)
233
+ self.fptr.utilFormTlv()
234
+ industry_info = self.fptr.getParamByteArray(IFptr.LIBFPTR_PARAM_TAG_VALUE)
235
+ self.fptr.setParam(1260, industry_info)
236
+ self.fptr.setParam(1212, 33)
237
+
238
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_COMMODITY_NAME, product_name)
239
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_PRICE, product_price)
240
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_QUANTITY, product_quantity)
241
+ # Для запроса суммы налога за чек необходимо вызвать метод queryData() с типом запроса LIBFPTR_PARAM_DATA_TYPE
242
+ # равным LIBFPTR_DT_RECEIPT_TAX_SUM и указать тип налога LIBFPTR_PARAM_TAX_TYPE.
243
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_TAX_TYPE, IFptr.LIBFPTR_TAX_VAT22)
244
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT, validation_result)
245
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE, product_nomenclature_code)
246
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_CODE_STATUS, 2)
247
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0)
248
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MEASUREMENT_UNIT, IFptr.LIBFPTR_IU_PIECE)
249
+ else:
250
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_MEASUREMENT_UNIT, IFptr.LIBFPTR_IU_PIECE)
251
+ self.fptr.setParam(1212, 1)
252
+
253
+ if product_disc_sum > 0:
254
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_INFO_DISCOUNT_SUM, product_disc_sum)
255
+
256
+ if self.fptr.registration() < 0:
257
+ self.core._error_log()
258
+ else:
259
+ status = True
260
+
261
+ return status
262
+
263
+ def receipt_payment(self, money_position):
264
+ """
265
+ Регистрация оплаты
266
+
267
+ Способ расчета (LIBFPTR_PARAM_PAYMENT_TYPE) может принимать следующие значения:
268
+ LIBFPTR_PT_CASH - наличными
269
+ LIBFPTR_PT_ELECTRONICALLY - безналичными
270
+ LIBFPTR_PT_PREPAID - предварительная оплата (аванс)
271
+ LIBFPTR_PT_CREDIT - последующая оплата (кредит)
272
+ LIBFPTR_PT_OTHER - иная форма оплаты (встречное предоставление)
273
+ LIBFPTR_PT_6 - способ расчета №6
274
+ LIBFPTR_PT_7 - способ расчета №7
275
+ LIBFPTR_PT_8 - способ расчета №8
276
+ LIBFPTR_PT_9 - способ расчета №9
277
+ LIBFPTR_PT_10 - способ расчета №10
278
+
279
+ Пример:
280
+ "moneyPositions": {
281
+ "paymentType": "CARD",
282
+ "sum": 46.8
283
+ }
284
+
285
+ :return: status
286
+ :rtype: bool
287
+ """
288
+ status = False
289
+
290
+ sum = money_position.get("sum")
291
+
292
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_PAYMENT_TYPE, IFptr.LIBFPTR_PT_ELECTRONICALLY)
293
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_PAYMENT_SUM, sum)
294
+
295
+ if self.fptr.payment() < 0:
296
+ self.core._error_log()
297
+ else:
298
+ status = True
299
+
300
+ return status
301
+
302
+ def receipt_total(self, money_position):
303
+ """
304
+ Регистрация итога на чек
305
+
306
+ "moneyPositions":[
307
+ {
308
+ "paymentType":"CARD",
309
+ "sum":6990
310
+ }
311
+ ]
312
+
313
+ :return: status
314
+ :rtype: bool
315
+ """
316
+ status = False
317
+
318
+ sum = money_position.get("sum")
319
+
320
+ self.fptr.setParam(IFptr.LIBFPTR_PARAM_SUM, sum)
321
+
322
+ if self.fptr.receiptTotal() < 0:
323
+ self.core._error_log()
324
+ else:
325
+ status = True
326
+
327
+ return status
328
+
329
+ def receipt_close(self):
330
+ """
331
+ Закрытие чека
332
+ :return: status
333
+ :rtype: bool
334
+ """
335
+ status = False
336
+
337
+ if self.fptr.closeReceipt() < 0:
338
+ self.core._error_log()
339
+ else:
340
+ status = True
341
+
342
+ return status
ORD/ord_setting.py ADDED
@@ -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()
ORD/ord_shift.py ADDED
@@ -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()
ORD/test/ORD_test.py ADDED
@@ -0,0 +1,12 @@
1
+ import unittest
2
+ import ORD
3
+
4
+
5
+ class TestCash(unittest.TestCase):
6
+ def test_connect(self):
7
+ cash = ORD()
8
+ self.assertTrue(cash.open_connect())
9
+
10
+
11
+ if __name__ == '__main__':
12
+ unittest.main()
ORD/test/__init__.py ADDED
File without changes
@@ -0,0 +1,17 @@
1
+ Metadata-Version: 2.4
2
+ Name: ORD
3
+ Version: 1.8.13
4
+ Summary: Module for working with the ATOL cash register driver
5
+ Home-page: https://github.com/brandshopru
6
+ Author: Vladimir Smirnov
7
+ Author-email: volodya@brandshop.ru
8
+ Description-Content-Type: text/markdown
9
+ Dynamic: author
10
+ Dynamic: author-email
11
+ Dynamic: description
12
+ Dynamic: description-content-type
13
+ Dynamic: home-page
14
+ Dynamic: summary
15
+
16
+ Модуль для работы с драйвером кассы АТОЛ
17
+ ===========
@@ -0,0 +1,13 @@
1
+ ORD/__init__.py,sha256=hr4slw4ghZ11wmJnxZ1Pq8aWBQWumqzeu6iNYudVJxE,172
2
+ ORD/ord_cash.py,sha256=liZc_QUgFvysPXkbX6Pc_87be0LFYPuZe3wBYJ90pDw,6468
3
+ ORD/ord_core.py,sha256=uWwV1wQf178i6UxdHGCyD4c2D8qn8m6sOoU51VX23RE,8497
4
+ ORD/ord_fn.py,sha256=NoKB2CITV_r15KSsv69zYH91mjQY7o97XdwcvLQfaj0,12771
5
+ ORD/ord_receipt.py,sha256=6YTN1lRcFUfKgyYaT0kc9gwKdEH7BpEpmqcS75COtLE,14066
6
+ ORD/ord_setting.py,sha256=i4q3G8olOIx14IMGiT8TGfGdhS2YKiTPP9ropohcV5k,2228
7
+ ORD/ord_shift.py,sha256=AIz-y0oilkgtCXM2q8TOFoIspvP3CCoqHBoL7Gzwdlg,2427
8
+ ORD/test/ORD_test.py,sha256=Ak6cKbfcBr4Dss3bySNfSBoLHZzPtHwe1CVFFoUF0KM,207
9
+ ORD/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ ord-1.8.13.dist-info/METADATA,sha256=G6MQoEJvOg_ISQX_wfEOkkhOG9iVFyg9exRjrAhR90A,470
11
+ ord-1.8.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ ord-1.8.13.dist-info/top_level.txt,sha256=8n708F8RT49tSXTCLyLkv9Pjh79msvpquJ5RQKK3gb4,4
13
+ ord-1.8.13.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ ORD