diff --git a/README.md b/README.md index fe9bc4f..5149ff2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Este proyecto está en continuo desarrollo, contratar un esquema de soporte, nos ayuda a continuar su desarrollo. Ponte en contacto con nosotros para -contratar: administracion@empresalibre.net +contratar: administracion ARROBA empresalibre.net ### Requerimientos: diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 18ce108..e3c3924 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -71,6 +71,13 @@ class AppValues(object): req.context['result'] = self._db.get_values(table, values) resp.status = falcon.HTTP_200 + def on_delete(self, req, resp, table): + values = req.params + if self._db.delete(table, values['id']): + resp.status = falcon.HTTP_200 + else: + resp.status = falcon.HTTP_204 + def on_post(self, req, resp, table): file_object = req.get_param('upload') if file_object is None: @@ -84,6 +91,8 @@ class AppValues(object): req.context['result'] = self._db.enviar_prefac(values) elif table == 'addunidad': req.context['result'] = self._db.add_unidad(values) + elif table == 'addimpuesto': + req.context['result'] = self._db.add_impuesto(values) 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 d8b4898..f1fb86d 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -36,7 +36,7 @@ from dateutil import parser from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice from settings import DEBUG, log, template_lookup, COMPANIES, DB_SAT, \ PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PATH_MEDIA, PRE, \ - PATH_XMLSEC, TEMPLATE_CANCEL + PATH_XMLSEC, TEMPLATE_CANCEL, IMPUESTOS #~ def _get_hash(password): diff --git a/source/app/models/db.py b/source/app/models/db.py index f526a94..c0b498b 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -85,6 +85,9 @@ class StorageEngine(object): def add_unidad(self, values): return main.SATUnidades.add(values) + def add_impuesto(self, values): + return main.SATImpuestos.add(values) + def _get_taxes(self, values): return main.SATImpuestos.get_activos() @@ -153,6 +156,8 @@ class StorageEngine(object): return main.Folios.remove(id) if table == 'preinvoice': return main.PreFacturas.remove(id) + if table == 'satimpuesto': + return main.SATImpuestos.remove(id) return False def _get_client(self, values): diff --git a/source/app/models/main.py b/source/app/models/main.py index ec9e0b5..b304403 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -15,7 +15,7 @@ if __name__ == '__main__': from controllers import util from settings import log, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \ - INIT_VALUES, DEFAULT_PASSWORD, DECIMALES + INIT_VALUES, DEFAULT_PASSWORD, DECIMALES, IMPUESTOS FORMAT = '{0:.2f}' @@ -740,9 +740,43 @@ class SATImpuestos(BaseModel): (('key', 'factor', 'tipo', 'tasa'), True), ) + @classmethod + def add(self, values): + tasa = float(values['tasa']) + tipo = 'T' + if tasa < 0: + tipo: 'R' + + row = { + 'key': IMPUESTOS.get(values['impuesto']), + 'name': values['impuesto'], + 'tipo': tipo, + 'tasa': abs(tasa), + } + try: + obj = SATImpuestos.create(**row) + row['id'] = obj.id + row['delete'] = '-' + return {'ok': True, 'row': row} + except IntegrityError: + return {'ok': False, 'msg': 'El impuesto ya existe'} + + @classmethod + def remove(cls, id): + with database_proxy.transaction(): + q = SATImpuestos.delete().where(SATImpuestos.id==id) + return bool(q.execute()) + @classmethod def get_(self): - rows = SATImpuestos.select().dicts() + rows = (SATImpuestos.select( + SATImpuestos.id, + SQL(" '-' AS delete"), + SATImpuestos.name, + SATImpuestos.tipo, + SATImpuestos.tasa) + .dicts() + ) return tuple(rows) @classmethod diff --git a/source/app/settings.py b/source/app/settings.py index a2e008d..c670fb1 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -93,3 +93,12 @@ PRE = { CURRENT_CFDI = '3.3' DEFAULT_PASSWORD = 'blades3.3' DECIMALES = 2 +IMPUESTOS = { + 'ISR': '001', + 'IVA': '002', + 'IEPS': '003', + 'ISH': '000', + 'INSPECCION DE OBRA': '000', + 'ICIC': '000', + 'CEDULAR': '000', +} diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index b09f472..dfabde5 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -27,10 +27,12 @@ var controllers = { tb_sat = $$('tab_sat').getTabbar() tb_sat.attachEvent('onChange', tab_sat_change) $$('grid_admin_taxes').attachEvent('onCheck', grid_admin_taxes_on_check) + $$('grid_admin_taxes').attachEvent('onItemClick', grid_admin_taxes_click) $$('grid_admin_monedas').attachEvent('onCheck', grid_admin_monedas_on_check) $$('grid_admin_bancos').attachEvent('onCheck', grid_admin_bancos_on_check) $$('grid_admin_unidades').attachEvent('onCheck', grid_admin_unidades_on_check) $$('grid_unidad_found').attachEvent('onValueSuggest', grid_unidad_found_click) + $$('cmd_agregar_impuesto').attachEvent('onItemClick', cmd_agregar_impuesto_click) //~ Opciones tb_options = $$('tab_options').getTabbar() tb_options.attachEvent('onChange', tab_options_change) @@ -992,7 +994,7 @@ function agregar_nueva_unidad(obj){ webix.ajax().post('/values/addunidad', values, { error: function(text, data, xhr) { - webix.message({type: 'error', text: 'Error al consultar'}) + webix.message({type: 'error', text: 'Error al agregar'}) }, success: function(text, data, xhr){ var values = data.json() @@ -1005,8 +1007,6 @@ function agregar_nueva_unidad(obj){ function grid_unidad_found_click(obj){ - - msg = '¿Estás seguro de agregar la siguiente unidad?' msg += '(' + obj.key + ')
' msg += obj.name @@ -1025,3 +1025,103 @@ function grid_unidad_found_click(obj){ }) $$('buscar_nueva_unidad').setValue('') } + + +function agregar_impuesto(impuesto, tasa){ + var grid = $$('grid_admin_taxes') + var values = {impuesto: impuesto, tasa: tasa} + + webix.ajax().post('/values/addimpuesto', values, { + error: function(text, data, xhr) { + webix.message({type: 'error', text: 'Error al agregar'}) + }, + success: function(text, data, xhr){ + var values = data.json() + if (values.ok){ + $$('lst_admin_impuestos').setValue('') + $$('txt_admin_tasa').setValue('') + grid.add(values.row) + }else{ + msg_error(values.msg) + } + } + }) +} + + +function cmd_agregar_impuesto_click(){ + var impuesto = $$('lst_admin_impuestos').getValue().trim() + var tasa = $$('txt_admin_tasa').getValue().trim() + + if(!impuesto){ + msg = 'Selecciona un impuesto' + msg_error(msg) + return + } + if(!tasa){ + msg = 'Captura una tasa' + msg_error(msg) + return + } + if(!isFinite(tasa)){ + msg = 'La tasa debe ser un número' + msg_error(msg) + return + } + + tasa = parseFloat(tasa) + if(tasa >= 1){ + msg = 'La tasa debe ser menor a uno' + msg_error(msg) + return + } + + msg = 'Datos correctos.

¿Estás seguro de agregar este impuesto?' + webix.confirm({ + title: 'Agregar impuesto', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + agregar_impuesto(impuesto, tasa) + } + } + }) +} + + +function borrar_impuesto(row){ + var grid = $$('grid_admin_taxes') + + webix.ajax().del('/values/satimpuesto', {id: row}, function(text, xml, xhr){ + var msg = 'Impuesto eliminado correctamente' + if(xhr.status == 200){ + grid.remove(row) + msg_sucess(msg) + } + }) +} + + +function grid_admin_taxes_click(id, e, node){ + if(id.column != 'delete'){ + return + } + + msg = '¿Estás seguro de borrar el impuesto seleccionado?' + webix.confirm({ + title: 'Borrar impuesto', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + borrar_impuesto(id.row) + } + } + }) + +} diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index da7ab85..d4461cd 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -21,7 +21,7 @@ var sidebar_admin = { onAfterSelect: function(id){ $$('multi_admin').setValue(id) } - } + }, } @@ -154,7 +154,7 @@ var grid_emisor_cuentas_banco = { adjust: true, autoheight: true, headermenu: true, - columns: grid_emisor_cuentas_banco_cols + columns: grid_emisor_cuentas_banco_cols, } @@ -239,7 +239,7 @@ var form_emisor = { rules: { emisor_nombre: function(value){return value.trim() != ''}, } - }] + }], } @@ -266,7 +266,7 @@ var grid_folios = { select: 'row', adjust: true, headermenu: true, - columns: grid_folios_cols + columns: grid_folios_cols, } @@ -384,7 +384,7 @@ var form_folios = { folio_serie: function(value){return value.trim() != ''}, folio_inicio: function(value){return value > 0}, } - }] + }], } @@ -400,7 +400,7 @@ var form_correo = { labelAlign: 'right' }, autoheight: true - }] + }], } @@ -434,13 +434,14 @@ var tab_options = { {id: 'Plantillas', rows: options_templates}, {id: 'Otros', rows: [{}]}, {}, - ] + ], } var grid_admin_taxes_cols = [ {id: 'id', header: 'ID', hidden: true}, - {id: 'name', header: 'Nombre'}, + {id: 'delete', header: '', width: 30, css: 'delete'}, + {id: 'name', header: 'Nombre', adjust: 'data'}, {id: 'tipo', header: 'Tipo'}, {id: 'tasa', header: 'Tasa'}, {id: 'activo', header: 'Activo', template: '{common.checkbox()}', @@ -490,7 +491,7 @@ var grid_admin_taxes = { autoheight: true, autowidth: true, headermenu: true, - columns: grid_admin_taxes_cols + columns: grid_admin_taxes_cols, } @@ -503,7 +504,7 @@ var grid_admin_monedas = { autoheight: true, autowidth: true, headermenu: true, - columns: grid_admin_monedas_cols + columns: grid_admin_monedas_cols, } @@ -516,7 +517,7 @@ var grid_admin_bancos = { autowidth: true, headermenu: true, footer: true, - columns: grid_admin_bancos_cols + columns: grid_admin_bancos_cols, } @@ -530,15 +531,28 @@ var grid_admin_unidades = { autoheight: true, headermenu: true, footer: true, - columns: grid_admin_unidades_cols + columns: grid_admin_unidades_cols, } +var admin_sat_impuestos = {cols: [{maxWidth: 15}, + {view: 'richselect', id: 'lst_admin_impuestos', label: 'Impuesto', options: + ['ISR', 'IVA', 'IEPS', 'ISH', 'INSPECCION DE OBRA', 'ICIC', 'CEDULAR'], + labelAlign: 'right', required: true}, + {view: 'text', id: 'txt_admin_tasa', label: 'Tasa', labelAlign: 'right', + required: true}, + {view: 'button', id: 'cmd_agregar_impuesto', label: 'Agregar', + autowidth: true, type: 'iconButton', icon: 'plus'}, +{}],} + + var msg_tax = 'Activa los impuestos que uses. El predeterminado se muestra primero' var sat_impuestos = [ {maxHeight: 20}, {cols: [{maxWidth: 15}, {view: 'label', label: msg_tax}, {}]}, {maxHeight: 20}, + {cols: [{maxWidth: 15}, admin_sat_impuestos]}, + {maxHeight: 20}, {cols: [{maxWidth: 15}, grid_admin_taxes, {}]}, {}] @@ -584,7 +598,7 @@ var suggest_sat_unidad = { this.hide() } } - } + }, } @@ -626,7 +640,7 @@ var tab_sat = { {id: 'Monedas', rows: sat_monedas}, {id: 'Bancos', rows: sat_bancos}, {id: 'Unidades', rows: sat_unidades}, - ] + ], } @@ -643,7 +657,7 @@ var app_emisor = { {}] }, {}, - ] + ], } @@ -654,7 +668,7 @@ var app_folios = { template: 'Folios'}, form_folios, {}, - ] + ], } @@ -665,7 +679,7 @@ var app_correo = { template: 'Configuración de correo'}, form_correo, {}, - ] + ], } @@ -675,7 +689,7 @@ var app_sat = { {view: 'template', id: 'th_sat', type: 'header', template: 'Catálogos del SAT'}, tab_sat, - ] + ], } @@ -685,7 +699,7 @@ var app_options = { {view: 'template', id: 'th_options', type: 'header', template: 'Opciones'}, tab_options, - ] + ], } @@ -703,7 +717,7 @@ var multi_admin = { app_correo, app_sat, app_options, - ] + ], } @@ -717,7 +731,7 @@ var menu_user = { ], type: { subsign: true, - } + }, } @@ -742,7 +756,7 @@ var ui_admin = { ] } ] -}; +} diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index b99c319..d2c3d82 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -582,7 +582,7 @@ var app_invoices = { rows:[ {view: "template", id: "th_invoices", type: "header", template:"Administración de Facturas" }, multi_invoices - ] + ], }