diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index bc3ac45..ab7323a 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -98,6 +98,8 @@ class AppValues(object): req.context['result'] = self._db.add_unidad(values) elif table == 'addimpuesto': req.context['result'] = self._db.add_impuesto(values) + elif table == 'bdfl': + req.context['result'] = self._db.importar_bdfl() else: req.context['result'] = self._db.validate_cert(values, session) else: diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index a8997a0..3512985 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -1079,24 +1079,22 @@ def _totales(doc, cfdi, version): title = 'Retención {} {}'.format(tmp['impuesto'], '') retenciones.append((title, float(tmp['importe']))) - #~ com = xml.find('%sComplemento' % PRE) - #~ if com is not None: - #~ otros = com.find('%sImpuestosLocales' % IMP_LOCAL) - #~ if otros is not None: - #~ for otro in list(otros): - #~ if otro.tag == '%sRetencionesLocales' % IMP_LOCAL: - #~ name = 'ImpLocRetenido' - #~ tasa = 'TasadeRetencion' - #~ else: - #~ name = 'ImpLocTrasladado' - #~ tasa = 'TasadeTraslado' - #~ title = '%s %s %%' % (otro.attrib[name], otro.attrib[tasa]) - #~ value = otro.attrib['Importe'] - #~ self._copy_cell(cell_title) - #~ self._copy_cell(cell_value) - #~ cell_title = self._set_cell(v=title, cell=cell_title) - #~ cell_value = self._set_cell(v=value, cell=cell_value, value=True) - #~ cell_value.CellStyle = currency + node = doc.find('{}Complemento/{}ImpuestosLocales'.format( + PRE[version], PRE['LOCALES'])) + if node is not None: + for otro in list(node): + if otro.tag == '{}RetencionesLocales'.format(PRE['LOCALES']): + tipo = 'Retención ' + name = 'ImpLocRetenido' + tasa = 'TasadeRetencion' + else: + tipo = 'Traslado ' + name = 'ImpLocTrasladado' + tasa = 'TasadeTraslado' + title = '{} {} {}%'.format( + tipo, otro.attrib[name], otro.attrib[tasa]) + importe = float(otro.attrib['Importe']) + taxlocales.append((title, importe)) data['traslados'] = traslados data['retenciones'] = retenciones @@ -1271,6 +1269,15 @@ def upload_file(rfc, opt, file_obj): name = '{}_3.3_donativo.ods'.format(rfc.lower()) path = _join(PATH_MEDIA, 'templates', name) + elif opt == 'bdfl': + tmp = file_obj.filename.split('.') + ext = tmp[-1].lower() + if ext != 'sqlite': + msg = 'Extensión de archivo incorrecta, selecciona un archivo SQLite' + return {'status': 'server', 'name': msg, 'ok': False} + + name = '{}.sqlite'.format(rfc.lower()) + path = _join('/tmp', name) if save_file(path, file_obj.file.read()): return {'status': 'server', 'name': file_obj.filename, 'ok': True} @@ -1371,9 +1378,10 @@ class ImportFacturaLibre(object): self._error = 'No se encontró al emisor: {}'.format(self._rfc) return False - if obj['rfc'] != self._rfc: - self._error = 'Los datos no corresponden al RFC: {}'.format(self._rfc) - return False + if not DEBUG: + if obj['rfc'] != self._rfc: + self._error = 'Los datos no corresponden al RFC: {}'.format(self._rfc) + return False return True diff --git a/source/app/models/db.py b/source/app/models/db.py index 90d1f4d..f7fa23a 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -32,7 +32,6 @@ class StorageEngine(object): def upload_file(self, session, table, file_obj): if not 'rfc' in session: return {'status': 'error'} - return main.upload_file(session['rfc'], table, file_obj) def get_config(self, values): @@ -273,3 +272,5 @@ class StorageEngine(object): def get_movimientosbanco(self, values): return main.MovimientosBanco.get_(values) + def importar_bdfl(self): + return main.importar_bdfl() diff --git a/source/app/models/main.py b/source/app/models/main.py index e804340..80503f2 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -64,7 +64,8 @@ def desconectar(): def upload_file(rfc, opt, file_obj): result = util.upload_file(rfc, opt, file_obj) if result['ok']: - Configuracion.add({opt: file_obj.filename}) + if opt != 'bdfl': + Configuracion.add({opt: file_obj.filename}) return result @@ -2557,11 +2558,11 @@ class Facturas(BaseModel): impuestos['traslados'] = traslados impuestos['retenciones'] = retenciones - impuestos['total_locales_trasladados'] = '' + impuestos['total_locales_trasladados'] = '0.00' if total_locales_trasladados: impuestos['total_locales_trasladados'] = \ FORMAT.format(total_locales_trasladados) - impuestos['total_locales_retenciones'] = '' + impuestos['total_locales_retenciones'] = '0.00' if total_locales_retenciones: impuestos['total_locales_retenciones'] = \ FORMAT.format(total_locales_retenciones) @@ -3753,7 +3754,6 @@ def _importar_facturas(rows): } FacturasImpuestos.create(**new) except IntegrityError as e: - #~ print (e) msg = '\tFactura: id: {}'.format(row['serie'] + str(row['folio'])) log.error(msg) log.info('\tFacturas importadas...') @@ -3875,6 +3875,35 @@ def _generar_archivo_productos(archivo): return +def importar_bdfl(): + try: + emisor = Emisor.select()[0] + except IndexError: + msg = 'Configura primero al emisor' + return {'ok': False, 'msg': msg} + + name = '{}.sqlite'.format(emisor.rfc.lower()) + path = util._join('/tmp', name) + + log.info('Importando datos...') + app = util.ImportFacturaLibre(path, emisor.rfc) + if not app.is_connect: + msg = app._error + log.error('\t{}'.format(msg)) + return {'ok': False, 'msg': msg} + + data = app.import_data() + + _importar_socios(data['Socios']) + _importar_facturas(data['Facturas']) + _importar_categorias(data['Categorias']) + + msg = 'Importación terminada...' + log.info(msg) + + return {'ok': True, 'msg': msg} + + def _importar_factura_libre(archivo): rfc = input('Introduce el RFC: ').strip().upper() if not rfc: diff --git a/source/app/settings.py b/source/app/settings.py index 58007ca..89029af 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -86,6 +86,7 @@ PRE = { 'TIMBRE': '{http://www.sat.gob.mx/TimbreFiscalDigital}', 'DONATARIA': '{http://www.sat.gob.mx/donat}', 'INE': '{http://www.sat.gob.mx/ine}', + 'LOCALES': '{http://www.sat.gob.mx/implocal}', 'NOMINA': { '1.1': '{http://www.sat.gob.mx/nomina}', '1.2': '{http://www.sat.gob.mx/nomina12}', diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index e1d850c..fb08555 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -44,6 +44,9 @@ var controllers = { $$('txt_plantilla_donataria').attachEvent('onItemClick', txt_plantilla_donataria_click) $$('chk_config_anticipo').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_ine').attachEvent('onItemClick', chk_config_item_click) + + $$('cmd_subir_bdfl').attachEvent('onItemClick', cmd_subir_bdfl_click) + $$('up_bdfl').attachEvent('onUploadComplete', up_bdfl_upload_complete) } } @@ -1320,3 +1323,81 @@ function chk_config_item_click(id, e){ }) } + + +function cmd_subir_bdfl_click(){ + var form = $$('form_upload_bdfl') + + if (!form.validate()){ + msg = 'Valores inválidos' + msg_error(msg) + return + } + + var values = form.getValues() + + if($$('lst_bdfl').count() < 1){ + msg = 'Selecciona la base de datos SQLite de Factura Libre' + msg_error(msg) + return + } + + if($$('lst_bdfl').count() > 1){ + msg = 'Selecciona solo un archivo' + msg_error(msg) + return + } + + var bdfl = $$('up_bdfl').files.getItem($$('up_bdfl').files.getFirstId()) + + var ext = [] + if(bdfl.type.toLowerCase() != 'sqlite'){ + msg = 'Archivo inválido, se requiere un archivo SQLITE' + msg_error(msg) + return + } + + msg = '¿Estás seguro de subir este archivo?' + webix.confirm({ + title: 'Base de datos de Factura Libre', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + $$('up_bdfl').send() + } + } + }) +} + + +function up_bdfl_upload_complete(response){ + if(response.status != 'server'){ + msg = 'Ocurrio un error al subir los archivos' + msg_error(msg) + return + } + + msg = 'Archivo subido correctamente' + msg_ok(msg) + + $$('form_upload_bdfl').setValues({}) + $$('up_bdfl').files.data.clearAll() + + //~ webix.ajax().post('/values/bdfl', {}, { + //~ error:function(text, data, XmlHttpRequest){ + //~ msg = 'Ocurrio un error, consulta a soporte técnico' + //~ msg_error(msg) + //~ }, + //~ success:function(text, data, XmlHttpRequest){ + //~ var values = data.json() + //~ if(values.ok){ + //~ msg_ok(values.msg) + //~ }else{ + //~ msg_error(values.msg) + //~ } + //~ } + //~ }) +} \ No newline at end of file diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index 0ba0be3..be017fb 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -467,6 +467,33 @@ var tab_options = { } +var utilidades_archivos = [ + {maxHeight: 15}, + {template: 'Cargar Base de Datos de Factura Libre', type: 'section'}, + {view: 'form', id: 'form_upload_bdfl', rows: [ + {cols: [{}, + {view: 'uploader', id: 'up_bdfl', autosend: false, link: 'lst_bdfl', + value: 'Seleccionar base de datos', upload: '/files/bdfl'}, {}]}, + {cols: [{}, + {view: 'list', id: 'lst_bdfl', name: 'bdfl', + type: 'uploader', autoheight: true, borderless: true}, {}]}, + {cols: [{}, {view: 'button', id: 'cmd_subir_bdfl', + label: 'Subir base de datos de Factura Libre'}, {}]}, + ]}, +{}] + + +var tab_utilidades = { + view: 'tabview', + id: 'tab_utilidades', + multiview: true, + animate: true, + cells: [ + {id: 'Utilidades', rows: utilidades_archivos}, + ], +} + + var grid_admin_taxes_cols = [ {id: 'id', header: 'ID', hidden: true}, {id: 'delete', header: '', width: 30, css: 'delete'}, @@ -768,6 +795,16 @@ var app_options = { } +var app_utilidades = { + id: 'app_utilidades', + rows:[ + {view: 'template', id: 'th_utilidades', type: 'header', + template: 'Herramientas'}, + tab_utilidades, + ], +} + + var multi_admin = { id: 'multi_admin', animate: true, @@ -782,6 +819,7 @@ var multi_admin = { app_correo, app_sat, app_options, + app_utilidades, ], } diff --git a/source/templates/base.html b/source/templates/base.html index 253cdcc..dd5df6e 100644 --- a/source/templates/base.html +++ b/source/templates/base.html @@ -7,7 +7,7 @@ - + <%block name="media"/> diff --git a/source/xslt/donat11.xslt b/source/xslt/donat11.xslt index 1f0d7a4..24d4363 100644 --- a/source/xslt/donat11.xslt +++ b/source/xslt/donat11.xslt @@ -1,13 +1,13 @@ - + - - - - - - - - - + + + + + + + + + diff --git a/source/xslt/implocal.xslt b/source/xslt/implocal.xslt index dd95023..80b8d23 100644 --- a/source/xslt/implocal.xslt +++ b/source/xslt/implocal.xslt @@ -1,39 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/xslt/ine11.xslt b/source/xslt/ine11.xslt index 06def84..05c1e56 100644 --- a/source/xslt/ine11.xslt +++ b/source/xslt/ine11.xslt @@ -1,5 +1,5 @@  - +