diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 866b155..885f6d6 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -72,6 +72,7 @@ from .configpac import AUTH # ~ v2 from settings import ( + EXT, MXN, PATHS, ) @@ -2124,35 +2125,55 @@ def get_date(value, next_day=False): return d +class UpFile(object): + + + def __init__(self): + self._init_values() + + def _init_values(self): + + return + + def upload_file(rfc, opt, file_obj): - if opt == 'txt_plantilla_factura_32': - tmp = file_obj.filename.split('.') - ext = tmp[-1].lower() - if ext != 'ods': - msg = 'Extensión de archivo incorrecta, selecciona un archivo ODS' + rfc = rfc.lower() + tmp = file_obj.filename.split('.') + ext = tmp[-1].lower() + + EXTENSIONS = { + 'txt_plantilla_factura_32': EXT['ODS'], + 'txt_plantilla_factura_33': EXT['ODS'], + 'txt_plantilla_factura_html': EXT['HTML'], + 'txt_plantilla_factura_css': EXT['CSS'], + } + + if opt in EXTENSIONS: + if ext != EXTENSIONS[opt]: + msg = ( + f"Extensión de archivo incorrecta, " + f"selecciona un archivo {EXTENSIONS[opt].upper()}" + ) return {'status': 'server', 'name': msg, 'ok': False} - name = '{}_3.2.ods'.format(rfc.lower()) - path = _join(PATH_MEDIA, 'templates', name) - elif opt == 'txt_plantilla_factura_33': - tmp = file_obj.filename.split('.') - ext = tmp[-1].lower() - if ext != 'ods': - msg = 'Extensión de archivo incorrecta, selecciona un archivo ODS' - return {'status': 'server', 'name': msg, 'ok': False} + NAMES = { + 'txt_plantilla_factura_32': f"{rfc}_3.2.ods", + 'txt_plantilla_factura_33': f"{rfc}_3.3.ods", + 'txt_plantilla_factura_html': f"{rfc}_3.3.html", + 'txt_plantilla_factura_css': f"{rfc}.css" + } + name = NAMES[opt] + paths = { + 'txt_plantilla_factura_32': _join(PATHS['USER'], name), + 'txt_plantilla_factura_33': _join(PATHS['USER'], name), + 'txt_plantilla_factura_html': _join(PATHS['USER'], name), + 'txt_plantilla_factura_css': _join(PATHS['CSS'], name), + } + if save_file(paths[opt], file_obj.file.read()): + return {'status': 'server', 'name': file_obj.filename, 'ok': True} + return {'status': 'error', 'ok': False} - name = '{}_3.3.ods'.format(rfc.lower()) - path = _join(PATH_MEDIA, 'templates', name) - elif opt == 'txt_plantilla_factura_33j': - tmp = file_obj.filename.split('.') - ext = tmp[-1].lower() - if ext != 'json': - msg = 'Extensión de archivo incorrecta, selecciona un archivo JSON' - return {'status': 'server', 'name': msg, 'ok': False} - - name = '{}_3.3.json'.format(rfc.lower()) - path = _join(PATH_MEDIA, 'templates', name) - elif opt == 'txt_plantilla_ticket': + if opt == 'txt_plantilla_ticket': tmp = file_obj.filename.split('.') ext = tmp[-1].lower() if ext != 'ods': diff --git a/source/app/models/main.py b/source/app/models/main.py index 7d5241f..cd3b7b7 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -471,7 +471,8 @@ class Configuracion(BaseModel): fields = ( 'txt_plantilla_factura_32', 'txt_plantilla_factura_33', - 'txt_plantilla_factura_33j', + 'txt_plantilla_factura_html', + 'txt_plantilla_factura_css', 'txt_plantilla_nomina1233', 'txt_plantilla_pagos10', 'txt_plantilla_ticket', @@ -846,7 +847,7 @@ class Emisor(BaseModel): emisor = Emisor.select()[0] rfc = emisor.rfc.lower() name = f'{rfc}.png' - path = util._join(PATHS['STATIC'], 'img', name) + path = util._join(PATHS['IMG'], name) if util.save_file(path, file_obj.file.read()): emisor.logo = file_obj.filename emisor.save() @@ -3736,7 +3737,7 @@ class Facturas(BaseModel): for n in node: d = util.get_dict(n.attrib) name = VALUES_PDF['TAX'].get(d['impuesto']) - tasa = FORMAT.format(float(d['tasaocuota'])) + tasa = f"{float(d['tasaocuota']):.2f}" title = f"{type_tax} {name} {tasa}" importe = util.format_currency(d['importe'], currency) data['totales'].append((title, importe)) diff --git a/source/app/settings.py b/source/app/settings.py index 13c166c..76b9086 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -54,6 +54,12 @@ TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION) BASE_DIR = os.path.abspath(os.path.dirname(__file__)) path_static = os.path.abspath(os.path.join(BASE_DIR, '..', 'static')) +path_docs = os.path.abspath(os.path.join(BASE_DIR, '..', 'docs')) + +path_css = os.path.join(path_static, 'css') +path_img = os.path.join(path_static, 'img') +path_user_template = os.path.join(path_docs, 'templates') + # ~ PATH_STATIC = os.path.abspath(os.path.join(BASE_DIR, '..')) PATH_TEMPLATES = os.path.abspath(os.path.join(BASE_DIR, '..', 'templates')) @@ -190,11 +196,18 @@ CURRENCY_MN = 'MXN' # ~ v2 EXT = { + 'CSS': 'css', + 'HTML': 'html', + 'ODS': 'ods', 'PNG': 'png', } MXN = 'MXN' PATHS = { 'STATIC': path_static, + 'CSS': path_css, + 'IMG': path_img, + 'DOCS': path_docs, + 'USER': path_user_template, } VALUES_PDF = { 'CANCEL': {True: 'inline', False: 'none'}, diff --git a/source/static/css/invoice.css b/source/static/css/invoice.css index 788ac7c..e3b4384 100644 --- a/source/static/css/invoice.css +++ b/source/static/css/invoice.css @@ -397,7 +397,7 @@ header .cfdi{ float: left; font-size: 12px; line-height: 15px; - margin: 4px 0; + margin: 5px 0; width: 63%; } @@ -424,19 +424,28 @@ table.subtotal td{ .condiciones-pago{ font-size: 11px; - line-height: 15px; + line-height: 14px; } .notas{ + float: left; font-size: 11px; margin: 20px 0; + width: 70%; } .formapago-metodopago, .moneda-tipocambio, .tiporelacion, .relacionados{ float: left; - font-size: 10px; + font-size: 11px; line-height: 12px; - width: 80%; + width: 70%; +} + +.factura-info{ + float: left; + font-size: 11px; + line-height: 13px; + width: 70%; } .tipocomite, .tipoproceso, .idcontabilidad{ diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index 9569a3c..e17be00 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -69,7 +69,8 @@ var controllers = { tb_options.attachEvent('onChange', tab_options_change) $$('txt_plantilla_factura_32').attachEvent('onItemClick', txt_plantilla_factura_32_click) $$('txt_plantilla_factura_33').attachEvent('onItemClick', txt_plantilla_factura_33_click) - $$('txt_plantilla_factura_33j').attachEvent('onItemClick', txt_plantilla_factura_33j_click) + $$('txt_plantilla_factura_html').attachEvent('onItemClick', txt_plantilla_factura_html_click) + $$('txt_plantilla_factura_css').attachEvent('onItemClick', txt_plantilla_factura_css_click) $$('txt_plantilla_ticket').attachEvent('onItemClick', txt_plantilla_ticket_click) $$('txt_plantilla_donataria').attachEvent('onItemClick', txt_plantilla_donataria_click) $$('txt_plantilla_nomina1233').attachEvent('onItemClick', txt_plantilla_nomina1233_click) @@ -978,13 +979,16 @@ function txt_plantilla_factura_32_click(e){ } -function txt_plantilla_factura_33j_click(e){ +function txt_plantilla_factura_html_click(e){ var body_elements = [ - {cols: [{width: 100}, {view: 'uploader', id: 'up_template', autosend: true, link: 'lst_files', - value: 'Seleccionar archivo', upload: '/files/txt_plantilla_factura_33j', - width: 200}, {width: 100}]}, - {view: 'list', id: 'lst_files', type: 'uploader', autoheight:true, + {cols: [ + {width: 100}, + {view: 'uploader', id: 'up_template', autosend: true, + link: 'lst_files', value: 'Seleccionar archivo', + upload: '/files/txt_plantilla_factura_html', width: 200}, + {width: 100}]}, + {view: 'list', id: 'lst_files', type: 'uploader', autoheight: true, borderless: true}, {}, {cols: [{}, {view: 'button', label: 'Cerrar', autowidth: true, @@ -996,7 +1000,7 @@ function txt_plantilla_factura_33j_click(e){ id: 'win_template', modal: true, position: 'center', - head: 'Subir Plantilla 3.3 JSON', + head: 'Subir Plantilla 3.3 HTML', body: { view: 'form', elements: body_elements, @@ -1007,7 +1011,48 @@ function txt_plantilla_factura_33j_click(e){ $$('up_template').attachEvent('onUploadComplete', function(response){ if(response.ok){ - $$('txt_plantilla_factura_33j').setValue(response.name) + $$('txt_plantilla_factura_html').setValue(response.name) + msg_ok('Plantilla cargada correctamente') + }else{ + msg_error(response.name) + } + }) +} + + +function txt_plantilla_factura_css_click(e){ + + var body_elements = [ + {cols: [ + {width: 100}, + {view: 'uploader', id: 'up_template', autosend: true, + link: 'lst_files', value: 'Seleccionar archivo', + upload: '/files/txt_plantilla_factura_css', width: 200}, + {width: 100}]}, + {view: 'list', id: 'lst_files', type: 'uploader', autoheight: true, + borderless: true}, + {}, + {cols: [{}, {view: 'button', label: 'Cerrar', autowidth: true, + click:("$$('win_template').close();")}, {}]} + ] + + var w = webix.ui({ + view: 'window', + id: 'win_template', + modal: true, + position: 'center', + head: 'Subir Archivo de Estilos CSS', + body: { + view: 'form', + elements: body_elements, + } + }) + + w.show() + + $$('up_template').attachEvent('onUploadComplete', function(response){ + if(response.ok){ + $$('txt_plantilla_factura_css').setValue(response.name) msg_ok('Plantilla cargada correctamente') }else{ msg_error(response.name) diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index c70d80c..29f05d5 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -581,31 +581,33 @@ var form_correo = { var options_templates = [ {maxHeight: 15}, - {cols: [{maxWidth: 15}, + {cols: [{maxWidth: 20}, {view: 'search', id: 'txt_plantilla_factura_32', name: 'plantilla_factura_32', label: 'Plantilla Factura v3.2 (ODS): ', labelPosition: 'top', - icon: 'file'}, {}]}, - {maxHeight: 20}, - {cols: [{maxWidth: 15}, + icon: 'file'}, {maxWidth: 25}, {view: 'search', id: 'txt_plantilla_factura_33', labelPosition: 'top', - label: 'Plantilla Factura v3.3 (ODS): ', icon: 'file'}, {}]}, + label: 'Plantilla Factura v3.3 (ODS): ', icon: 'file'}, + {maxWidth: 20} ]}, {maxHeight: 20}, - {cols: [{maxWidth: 15}, - {view: 'search', id: 'txt_plantilla_factura_33j', name: 'plantilla_factura_33j', - label: 'Plantilla Factura v3.3 (JSON): ', labelPosition: 'top', - icon: 'file'}, {}]}, + {cols: [{maxWidth: 20}, + {view: 'search', id: 'txt_plantilla_factura_html', name: 'plantilla_factura_html', + label: 'Plantilla Factura v3.3 (HTML): ', labelPosition: 'top', + icon: 'file'}, {maxWidth: 25}, + {view: 'search', id: 'txt_plantilla_factura_css', name: 'plantilla_factura_css', + label: 'Archivo de estilos (CSS): ', labelPosition: 'top', + icon: 'file'}, {maxWidth: 20} ]}, {maxHeight: 20}, - {cols: [{maxWidth: 15}, + {cols: [{maxWidth: 20}, {view: 'search', id: 'txt_plantilla_nomina1233', name: 'plantilla_nomina1233', label: 'Plantilla Nomina v1.2 - Cfdi 3.3 (ODS): ', labelPosition: 'top', - icon: 'file'}, {}]}, + icon: 'file'}, {maxWidth: 40}, {}]}, {maxHeight: 20}, - {cols: [{maxWidth: 15}, + {cols: [{maxWidth: 20}, {view: 'search', id: 'txt_plantilla_pagos10', name: 'plantilla_pagos10', label: 'Plantilla Factura de Pagos v1.0 - Cfdi 3.3 (ODS): ', - labelPosition: 'top', icon: 'file'}, {}]}, + labelPosition: 'top', icon: 'file'}, {maxWidth: 40}, {}]}, {maxHeight: 20}, - {cols: [{maxWidth: 15}, + {cols: [{maxWidth: 20}, {view: 'search', id: 'txt_plantilla_ticket', name: 'plantilla_ticket', label: 'Plantilla para Tickets (ODS): ', labelPosition: 'top', icon: 'file'}, diff --git a/source/templates/plantilla_factura.html b/source/templates/plantilla_factura.html index c66689a..f3b6d1c 100644 --- a/source/templates/plantilla_factura.html +++ b/source/templates/plantilla_factura.html @@ -5,7 +5,7 @@ Empresa Libre - +
Cancelada @@ -113,6 +113,36 @@
${cfdi_totalenletras} + +
+ ${cfdi_condicionespago}
+ ${cfdi_formapago}
+ ${cfdi_metodopago}
+ ${cfdi_moneda}, Tipo de Cambio: ${cfdi_tipocambio}
+ ${cfdi_tiporelacion}
+ ${cfdi_relacionados}
+ ${cfdi_notas} +
% for total in totales: @@ -123,34 +153,18 @@ % endfor
+