Generar PDF de Ticket

This commit is contained in:
Mauricio Baeza 2017-12-31 00:17:20 -06:00
parent e39e4c5585
commit 9376fee407
9 changed files with 206 additions and 54 deletions

View File

@ -385,13 +385,13 @@ class AppDocumentos(object):
def __init__(self, db):
self._db = db
#~ self._not_json = True
def on_get(self, req, resp, type_doc, id_doc):
session = req.env['beaker.session']
req.context['result'], file_name, content_type = \
self._db.get_doc(type_doc, id_doc, session['rfc'])
# ~ resp.append_header('Content-Disposition',
# ~ 'attachment; filename={}'.format(file_name))
if not type_doc in ('pdf', 'pre', 'tpdf'):
resp.append_header('Content-Disposition',
'attachment; filename={}'.format(file_name))
resp.content_type = content_type
resp.status = falcon.HTTP_200

View File

@ -269,7 +269,7 @@ def get_size(path):
def get_template(name, data={}):
#~ print ('NAME', name, data)
# ~ print ('NAME', name)
template = template_lookup.get_template(name)
return template.render(**data)
@ -774,18 +774,30 @@ class LIBO(object):
cell_6 = self._set_cell(v=importe, cell=cell_6, value=True)
return
def _add_totales(self, data):
currency = data['moneda']
value = data['total']
cell_value = self._set_cell('{total}', value, value=True)
if cell_value is None:
return False
cell_value.CellStyle = currency
return True
def _totales(self, data):
currency = data['moneda']
cell_title = self._set_cell('{subtotal.titulo}', 'SubTotal')
value = data['subtotal']
cell_value = self._set_cell('{subtotal}', value, value=True)
cell_value.CellStyle = currency
if not cell_value is None:
cell_value.CellStyle = currency
#~ Si encuentra el campo {total}, se asume que los totales e impuestos
#~ están declarados de forma independiente cada uno
#~ if self._add_totales(xml):
#~ return
if self._add_totales(data):
return
#~ Si no se encuentra, copia las celdas hacia abajo de
#~ {subtotal.titulo} y {subtotal}
@ -828,7 +840,7 @@ class LIBO(object):
return
def _timbre(self, data):
if self._es_pre:
if self._es_pre or self._is_ticket:
return
for k, v in data.items():
@ -863,6 +875,7 @@ class LIBO(object):
def _render(self, data):
self._set_search()
self._es_pre = data.pop('es_pre', False)
self._is_ticket = data.pop('is_ticket', False)
self._comprobante(data['comprobante'])
self._emisor(data['emisor'])
self._receptor(data['receptor'])
@ -910,6 +923,7 @@ def to_pdf(data, emisor_rfc):
if data['donativo']:
donativo = '_donativo'
name = '{}_{}{}.ods'.format(rfc.lower(), version, donativo)
print (name)
path = get_template_ods(name)
if path:
return app.pdf(path, data)

View File

@ -31,6 +31,9 @@ class StorageEngine(object):
def _get_configtimbrar(self, values):
return main.config_timbrar()
def _get_configticket(self, values):
return main.config_ticket()
def _get_saldocuenta(self, values):
return main.CuentasBanco.get_saldo(values['id'])
@ -303,20 +306,7 @@ class StorageEngine(object):
return main.Folios.add(values)
def get_doc(self, type_doc, id, rfc):
if type_doc == 'xml':
data, file_name = main.Facturas.get_xml(id)
content_type = 'application/xml'
elif type_doc == 'pdf':
data, file_name = main.Facturas.get_pdf(id, rfc)
content_type = 'application/pdf'
elif type_doc == 'zip':
data, file_name = main.Facturas.get_zip(id, rfc)
content_type = 'application/octet-stream'
elif type_doc == 'pdf2':
data, file_name = main.PreFacturas.get_pdf(id)
content_type = 'application/pdf'
return data, file_name, content_type
return main.get_doc(type_doc, id, rfc)
def get_movimientosbanco(self, values):
return main.MovimientosBanco.get_(values)

View File

@ -104,6 +104,26 @@ def validar_timbrar():
return {'ok': True, 'msg': msg}
def get_doc(type_doc, id, rfc):
types = {
'xml': 'application/xml',
'zip': 'application/octet-stream',
}
content_type = types.get(type_doc, 'application/pdf')
if type_doc == 'xml':
data, file_name = Facturas.get_xml(id)
elif type_doc == 'pdf':
data, file_name = Facturas.get_pdf(id, rfc)
elif type_doc == 'zip':
data, file_name = Facturas.get_zip(id, rfc)
elif type_doc == 'pre':
data, file_name = PreFacturas.get_pdf(id)
elif type_doc == 'tpdf':
data, file_name = Tickets.get_pdf(id)
return data, file_name, content_type
def config_main():
try:
obj = Emisor.select()[0]
@ -141,6 +161,13 @@ def config_timbrar():
return conf
def config_ticket():
conf = {
'open_pdf': Configuracion.get_bool('chk_ticket_pdf_show'),
}
return conf
class Configuracion(BaseModel):
clave = TextField(unique=True)
valor = TextField(default='')
@ -221,7 +248,9 @@ class Configuracion(BaseModel):
'chk_config_codigo_barras',
'chk_config_precio_con_impuestos',
'chk_config_ine',
'chk_config_edu',
'chk_usar_punto_de_venta',
'chk_ticket_pdf_show',
)
data = (Configuracion
.select()
@ -3261,6 +3290,7 @@ class PreFacturas(BaseModel):
options = {
'para': obj.cliente.correo_facturas,
'copia': values['correo_copia'],
'confirmar': util.get_bool(values.get('correo_confirmacion', '0')),
'asunto': asunto,
'mensaje': util.make_info_mail(values['correo_mensaje'], fields),
'files': files,
@ -4243,6 +4273,61 @@ class Tickets(BaseModel):
data += [{'id': int(r.year), 'value': int(r.year)} for r in rows]
return tuple(data)
def _get_info_to_pdf(self, id):
data = {}
obj = Tickets.select().where(Tickets.id==id).dicts()[0]
formapago = SATFormaPago.get(SATFormaPago.key==obj['forma_pago'])
emisor = util.get_dict(Emisor.select().dicts()[0])
emisor['nointerior'] = emisor['no_interior']
emisor['noexterior'] = emisor['no_exterior']
emisor['codigopostal'] = emisor['codigo_postal']
data['is_ticket'] = True
data['cancelada'] = obj['cancelado']
data['donativo'] = ''
data['comprobante'] = obj
data['comprobante']['version'] = 'ticket'
data['comprobante']['folio'] = str(data['comprobante']['folio'])
data['comprobante']['seriefolio'] = '{}-{}'.format(
data['comprobante']['serie'], data['comprobante']['folio'])
data['comprobante']['fecha'] = str(data['comprobante']['fecha'])
# ~ data['comprobante']['lugarexpedicion'] = \
# ~ 'C.P. de Expedición: {}'.format(
# ~ data['comprobante']['lugar_expedicion'])
data['comprobante']['formadepago'] = str(formapago)
data['comprobante']['totalenletras'] = util.to_letters(
data['comprobante']['total'], 'peso')
data['emisor'] = emisor
data['receptor'] = {'nombre': 'Público en general'}
data['conceptos'] = TicketsDetalle.get_by_ticket(id)
data['totales'] = {}
data['totales']['total'] = str(data['comprobante']['total'])
data['totales']['subtotal'] = str(data['comprobante']['subtotal'])
data['totales']['moneda'] = 'peso'
data['totales']['traslados'] = ()
data['totales']['retenciones'] = ()
data['totales']['taxlocales'] = ()
data['timbre'] = {}
data['donataria'] = {}
data['ine'] = {}
# ~ if obj['descuento']:
# ~ data['totales']['descuento'] = float(obj['descuento'])
return data
@classmethod
def get_pdf(cls, id):
obj = Tickets.get(Tickets.id==id)
name = '{}{}.pdf'.format(obj.serie, obj.folio)
data = cls._get_info_to_pdf(cls, id)
doc = util.to_pdf(data, data['emisor']['rfc'])
return doc, name
class TicketsDetalle(BaseModel):
ticket = ForeignKeyField(Tickets)
@ -4262,6 +4347,35 @@ class TicketsDetalle(BaseModel):
class Meta:
order_by = ('ticket',)
def _with_tax(self, product):
precio_final = float(product.precio_final)
base = float(product.precio_final)
for tax in product.producto.impuestos:
impuesto_producto = round(float(tax.tasa) * base, DECIMALES)
precio_final += impuesto_producto
return precio_final
@classmethod
def get_by_ticket(cls, id):
data = []
productos = TicketsDetalle.select().where(TicketsDetalle.ticket==id)
for p in productos:
producto = {}
producto['noidentificacion'] = p.producto.clave
producto['descripcion'] = p.descripcion
producto['unidad'] = p.producto.unidad.name
producto['cantidad'] = str(p.cantidad)
price_with_tax = cls._with_tax(cls, p)
producto['valorunitario'] = str(price_with_tax)
importe = round(price_with_tax * float(p.cantidad), DECIMALES)
producto['importe'] = str(importe)
data.append(producto)
return data
class TicketsImpuestos(BaseModel):
ticket = ForeignKeyField(Tickets)

View File

@ -56,10 +56,12 @@ var controllers = {
$$('chk_config_open_pdf').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_anticipo').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_ine').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_edu').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_cuenta_predial').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_codigo_barras').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_precio_con_impuestos').attachEvent('onItemClick', chk_config_item_click)
$$('chk_usar_punto_de_venta').attachEvent('onItemClick', chk_config_item_click)
$$('chk_ticket_pdf_show').attachEvent('onItemClick', chk_config_item_click)
$$('cmd_subir_bdfl').attachEvent('onItemClick', cmd_subir_bdfl_click)
$$('up_bdfl').attachEvent('onUploadComplete', up_bdfl_upload_complete)

View File

@ -10,6 +10,33 @@ var cfg_invoice = new Object()
var invoices_controllers = {
init: function(){
//~ Invoices
$$('cmd_new_invoice').attachEvent("onItemClick", cmd_new_invoice_click)
$$('cmd_refacturar').attachEvent("onItemClick", cmd_refacturar_click)
$$('cmd_delete_invoice').attachEvent("onItemClick", cmd_delete_invoice_click)
$$('cmd_timbrar').attachEvent('onItemClick', cmd_timbrar_click)
$$('cmd_close_invoice').attachEvent('onItemClick', cmd_close_invoice_click)
$$('search_client_id').attachEvent('onKeyPress', search_client_id_key_press)
$$('grid_clients_found').attachEvent('onValueSuggest', grid_clients_found_click)
$$('search_product_id').attachEvent('onKeyPress', search_product_id_key_press)
$$('grid_products_found').attachEvent('onValueSuggest', grid_products_found_click)
$$('grid_details').attachEvent('onItemClick', grid_details_click)
$$('grid_details').attachEvent('onHeaderClick', grid_details_header_click)
$$('grid_details').attachEvent('onBeforeEditStart', grid_details_before_edit_start)
$$('grid_details').attachEvent('onBeforeEditStop', grid_details_before_edit_stop)
$$('cmd_invoice_timbrar').attachEvent('onItemClick', cmd_invoice_timbrar_click)
$$('cmd_invoice_sat').attachEvent('onItemClick', cmd_invoice_sat_click)
$$('cmd_invoice_cancelar').attachEvent('onItemClick', cmd_invoice_cancelar_click)
$$('grid_invoices').attachEvent('onItemClick', grid_invoices_click)
$$('filter_year').attachEvent('onChange', filter_year_change)
$$('filter_month').attachEvent('onChange', filter_month_change)
$$('filter_dates').attachEvent('onChange', filter_dates_change)
$$('cmd_prefactura').attachEvent('onItemClick', cmd_prefactura_click)
$$('cmd_cfdi_relacionados').attachEvent('onItemClick', cmd_cfdi_relacionados_click)
$$('lst_metodo_pago').attachEvent('onChange', lst_metodo_pago_change)
$$('lst_moneda').attachEvent('onChange', lst_moneda_change)
$$('lst_serie').attachEvent('onChange', lst_serie_change)
$$('cmd_cfdi_notes').attachEvent('onItemClick', cmd_cfdi_notes_click)
webix.extend($$('grid_invoices'), webix.ProgressBar)
@ -1442,7 +1469,7 @@ function enviar_prefactura(id){
text: msg,
callback:function(result){
if(result){
webix.ajax().post('/values/enviarprefac', {'id': id}, {
webix.ajax().post('/values/enviarprefac', {'id': id.row}, {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico'
msg_error(msg)
@ -1463,12 +1490,13 @@ function enviar_prefactura(id){
function grid_preinvoices_click(id, e, node){
var row = this.getItem(id)
//~ var row = this.getItem(id)
if(id.column == 'pdf'){
location = '/doc/pdf2/' + row.id
//~ location = '/doc/pre/' + row.id
window.open('/doc/pre/' + id, '_blank')
}else if(id.column == 'email'){
enviar_prefactura(row.id)
enviar_prefactura(id)
}
}

View File

@ -33,33 +33,6 @@ var controllers = {
$$('menu_user').attachEvent('onMenuItemClick', menu_user_click);
configuracion_inicial()
//~ Invoices
$$('cmd_new_invoice').attachEvent("onItemClick", cmd_new_invoice_click)
$$('cmd_refacturar').attachEvent("onItemClick", cmd_refacturar_click)
$$('cmd_delete_invoice').attachEvent("onItemClick", cmd_delete_invoice_click)
$$('cmd_timbrar').attachEvent('onItemClick', cmd_timbrar_click)
$$('cmd_close_invoice').attachEvent('onItemClick', cmd_close_invoice_click)
$$('search_client_id').attachEvent('onKeyPress', search_client_id_key_press)
$$('grid_clients_found').attachEvent('onValueSuggest', grid_clients_found_click)
$$('search_product_id').attachEvent('onKeyPress', search_product_id_key_press)
$$('grid_products_found').attachEvent('onValueSuggest', grid_products_found_click)
$$('grid_details').attachEvent('onItemClick', grid_details_click)
$$('grid_details').attachEvent('onHeaderClick', grid_details_header_click)
$$('grid_details').attachEvent('onBeforeEditStart', grid_details_before_edit_start)
$$('grid_details').attachEvent('onBeforeEditStop', grid_details_before_edit_stop)
$$('cmd_invoice_timbrar').attachEvent('onItemClick', cmd_invoice_timbrar_click)
$$('cmd_invoice_sat').attachEvent('onItemClick', cmd_invoice_sat_click)
$$('cmd_invoice_cancelar').attachEvent('onItemClick', cmd_invoice_cancelar_click)
$$('grid_invoices').attachEvent('onItemClick', grid_invoices_click)
$$('filter_year').attachEvent('onChange', filter_year_change)
$$('filter_month').attachEvent('onChange', filter_month_change)
$$('filter_dates').attachEvent('onChange', filter_dates_change)
$$('cmd_prefactura').attachEvent('onItemClick', cmd_prefactura_click)
$$('cmd_cfdi_relacionados').attachEvent('onItemClick', cmd_cfdi_relacionados_click)
$$('lst_metodo_pago').attachEvent('onChange', lst_metodo_pago_change)
$$('lst_moneda').attachEvent('onChange', lst_moneda_change)
$$('lst_serie').attachEvent('onChange', lst_serie_change)
var tb_invoice = $$('tv_invoice').getTabbar()
tb_invoice.attachEvent('onChange', tb_invoice_change)
$$('prefilter_year').attachEvent('onChange', prefilter_year_change)

View File

@ -1,5 +1,6 @@
var query = []
var msg = ''
var cfg_ticket = new Object()
var tickets_controllers = {
@ -15,6 +16,7 @@ var tickets_controllers = {
$$('cmd_move_tickets_left').attachEvent('onItemClick', cmd_move_tickets_left_click)
$$('cmd_ticket_notes').attachEvent('onItemClick', cmd_ticket_notes_click)
$$('tsearch_product_key').attachEvent('onKeyPress', tsearch_product_key_press)
$$('grid_tickets').attachEvent('onItemClick', grid_tickets_click)
$$('grid_tdetails').attachEvent('onItemClick', grid_ticket_details_click)
$$('grid_tdetails').attachEvent('onBeforeEditStop', grid_tickets_details_before_edit_stop)
$$('gt_productos_found').attachEvent('onValueSuggest', gt_productos_found_click)
@ -26,6 +28,7 @@ var tickets_controllers = {
$$('tsearch_client_key').attachEvent('onKeyPress', tsearch_client_key_press)
$$('grid_ticket_clients_found').attachEvent('onValueSuggest', grid_ticket_clients_found_click)
webix.extend($$('grid_tickets'), webix.ProgressBar)
webix.extend($$('grid_tickets_active'), webix.ProgressBar)
}
@ -92,6 +95,12 @@ function filter_month_ticket_change(nv, ov){
function configuracion_inicial_ticket(){
current_dates_tickets()
get_tickets()
webix.ajax().sync().get('/values/configticket', function(text, data){
var values = data.json()
//~ showvar(values)
cfg_ticket['open_pdf'] = values.open_pdf
})
}
@ -172,6 +181,11 @@ function validar_ticket(){
}
function get_ticket_pdf(id){
window.open('/doc/tpdf/' + id, '_blank')
}
function guardar_ticket(values){
var gd = $$('grid_tdetails')
var grid = $$('grid_tickets')
@ -206,6 +220,9 @@ function guardar_ticket(values){
gd.clearAll()
grid.add(values.row)
$$('multi_tickets').setValue('tickets_home')
if(cfg_ticket.open_pdf){
get_ticket_pdf(values.row.id)
}
}else{
msg_error(values.msg)
}
@ -631,4 +648,14 @@ function cmd_ticket_notes_click(){
function ticket_notes_key_up(){
var value = this.getValue()
$$('form_new_ticket').setValues({notas: value}, true)
}
function grid_tickets_click(id, e, node){
//~ var row = this.getItem(id)
if(id.column == 'pdf'){
//~ window.open('/doc/tpdf/' + id, '_blank')
get_ticket_pdf(id)
}
}

View File

@ -522,13 +522,17 @@ var options_admin_otros = [
{template: 'Complementos', type: 'section'},
{cols: [{maxWidth: 15},
{view: 'checkbox', id: 'chk_config_ine', labelWidth: 0,
labelRight: 'Mostrar el complemento INE al facturar'},
labelRight: 'Usar el complemento INE'},
{view: 'checkbox', id: 'chk_config_edu', labelWidth: 0,
labelRight: 'Usar el complemento EDU'},
{}]},
{maxHeight: 20},
{template: 'Punto de venta', type: 'section'},
{cols: [{maxWidth: 15},
{view: 'checkbox', id: 'chk_usar_punto_de_venta', labelWidth: 0,
labelRight: 'Usar punto de venta'},
{view: 'checkbox', id: 'chk_ticket_pdf_show', labelWidth: 0,
labelRight: 'Abrir PDF al generar'},
{}]},
{maxHeight: 20},