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.
@@ -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
@@ -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()
@@ -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()
@@ -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()
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
+ 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
@@ -0,0 +1,2 @@
1
+ Модуль для работы с драйвером кассы АТОЛ
2
+ ===========
ORD-1.7.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
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
+ )