Imprimir ticket

This commit is contained in:
Mauricio Baeza 2018-01-01 02:14:30 -06:00
parent 3e323678d7
commit fad45cb502
7 changed files with 206 additions and 10 deletions

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
#~ import falcon import os
import re import re
import smtplib import smtplib
import ssl import ssl
@ -13,8 +13,8 @@ from email.mime.text import MIMEText
from email import encoders from email import encoders
from email.utils import formatdate from email.utils import formatdate
import os
import requests import requests
from escpos import printer
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Image from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Image
from reportlab.lib import colors from reportlab.lib import colors
@ -949,3 +949,92 @@ class SeaFileAPI(object):
resp = requests.get(url, headers=self._headers) resp = requests.get(url, headers=self._headers)
return resp.json() return resp.json()
class PrintTicket(object):
LINE = '------------------------------------------------\n'
TITLES = 'CANT. U ARTICULO P.U. TOTAL\n'
LEYENDA = 'GRACIAS POR SU COMPRA\n\nGuarde este ticket para cualquier ' \
'aclaración.\nComprobante simplificado de operación con\npúblico en ' \
'general de acuerdo al Art. 37\nFracc II inc. v del Reglamento del\n' \
'Código Fiscal de la Federación.\n\n'
def __init__(self, info):
self.p = self._init_printer(info)
def _init_printer(self, info):
try:
if info['ip']:
p = printer.Network(info['ip'])
else:
p = printer.Usb(*info['usb'])
p.codepage = 'cp850'
return p
except Exception as e:
print (e)
return
def _set(self, *data):
self.p.set(*data)
return
def _t(self, text):
self.p.text(text)
return
def _l(self):
self._t(self.LINE)
return
def printer(self, data):
if self.p is None:
return False
self._emisor(data['emisor'])
self._receptor(data['receptor'])
self._ticket(data['ticket'])
self._products(data['products'])
self._footer(data['ticket'])
self.p.cut()
return True
def _emisor(self, data):
self._set('center', 'B', 'B', 2, 2)
self._t(data['name'])
self._set('center', 'B', 'B', 2)
self._t(data['rfc'])
self._set('center', 'A')
self._t(data['address'])
return
def _receptor(self, data):
self._set('center', 'B', 'B', 2)
self._t(data['name'])
return
def _ticket(self, data):
self._set('left', 'B', 'B', 2)
self._t(data['title'])
self._set('left', 'A')
self._t(data['date'])
return
def _products(self, data):
self._l()
self._t(self.TITLES)
self._l()
for p in data:
self._t(p)
self._l()
self._t('Total artículos: {}\n'.format(len(data)))
self._l()
return
def _footer(self, data):
self._set('right', 'B', 'B', 2)
self._t(data['total'])
self._set('center', 'A')
self._t(data['letters'])
self._t(self.LEYENDA)
self._set('center', 'A', 'B')
self._t('empresalibre.net')
return

View File

@ -36,7 +36,7 @@ import pyqrcode
from dateutil import parser from dateutil import parser
from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice, \ from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice, \
SeaFileAPI SeaFileAPI, PrintTicket
from settings import DEBUG, MV, log, template_lookup, COMPANIES, DB_SAT, \ from settings import DEBUG, MV, log, template_lookup, COMPANIES, DB_SAT, \
PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PATH_MEDIA, PRE, \ PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PATH_MEDIA, PRE, \
PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES, DIR_FACTURAS PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES, DIR_FACTURAS
@ -1705,12 +1705,12 @@ class ImportFacturaLibreGambas(object):
('cfdifacturas', 'Facturas'), ('cfdifacturas', 'Facturas'),
('categorias', 'Categorias'), ('categorias', 'Categorias'),
('productos', 'Productos'), ('productos', 'Productos'),
# ~ ('tickets', 'Tickets'), ('tickets', 'Tickets'),
) )
for source, target in tables: for source, target in tables:
data[target] = self._get_table(source) data[target] = self._get_table(source)
# ~ data['Socios'] += self._clientes data['Socios'] += self._clientes
return data return data
@ -2505,3 +2505,8 @@ class ImportFacturaLibre(object):
data.append(new) data.append(new)
return data return data
def print_ticket(data, info):
p = PrintTicket(info)
return p.printer(data)

View File

@ -268,6 +268,8 @@ class StorageEngine(object):
return main.Tickets.cancel(values) return main.Tickets.cancel(values)
if opt == 'invoice': if opt == 'invoice':
return main.Tickets.invoice(values) return main.Tickets.invoice(values)
if opt == 'print':
return main.Tickets.printer(values)
def get_tickets(self, values): def get_tickets(self, values):
return main.Tickets.get_by(values) return main.Tickets.get_by(values)

View File

@ -17,7 +17,7 @@ if __name__ == '__main__':
from controllers import util from controllers import util
from settings import log, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \ from settings import log, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \
INIT_VALUES, DEFAULT_PASSWORD, DECIMALES, IMPUESTOS, DEFAULT_SAT_PRODUCTO, \ INIT_VALUES, DEFAULT_PASSWORD, DECIMALES, IMPUESTOS, DEFAULT_SAT_PRODUCTO, \
CANCEL_SIGNATURE CANCEL_SIGNATURE, PUBLIC
FORMAT = '{0:.2f}' FORMAT = '{0:.2f}'
@ -4328,6 +4328,63 @@ class Tickets(BaseModel):
doc = util.to_pdf(data, data['emisor']['rfc']) doc = util.to_pdf(data, data['emisor']['rfc'])
return doc, name return doc, name
def _format_ticket(self, id):
emisor = util.get_dict(Emisor.select().dicts()[0])
ticket = Tickets.select().where(Tickets.id==id).dicts()[0]
products = TicketsDetalle.get_by_print(id)
emisor['name'] = '{}\n'.format(emisor['nombre'])
emisor['rfc'] = 'RFC: {}\n'.format(emisor['rfc'])
interior = ''
if emisor['no_interior']:
interior = ', {}'.format(emisor['no_interior'])
colonia = ''
if emisor['colonia']:
colonia = ', Col. {}'.format(emisor['colonia'])
municipio = ''
if emisor['municipio']:
municipio = ', {}'.format(emisor['municipio'])
estado = ''
if emisor['estado']:
estado = ', {}'.format(emisor['estado'])
cp = ''
if emisor['codigo_postal']:
cp = ', C.P. {}'.format(emisor['codigo_postal'])
pais = ''
if emisor['pais']:
pais = ', {}'.format(emisor['pais'])
direccion = '{} {}{}{}{}{}{}{}\n\n'.format(emisor['calle'],
emisor['no_exterior'], interior, colonia, municipio, estado, cp,
pais)
emisor['address'] = direccion
ticket['title'] = 'Ticket: {}{}\n\n'.format(ticket['serie'],
ticket['folio'])
ticket['date'] = 'Fecha y hora: {}\n'.format(ticket['fecha'])
ticket['letters'] = '{}\n\n'.format(
util.to_letters(ticket['total'], 'peso'))
ticket['total'] = 'TOTAL: $ {:>12,.2f}\n\n'.format(ticket['total'])
data = {
'emisor': emisor,
'receptor': {'name': '{}\n\n'.format(PUBLIC)},
'ticket': ticket,
'products': products,
}
return data
@classmethod
def printer(cls, values):
id = int(values['id'])
info = {'ip': '', 'usb': (int('1ba0', 16), int('2204', 16))}
data = cls._format_ticket(cls, id)
result = util.print_ticket(data, info)
msg = 'Ticket impreso correctamente'
if not result:
msg = 'Asegurate de que la impresora este conectada y funcionando.'
result = {'ok': result, 'msg': msg}
return result
class TicketsDetalle(BaseModel): class TicketsDetalle(BaseModel):
ticket = ForeignKeyField(Tickets) ticket = ForeignKeyField(Tickets)
@ -4356,6 +4413,21 @@ class TicketsDetalle(BaseModel):
return precio_final return precio_final
@classmethod
def get_by_print(cls, id):
products = TicketsDetalle.select().where(TicketsDetalle.ticket==id)
lines = []
for p in products:
price_with_tax = cls._with_tax(cls, p)
importe = round(price_with_tax * float(p.cantidad), DECIMALES)
l = '{:>6,.2f} {:<4} {:<14} {:>9,.2f} {:>10,.2f}\n'.format(
p.cantidad, p.producto.unidad.name, p.descripcion,
price_with_tax, importe
)
lines.append(l)
return lines
@classmethod @classmethod
def get_by_ticket(cls, id): def get_by_ticket(cls, id):
data = [] data = []

View File

@ -117,4 +117,5 @@ IMPUESTOS = {
DEFAULT_SAT_PRODUCTO = '01010101' DEFAULT_SAT_PRODUCTO = '01010101'
DIR_FACTURAS = 'facturas' DIR_FACTURAS = 'facturas'
USAR_TOKEN = False USAR_TOKEN = False
CANCEL_SIGNATURE = False CANCEL_SIGNATURE = False
PUBLIC = 'Público en general'

View File

@ -651,11 +651,38 @@ function ticket_notes_key_up(){
} }
function print_ticket(id){
var data = new Object()
data['opt'] = 'print'
data['id'] = id
webix.ajax().post('tickets', data, {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico'
msg_error(msg)
},
success:function(text, data, XmlHttpRequest){
values = data.json();
if(values.ok){
msg_ok(values.msg)
}else{
msg_error(values.msg)
}
}
})
}
function grid_tickets_click(id, e, node){ function grid_tickets_click(id, e, node){
//~ var row = this.getItem(id)
if(id.column == 'pdf'){ if(id.column == 'pdf'){
//~ window.open('/doc/tpdf/' + id, '_blank') //~ window.open('/doc/tpdf/' + id, '_blank')
get_ticket_pdf(id) get_ticket_pdf(id.row)
return
}
if(id.column == 'print'){
print_ticket(id.row)
return
} }
} }

View File

@ -38,7 +38,7 @@ var grid_tickets_cols = [
{id: "cliente", header: ["Razón Social", {content: "selectFilter"}], {id: "cliente", header: ["Razón Social", {content: "selectFilter"}],
fillspace:true, sort:"string", hidden: true}, fillspace:true, sort:"string", hidden: true},
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')}, {id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
{id: 'print', header: 'I', adjust: 'data', template: get_icon('print')}, {id: 'print', header: '', adjust: 'data', template: get_icon('print')},
] ]