# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os import logging from datetime import datetime from decimal import Decimal from .printing.protocols import FileSSH try: from escpos import printer except ImportError as error: logging.warning(f"Error importing ! {error}") pyudev = None try: import pyudev except ImportError as error: logging.warning(f"Error importing ! {error}") try: import cups except ImportError as error: logging.warning(f"Error importing ! {error}") __all__ = ['Receipt'] _ROW_CHARACTERS = 48 _DIGITS = 9 _PRINT_TAX_ID = False _DIGITS_CODE_RECEIPT = 4 # Type Font Escpos _FONT_A = 'a' # Normal Font _FONT_B = 'b' # Condensed Font if os.name == 'posix': homex = 'HOME' dirconfig = '.tryton/temp' elif os.name == 'nt': homex = 'USERPROFILE' dirconfig = 'AppData/Local/tryton/temp' HOME_DIR = os.getenv(homex) directory = os.path.join(HOME_DIR, dirconfig) ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) image_test_file = os.path.join(ROOT_DIR, 'image_test.jpeg') if not os.path.exists(directory): os.makedirs(directory) TEMP_INVOICE_FILE = os.path.join(directory, 'invoice.txt') SSH_PORT = 23 def money(value): if type(value) != int: value = int(value) return '{:,}'.format(value) dev_printers = {} if os.name == 'posix' and pyudev: context = pyudev.Context() for device in context.list_devices(): if device.subsystem == 'usbmisc': # print(device.subsystem, device.sys_path.split('2-1/')[1][0:5], device.device_node) # dev_printers[str(device.sys_path.split('2-1/')[1][0:5])] = device.device_node pass class Receipt(object): __name__ = 'frontend_pos.ticket' def __init__(self, context, row_characters=None, logo=None, environment='retail'): self.logger = logging.getLogger('reporting') self._company = context.get('company') self._sale_device = context.get('sale_device') self._shop = context.get('shop') self._street = context.get('street') self._city = context.get('city') self._phone = context.get('phone') self._id_number = context.get('id_number') self._regime_tax = context.get('regime_tax') self._gta_info = context.get('gta_info') self._authorizations = context.get('authorizations') self._user = context.get('user') self._footer = context.get('footer') self._header = context.get('header') self._printing_taxes = context.get('printing_taxes') self._print_invoice_payment = context.get('print_invoice_payment') self._delta_locale = context.get('delta_locale') self._environment = environment self._row_characters = _ROW_CHARACTERS if context.get('row_characters'): self._row_characters = int(context.get('row_characters')) taxes_col = int(self._row_characters / 3) self.taxes_col_width1 = taxes_col + 4 self.taxes_col_width2 = taxes_col - 3 self.taxes_col_width3 = taxes_col - 1 delivery_col = int(self._row_characters / 3) self.delivery_col_width1 = delivery_col self.delivery_col_width2 = delivery_col - 1 self.delivery_col_width3 = delivery_col - 1 payments_col = int(self._row_characters / 3) self.payments_col_width1 = payments_col + 3 self.payments_col_width2 = payments_col - 2 self.payments_col_width3 = payments_col order_col_width = int(self._row_characters / 3) self.order_col_1 = order_col_width - 10 self.order_col_2 = order_col_width + 15 self.order_col_3 = order_col_width - 5 if self._row_characters <= 33: self.order_col_1 = order_col_width - 6 self._show_position = context.get('show_position') self._show_discount = context.get('show_discount') self._print_lines_product = context.get('print_lines_product') self._img_logo = logo if logo else None # if logo: # self._img_logo = StringIO(logo) def printer_found(self): return self._printer def test_printer(self): if self._interface == 'usb': if os.name == 'posix': self._printer = printer.File( self._device, profile=self._profile) elif os.name == 'nt': self._printer = printer.Win32Raw(self._device) self._printer.open() elif self._interface == 'network': self._printer = printer.Network(self._device, timeout=15) elif self._interface == 'ssh': self._printer = FileSSH(*self._device.split('@')) self._printer.open() if not self._printer: return self.print_enter() try: self._printer.image(image_test_file, center=True) except: pass self.print_enter() self.print_header() self.print_enter() self.print_enter() self.print_enter() self._printer.cut() self._printer.cashdraw(2) # self._printer.beep() def config_printer(self, printer): if dev_printers.get(printer['device']): device = dev_printers[printer['device']] else: device = printer['device'] self._interface = printer['interface'] self._device = device self._profile = printer['profile'] def set_printer(self): try: if self._interface == 'usb': if os.name == 'posix': self._printer = printer.File( self._device, profile=self._profile) elif os.name == 'nt': self._printer = printer.Win32Raw(self._device) self._printer.open() elif self._interface == 'network': self._printer = printer.Network(self._device, timeout=15) elif self._interface == 'ssh': self._printer = FileSSH(*self._device.split('@')) self._printer.open() elif self._interface == 'cups': self.conn = cups.Connection() self._file = open(TEMP_INVOICE_FILE, 'w') self._printer = CupsPrinter(self._file, self._row_characters) if not self._printer: self.logger.info("Warning: Can not found Printer!") return self.logger.info("Info: Printer is OK!") except: self.logger.info("Warning: Printer error or device not found!") def print_sale(self, sale, type_doc=None, open_box=False): try: if self._interface == 'usb': if os.name == 'posix': self._printer = printer.File( self._device, profile=self._profile) elif os.name == 'nt': self._printer = printer.Win32Raw(self._device) self._printer.open() elif self._interface == 'network': self._printer = printer.Network(self._device, timeout=15) elif self._interface == 'ssh': self._printer = FileSSH(*self._device.split('@')) self._printer.open() elif self._interface == 'cups': self.conn = cups.Connection() self._file = open(TEMP_INVOICE_FILE, 'w') self._printer = CupsPrinter(self._file, self._row_characters) if not self._printer: self.logger.info("Warning: Can not found Printer!") return self.logger.info("Info: Printer is OK!") if type_doc == 'invoice' or self._environment == 'retail': self._print_sale(sale, type_doc, open_box) else: self._print_sale_verification(sale) except: self.logger.info("Warning: Printer error or device not found!") def _print_sale(self, sale, type_doc=None, open_box=False): self.print_header() self.print_body(sale, type_doc) if sale.get('cufe'): self._printer.text('CUFE: ' + sale['cufe']) try: if sale.get('qr_code'): self.print_qrcode(sale['qr_code']) except: pass self.print_footer(open_box) # self.print_extra_info(sale) if self._interface == 'cups': self._file.close() self.conn.printFile(self._printer_name, TEMP_INVOICE_FILE, 'POS Invoice', {}) else: self._printer.close() def _print_sale_verification(self, sale): self.print_header_sale_verification(sale) self.print_sale_lines(sale) self.print_totals(sale) self.print_enter() self.print_enter() self.print_enter() self._printer.cut() self.print_enter() self.print_enter() self._printer.close() def print_line(self, *args): text = '' for arg in args: text += arg + ' ' self._printer.text(text.rstrip()) def word_space(self, word, space, aling): space = space - len(word) if aling == 'right': text = ' ' * space + word elif aling == 'left': text = word + ' ' * space return text def print_delivery_report(self, data): self.set_printer() self._printer.set(align='center') self._printer.text('REPORTE DE ENTREGA DE DOMICILIARIOS') self.print_enter() self.print_enter() self.print_horinzontal_line() self._printer.set(align='left') name = data['name'] sale_date = data['sale_date'] self._printer.text(f'DOMICILIARIO: {name}') self.print_enter() self._printer.text(f'FECHA: {sale_date}') self.print_enter() self.print_horinzontal_line() self.print_enter() for sale in data['sales']: sale_total = self.word_space(money(sale['total']), 9, 'right') sale_number = self.word_space(sale['number'], 9, 'left') address = sale['consumer_address'] character_address = self._row_characters - 20 if len(address) > character_address: address = address[:character_address] address = self.word_space(address, character_address, 'left') self.print_line(sale_number, address, sale_total) self.print_enter() self.print_enter() total = money(data['total']) self._printer.text(f'TOTAL: {total}') self.print_enter() self._printer.cut() self.print_enter() self.print_enter() self._printer.close() def print_count_money(self, data): self.set_printer() self._printer.set(align='center') self.print_enter() self._printer.text('REPORTE DE DINERO EN CAJA') self.print_enter() self.print_enter() self.print_horinzontal_line() self._printer.set(align='left') type_ = data['type'] self._printer.text(f'TIPO: {type_}') self.print_enter() now = datetime.now() print_date = now.strftime("%Y-%m-%d %H:%M %p") self._printer.text(f'FECHA / HORA: {print_date}') self.print_enter() self.print_horinzontal_line() self.print_enter() self.print_col('Moneda', self.taxes_col_width1) self.print_col('Cant.', self.taxes_col_width2) self.print_col('Subtotal', self.taxes_col_width3) self.print_enter() for line in data['lines']: self.print_col(str(line[0]), self.taxes_col_width1) self.print_col(str(line[1]), self.taxes_col_width2) self.print_col(str(line[2]), self.taxes_col_width3) self.print_enter() self.print_enter() self._printer.set(custom_size=True, width=2, height=2, align='center') _total = data['total'] self._printer.text(f'TOTAL: {_total}') self.print_enter() self._printer.cut() self.print_enter() self.print_enter() self._printer.close() def print_header_sale_verification(self, sale): title = 'VERIFICACION DE CUENTA' msg = """ESTIMADO CLIENTE UNA VEZ REALICE EL \n PAGO DE LA CUENTA POR \n FAVOR EXIJA SU RESPECTIVA FACTURA""" self.print_enter() self.print_enter() self._printer.set(custom_size=True, width=2, height=2, align='center') self._printer.text(title) self.print_enter() self.print_horinzontal_line('big') self.print_enter() self.print_enter() self._printer.set(align='center') self._printer.text(msg) self.print_enter() self._printer.set(align='left') self.print_enter() self.print_enter() create_date = sale.get('create_date') if create_date: self._printer.text(f'FECHA: {create_date}') self.print_enter() salesman = sale.get('salesman') if salesman: self._printer.text(f'VENDEDOR: {salesman}') self.print_enter() comment = sale.get('comment') if comment: self._printer.text(f'NOTAS: {comment}') self.print_enter() table_assigned = sale.get('table_assigned') if table_assigned: self._printer.text(f'MESA: {table_assigned}') self.print_enter() position = sale.get('position') if position: self._printer.text(f'POSICION: {position}') self.print_enter() self.print_enter() def print_logo(self): try: self._printer.set(align='center') self._printer.image(self._img_logo, center=True) self.print_enter() except: pass def print_qrcode(self, qrcode): self._printer.qr(qrcode, center=True, size=5) self.print_enter() def print_header(self): if self._img_logo: self.print_logo() self._printer.set(align='center') if self._header != '' and self._header is not None: self._printer.text(self._header) self.print_enter() self._printer.text(self._company) self.print_enter() self._printer.text(self._shop) self.print_enter() if self._id_number: self._printer.text('NIT:' + self._id_number) if self._regime_tax: self._printer.text(' ' + self._regime_tax) self.print_enter() if self._street: self._printer.text(self._street) self.print_enter() if self._city: self._printer.text(self._city) if self._phone: if self._city: self._printer.text(' ') self._printer.text('Telefono:' + self._phone) if self._city or self._phone: self.print_enter() self.print_enter() self.print_enter() def print_horinzontal_line(self, size=None): if size == 'big': row_characters = '-' * int(self._row_characters / 2) else: row_characters = '-' * self._row_characters self._printer.text(row_characters) self.print_enter() def print_horinzontal_double_line(self): self._printer.text('=' * self._row_characters) def print_enter(self): self._printer.text('\n') def print_split(self, left, right): len_left = self._row_characters - len(right) - 1 left = left[:len_left] if type(left) == bytes: left = left.decode("utf-8") if type(right) == bytes: right = right.decode("utf-8") left += (len_left - len(left) + 1) * ' ' self._printer.text(left) self._printer.text(right + '\n') def print_sale_lines(self, sale): self.print_enter() self.print_horinzontal_line() self.print_split(' Articulo ', 'Subtotal ') self.print_horinzontal_line() len_row = self._row_characters - \ (_DIGITS_CODE_RECEIPT + 1) - (_DIGITS + 1) for line in sale['lines']: if line['taxes'] and _PRINT_TAX_ID: tax_id = ' ' + str(line['taxes'][0].id) else: tax_id = '' line_total = money(line['amount_w_tax']) + tax_id discount = line.get('discount') if self._show_discount and discount and Decimal(discount) > 0: amount_w_tax = Decimal(line['amount_w_tax']) discount = Decimal(discount) initial = 'DCTO - ' + str(round(discount*100, 0)) + '%' if discount == 1: line_total = 0 else: line_total = amount_w_tax/(1-discount) discount = '-' + money(line_total - amount_w_tax) line_total = money(line_total) code = line['code'] or ' ' if line['quantity'] != 1: length_name = self._row_characters - 11 first_line = code + ' ' + line['name'][:length_name] if type(first_line) == bytes: first_line = first_line.decode('utf-8') self._printer.text(first_line + '\n') unit_price_w_tax = str(round(line['unit_price_w_tax'], 2)) second_line = ' %s x %s' % ( line['quantity'], unit_price_w_tax) second_line = second_line.encode('utf-8') self.print_split(second_line, line_total) if self._show_discount and discount: self.print_split(initial, str(discount)) else: if self._environment == 'retail': line_pt = code + ' ' + line['name'][:len_row] else: line_pt = line['name'][:len_row] self.print_split(line_pt, line_total) if line['discount'] and Decimal(line['discount']) and self._show_discount: self.print_split(initial, discount) def print_totals(self, sale): untaxed_amount = sale['untaxed_amount'] total_amount = sale['total_amount'] self.print_split('', '----------------') self.print_split('Subtotal Base:', money(untaxed_amount)) self.print_split('Impuesto:', money(sale['tax_amount'])) self.print_split('', '----------------') self.print_split('Total:', money(total_amount)) self.print_enter() net_amount = sale['total_amount'] delivery_amount = sale.get('delivery_amount', 0) if delivery_amount and delivery_amount > 0: net_amount = net_amount + delivery_amount tip_amount = sale.get('tip_amount', 0) if tip_amount and tip_amount > 0: net_amount = net_amount + tip_amount if tip_amount: self.print_split('Propina:', money(tip_amount)) if delivery_amount: self.print_split('Domicilio:', money(delivery_amount)) if tip_amount or delivery_amount: self.print_split('Valor Neto:', money(net_amount)) # if self._show_discount: # self.print_split('Descuento:', money(sale['discount'])) self.print_enter() if sale['cash_received']: self.print_split('Recibido:', money(sale['cash_received'])) else: pass change = sale['change'] if sale['cash_received'] < net_amount: msg_residual = 'Pendiente:' else: msg_residual = 'Cambio:' self.print_split(msg_residual, money(change)) self.print_enter() order = sale.get('order') if order: self._printer.text(f'CODIGO: {order}') self.print_enter() def _print_info_consumer(self, sale): consumer = sale.get('consumer', None) if consumer: payment_method = sale.get('payment_method', None) consumer_name = consumer.get('consumer_name', None) consumer_address = consumer.get('consumer_address', '') consumer_phone = consumer.get('consumer_phone', '') self.print_horinzontal_line() self.print_enter() self._printer.set(align='center') self._printer.text('========== INFO CONSUMIDOR ==========') self.print_enter() self._printer.set(align='left') self._printer.text('NOMBRE: %s' % consumer_name) self.print_enter() self._printer.text('DIRECCION: %s' % consumer_address) self.print_enter() self._printer.text('TELEFONO: %s' % consumer_phone) self.print_enter() if payment_method and payment_method == 'terminal': payment_method = '- PAGA CON DATAFONO' elif payment_method and payment_method == 'all_paid': payment_method = '- TODO PAGO' elif payment_method and payment_method == 'partial_paid': payment_method = '- PAGO PARCIAL' else: payment_method = '- PAGA EN EFECTIVO' self._printer.text(f'MEDIO DE PAGO: {payment_method}') self.print_enter() self.print_enter() delivery_amount = money(sale.get('delivery_amount', 0)) self._printer.text(f'Domicilio: {delivery_amount}') self.print_enter() self.print_enter() def print_body(self, sale, type_doc='invoice'): self._printer.set(font=_FONT_B) kind_string = sale.get('kind_string', None) if type_doc != 'invoice' and kind_string and self._environment != 'retail': self._printer.set(custom_size=True, width=2, height=2, align='center') kind = f'- - - {kind_string} - - -' self._printer.text(kind) self.print_enter() self.print_enter() self._printer.set(custom_size=False) self._printer.set(align='left') if type_doc == 'invoice': if sale['number']: if sale['total_amount'] >= 0: self._printer.text( 'FACTURA DE VENTA No. ' + sale['number']) else: self._printer.text('NOTA CREDITO No. ' + sale['number']) elif type_doc in ['order', 'delivery']: self._printer.text('PEDIDO: ' + sale['order']) self.print_enter() self._printer.text('Fecha:%s' % sale['date']) if sale.get('invoice_time'): self._printer.text(' Hora:%s' % sale['invoice_time']) self.print_enter() if sale.get('turn') and sale['turn'] != 0: self._printer.text('Turno: %s - ' % str(sale['turn'])) self.print_enter() self.print_horinzontal_line() party_name = 'Cliente: %s ' % sale['party'] party_id_number = 'Id: %s' % sale.get('party_id_number', '') if len(party_name + party_id_number) > self._row_characters: self._printer.text(party_name) self.print_enter() self._printer.text(party_id_number) else: self._printer.text(party_name + party_id_number) if sale.get('party_address'): self.print_enter() self._printer.text('Direccion: %s' % sale['party_address']) if sale.get('party_phone'): self.print_enter() self._printer.text('Telefono: %s' % sale['party_phone']) if sale.get('payment_term'): self.print_enter() self._printer.text('Forma de Pago: %s' % sale['payment_term']) self.print_enter() self._print_info_consumer(sale) self.print_sale_lines(sale) self.print_totals(sale) self.print_horinzontal_line() self.print_enter() self._printer.set(align='left') self._printer.text('DETALLE DE IMPUESTOS') self.print_enter() if self._printing_taxes: self.print_col('Tipo', self.taxes_col_width1) self.print_col('Base', self.taxes_col_width2) self.print_col('Imp.', self.taxes_col_width3) self.print_enter() taxes = sale['taxes'] for tax in taxes: self.print_col(str(taxes[tax]['name']) + ' ', self.taxes_col_width1) self.print_col( str(int(taxes[tax]['base'])), self.taxes_col_width2) self.print_col( str(int(taxes[tax]['tax'])), self.taxes_col_width3) self.print_enter() self.print_enter() self.print_horinzontal_line() if sale.get('payments'): self.print_enter() self.print_col('MEDIO PAGO', self.payments_col_width1) self.print_col('# APROB', self.payments_col_width2) self.print_col('VALOR', self.payments_col_width3) self.print_enter() payments = sale['payments'] for p in payments: self.print_col(str(p['name']) + ' ', self.payments_col_width1) self.print_col(str(p['voucher']) + ' ', self.payments_col_width2) self.print_col(str(int(p['amount'])), self.payments_col_width3) self.print_enter() self.print_horinzontal_line() no_products = 'No ITEMS: %s' % str(sale['num_products']) self._printer.text(no_products) self.print_enter() comment = sale.get('comment') if comment: self.print_horinzontal_line() self.print_enter() self._printer.text(f'NOTAS: {comment}') self.print_enter() self.print_horinzontal_line() # if type_doc == 'invoice': # self._printer.text('No PEDIDO: ' + sale['order']) # self.print_enter() register = 'CAJA No. %s' % self._sale_device self._printer.text(register) self.print_enter() self._printer.text('CAJERO: %s' % self._user) self.print_enter() if sale.get('salesman'): self._printer.text('VENDEDOR: %s' % sale['salesman']) self.print_enter() if sale.get('channel'): self._printer.text('CANAL DE VENTA: %s' % sale['channel']) self.print_enter() if sale.get('delivery_party'): self._printer.text('DOMICILIARIO: %s' % sale['delivery_party']) self.print_enter() print(self._show_position, sale['position'], '*************') if self._show_position: self._printer.text('POSICION: %s' % str(sale['position'])) self.print_enter() self.print_horinzontal_line() auth_kind = sale.get('auth_kind', None) if auth_kind and sale['state'] not in ['draft']: auth_data = self._authorizations[auth_kind] self._printer.text(self.get_authorization(auth_data)) self.print_enter() elif self._gta_info and sale['state'] not in ['draft']: self._printer.text(self._gta_info) self.print_enter() self._printer.text('Fecha de creacion: %s' % sale["create_date"]) self.print_enter() self.print_enter() def print_extra_info(self, sale): if sale.get('pos_notes'): self.print_enter() self.print_header() self.print_horinzontal_line() self.print_enter() party_name = 'Cliente: %s ' % sale['party'] self._printer.text(party_name) self.print_enter() if self._show_position: self._printer.text('Posicion: %s' % str(sale['position'])) self.print_enter() if sale['state'] in ['draft']: self._printer.text('Cotizacion: ', sale['order']) else: self._printer.text('Factura No. ' + sale['number']) self.print_enter() self._printer.text(str(sale.get('pos_notes'))) self.print_enter() self.print_horinzontal_line() self.print_enter() self._printer.cut() def print_col(self, x, l): self._printer.text(x[:l] + (l - len(x)) * ' ') def print_footer(self, open_box=False): if self._footer: self._printer.text(self._footer) self.print_enter() self._printer.text('SOFTWARE TRYTON - www.presik.com') self.print_enter() self._printer.cut() if open_box: self._printer.cashdraw(2) self.print_enter() def print_orders(self, orders, reversion=None, kind='command'): res = [] self.order_kind = kind for order in orders.values(): try: if dev_printers.get(order['host']): host = dev_printers[order['host']] else: host = order['host'] if order['interface'] == 'usb': if os.name == 'posix': self._printer = printer.File(host) elif os.name == 'nt': self._printer = printer.Win32Raw(host) self._printer.open() elif order['interface'] == 'network': self._printer = printer.Network(host, timeout=15) elif order['interface'] == 'ssh': self._printer = FileSSH(*host.split('@')) if self._printer: self._printer.open() elif order['interface'] == 'cups': pass if not self._printer: self.logger.info( "Warning: Interface not found for printer!") res.append(None) continue self.logger.info("Info: Printer is OK!") res.append(self._print_order(order, reversion)) self._printer.close() except: self.logger.info("Warning: Can not found Printer!") res.append(None) return all(res) def _print_order(self, order, reversion): self.print_body_order(order, reversion) self._print_info_consumer(order) self._printer.cut() self._row_characters = order['row_characters'] return True def print_body_order(self, order, reversion): # Exists 2 types of order: # command => For restaurants kitchens # dispatch => For external dispatch self._printer.set(font=_FONT_B) self._printer.set(align='center') turn = order.get('turn') if turn: self._printer.text('TURNO: %s' % str(turn)) self.print_enter() self.print_enter() if self._environment != 'retail': kind = order.get('kind', 'delivery') if kind == 'take_away': _kind = 'PARA LLEVAR' elif kind == 'to_table': _kind = 'PARA MESA' else: _kind = 'DOMICILIO' self._printer.set(custom_size=True, width=2, height=2, align='center') title = f'+ + + {_kind} + + +' self._printer.text(title) self.print_enter() self._printer.set(custom_size=True, width=2, height=2, align='center') self.print_enter() self._printer.text(order['sale_number']) self.print_enter() self._printer.set(custom_size=False) self._printer.set(align='left') self.print_enter() date_ = datetime.now().strftime("%Y-%m-%d %H:%M %p") self._printer.text('FECHA: ' + date_) self.print_enter() table_assigned = order.get('table_assigned', None) if table_assigned: self.print_enter() self._printer.set(custom_size=True, width=2, height=2, align='center') self._printer.text('MESA: %s' % table_assigned) self.print_enter() self._printer.set(align='left') delivery_charge = order.get('delivery_charge', None) if self.order_kind == 'dispatch' and delivery_charge: self._printer.text('FACTURA: ' + order['number']) self.print_enter() _charge_to = 'Cliente' if delivery_charge == 'company': _charge_to = 'Empresa' self._printer.text('CARGO DEL DOMICILIO: ' + _charge_to) self.print_enter() if self.order_kind == 'dispatch': self._printer.text('FORMA DE PAGO: ' + order.get('payment_term', '')) self.print_enter() position = order.get('position') if position: self._printer.text('POSICION: %s' % str(position)) self.print_enter() self._printer.text('VENDEDOR: %s' % order['salesman']) self.print_enter() self._printer.text('SUCURSAL: %s' % order['shop']) self.print_enter() self._printer.text('CLIENTE: %s' % order['party']) self.print_enter() if self.order_kind == 'dispatch': self._printer.text('VALOR: ' + str(order['total_amount'])) self.print_enter() if order.get('pos_notes'): self._printer.text(order['pos_notes']) self.print_enter() self._printer.text('CAJA No: %s' % self._sale_device or '') self.print_enter() self.print_enter() self._printer.set(align='center') if self.order_kind == 'command': self._printer.set(custom_size=True, width=2, height=2, align='center') if reversion: self._printer.text('>> R E V E R S I O N <<') self.print_enter() col_width_name = self.order_col_2 + self.order_col_3 self._printer.set(align='left') self._printer.set(custom_size=True, width=1, height=2) if not self._print_lines_product: self.print_horinzontal_double_line() self.print_enter() for line in order['lines']: if self.order_kind == 'command': self._printer.set(custom_size=True, width=1, height=2) qty = ' ' + str(int(Decimal(line['quantity']))) self.print_col(qty, self.order_col_1) self.print_col(line['name'], col_width_name) if line['note']: self.print_enter() for msg_note in line['note'].split('\n'): self._printer.text(f' NOTA -> {msg_note}') self.print_enter() self.print_enter() self.print_enter() self.print_horinzontal_double_line() self.print_enter() self._printer.set(custom_size=True, width=2, height=2, align='left') self._printer.text('NOTA:') self.print_enter() if order['comment']: self._printer.text(str(order['comment'])) self.print_enter() self.print_enter() self.print_enter() # if self._environment != 'retail': # self._printer.set(custom_size=True, width=2, height=2, align='center') # title = f'+ + + {_kind} + + +' # self._printer.text(title) # self.print_enter() # self.print_enter() @classmethod def get_authorization(cls, auth): res = '' kind = auth['kind'] start_date_auth = auth['start_date_auth'] from_auth = auth['from_auth'] to_auth = auth['to_auth'] number = auth['number'] if auth: res = f"Autorizacion de facturacion {kind} No {number} del {start_date_auth}, habilita desde {from_auth} a {to_auth}" return res class CupsPrinter(object): "Cups Printer" __name__ = 'sale_pos_frontend.cups_printer' def __init__(self, _file, row_characters): self._file = _file self.align = 'left' self._row_characters = row_characters def text(self, text): self._text(text) def set(self, align='left', font=_FONT_A): if align: self.align = align if font: self.font = font def cut(self): pass def cashdraw(number): pass def _text(self, text): start_spaces = '' if self.align == 'center': start_spaces = int((self._row_characters - len(text)) / 2) * ' ' elif self.align == 'right': start_spaces = int(self._row_characters - len(text)) * ' ' else: pass text = start_spaces + text self._file.write(text) if __name__ == '__main__': # Test for Escpos interface printer Linux # Network example # device = 'network', '192.168.0.33' # Unix-like Usb example device = ('usb', ' /dev/usb/lp1') # Windows Usb example for printer name SATPOS # device = 'usb', 'SATPOS' # SSH example # device = 'ssh', 'psk@123@192.168.20.25@22@/dev/usb/lp1' example_dev = { 'interface': device[0], 'device': device[1], 'profile': 'TM-P80', } ctx_printing = {} ctx_printing['company'] = 'OSCORP INC' ctx_printing['sale_device'] = 'CAJA-10' ctx_printing['shop'] = 'Shop Wall Boulevard' ctx_printing['street'] = 'Cll 21 # 172-81. Central Park' ctx_printing['user'] = 'Charles Chapplin' ctx_printing['city'] = 'Dallas' ctx_printing['zip'] = '0876' ctx_printing['phone'] = '591 5513 455' ctx_printing['id_number'] = '123456789-0' ctx_printing['tax_regime'] = 'none' receipt = Receipt(ctx_printing) receipt.config_printer(example_dev) receipt.test_printer()