diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 353f7ad..5952af9 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -510,7 +510,7 @@ class AppDocumentos(object): session = req.env['beaker.session'] req.context['result'], file_name, content_type = \ self._db.get_doc(type_doc, id_doc, session['rfc']) - if not type_doc in ('pdf', 'pre', 'tpdf', 'pdfpago'): + if not type_doc in ('pdf', 'pre', 'tpdf', 'pdfpago', 'html'): resp.append_header('Content-Disposition', 'attachment; filename={}'.format(file_name)) resp.content_type = content_type diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 5338e94..f681622 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -52,6 +52,11 @@ except ImportError: import pyqrcode from dateutil import parser +from lxml import etree + +import mako.runtime +from mako.exceptions import TopLevelLookupException +mako.runtime.UNDEFINED = '' from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice, \ SeaFileAPI, PrintTicket @@ -1576,6 +1581,27 @@ def to_pdf(data, emisor_rfc, ods=False): return read_file(path) +def format_currency(value, currency, digits=2): + c = { + 'MXN': '$', + 'USD': '$', + 'EUR': '€', + } + s = c.get(currency, 'MXN') + return f'{s} {float(value):,.{digits}f}' + + +def to_html(data): + name = f"{data['rfc']}_{data['version']}.html" + try: + template = template_lookup.get_template(name) + except TopLevelLookupException: + template = template_lookup.get_template('plantilla_factura.html') + data['rfc'] = 'estilos' + + return template.render(**data) + + def import_employees(rfc): name = '{}_employees.ods'.format(rfc.lower()) path = _join(PATH_MEDIA, 'tmp', name) @@ -1621,8 +1647,8 @@ def get_dict(data): return CaseInsensitiveDict(data) -def to_letters(value, moneda): - return NumLet(value, moneda).letras +def to_letters(value, currency): + return NumLet(value, currency).letras def get_qr(data): @@ -3648,3 +3674,8 @@ def validate_rfc(value): return '' except: return msg + + +def parse_xml2(xml_str): + return etree.fromstring(xml_str.encode('utf-8')) + diff --git a/source/app/models/main.py b/source/app/models/main.py index 71eb26f..2d0d909 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -204,12 +204,15 @@ def get_doc(type_doc, id, rfc): 'ods': 'application/octet-stream', 'zip': 'application/octet-stream', 'nomlog': 'application/txt', + 'html': 'text/html', } 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 == 'html': + data, file_name = Facturas.get_html(id) elif type_doc == 'ods': data, file_name = Facturas.get_ods(id, rfc) elif type_doc == 'zip': @@ -3671,6 +3674,138 @@ class Facturas(BaseModel): return doc, name + def _get_description(self, node, data): + return data['descripcion'] + + def _get_others_values(self, invoice, emisor): + v_cancel = {True: 'inline', False: 'none'} + v_type = {'I': 'Ingreso', 'E': 'Egreso', 'T': 'Traslado'} + v_method = { + 'PUE': 'Pago en una sola exhibición', + 'PPD': 'Pago en parcialidades o diferido', + } + v_tax = { + '001': 'ISR', + '002': 'IVA', + '003': 'IEPS', + } + + data = { + 'rfc': emisor.rfc.lower(), + 'version': invoice.version, + 'cancelada': v_cancel.get(invoice.cancelada), + 'cfdi_notas': invoice.notas, + } + + xml = util.parse_xml2(invoice.xml) + d = util.get_dict(xml.attrib) + d.pop('Certificado', '') + currency = d.get('Moneda', 'MXN') + + data.update({f'cfdi_{k.lower()}': v for k, v in d.items()}) + + data['cfdi_tipodecomprobante'] = v_type[data['cfdi_tipodecomprobante']] + + if data.get('cfdi_formapago', ''): + obj = SATFormaPago.get(SATFormaPago.key==invoice.forma_pago) + data['cfdi_formapago'] = str(obj) + if data.get('cfdi_metodopago', ''): + data['cfdi_metodopago'] = 'Método de Pago: ({}) {}'.format( + data['cfdi_metodopago'], v_method[data['cfdi_metodopago']]) + + obj = SATMonedas.get(SATMonedas.key==currency) + data['cfdi_moneda'] = str(obj) + data['cfdi_tipocambio'] = util.format_currency( + data['cfdi_tipocambio'], currency, 4) + data['cfdi_totalenletras'] = util.to_letters( + float(data['cfdi_total']), currency) + + data['totales'] = [( + 'Subtotal', util.format_currency(data['cfdi_subtotal'], currency))] + + for node in xml: + if 'Emisor' in node.tag: + d = util.get_dict(node.attrib) + data.update( + {f'emisor_{k.lower()}': v for k, v in d.items()} + ) + elif 'Receptor' in node.tag: + d = util.get_dict(node.attrib) + data.update( + {f'receptor_{k.lower()}': v for k, v in d.items()} + ) + elif 'Conceptos' in node.tag: + data['conceptos'] = [] + for subnode in node: + d = util.get_dict(subnode.attrib) + concepto = { + 'clave': f"{d['noidentificacion']}
({d['claveprodserv']})", + 'descripcion': self._get_description(self, subnode, d), + 'unidad': f"{d['unidad']}
({d['claveunidad']})", + 'cantidad': d['cantidad'], + 'valorunitario': util.format_currency(d['valorunitario'], currency), + 'importe': util.format_currency(d['importe'], currency), + } + data['conceptos'].append(concepto) + elif 'Impuestos' in node.tag: + for subnode in node: + if 'Traslados' in subnode.tag: + for t in subnode: + d = util.get_dict(t.attrib) + name = v_tax.get(d['impuesto']) + tasa = FORMAT.format(float(d['tasaocuota'])) + title = f"Traslado {name} {tasa}" + importe = util.format_currency(d['importe'], currency) + data['totales'].append((title, importe)) + elif 'Retenciones' in subnode.tag: + for r in subnode: + d = util.get_dict(r.attrib) + name = v_tax.get(d['impuesto']) + tasa = FORMAT.format(float(d['tasaocuota'])) + title = f"Retención {name} {tasa}" + importe = util.format_currency(d['importe'], currency) + data['totales'].append((title, importe)) + elif 'Complemento' in node.tag: + for subnode in node: + if 'TimbreFiscalDigital' in subnode.tag: + d = util.get_dict(subnode.attrib) + data.update( + {f'timbre_{k.lower()}': v for k, v in d.items()} + ) + + obj = SATRegimenes.get(SATRegimenes.key==data['emisor_regimenfiscal']) + data['emisor_regimenfiscal'] = str(obj) + data['emisor_logo'] = data['emisor_rfc'].lower() + + obj = SATUsoCfdi.get(SATUsoCfdi.key==data['receptor_usocfdi']) + data['receptor_usocfdi'] = str(obj) + + data['totales'].append(( + 'Total', util.format_currency(data['cfdi_total'], currency))) + + data['timbre_cadenaoriginal'] = f"""||{data['timbre_version']}| + {data['timbre_uuid']}|{data['timbre_fechatimbrado']}| + {data['timbre_sellocfd']}|{data['timbre_nocertificadosat']}||""" + # ~ print(data) + return data + + @classmethod + def get_html(cls, id): + try: + emisor = Emisor.select()[0] + except IndexError: + return '', 'sin_datos_de_emisor.html' + + obj = Facturas.get(Facturas.id==id) + name = '{}{}_{}.html'.format(obj.serie, obj.folio, obj.cliente.rfc) + if obj.uuid is None: + return '', name + + data = cls._get_others_values(cls, obj, emisor) + doc = util.to_html(data) + + return doc, name + @classmethod def get_ods(cls, id, rfc): try: diff --git a/source/app/settings.py b/source/app/settings.py index df4130f..6897b81 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -74,7 +74,10 @@ TEMPLATE_CANCEL = os.path.abspath(os.path.join(PATH_TEMPLATES, CT)) PATH_XSLT = os.path.abspath(os.path.join(BASE_DIR, '..', 'xslt')) PATH_BIN = os.path.abspath(os.path.join(BASE_DIR, '..', 'bin')) -template_lookup = TemplateLookup(directories=[PATH_TEMPLATES], +PATH_TEMPLATES_USER = os.path.abspath(os.path.join( + BASE_DIR, '..', 'docs', 'templates')) +directories=[PATH_TEMPLATES, PATH_TEMPLATES_USER] +template_lookup = TemplateLookup(directories=directories, input_encoding='utf-8', output_encoding='utf-8') diff --git a/source/static/css/estilos.css b/source/static/css/estilos.css new file mode 100644 index 0000000..0dbd2a0 --- /dev/null +++ b/source/static/css/estilos.css @@ -0,0 +1,508 @@ +.emisor-cintilla{ + background-color: #975759; + color: #fff; +} + +.fiscales-emisor{ + color: #7d1916; +} + +.fiscales-emisor .telefono, .fiscales-emisor .correo, .fiscales-emisor .web{ + color: #333; +} + +header .titulo-vertical{ + background-color: #dbc5c6; + color: #000; +} + +.receptor .nombre{ + color: #000; +} + +.receptor .rfc{ + color: #000; +} + +.receptor .direccion{ + color: #000; +} + +.receptor .estado{ + color: #000; +} + +.cfdi .folio span{ + color: #ed483d; +} + +.cfdi .tipo span{ + color: #ed483d; +} + +.cfdi .folio-fiscal span{ + color: #ed483d; +} + +.conceptos th{ + background-color: #975759; +} + +.conceptos td.clave, .conceptos td.unidad, .conceptos td.valor-unitario{ + background-color: #dbc5c6; +} + +.conceptos td.descripcion, .conceptos td.cantidad, .conceptos td.importe{ + background-color: #f0e7e7; +} + +table.subtotal th{ + background-color: #dbc5c6; +} + +table.subtotal td{ + background-color: #f0e7e7; +} + +.sello .cadenas-sello .cadena div { + background-color: #dbc5c6; + color: #7d1916; +} + +.rfc-pac { + background-color: #dbc5c6; + color: #7d1916; +} + +.cancelada{ + color: #ed3833; +} + +@font-face { + font-family: 'Avenir Next'; + src: url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot'); + src: url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot?#iefix') format('embedded-opentype'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff2') format('woff2'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff') format('woff'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.ttf') format('truetype'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.svg#AvenirNextLTPro-Regular') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Avenir Next'; + src: url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot'); + src: url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot?#iefix') format('embedded-opentype'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff2') format('woff2'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff') format('woff'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.ttf') format('truetype'), + url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.svg#AvenirNextLTPro-Bold') format('svg'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Avenir Next'; + src: url('/static/fonts/avenir_next/AvenirNextLTPro-It.eot'); + src: url('/static/fonts/avenir_next/AvenirNextLTPro-It.eot?#iefix') format('embedded-opentype'), + url('/static/fonts/avenir_next/AvenirNextLTPro-It.woff2') format('woff2'), + url('/static/fonts/avenir_next/AvenirNextLTPro-It.woff') format('woff'), + url('/static/fonts/avenir_next/AvenirNextLTPro-It.ttf') format('truetype'), + url('/static/fonts/avenir_next/AvenirNextLTPro-It.svg#AvenirNextLTPro-It') format('svg'); + font-weight: normal; + font-style: italic; +} + + +@page{ + size: 8.5in 11in; + margin: 1cm ; + background-color: white !important; +} + +@media print { + thead {display: table-header-group;} + body { + background-color: #fff; + } +} + +body { + background-color: rgb(204,204,204); + font-family: 'Avenir Next'; +} + +#plantilla { + background: #fff; + display: block; + margin: 0 auto; + width: 21.5cm; + height: 27.9cm; + position: relative; +} + +.cancelada{ + -ms-transform: rotate(320deg); + -webkit-transform: rotate(320deg); + transform: rotate(320deg); + color: #ed3833; + font-size: 100px; + font-weight: bold; + left: 18%; + position: absolute; + text-align: center; + top: 30%; + z-index: 1000; +} + +.cancelada div{ + font-size: 20px; +} + +.emisor-cintilla{ + background-color: #975759; + color: #fff; + font-size: 7pt; + padding: 5px; + text-align: center; +} + +.datos-emisor .logo{ + margin-left: 20px; + max-width: 180px; +} + +.datos-emisor .fiscales-emisor{ + float: right; +} + +.fiscales-emisor{ + color: #7d1916; + font-weight: bold; + margin-top: 20px; + text-align: right; +} + +.fiscales-emisor .nombre{ + font-size: 18px; + padding-right: 30px; +} + +.fiscales-emisor .rfc{ + font-size: 16px; + padding-right: 30px; +} + +.fiscales-emisor .regimen{ + font-size: 12px; + padding-right: 30px; +} + +.fiscales-emisor .telefono, .fiscales-emisor .correo, .fiscales-emisor .web{ + color: #333; + font-size: 14px; + line-height: 15px; + padding-right: 10px; +} + +.fiscales-emisor img{ + margin-left: 10px; + width: 10px; +} + +.clear{ + clear: both; +} + +header .titulo-vertical{ + background-color: #dbc5c6; + -ms-transform: rotate(270deg); + -webkit-transform: rotate(270deg); + transform: rotate(270deg); + font-size: 15px; + font-weight: bold; + left: -31px; + line-height: 35px; + position: absolute; + text-align: center; + top: 35px; + width: 105px; +} + +header .receptor{ + box-sizing: border-box; + float: left; + font-size: 10px; + height: 106px; + margin-top: 10px; + position: relative; + padding-bottom: 5px; + padding-left: 45px; + padding-top: 5px; + width: 65%; +} + +.receptor .nombre{ + color: #000; + font-size: 17px; + font-weight: bold; +} + +.receptor .rfc{ + color: #000; + font-size: 15px; + font-weight: bold; +} + +.receptor .direccion, +.receptor .estado{ + color: #000; + font-size: 10px; +} + +.receptor img{ + width: 10px; +} + +.receptor .correo, +.receptor .telefono{ + float: right; + width: 40%; +} + +.receptor .uso-cfdi{ + color: #000; + font-size: 12px; + font-weight: bold; + float: left; + width: 60%; +} + +header .cfdi{ + box-sizing: border-box; + float: right; + font-size: 10px; + height: 100px; + margin-top: 10px; + position: relative; + padding-bottom: 5px; + padding-left: 45px; + padding-top: 5px; + width: 35%; +} + +.cfdi .folio, .cfdi .tipo{ + color: #000; + float: left; + font-size: 11px; + font-weight: bold; + line-height: 15px; + width: 50%; +} + +.cfdi .folio span, .cfdi .tipo span{ + color: #ed483d; +} + +.cfdi .folio span{ + font-size: 10px; +} + +.cfdi .tipo span{ + font-size: 10px; +} + +.cfdi .folio-fiscal{ + color: #000; + font-size: 10px; + font-weight: bold; + line-height: 15px; + text-align: center; +} + +.cfdi .folio-fiscal span{ + color: #ed483d; +} + +.cfdi .fecha-emision, .cfdi .fecha-certificacion, .cfdi .lugar-expedicion{ + color: #333; + font-size: 10px; + font-weight: bold; + line-height: 15px; +} + +.conceptos{ + margin-bottom: 10px; + margin-top: 20px; + width: 100%; + text-align: center; +} + +.conceptos th{ + background-color: #975759; + color: #fff; + font-size: 11px; + line-height: 15px; +} + +.conceptos .clave{ + width: 10%; +} + +.conceptos .descripcion{ + width: 45%; +} +.conceptos .descripcion div{ + text-align: justify; +} + +.conceptos .unidad{ + width: 8%; +} + +.conceptos .cantidad{ + width: 9%; +} + +.conceptos .valor-unitario{ + width: 13%; +} + +.conceptos .importe{ + width: 15%; +} + +.conceptos td{ + background-color: #975759; + color: #000; + font-size: 11px; + line-height: 15px; +} + +.conceptos td.clave, .conceptos td.unidad, .conceptos td.valor-unitario{ + background-color: #dbc5c6; +} + +.conceptos td.descripcion, .conceptos td.cantidad, .conceptos td.importe{ + background-color: #f0e7e7; +} + +.conceptos td.valor-unitario, .conceptos td.importe{ + text-align: right; +} + +.total-letras{ + float: left; + font-size: 12px; + line-height: 15px; + margin: 4px 0; + width: 63%; +} + +table.subtotal{ + float: right; + font-size: 12px; + line-height: 15px; + text-align: right; + width: 37%; + font-weight: bold; +} + +table.subtotal th{ + background-color: #f0e7e7; + width: 60%; + padding: 3px 3px 3px 3px; +} + +table.subtotal td{ + background-color: #dbc5c6; + width: 40%; + padding: 3px 3px 3px 3px; +} + +.condiciones-pago{ + font-size: 11px; + line-height: 15px; +} + +.notas{ + font-size: 11px; + margin: 20px 0; +} + +.formapago-metodopago, .moneda-tipocambio, .tiporelacion, .relacionados{ + float: left; + font-size: 10px; + line-height: 12px; + width: 85%; +} + +.tipocomite, .tipoproceso, .idcontabilidad{ + float: right; + font-size: 10px; + line-height: 12px; + width: 30%; +} + +.sello{ + margin: 20px 0; +} + +.sello .cbb{ + border: 1px solid #000; + height: auto; + margin-top: 20px; + margin-right: 5%; + width: 15%; +} + +.sello .cadenas-sello{ + color: #000; + float: right; + font-size: 8px; + font-weight: bold; + line-height: 16px; + width: 79%; + margin-left: 2px; + margin-right: 2px; + word-break: break-all; +} + +.sello .cadenas-sello .cadena{ + margin: 10px 0; +} + +.sello .cadenas-sello .cadena div{ + font-weight: normal; + background-color: #dbc5c6; + color: #7d1916; +} + +.sello .cadena-original{ + color: #000; + float: right; + font-size: 8px; + font-weight: bold; + line-height: 16px; + width: 100%; + margin: 10px; + margin-left: 5px; + margin-right: 2px; + word-break: break-all; +} + +.sello .cadena-original div{ + font-weight: normal; + background-color: #dbc5c6; + color: #7d1916; +} + +.rfc-pac{ + background-color: #dbc5c6; + color: #7d1916; + font-size: 10px; + line-height: 16px; + text-align: center; + margin-right: 2px; +} diff --git a/source/static/fonts/avenir_next/.DS_Store b/source/static/fonts/avenir_next/.DS_Store new file mode 100644 index 0000000..7b40fe9 Binary files /dev/null and b/source/static/fonts/avenir_next/.DS_Store differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot new file mode 100755 index 0000000..6ff4d6c Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.svg b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.svg new file mode 100755 index 0000000..3d73033 --- /dev/null +++ b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.svg @@ -0,0 +1,2842 @@ + + + + +Created by FontForge 20161013 at Thu Mar 18 18:16:44 2004 + By ,,, +Copyright (c) 2004 Linotype Library GmbH, www.linotype.com. All rights reserved. This software may not be reproduced, used, displayed, modified, disclosed or transferred without the express written approval of Linotype Library GmbH. Avenir is a trademark of Heidelberger Druckmaschinen AG, exclusively licensed through Linotype Library GmbH, and may be registered in certain jurisdictions. This typeface is original artwork of Adrian Frutiger. The design may be protected in certain jurisdictions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.ttf b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.ttf new file mode 100755 index 0000000..d32eacb Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.ttf differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff new file mode 100755 index 0000000..82bac28 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff2 b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff2 new file mode 100755 index 0000000..018ab10 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff2 differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-It.eot b/source/static/fonts/avenir_next/AvenirNextLTPro-It.eot new file mode 100755 index 0000000..67eff78 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-It.eot differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-It.svg b/source/static/fonts/avenir_next/AvenirNextLTPro-It.svg new file mode 100755 index 0000000..7187cbc --- /dev/null +++ b/source/static/fonts/avenir_next/AvenirNextLTPro-It.svg @@ -0,0 +1,1956 @@ + + + + +Created by FontForge 20161013 at Thu Jan 29 17:13:50 2004 + By ,,, +Copyright (c) 2004 Linotype Library GmbH, www.linotype.com. All rights reserved. This software may not be reproduced, used, displayed, modified, disclosed or transferred without the express written approval of Linotype Library GmbH. Avenir is a trademark of Heidelberger Druckmaschinen AG, exclusively licensed through Linotype Library GmbH, and may be registered in certain jurisdictions. This typeface is original artwork of Adrian Frutiger and Akira Kobayashi. The design may be protected in certain jurisdictions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-It.ttf b/source/static/fonts/avenir_next/AvenirNextLTPro-It.ttf new file mode 100755 index 0000000..433a0a0 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-It.ttf differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-It.woff b/source/static/fonts/avenir_next/AvenirNextLTPro-It.woff new file mode 100755 index 0000000..4afb82b Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-It.woff differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-It.woff2 b/source/static/fonts/avenir_next/AvenirNextLTPro-It.woff2 new file mode 100755 index 0000000..5c1f3b7 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-It.woff2 differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot new file mode 100755 index 0000000..f91a884 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.svg b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.svg new file mode 100755 index 0000000..ea10cd4 --- /dev/null +++ b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.svg @@ -0,0 +1,2825 @@ + + + + +Created by FontForge 20161013 at Thu Jan 29 17:13:34 2004 + By ,,, +Copyright (c) 2004 Linotype Library GmbH, www.linotype.com. All rights reserved. This software may not be reproduced, used, displayed, modified, disclosed or transferred without the express written approval of Linotype Library GmbH. Avenir is a trademark of Heidelberger Druckmaschinen AG, exclusively licensed through Linotype Library GmbH, and may be registered in certain jurisdictions. This typeface is original artwork of Adrian Frutiger and Akira Kobayashi. The design may be protected in certain jurisdictions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.ttf b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.ttf new file mode 100755 index 0000000..ad46859 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.ttf differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff new file mode 100755 index 0000000..f19e41f Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff differ diff --git a/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff2 b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff2 new file mode 100755 index 0000000..32eccb0 Binary files /dev/null and b/source/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff2 differ diff --git a/source/static/img/correo.png b/source/static/img/correo.png new file mode 100644 index 0000000..3e3233f Binary files /dev/null and b/source/static/img/correo.png differ diff --git a/source/static/img/tcm970625mb1.png b/source/static/img/tcm970625mb1.png new file mode 100644 index 0000000..37dbe13 Binary files /dev/null and b/source/static/img/tcm970625mb1.png differ diff --git a/source/static/img/telefono.png b/source/static/img/telefono.png new file mode 100644 index 0000000..edccef9 Binary files /dev/null and b/source/static/img/telefono.png differ diff --git a/source/static/img/web.png b/source/static/img/web.png new file mode 100644 index 0000000..fe9fde2 Binary files /dev/null and b/source/static/img/web.png differ diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index fac40e6..893312e 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -1282,11 +1282,15 @@ function enviar_correo(row){ function get_pdf(id){ - //~ location = '/doc/pdf/' + id window.open('/doc/pdf/' + id, '_blank') } +function get_html(id){ + window.open('/doc/html/' + id, '_blank') +} + + function grid_invoices_click(id, e, node){ var row = this.getItem(id) @@ -1294,6 +1298,8 @@ function grid_invoices_click(id, e, node){ location = '/doc/xml/' + row.id }else if(id.column == 'pdf'){ get_pdf(row.id) + }else if(id.column == 'html'){ + get_html(row.id) }else if(id.column == 'ods'){ location = '/doc/ods/' + row.id }else if(id.column == 'zip'){ diff --git a/source/static/js/controller/util.js b/source/static/js/controller/util.js index bae66bd..e74b00e 100644 --- a/source/static/js/controller/util.js +++ b/source/static/js/controller/util.js @@ -59,6 +59,7 @@ function get_icon(tipo){ icons = { xml: 'fa-file-code-o', pdf: 'fa-file-pdf-o', + html: 'fa-html5', zip: 'fa-file-zip-o', email: 'fa-envelope-o', print: 'fa-print', diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 49fe2f4..09d7e1d 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -267,6 +267,7 @@ var grid_invoices_cols = [ fillspace: true, sort: 'string', footer: {text: '$ 0.00', colspan: 2}}, {id: 'xml', header: 'XML', adjust: 'data', template: get_icon('xml')}, {id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')}, + {id: 'html', header: 'HTML', adjust: 'data', template: get_icon('html')}, {id: 'ods', header: 'ODS', adjust: 'data', template: get_icon('table')}, {id: 'zip', header: 'ZIP', adjust: 'data', template: get_icon('zip')}, {id: 'email', header: '', adjust: 'data', template: get_icon('email')} diff --git a/source/templates/plantilla_factura.html b/source/templates/plantilla_factura.html new file mode 100644 index 0000000..84639cb --- /dev/null +++ b/source/templates/plantilla_factura.html @@ -0,0 +1,191 @@ + + + + + + Empresa Libre + + +
+
+ Cancelada +
Sin valor fiscal
+
+
+
+ ${emisor_calle} ${emisor_noexterior} ${emisor_nointerior} + ${emisor_colonia} ${emisor_codigopostal} ${emisor_municipio} + ${emisor_estado} ${emisor_pais} +
+
+ +
+
+ ${emisor_nombre} +
+
+ ${emisor_rfc} +
+
+ ${emisor_regimenfiscal} +
+
+ (55) 5810-8088 + +
+
+ administracion@empresalibre.net + +
+
+ https://empresalibre.net + +
+
+
+
+
Receptor
+
+ ${receptor_nombre} +
+
+ ${receptor_rfc} +
+
+ ${receptor_calle} ${receptor_noexterior} ${receptor_nointerior} + ${receptor_colonia} ${receptor_codigopostal} +
+
+ ${receptor_municipio} ${receptor_estado} ${receptor_pais} +
+
+ ${receptor_correo_1} +
+
+
+ ${receptor_usocfdi} +
+
+ ${receptor_telefono_1} +
+
+
+
Datos CFDI
+
Folio: ${cfdi_serie}-${cfdi_folio}
+
Tipo: ${cfdi_tipodecomprobante}
+
+
+ Folio Fiscal
+ ${timbre_uuid} +
+
Fecha Emisión: ${cfdi_fecha}
+
Fecha Certificacion: ${timbre_fechatimbrado}
+
CP de Expedición: ${cfdi_lugarexpedicion}
+
+
+
+ +
+ + + + + + + + + + + + + % for c in conceptos: + + + + + + + + + % endfor + +
ClaveDescripciónUnidadCantidadValor UnitarioImporte
${c['clave']}
${c['descripcion']}
${c['unidad']}${c['cantidad']}${c['valorunitario']}${c['importe']}
+ +
+ ${cfdi_totalenletras} +
+ + % for total in totales: + + + + + % endfor +
${total[0]}${total[1]}
+
+
+ ${cfdi_condicionespago} +
+
+ ${cfdi_notas} +
+
+ ${cfdi_formapago}
${cfdi_metodopago} +
+
+ ${cfdi_moneda}, Tipo de Cambio: ${cfdi_tipocambio} +
+
+ {ine.tipocomite} +
+
+ {cfdi.tiporelacion} +
+
+ {ine.tipoproceso} +
+
+ {cfdi.relacionados} +
+
+ {ine.idcontabilidad} +
+ +
+
+ + +
+
+ Sello Digital del CFDI: +
+ ${cfdi_sello} +
+
+
+ Sello del SAT: +
+ ${timbre_sellosat} +
+
+
+
+ +
+
+ Cadena original del complemento de certificación digital del SAT: +
+ ${timbre_cadenaoriginal} +
+
+
+ +
+
+ RFC del PAC que Certifico: ${timbre_rfcprovcertif} + Serie CSD SAT: ${timbre_nocertificadosat} + Serie CSD Emisor: ${cfdi_nocertificado} +
+
+ + diff --git a/source/templates/plantilla_factura.ods b/source/templates/plantilla_factura.ods index 8061850..cab2f95 100644 Binary files a/source/templates/plantilla_factura.ods and b/source/templates/plantilla_factura.ods differ