From 361aa131d38d892812f6d377559552435bfb76d1 Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Sat, 7 Oct 2017 23:52:11 -0500 Subject: [PATCH] Guardar emisor --- source/app/controllers/main.py | 24 +++ source/app/main.py | 6 +- source/app/models/db.py | 7 +- source/app/models/main.py | 95 ++++++++++- source/db/valores_iniciales.json | 18 +-- source/static/js/controller/admin.js | 201 ++++++++++++++++++++++++ source/static/js/controller/partners.js | 14 +- source/static/js/ui/admin.js | 24 +-- 8 files changed, 350 insertions(+), 39 deletions(-) diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 82d7ebc..be2322c 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -138,3 +138,27 @@ class AppInvoices(object): resp.status = falcon.HTTP_200 else: resp.status = falcon.HTTP_204 + + +class AppEmisor(object): + + def __init__(self, db): + self._db = db + + def on_get(self, req, resp): + values = req.params + session = req.env['beaker.session'] + req.context['result'] = self._db.get_emisor(session['rfc']) + resp.status = falcon.HTTP_200 + + def on_post(self, req, resp): + values = req.params + req.context['result'] = self._db.emisor(values) + resp.status = falcon.HTTP_200 + + def on_delete(self, req, resp): + values = req.params + if self._db.delete('invoice', values['id']): + resp.status = falcon.HTTP_200 + else: + resp.status = falcon.HTTP_204 diff --git a/source/app/main.py b/source/app/main.py index 921faf6..47a2530 100644 --- a/source/app/main.py +++ b/source/app/main.py @@ -12,8 +12,8 @@ from middleware import ( ) from models.db import StorageEngine from controllers.main import ( - AppLogin, AppLogout, AppAdmin, AppMain, AppValues, AppPartners, AppProducts, - AppInvoices + AppLogin, AppLogout, AppAdmin, AppEmisor, + AppMain, AppValues, AppPartners, AppProducts, AppInvoices ) from settings import DEBUG @@ -28,6 +28,7 @@ api.add_sink(handle_404, '') api.add_route('/', AppLogin(db)) api.add_route('/logout', AppLogout(db)) api.add_route('/admin', AppAdmin(db)) +api.add_route('/emisor', AppEmisor(db)) api.add_route('/main', AppMain(db)) api.add_route('/values/{table}', AppValues(db)) api.add_route('/partners', AppPartners(db)) @@ -35,6 +36,7 @@ api.add_route('/products', AppProducts(db)) api.add_route('/invoices', AppInvoices(db)) + if DEBUG: api.add_sink(static, '/static') diff --git a/source/app/models/db.py b/source/app/models/db.py index 102bab4..123ea77 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -42,7 +42,7 @@ class StorageEngine(object): return main.SATMonedas.get_activos() def _get_regimenes(self, values): - return main.Emisor.get_regimenes() + return main.Emisor.get_regimenes(values) def _get_usocfdi(self, values): return main.SATUsoCfdi.get_activos(values) @@ -92,5 +92,10 @@ class StorageEngine(object): def _get_timbrar(self, values): return main.Facturas.timbrar(int(values['id'])) + def get_emisor(self, rfc): + return main.Emisor.get_(rfc) + + def emisor(self, values): + return main.Emisor.add(values) diff --git a/source/app/models/main.py b/source/app/models/main.py index fb93947..53137f3 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -108,28 +108,38 @@ class SATRegimenes(BaseModel): ) @classmethod - def get_activos(cls): + def get_(cls, ids): + if isinstance(ids, int): + ids = [ids] + return SATRegimenes.select().where(SATRegimenes.id.in_(ids)) + + @classmethod + def get_activos(cls, rfc): + where = ((SATRegimenes.activo==True) & (SATRegimenes.fisica==True)) + if (len(rfc) == 12): + where = ((SATRegimenes.activo==True) & (SATRegimenes.moral==True)) + rows = (SATRegimenes .select( - SATRegimenes.key.alias('id'), + SATRegimenes.id, SATRegimenes.name.alias('value')) - .where(SATRegimenes.activo==True) + .where(where) .dicts() ) return tuple(rows) class Emisor(BaseModel): - rfc = TextField(index=True) - nombre = TextField() - nombre_comercial = TextField() + rfc = TextField(unique=True) + nombre = TextField(default='') + nombre_comercial = TextField(default='') calle = TextField(default='') no_exterior = TextField(default='') no_interior = TextField(default='') colonia = TextField(default='') municipio = TextField(default='') estado = TextField(default='') - pais = TextField(default='') + pais = TextField(default='México') codigo_postal = TextField(default='') cp_expedicion = TextField(default='') es_moral = BooleanField(default=False) @@ -151,12 +161,81 @@ class Emisor(BaseModel): class Meta: order_by = ('nombre',) + @classmethod + def get_(cls, rfc): + regimenes = SATRegimenes.get_activos(rfc) + row = {'regimenes': regimenes} + + obj = Emisor.select().where(Emisor.rfc==rfc) + if bool(obj): + obj = obj[0] + row['emisor'] = { + 'emisor_rfc': obj.rfc, + 'emisor_nombre': obj.nombre, + 'emisor_cp': obj.codigo_postal, + 'emisor_cp2': obj.cp_expedicion, + 'emisor_calle': obj.calle, + 'emisor_no_exterior': obj.no_exterior, + 'emisor_no_interior': obj.no_interior, + 'emisor_colonia': obj.colonia, + 'emisor_municipio': obj.municipio, + 'emisor_estado': obj.estado, + 'emisor_pais': obj.pais, + 'emisor_nombre_comercial': obj.nombre_comercial, + 'emisor_telefono': obj.telefono, + 'emisor_correo': obj.correo, + 'emisor_web': obj.web, + 'es_escuela': obj.es_escuela, + 'es_ong': obj.es_ong, + 'ong_autorizacion': obj.autorizacion, + 'ong_fecha': obj.fecha_autorizacion, + 'ong_fecha_dof': obj.fecha_dof, + 'regimenes': [row.id for row in obj.regimenes] + } + else: + row['emisor'] = {'emisor_rfc': rfc} + + return {'ok': True, 'row': row} + @classmethod def get_regimenes(cls): obj = Emisor.select()[0] rows = [{'id': row.key, 'value': row.name} for row in obj.regimenes] return tuple(rows) + def _clean(self, values): + fields = util.clean(values) + fields['rfc'] = fields.pop('emisor_rfc') + fields['nombre'] = fields.pop('emisor_nombre') + fields['codigo_postal'] = fields.pop('emisor_cp') + fields['cp_expedicion'] = fields.pop('emisor_cp2', '') or fields['codigo_postal'] + fields['colonia'] = fields.pop('emisor_colonia', '') + fields['municipio'] = fields.pop('emisor_municipio', '') + fields['estado'] = fields.pop('emisor_estado', '') + fields['pais'] = fields.pop('emisor_pais', 'México') + fields['nombre_comercial'] = fields.pop('emisor_nombre_comercial', '') + fields['telefono'] = fields.pop('emisor_telefono', '') + fields['correo'] = fields.pop('emisor_correo', '') + fields['web'] = fields.pop('emisor_web', '') + fields['es_escuela'] = bool(fields['es_escuela'].replace('0', '')) + fields['es_ong'] = bool(fields['es_ong'].replace('0', '')) + fields['autorizacion'] = fields.pop('ong_autorizacion', '') + fields['fecha_autorizacion'] = fields.pop('ong_fecha', None) + fields['fecha_dof'] = fields.pop('ong_fecha_dof', None) + if len(fields['rfc']) == 12: + fields['es_moral'] = True + fields['regimenes'] = SATRegimenes.get_( + util.loads(fields['regimenes'])) + return fields + + @classmethod + def add(cls, values): + fields = cls._clean(cls, values) + obj, created = Emisor.get_or_create(rfc=fields['rfc']) + obj.regimenes = fields.pop('regimenes') + q = Emisor.update(**fields).where(Emisor.id==obj.id) + return {'ok': bool(q.execute())} + class Certificado(BaseModel): key = BlobField() @@ -421,7 +500,7 @@ class Socios(BaseModel): fields['rfc'] = fields['rfc'].upper() fields['nombre'] = util.spaces(fields['nombre']) fields['slug'] = util.to_slug(fields['nombre']) - fields['uso_cfdi'] = fields.pop('uso_cfdi_socio') + fields['uso_cfdi'] = fields.pop('uso_cfdi_socio', None) fb = ('dias_habiles', 'es_activo', 'es_cliente', 'es_proveedor', 'es_ong') for name in fb: diff --git a/source/db/valores_iniciales.json b/source/db/valores_iniciales.json index c5edd38..048e394 100644 --- a/source/db/valores_iniciales.json +++ b/source/db/valores_iniciales.json @@ -1,12 +1,4 @@ [ -{ - "tabla": "Emisor", - "datos": [ - {"rfc": "LAN7008173R5", "nombre": "Empresa Libre AC", - "codigo_postal": "06850", "moral": true} - ], - "regimen": "603" -}, { "tabla": "Categorias", "datos": [ @@ -42,12 +34,6 @@ {"key": "EUR", "name": "Euro", "activo": false} ] }, -{ - "tabla": "Folios", - "datos": [ - {"serie": "F", "inicio": 1, "default": true} - ] -}, { "tabla": "SATFormaPago", "datos": [ @@ -77,7 +63,7 @@ { "tabla": "SATRegimenes", "datos": [ - {"key": "601", "name": "General de Ley Personas Morales", "moral": true, "activo": true}, + {"key": "601", "name": "General de Ley Personas Morales", "moral": true, "activo": true, "default": true}, {"key": "603", "name": "Personas Morales con Fines no Lucrativos", "moral": true, "activo": true}, {"key": "605", "name": "Sueldos y Salarios e Ingresos Asimilados a Salarios", "fisica": true, "activo": true}, {"key": "606", "name": "Arrendamiento", "fisica": true, "activo": true}, @@ -85,7 +71,7 @@ {"key": "609", "name": "Consolidación", "moral": true, "activo": false}, {"key": "610", "name": "Residentes en el Extranjero sin Establecimiento Permanente en México", "fisica": true, "moral": true, "activo": false}, {"key": "611", "name": "Ingresos por Dividendos (socios y accionistas)", "fisica": true, "activo": false}, - {"key": "612", "name": "Personas Físicas con Actividades Empresariales y Profesionales", "fisica": true, "activo": true}, + {"key": "612", "name": "Personas Físicas con Actividades Empresariales y Profesionales", "fisica": true, "activo": true, "default": true}, {"key": "614", "name": "Ingresos por intereses", "fisica": true, "activo": false}, {"key": "616", "name": "Sin obligaciones fiscales", "fisica": true, "activo": false}, {"key": "620", "name": "Sociedades Cooperativas de Producción que optan por diferir sus ingresos", "moral": true, "activo": false}, diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index ae942b7..361df79 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -1,3 +1,4 @@ +var msg = '' var reg = /^[a-z]+$/i //~ reg.test("somethingELSE") @@ -5,6 +6,14 @@ var controllers = { init: function(){ //~ Admin $$('menu_user').attachEvent('onMenuItemClick', menu_user_click) + $$('multi_admin').attachEvent('onViewChange', multi_admin_change) + //~ Emisor + $$('cmd_save_emisor').attachEvent('onItemClick', cmd_save_emisor_click) + $$('emisor_cp').attachEvent('onKeyPress', emisor_postal_code_key_press) + $$('emisor_cp').attachEvent('onTimedKeyPress', emisor_postal_code_key_up) + $$('chk_escuela').attachEvent('onChange', chk_escuela_change) + $$('chk_ong').attachEvent('onChange', chk_ong_change) + } } @@ -20,3 +29,195 @@ function menu_user_click(id, e, node){ function cmd_home_click(){ window.location = '/main' } + + +function cmd_save_emisor_click(){ + var valid_cp = false + var form = $$('form_emisor') + + if (!form.validate()){ + msg = 'Valores inválidos' + msg_error(msg) + return + } + + var values = form.getValues() + + var ids = $$('lst_emisor_regimen').getSelectedId() + if(!ids){ + msg = 'Selecciona al menos un Regimen Fiscal' + msg_error(msg) + return + } + if(values.emisor_cp && values.emisor_cp.length != 5){ + msg = 'Longitud inválida del C.P.' + msg_error(msg) + return + } + if(values.emisor_cp2 && values.emisor_cp2.length != 5){ + msg = 'Longitud inválida del C.P. de Expedición' + msg_error(msg) + return + }else if(values.emisor_cp2){ + webix.ajax().sync().get('/values/cp', {cp: values.emisor_cp2}, { + error: function(text, data, xhr) { + msg = 'Error al consultar el C.P. de Expedición' + msg_error(msg) + }, + success: function(text, data, xhr) { + var values = data.json(); + if (values.estado == undefined){ + msg = 'No se encontró el C.P., asegurate de que sea correcto' + msg_error(msg) + }else{ + valid_cp = true + } + } + }) + } + if(!valid_cp){ + return + } + + if(values.es_ong){ + if(!values.ong_autorizacion){ + msg = 'Si es ONG, el Número de Autorización del SAT es requerido' + msg_error(msg) + return + } + if(!values.ong_fecha){ + msg = 'Si es ONG, la Fecha de Autorización del SAT es requerida' + msg_error(msg) + return + } + if(!values.ong_fecha_dof){ + msg = 'Si es ONG, la Fecha de Publicación en DOF es requerida' + msg_error(msg) + return + } + } + + + values['regimenes'] = ids + webix.ajax().post('/emisor', 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){ + msg_sucess('Emisor guardado correctamente') + }else{ + msg_error(values.msg) + } + } + }) + +} + + +function get_emisor(){ + var form = $$('form_emisor') + + webix.ajax().get("/emisor", {}, { + error: function(text, data, xhr) { + msg = 'Error al consultar' + msg_error(msg) + }, + success: function(text, data, xhr) { + var values = data.json() + if (values.ok){ + var emisor = values.row.emisor + $$('lst_emisor_regimen').parse(values.row.regimenes) + form.setValues(emisor, true) + $$('lst_emisor_regimen').select(emisor.regimenes) + }else{ + msg_error(values.msg) + } + } + }) + +} + + +function multi_admin_change(prevID, nextID){ + //~ webix.message(nextID) + if(nextID == 'app_emisor'){ + $$('tab_emisor').setValue('Datos Fiscales') + get_emisor() + return + } + +} + + +function emisor_postal_code_key_up(){ + var value = this.getValue() + + if( value.length == 5 ){ + webix.ajax().get('/values/cp', {cp: value}, { + error: function(text, data, xhr) { + msg = 'Error al consultar el C.P.' + msg_error(msg) + }, + success: function(text, data, xhr) { + var values = data.json(); + if (values.estado == undefined){ + msg = 'No se encontró el C.P., asegurate de que sea correcto' + msg_error(msg) + } else { + $$('form_emisor').setValues({ + emisor_cp2: value, + emisor_estado: values.estado, + emisor_municipio: values.municipio, + emisor_colonia: ''}, true) + $$('emisor_colonia').define('suggest', []) + if (webix.isArray(values.colonia)){ + $$('emisor_colonia').define('suggest', values.colonia) + }else{ + $$('form_emisor').setValues( + {emisor_colonia: values.colonia}, true) + } + $$('emisor_colonia').refresh() + } + } + }) + } +} + + +function emisor_postal_code_key_press(code, e){ + var data = [8, 9, 37, 39, 46] + if ( data.indexOf(code) >= 0 ){ + return true; + } + + if ( code < 48 || code > 57){ + return false; + } +} + + +function chk_escuela_change(new_value, old_value){ + var value = Boolean(new_value) + if (value){ + $$('cmd_niveles').enable() + } else { + $$('cmd_niveles').disable() + } +} + + +function chk_ong_change(new_value, old_value){ + var value = Boolean(new_value) + if (value){ + $$('ong_autorizacion').enable() + $$('ong_fecha').enable() + $$('ong_fecha_dof').enable() + } else { + $$('ong_autorizacion').disable() + $$('ong_fecha').disable() + $$('ong_fecha_dof').disable() + } +} diff --git a/source/static/js/controller/partners.js b/source/static/js/controller/partners.js index 284e972..30d22c4 100644 --- a/source/static/js/controller/partners.js +++ b/source/static/js/controller/partners.js @@ -48,6 +48,12 @@ function cmd_edit_partner_click(id, e, node){ query = [{id: 'P01', value: 'Por definir'}] } $$('lst_uso_cfdi_socio').getList().parse(query) + if(values.es_cliente){ + $$('cuenta_cliente').enable() + } + if(values.es_proveedor){ + $$('cuenta_proveedor').enable() + } } }) @@ -111,9 +117,15 @@ function cmd_save_partner_click(id, e, node){ var values = form.getValues(); + if(values.codigo_postal && values.codigo_postal.length != 5){ + msg = 'Longitud inválida del C.P.' + msg_error(msg) + return + } + if (!values.es_cliente && !values.es_proveedor){ msg = 'Selecciona si es cliente, proveedor o ambos' - webix.message({type: 'error', text: msg}) + msg_error(msg) $$('tab_partner').setValue('Otros Datos') return } diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index 30e89cc..9f45d8e 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -15,7 +15,7 @@ var sidebar = { }, on:{ onAfterSelect: function(id){ - $$('multi').setValue(id) + $$('multi_admin').setValue(id) } } } @@ -31,14 +31,15 @@ var emisor_datos_fiscales = [ invalidMessage: 'La Razón Social es requerida'}, {cols: [ {view: 'search', id: 'emisor_cp', name: 'emisor_cp', width: 300, - label: 'C.P.: ', required: true, attributes: {maxlength: 5}}, + label: 'C.P.: ', required: true, attributes: {maxlength: 5}, + invalidMessage: 'El C.P. es requerido'}, {view: 'text', id: 'emisor_cp2', name: 'emisor_cp2', width: 300, label: 'C.P. de Expedición: ', attributes: {maxlength: 5}}, {}]}, {cols: [ {view: 'label', label: 'Regimenes Fiscales *', required: true}, {}]}, {cols: [{view: 'list', id: 'lst_emisor_regimen', select: 'multiselect', - name: 'lst_emisor_regimen', width: 600, height: 100, required: true, + name: 'lst_emisor_regimen', width: 600, height: 125, required: true, data: []}, {}]}, {template: 'Dirección Fiscal', type: 'section'}, {view: 'text', id: 'emisor_calle', name: 'emisor_calle', label: 'Calle: '}, @@ -71,18 +72,19 @@ var emisor_otros_datos= [ {template: 'Escuela', type: 'section'}, {cols: [{view: 'checkbox', id: 'chk_escuela', name: 'es_escuela', label: 'Es Escuela'}, - {view: 'button', id: 'cmd_niveles', label: 'Niveles', type: 'form', - align: 'center', autowidth: true, disabled: true}, {}, {}]}, + {view: 'button', id: 'cmd_niveles', label: 'Niveles Escolares', + type: 'form', align: 'center', autowidth: true, disabled: true}, + {}, {}]}, {template: 'ONG', type: 'section'}, {view: 'checkbox', id: 'chk_ong', name: 'es_ong', label: 'Es ONG'}, {cols: [{view: 'text', id: 'ong_autorizacion', name: 'ong_autorizacion', label: 'Autorización: ', disabled: true, placeholder: 'Número de autorización del SAT'}, {}]}, {cols: [{view: 'datepicker', id: 'ong_fecha', name: 'ong_fecha', - label: 'Fecha de Autorización: ', disabled: true, + label: 'Fecha de Autorización: ', disabled: true, format: '%d-%M-%Y', placeholder: 'Fecha de autorización en el SAT'}, {}]}, {cols: [{view: 'datepicker', id: 'ong_fecha_dof', name: 'ong_fecha_dof', - label: 'Fecha de DOF: ', disabled: true, + label: 'Fecha de DOF: ', disabled: true, format: '%d-%M-%Y', placeholder: 'Fecha de publicación en el DOF'}, {}]}, ] @@ -264,12 +266,12 @@ var app_folios = { } -var multi_main = { - id: 'multi', +var multi_admin = { + id: 'multi_admin', animate: true, cells:[ { - id: 'app_home', + id: 'app_admin_home', view: 'template', template: 'HOME' }, @@ -309,7 +311,7 @@ var ui_admin = { { cols:[ sidebar, - multi_main, + multi_admin, ] } ]