diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 0fe369e..83f0446 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -94,15 +94,20 @@ class AppValues(object): def on_get(self, req, resp, table): values = req.params + session = req.env['beaker.session'] if table == 'admin': - session = req.env['beaker.session'] req.context['result'] = session['userobj'].es_admin else: - req.context['result'] = self._db.get_values(table, values) + req.context['result'] = self._db.get_values(table, values, session) resp.status = falcon.HTTP_200 def on_delete(self, req, resp, table): values = req.params + session = req.env['beaker.session'] + if table == 'usuario' and (session['userobj'].id == int(values['id'])): + resp.status = falcon.HTTP_204 + return + if self._db.delete(table, values['id']): resp.status = falcon.HTTP_200 else: @@ -123,6 +128,10 @@ class AppValues(object): req.context['result'] = self._db.add_unidad(values) elif table == 'addimpuesto': req.context['result'] = self._db.add_impuesto(values) + elif table == 'addusuario': + req.context['result'] = self._db.add_usuario(values) + elif table == 'editusuario': + req.context['result'] = self._db.edit_usuario(values) elif table == 'bdfl': req.context['result'] = self._db.importar_bdfl() else: diff --git a/source/app/models/db.py b/source/app/models/db.py index 6398df5..c2b74f2 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -20,7 +20,9 @@ class StorageEngine(object): def _get_empresas(self, values): return main.get_empresas() - def get_values(self, table, values=None): + def get_values(self, table, values=None, session=None): + if table in ('allusuarios', 'usuarioupdate'): + return getattr(self, '_get_{}'.format(table))(values, session) return getattr(self, '_get_{}'.format(table))(values) def _get_main(self, values): @@ -108,6 +110,12 @@ class StorageEngine(object): def add_impuesto(self, values): return main.SATImpuestos.add(values) + def add_usuario(self, values): + return main.Usuarios.add(values) + + def edit_usuario(self, values): + return main.Usuarios.edit(values) + def _get_taxes(self, values): return main.SATImpuestos.get_activos() @@ -126,6 +134,12 @@ class StorageEngine(object): def _get_allformasdepago(self, values): return main.SATFormaPago.get_() + def _get_allusuarios(self, values, session): + return main.Usuarios.get_(session['userobj']) + + def _get_usuarioupdate(self, values, session): + return main.Usuarios.actualizar(values, session['userobj']) + def _get_taxupdate(self, values): return main.SATImpuestos.actualizar(values) @@ -191,6 +205,8 @@ class StorageEngine(object): return main.CuentasBanco.remove(id) if table == 'movbanco': return main.MovimientosBanco.remove(id) + if table == 'usuario': + return main.Usuarios.remove(id) return False def _get_client(self, values): diff --git a/source/app/models/main.py b/source/app/models/main.py index 7dd6033..344bf12 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -236,6 +236,73 @@ class Usuarios(BaseModel): class Meta: order_by = ('nombre', 'apellidos') + @classmethod + def add(cls, values): + values['contraseña'] = values.pop('contra') + try: + Usuarios.create(**values) + return {'ok': True} + except Exception as e: + log.error(e) + msg = 'Ocurrio un error, consulta a soporte técnico' + return {'ok': False, 'msg': msg} + + @classmethod + def remove(cls, id): + q = Usuarios.delete().where(Usuarios.id==int(id)) + return bool(q.execute()) + + @classmethod + def edit(self, values): + print (values) + id = int(values.pop('id')) + try: + q = Usuarios.update(**values).where(Usuarios.id==id) + result = {'ok': bool(q.execute())} + except IntegrityError: + msg = 'El usuario ya existe' + result = {'ok': False, 'msg': msg} + + return result + + @classmethod + def actualizar(self, values, user): + id = int(values['id']) + v = {'0': False, '1': True} + + if values['field'] == 'es_superusuario' and not user.es_superusuario: + msg = 'Solo un super usuario puede hacer este cambio' + return {'ok': False, 'msg': msg} + + if values['field'] == 'es_activo': + q = (Usuarios + .update(**{'es_activo': v[values['value']]}) + .where(Usuarios.id==id)) + result = bool(q.execute()) + elif values['field'] == 'es_admin': + q = (Usuarios + .update(**{'es_admin': v[values['value']]}) + .where(Usuarios.id==id)) + result = bool(q.execute()) + elif values['field'] == 'es_superusuario': + q = (Usuarios + .update(**{'es_superusuario': v[values['value']]}) + .where(Usuarios.id==id)) + result = bool(q.execute()) + + return {'ok': result} + + @classmethod + def get_(cls, user): + if user.es_superusuario: + rows = Usuarios.select().dicts() + else: + filters = (Usuarios.es_superusuario == False) + rows = Usuarios.select().where(filters).dicts() + for row in rows: + del row['contraseña'] + return tuple(rows) + class Registro(BaseModel): usuario = TextField() diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index fb08555..4c87b0b 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -35,6 +35,13 @@ var controllers = { $$('grid_admin_formasdepago').attachEvent('onCheck', grid_admin_formasdepago_on_check) $$('grid_unidad_found').attachEvent('onValueSuggest', grid_unidad_found_click) $$('cmd_agregar_impuesto').attachEvent('onItemClick', cmd_agregar_impuesto_click) + //~ Usuarios + $$('cmd_usuario_agregar').attachEvent('onItemClick', cmd_usuario_agregar_click) + $$('grid_usuarios').attachEvent('onItemClick', grid_usuarios_click) + $$('grid_usuarios').attachEvent('onCheck', grid_usuarios_on_check) + $$('grid_usuarios').attachEvent('onItemDblClick', grid_usuarios_double_click) + admin_ui_windows.init() + //~ Opciones tb_options = $$('tab_options').getTabbar() tb_options.attachEvent('onChange', tab_options_change) @@ -303,6 +310,15 @@ function get_admin_formasdepago(){ } +function get_admin_usuarios(){ + webix.ajax().sync().get('/values/allusuarios', function(text, data){ + var values = data.json() + $$('grid_usuarios').clearAll() + $$('grid_usuarios').parse(values, 'json') + }) +} + + function get_config_values(opt){ if(opt == undefined){ return @@ -353,6 +369,11 @@ function multi_admin_change(prevID, nextID){ return } + if(nextID == 'app_usuarios'){ + get_admin_usuarios() + return + } + if(nextID == 'app_options'){ get_config_values('templates') return @@ -1385,19 +1406,216 @@ function up_bdfl_upload_complete(response){ $$('form_upload_bdfl').setValues({}) $$('up_bdfl').files.data.clearAll() +} + + +function cmd_usuario_agregar_click(){ + var form = $$('form_usuario') + + if (!form.validate()){ + msg = 'Valores inválidos' + msg_error(msg) + return + } + + var values = form.getValues() + + if(!values.usuario_usuario.trim()){ + msg = 'El campo Usuario no puede estar vacío' + msg_error(msg) + return + } + + var rows = $$('grid_usuarios').data.getRange() + for (i = 0; i < rows.length; i++) { + if(rows[i]['usuario'] == values.usuario_usuario.trim()){ + msg = 'El usuario ya existe' + msg_error(msg) + return + } + } + + if(!values.usuario_contra1.trim()){ + msg = 'El campo Contraseña no puede estar vacío' + msg_error(msg) + return + } + + if(values.usuario_contra1.trim().length < 5){ + msg = 'El campo Contraseña debe tener al menos 5 caracteres' + msg_error(msg) + return + } + + if(!values.usuario_contra2.trim()){ + msg = 'El campo Confirmación de contraseña no puede estar vacío' + msg_error(msg) + return + } + + if(values.usuario_contra1.trim() != values.usuario_contra2.trim()){ + msg = 'Las contraseñas no coinciden' + msg_error(msg) + return + } + + var values = { + usuario: values.usuario_usuario.trim(), + contra: values.usuario_contra1.trim(), + } + + msg = 'Datos correctos.

¿Estás seguro de agregar al nuevo usuario?' + webix.confirm({ + title: 'Agregar Usuario', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + webix.ajax().post('/values/addusuario', values, { + 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){ + get_admin_usuarios() + msg_ok('Usuario agregado correctamente') + }else{ + msg_error(values.msg) + } + } + }) + } + } + }) +} + + +function grid_usuarios_double_click(id, e, node){ + $$('win_edit_usuario').show() +} + + +function grid_usuarios_click(id, e, node){ + if(id.column != 'delete'){ + return + } + + msg = '¿Estás seguro de borrar al usuario seleccionado?

ESTA ACCIÓN NO SE PUEDE DESHACER' + webix.confirm({ + title: 'Borrar Usuario', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + webix.ajax().del('/values/usuario', {id: id.row}, function(text, xml, xhr){ + msg = 'Usuario eliminado correctamente' + if(xhr.status == 200){ + $$('grid_usuarios').remove(id.row) + msg_ok(msg) + }else{ + msg = 'No se pudo eliminar. Asegurate de no intentar autoeliminarte' + msg_error(msg) + } + }) + } + } + }) +} + + +function grid_usuarios_on_check(row, column, state){ + + var values = { + id: row, + field: column, + value: state, + } + webix.ajax().get('/values/usuarioupdate', values, { + error: function(text, data, xhr) { + }, + success: function(text, data, xhr) { + var values = data.json() + if(values.ok){ + msg = 'Usuario actualizado correctamente' + msg_ok(msg) + }else{ + msg_error(values.msg) + } + } + }) +} + + +function update_grid_usuarios(form, win){ + var values = form.getValues() + + if (!form.validate()){ + msg = 'Valores inválidos' + msg_error(msg) + return + } + + if(!values.usuario.trim()){ + focus('txt_usuario_usuario') + msg = 'El usuario no puede estar vacío' + msg_error(msg) + return + } + if(!values.nombre.trim()){ + focus('txt_usuario_nombre') + msg = 'El nombre no puede estar vacío' + msg_error(msg) + return + } + + if(values.contra1.trim() != values.contra2.trim()){ + msg = 'Las contraseñas no coinciden' + msg_error(msg) + return + } + + if(values.contra1.trim().length > 0 && values.contra1.trim().length < 5){ + msg = 'El campo Contraseña debe tener al menos 5 caracteres' + msg_error(msg) + return + } + if(values.correo.trim()){ + if(!validate_email(values.correo.trim())){ + msg = 'Correo inválido' + msg_error(msg) + return + } + } + + var values = { + id: values.id, + usuario: values.usuario.trim(), + nombre: values.nombre.trim(), + apellidos: values.apellidos.trim(), + correo: values.correo.trim(), + contra: values.contra1.trim(), + } + + webix.ajax().post('/values/editusuario', values, { + error: function(text, data, xhr) { + }, + success: function(text, data, xhr) { + var values = data.json() + if(values.ok){ + msg = 'Usuario actualizado correctamente' + msg_ok(msg) + form.save() + win.hide() + }else{ + msg_error(values.msg) + } + } + }) - //~ 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 be017fb..ed40a97 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -1,10 +1,59 @@ + +var form_editar_usuario_elementos = [ + {view: "text", id: 'txt_usuario_usuario', label: "Usuario", + name: "usuario", labelPosition: 'top', required: true}, + {view: "text", id: 'txt_usuario_nombre', label: "Nombre", name: "nombre", + labelPosition: 'top', required: true}, + {view: "text", id: 'txt_usuario_apellidos', label: "Apellidos", + name: "apellidos", labelPosition: 'top'}, + {view: "text", id: 'txt_usuario_correo', label: "Correo", name: "correo", + labelPosition: 'top'}, + {view: 'text', id: 'txt_usuarioe_contra1', name: 'contra1', + label: 'Contraseña: ', type: 'password', + labelPosition: 'top'}, + {view: 'text', id: 'txt_usuarioe_contra2', name: 'contra2', + label: 'Confirmación de contraseña: ', + type: 'password', labelPosition: 'top'}, + {cols:[ + {view: "button", value: "Cancelar", click:function(){ + this.getTopParentView().hide(); + }}, + {view: "button", type:"form", value: "Guardar", + click:function(){ + update_grid_usuarios(this.getFormView(), this.getTopParentView()) + } + } + ]} +] + +var admin_ui_windows = { + init: function(){ + webix.ui({ + view: 'window', + id: 'win_edit_usuario', + head: 'Editar Usuario', + modal: true, + position: 'center', + body: { + view: 'form', id: 'form_editar_usuario', + elements: form_editar_usuario_elementos + } + }) + + $$('form_editar_usuario').bind($$('grid_usuarios')) + + } +} + + var menu_data = [ {id: 'app_home', icon: 'dashboard', value: 'Inicio'}, {id: 'app_emisor', icon: 'user-circle', value: 'Emisor'}, {id: 'app_folios', icon: 'sort-numeric-asc', value: 'Folios'}, {id: 'app_correo', icon: 'envelope-o', value: 'Correo'}, {id: 'app_sat', icon: 'table', value: 'Catalogos SAT'}, + {id: 'app_usuarios', icon: 'users', value: 'Usuarios'}, {id: 'app_options', icon: 'check-circle-o', value: 'Opciones'}, {id: 'app_utilidades', icon: 'cog', value: 'Utilidades'}, ] @@ -736,6 +785,82 @@ var tab_sat = { } +var usuarios_agregar = [{cols: [ + {maxWidth: 20}, + {view: 'text', id: 'txt_usuario_usuario', name: 'usuario_usuario', + label: 'Usuario: ', labelPosition: 'top', required: true}, + {view: 'text', id: 'txt_usuario_contra1', name: 'usuario_contra1', + required: true, label: 'Contraseña: ', type: 'password', + labelPosition: 'top'}, + {view: 'text', id: 'txt_usuario_contra2', name: 'usuario_contra2', + required: true, label: 'Confirmación de contraseña: ', + type: 'password', labelPosition: 'top'}, + {view: 'button', id: 'cmd_usuario_agregar', label: 'Agregar', + autowidth: true, type: 'iconButton', icon: 'plus'}, + {maxWidth: 20}, +]}] + + +var grid_usuarios_cols = [ + {id: 'id', header: 'ID', hidden: true}, + {id: 'delete', header: '', width: 30, css: 'delete'}, + {id: 'usuario', header: 'Usuario', fillspace: 1}, + {id: 'nombre', header: 'Nombre', fillspace: 1}, + {id: 'apellidos', header: 'Apellidos', fillspace: 2}, + {id: 'correo', header: 'Correo Electrónico', fillspace: 2}, + {id: 'fecha_ingreso', header: 'Fecha de Ingreso', fillspace: 1, + hidden: true}, + {id: 'ultimo_ingreso', header: 'Ultimo Ingreso', fillspace: 1, + hidden: true}, + {id: 'es_activo', header: 'Activo', template: '{common.checkbox()}', + editor: 'checkbox', adjust: 'header'}, + {id: 'es_admin', header: 'Es Admin', template: '{common.checkbox()}', + editor: 'checkbox', adjust: 'header'}, + {id: 'es_superusuario', header: 'Es SU', template: '{common.checkbox()}', + editor: 'checkbox', adjust: 'header'}, +] + + +var grid_usuarios = { + view: 'datatable', + id: 'grid_usuarios', + select: 'row', + adjust: true, + headermenu: true, + footer: true, + columns: grid_usuarios_cols, + on:{ + 'data->onStoreUpdated':function(){ + this.data.each(function(obj, i){ + obj.delete = '-' + }) + } + } +} + + +var usuarios_admin = [ + {maxHeight: 10}, + {template: 'Agregar Usuario', type: 'section'}, + {view: 'form', id: 'form_usuario', rows: usuarios_agregar}, + {maxHeight: 20}, + {template: 'Usuarios Registrados', type: 'section'}, + {cols: [{maxWidth: 10}, grid_usuarios, {maxWidth: 10}]}, + {}, +] + + +var tab_usuarios = { + view: 'tabview', + id: 'tab_usuarios', + multiview: true, + animate: true, + cells: [ + {id: 'Usuarios', rows: usuarios_admin}, + ], +} + + var app_emisor = { id: 'app_emisor', rows:[ @@ -785,6 +910,16 @@ var app_sat = { } +var app_usuarios = { + id: 'app_usuarios', + rows:[ + {view: 'template', id: 'th_usuarios', type: 'header', + template: 'Administración de Usuarios'}, + tab_usuarios, + ], +} + + var app_options = { id: 'app_options', rows:[ @@ -818,6 +953,7 @@ var multi_admin = { app_folios, app_correo, app_sat, + app_usuarios, app_options, app_utilidades, ], @@ -874,3 +1010,5 @@ var body_win_emisor_logo = [ click:("$$('win_emisor_logo').close();")}, {}]} ] + +