trytond-sale_pos_esc/reporting.py

338 lines
12 KiB
Python

# This file is part of sale_pos module for Tryton.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
from escpos import escpos
from decimal import Decimal
from cStringIO import StringIO
import datetime
import serial
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.pool import Pool
__all__ = ['Receipt', 'Display']
_ROW_CHARACTERS = 48
_DIGITS = 9
class Receipt(Report):
'Receipt'
__name__ = 'sale_pos.receipt'
@classmethod
def __setup__(cls):
super(Receipt, cls).__setup__()
cls._config = False
def load_config(self, device):
self._port = None
self._logo = None
self._config = device
if self._config.printer_port:
self._port = escpos.FileDevice(self._config.printer_port)
if self._config.logo:
self._logo = StringIO(self._config.logo)
def _open_device(self, device):
self._printer = None
if not self._config:
self.load_config()
if self._port:
self.is_open = self._port.open_device()
if self.is_open:
self._printer = escpos.Printer(self._port)
return
def device_active(self, device):
if not self._config:
self.load_config(device)
if self._port:
file_dev = escpos.FileDevice(self._config.printer_port)
return file_dev.open_device()
def _close_device(self):
if self._port:
self._port.close_device()
if self._printer:
del self._printer
def printing(f):
def p(self, *p, **kw):
self._open_device(device)
try:
res = f(self, *p, **kw)
finally:
self._close_device()
return res
return p
@printing
def test_printer(self, device):
#Configuration = Pool().get('sale_pos.device')
#configuration = Configuration(1)
if device.printer_port:
self.print_logo()
self._printer.text('\n\n')
self.print_impressum()
self._printer.text('\n\n\n')
self._printer.cut()
def print_logo(self):
if not self._logo:
return
self._printer.set(align='center')
self._printer.image(self._logo)
self._printer.text('\n')
def print_impressum(self):
self._printer.set(align='center')
company = self._config.company
street = None
city = None
zip_ = None
contact_type = None
contact_value = None
if company.party.addresses:
street = company.party.addresses[0].street
city = company.party.addresses[0].city
zip_ = company.party.addresses[0].zip
if company.party.contact_mechanisms:
contact_type = company.party.contact_mechanisms[0].type
contact_value = company.party.contact_mechanisms[0].value
self._printer.text(company.party.name + '\n')
if street:
self._printer.text(street + ' ')
if city:
self._printer.text(city)
if street or city:
self._printer.text('\n')
if zip_:
self._printer.text(zip_ + '\n')
if company.party.vat_number:
self._printer.text('NIT ' + company.party.vat_number + ' ')
if contact_type:
self._printer.text(contact_type + ':' + contact_value)
self._printer.text('\n')
@printing
def kick_cash_drawer(self):
self._printer.cashdraw(2)
@printing
def print_sale(self, sale):
Lang = Pool().get('ir.lang')
lang, = Lang.search([('code', '=', Transaction().language)])
Tax = Pool().get('account.tax')
def print_split(left, right):
len_left = _ROW_CHARACTERS - len(right) - 1
left = left[:len_left]
left += (len_left - len(left) + 1) * ' '
self._printer.text(left)
self._printer.text(right + '\n')
self.print_logo()
self.print_impressum()
self._printer.set(align='left')
self._printer.text('\n')
user = 'Usuario: %s' % sale.create_uid.name
self._printer.text(user)
self._printer.text('\n')
party = 'Tercero: %s' % sale.party.rec_name
self._printer.text(party)
self._printer.text('\n')
taxes = {}
i = 0
for tax in sale.taxes:
i += 1
taxes[tax.id] = {}
taxes[tax.id]['code'] = str(i)
taxes[tax.id]['rec'] = tax
taxes[tax.id]['amount'] = Decimal(0)
taxes = {}
self._printer.text('\n')
num_products = 0
for line in sale.lines:
if line.line_type == 'subtotal':
print_split('', '------------')
print_split('Total:', self.format_lang(line.total,
lang) + ' ')
self._printer.text('\n')
else:
num_products += 1
if line.taxes:
for tax in line.taxes:
values = Tax.compute([tax], line.unit_price,
line.quantity)[0]
tax_id = values['tax'].id
if tax_id not in taxes.keys():
taxes[tax_id] = {
'name': values['tax'].percentage,
'base': 0,
'tax': 0,
'total': 0
}
taxes[tax_id]['base'] += values['base']
taxes[tax_id]['tax'] += values['amount']
taxes[tax_id]['total'] += (values['base'] +
values['amount'])
else:
tax_id = 0
base = line.unit_price * line.quantity
tax = 0
total = base + tax
if '0' not in taxes.keys():
taxes['0'] = {
'name': 0,
'base': 0,
'tax': 0,
'total': 0,
}
taxes['0']['base'] += base
taxes['0']['tax'] += tax
taxes['0']['total'] += total
tax_id = str(tax_id)
if line.quantity != 1 or len(line.name) > (_ROW_CHARACTERS -
(_DIGITS + 1)):
self._printer.text(line.name[:_ROW_CHARACTERS] + '\n')
pos_text = ' %s x %s' % (
self.format_lang(line.quantity, lang, digits=1),
self.format_lang(line.unit_price, lang),
)
total = self.format_lang(line.total, lang)
print_split(pos_text, total + ' ' + tax_id)
else:
print_split(
line.name,
self.format_lang(line.total, lang) + ' ' + tax_id
),
print_split('Efectivo:', self.format_lang(sale.total_paid,
lang) + ' ')
print_split('Cambio:', self.format_lang(sale.drawback, lang) + ' ')
self._printer.text('\n' * 2)
#cols = 4
col_width = int(_ROW_CHARACTERS / 4)
f = lambda x, l: self._printer.text(x[:l] + (l - len(x)) * ' ')
f('Tipo', col_width)
f('Base', col_width)
f('Imp.', col_width)
f('Total', col_width)
self._printer.text('\n')
for tax in taxes:
f(str(tax) + '=' + self.format_lang(taxes[tax]['name'],
lang) + '%', col_width)
total = taxes[tax]['total']
base = taxes[tax]['base']
tax = taxes[tax]['tax']
f(self.format_lang(base, lang), col_width)
f(self.format_lang(tax, lang), col_width)
f(self.format_lang(total, lang), col_width)
self._printer.text('\n')
self._printer.text('\n')
no_products = 'No Productos: %d' % num_products
self._printer.text(no_products)
self._printer.text('\n')
self._printer.set(align='center')
self._printer.text('No Fact. ' + sale.receipt_code)
#printer.barcode(sale.receipt_code, 'CODE128B', 3, 50,'','')
self._printer.text('\n')
self._printer.text(self.format_lang(datetime.datetime.now(), lang,
date=True))
self._printer.text('\n')
self._printer.text('Presik Technologies - POS System')
self._printer.text('\n')
self._printer.text('www.presik.com - Cel: 3012457967')
self._printer.cut()
def _compute_tax(self, sale):
tax_codes = []
return tax_codes
class Display(Report):
'Display'
__name__ = 'sale_pos.display'
@classmethod
def __setup__(cls):
super(Display, cls).__setup__()
cls._display = False
def _get_lang(self):
Lang = Pool().get('ir.lang')
lang, = Lang.search([('code', '=', Transaction().language)])
return lang
def load_display(self):
Configuration = Pool().get('sale_pos.pos_device')
configuration = Configuration(1)
if configuration.display_port:
self._display = escpos.Display(serial.Serial(
configuration.display_port, configuration.display_baud),
digits=int(configuration.display_digits))
self._display.set_cursor(False)
def displaying(f):
def p(self, *p, **kw):
if not self._display:
self.load_display()
return f(self, *p, **kw)
return p
@displaying
def show_sale_line(self, sale_line):
Configuration = Pool().get('sale_pos.pos_device')
configuration = Configuration(1)
if configuration.display_port:
lang = self._get_lang()
self._display.clear()
self._display.set_align('left')
self._display.text(sale_line.product.name)
self._display.new_line()
self._display.text('%s x %s' % (
self.format_lang(sale_line.quantity, lang, digits=0),
self.format_lang(sale_line.unit_price, lang),
))
self._display.set_align('right')
self._display.text(self.format_lang(sale_line.total, lang))
@displaying
def show_total(self, sale):
Configuration = Pool().get('sale_pos.pos_device')
configuration = Configuration(1)
if configuration.display_port:
lang = self._get_lang()
self._display.clear()
self._display.text('Total:')
self._display.set_align('right')
self._display.text(self.format_lang(sale.total_amount, lang))
@displaying
def show_paid(self, sale):
Configuration = Pool().get('sale_pos.pos_device')
configuration = Configuration(1)
if configuration.display_port:
lang = self._get_lang()
self._display.clear()
self._display.text('Pagado:')
self._display.set_align('right')
f = lambda x: self.format_lang(x, lang)
self._display.text(f(sale.total_paid))
self._display.new_line()
self._display.set_align('left')
self._display.text('Cambio:')
self._display.set_align('right')
self._display.text(f(sale.drawback))