def begin(self, host_datetime=datetime.now()): """ Начало работы с кассой :param host_datetime: Время управляющего компьютера """ query = Output(0x10) query.add_param(host_datetime) self.send(query)
def send_command(self, code) -> Input: """ Отправляет команду с заданным кодом на сервер :param code: код команды :return: """ return self.send(Output(code))
def print_text(self, text: str, font: FontAttribute): """ C помощью данной команды печатается текст внутри открытого сервисного документа :param text: Текст :param font: Атрибуты текста """ self.send(Output(0x40).add_param(text).add_param(str(font)))
def sound(self, duration: int): """ Команда подает звуковой сигнал заданной длительности :param duration: длительность в мс (10..2000) """ if duration < 10 or duration > 2000: raise Exception("Неверное значение длительности сигнала") self.send(Output(0x82).add_param(duration))
def send(self, packet: Output) -> Input: if not self.check_link(): raise Exception("Нет связи!") data = packet.get_bytes(self.__pasword, 0x30) #print(" ".join("%02X" % x for x in data)) self.port.write(data) result = Input(self.port) if result.error: raise Exception(result.error) return result
def postpone_doc(self, cause: str): """ Эта команда работает аналогично команде “Аннулировать документ”, но подается в случаях, когда документ отменяется не навсегда, а будет обязательно повторно введен, в течении данной смены. Данные документа удаляются из оперативной памяти ККТ и печатается причина отказа от чека. Используя параметры печати отчета о закрытии смены в “Таблица настроек ККТ”, можно настроить в отчете о закрытии печать информации по отложенным за смену чекам. При этом, если команда "Отложить чек" выполняется без параметра (пустая строка), то такие чеки учитываются в отчете о закрытии, если с параметром – не учитываются. :param cause: Причина отказа от чека (Длина 40 символов) """ if len(cause) > 40: raise Exception("Неверная длина причины отказа") self.send(Output(0x33).add_param(cause))
def print_barcode(self, out: BarcodeOut, width, height, view: BarcodeView, text): """ С помощью данной команды можно распечатать штрих-код товара. Заметка: EAN-13 у меня печатаеться только с шириной 2 или 3 О_о :param out: Заголовок :param width: Ширина штрих-кода - значение задается в точках и может быть от 2 до 8 :param height: Высота штрих-кода - значение задается в точках и может принимать значения от 1 до 255 :param view: Тип штрих-кода - Определяет, какой штрих-код будет напечатан :param text: Штрих-код- строка содержащая штрих-код """ if self.status.current.no_begin: raise Exception("Вызовите начало работы!") self.send( Output(0x41).add_param(out.value).add_param(str(width)).add_param( str(height)).add_param(view.value).add_param(text))
def doc_payment(self, code_payment: int, total: float, text: str = ""): """ С помощью этой команды производится фиксирование всех взаиморасчетов с клиентом с указанием сумм и типов оплаты. При первом использовании этой команды в чеке печатается «Итоговая сумма», что является окончательной суммой чека. При передаче суммы наличными, больше требуемой, ККТ самостоятельно рассчитывает сдачу. Сумма по безналичным типам платежа (с кодами от 1 до 15), не должна превышать итоговой суммы по чеку. Код типа платежа должен соответствовать одному из запрограммированных средств оплаты в “Таблице настроек ККТ”. :param code_payment: код типа платежа (0..15) из настроек кассы обычно 0 - наличными, 1-электронными :param total: сумма, принятая от покупателя по данному платежу :param text: дополнительный текст (пока не знаю зачем) """ if code_payment < 0 or code_payment > 15: raise Exception("Неверный код типа платежа!") self.send( Output(0x47).add_param(str(code_payment)).add_param( "%0.3f" % total).add_param(text))
def report_x(self): """Сформировать отчет без гашения (X-отчет)""" self.send(Output(0x20).add_param(self.operator))
def datetime_last_operation(self) -> datetime: """Вернуть дату и время последней фискальной операции""" return self.kkt.send(Output(0x02).add_param("5")).to_datetime(1, 2)
def cancel_doc(self): """ Эта команда прерывает формирование текущего документа, данные удаляются из оперативной памяти ККТ и печатается сообщение об аннулировании """ self.send(Output(0x32))
def number_shift(self) -> int: """Вернуть номер смены регистрации""" return self.kkt.send(Output(0x02).add_param("9")).to_int(1)
def exchange_status(self) -> FNOFDStatus: """Вернуть состояние обмена с ОФД""" packet = self.kkt.send(Output(0x78).add_param('7')) print(packet) return FNOFDStatus(packet.to_int(1), packet.to_string(2), packet.to_string(3), packet.to_datetime(4, 5))
def get_inn(self): """ Возвращает ИНН организации :return: строка с номером ИНН """ return self.__machine.send(Output(0x02).add_param(0x33)).to_string(1)
def datetime_last_registration(self) -> datetime: """Вернуть дату регистрации / перерегистрации""" return self.kkt.send(Output(0x02).add_param("6")).to_date(1)
def add_item(self, title: str, article: str, count: float, price: float, number_tax: int, payment_type: PaymentType, subject_matter: SubjectMatter, discount_total: float = 0, number_item: str = "", number_departament: int = 0, code_country: str = None, number_customs: str = None, excise_total: float = None): """ Добавить товарную позицию Эта команда может быть вызвана сразу после открытия чека и может повторяться любое количество раз (если признак способа расчета не равен 7) внутри текущего документа для отражения всего списка товаров. Если позиция не может быть добавлена в ФН, на чеке после данных о позиции печатается строка “ОПЕРАЦИЯ ОТМЕНЕНА” и возвращается соответствующий код ошибки ФН. Для повышения точности вычислений, можно передавать количество с точностью до 9 знаков после запятой, при этом в умножении на цену будет участвовать 9 знаков после запятой, а печататься только первые 3. Сумма позиции, получаемая в результате умножения цены на количество, округляется к ближайшему целому, т.е. часть менее 0.5 коп отбрасывается, 0.5 коп и более округляется до 1 коп. Параметры ”Номер товарной позиции” и “Номер секции” не являются обязательными и могут отсутствовать. Если номер секции отсутствует (или равен нулю), учет ведется на номер отдела, указанный при открытии документа. Номер позиции - символьное поле, состоящее из цифр и символа разделителя, которым может быть пробел, двоеточие, тире и другие символы. В связи с требованиями ФФД поле "Название товара" при длине, большей 128 символов, будет обрезано до 128 символов. :param title: название товара(0..224) :param article: артикул или штриховой код товара/номер ТРК :param count: количество товара в товарной позиции :param price: цена товара по данному артикулу :param number_tax: номер ставки налога (Номер налога в регистре кассы обычно (1-20%, 2-10%, 3-Без НДС или 0%)) :param number_item: номер товарной позиции :param number_departament: номер секции :param discount_total: сумма скидки :param payment_type: признак способа расчета :param subject_matter: признак предмета расчета :param code_country: код страны происхождения товара (номер) :param number_customs: номер таможенной декларации :param excise_total: сумма акциза :return: """ query = Output(0x42) query.add_param(title) query.add_param(article) query.add_param("%0.3f" % count) query.add_param("%0.3f" % price) query.add_param(str(number_tax)) query.add_param(number_item) query.add_param(str(number_departament)) query.add_param("").add_param("") query.add_param("%0.3f" % discount_total) query.add_param(str(payment_type.value)) query.add_param(str(subject_matter.value)) # Насколько я понял нужны только для расчетов ЮР лиц if code_country: query.add_param(code_country) if number_customs: query.add_param(number_customs) if excise_total: query.add_param(excise_total) self.send(query)
def number_next_x_report(self) -> int: """Вернуть номер следующего X отчета""" return self.kkt.send(Output(0x02).add_param("10")).to_int(1)
def datetime(self, value: datetime): """Эта команда позволяет устанавливать новые время и дату ККТ, при условии закрытой смены""" str_date = value.strftime("%d%m%y") str_time = value.strftime("%H%M%S") self.send(Output(0x14).add_param(str_date).add_param(str_time))
def cashbox_total(self) -> str: """Вернуть сумму наличных в денежном ящике""" # TODO Float!! return self.kkt.send(Output(0x02).add_param("7")).to_string(1)
def status(self) -> KKTStatus: """Команда возвращает статус фатального состояния ККТ, статус текущих флагов ККТ и статус документа""" packet = self.send(Output(0x00)) return KKTStatus(packet.to_int(0), packet.to_int(1), packet.to_int(2))
def close_shift(self): """Сформировать отчет о закрытии смены""" # TODO Параметр (Целое число) Опции отчета в документации ничего=( self.send(Output(0x21).add_param(self.operator).add_param("0"))
def open_shift(self): """Открыть смену""" self.send(Output(0x23).add_param(self.operator))
def current_counter(self) -> str: """Вернуть текущий операционный счетчик""" return self.kkt.send(Output(0x02).add_param("11")).to_string(1)
def open_doc(self, doc_type: DocumentType, mode_bulk: bool = False, mode_delay: bool = False, departament: int = 0, number: int = 0): """ Открыть документ В пакетном режиме формирования документа, при успешном выполнении команд формирования чека - (Не реализовано) Установить дополнительные реквизиты позиции - print_text: Печать текста - print_barcode: Печатать штрих-код - add_item: Добавить товарную позицию - doc_subtotal: Подытог - Скидка на чек - doc_payment: Оплата - Внесение / изъятие суммы - Печать реквизита - Сравнить сумму по чеку , ответ на команду не посылается. Если какая-либо команда выполняется с ошибкой, то на нее возвращается стандартный ответ с кодом ошибки. Последующие команды формирования чека игнорируются, на каждую такую комадну возвращается стандартный ответ с кодом ошибки "Функция невыполнима при данном статусе ККТ" до поступления команд “Завершить документ” или “Аннулировать документ”. При возникновении ошибки в процессе наполнения документа в пакетном режиме необходимо аннулировать документ и полностью сформировать документ заново, начиная с команды "Открыть документ". :param doc_type: Тип документа :param mode_bulk: Пакетный режим формирования документа :param mode_delay: Режим отложенной печати реквизитов :param departament: Номер отдела (1-99) :param number: Номер документа """ param = doc_type.value if mode_bulk: param = param & 1 << 4 if mode_delay: param = param & 1 << 5 query = Output(0x30) query.add_param(str(param)) query.add_param(str(departament)) query.add_param(self.operator) if number == 0 and self.settings.cheque.external_counter: raise Exception( "Настроена внешняя нумерация чеков, необходимо передавать номер документа!" ) query.add_param(str(number)) query.add_param(self.tax_system) self.send(query)
def transition_nds(self) -> bool: """Вернуть состояние перехода на НДС 20%""" return self.kkt.send(Output(0x02).add_param("40")).to_bool(1)
def number_next_document(self) -> int: """Вернуть номер следующего документа""" return self.kkt.send(Output(0x02).add_param("8")).to_int(1)
def get_manufacture_number(self): """ Возвращает заводской номер :return: строка с заводским номером """ return self.__machine.send(Output(0x02).add_param(0x31)).to_string(1)
def close_doc(self, cut: CutFlag, sign_internet_payment: bool = None, address: str = None, title: str = None, value: str = None, buyer: str = None, buyer_inn: str = None) -> CloseDocData: """ Завершить документ Фискальный признак возвращается только при завершении чеков на приход, возврат прихода, расход и возврат расхода. В пакетном режиме формирования документа, команда “Завершить документ” выключает пакетный режим. Если в пакетном режиме ошибка возникла ранее команды “Завершить документ”, то ответ команду “Завершить документ” не возвращается. Можно продолжить формирование документа, начиная с команды вернувшей ошибку, обычном режиме. :param cut: флаг отрезки документов :param sign_internet_payment: установить признак расчетов в интернет :param address: адрес покупателя # TODO Email? :param title: название дополнительного реквизита пользователя :param value: значение дополнительного реквизита пользователя :param buyer: покупатель :param buyer_inn: ИНН покупателя :return: """ query = Output(0x31) query.add_param(cut) if address: query.add_param(address) if sign_internet_payment: query.add_param(sign_internet_payment) if title: query.add_param(title) if value: query.add_param(value) if buyer: query.add_param(buyer) if buyer_inn: query.add_param(buyer_inn) packet = self.send(query) return CloseDocData(packet)
def work_firmware_id(self) -> str: """Вернуть рабочий идентификатор прошивки""" return self.kkt.send(Output(0x02).add_param("70")).to_string(1)
def shift_status(self) -> FNShiftStatus: """Вернуть состояние текущей смены""" packet = self.kkt.send(Output(0x78).add_param('6')) return FNShiftStatus(packet.to_string(1), packet.to_bool(2), packet.to_string(3))