From e6c48d239d59b73c1150037f9c365524275d349d Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Wed, 4 Oct 2017 23:22:05 -0500 Subject: [PATCH] UI para facturar --- source/app/models/db.py | 9 + source/app/models/main.py | 40 +++- source/static/css/app.css | 6 + source/static/js/controller/invoices.js | 98 ++++++++-- source/static/js/controller/main.js | 4 +- source/static/js/controller/util.js | 2 + source/static/js/ui/invoices.js | 249 ++++++++++++++++++++---- 7 files changed, 353 insertions(+), 55 deletions(-) diff --git a/source/app/models/db.py b/source/app/models/db.py index 51a7138..813dee1 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -35,6 +35,15 @@ class StorageEngine(object): def _get_satkey(self, values): return main.get_sat_key(values['key']) + def _get_series(self, values): + return main.Folios.get_all() + + def _get_monedas(self, values): + return main.SATMonedas.get_activos() + + def _get_usocfdi(self, values): + return main.SATUsoCfdi.get_activos() + def delete(self, table, id): if table == 'partner': return main.Socios.remove(id) diff --git a/source/app/models/main.py b/source/app/models/main.py index 979e4e8..ff1781e 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -160,7 +160,7 @@ class Folios(BaseModel): serie = TextField() inicio = IntegerField(default=1) default = BooleanField(default=False) - usar_con = TextField(default='T') + usar_con = TextField(default='') class Meta: order_by = ('-default', 'serie', 'inicio') @@ -168,6 +168,18 @@ class Folios(BaseModel): (('serie', 'inicio'), True), ) + @classmethod + def get_all(cls): + rows = (Folios + .select( + Folios.id, + Folios.serie.alias('value'), + Folios.usar_con, + ) + .dicts() + ) + return tuple(rows) + class Categorias(BaseModel): categoria = TextField() @@ -269,6 +281,17 @@ class SATMonedas(BaseModel): (('key', 'name'), True), ) + @classmethod + def get_activos(cls): + rows = (SATMonedas + .select( + SATMonedas.key.alias('id'), + SATMonedas.name.alias('value')) + .where(SATMonedas.activo==True) + .dicts() + ) + return tuple(rows) + class SATImpuestos(BaseModel): key = TextField(index=True) @@ -305,6 +328,20 @@ class SATUsoCfdi(BaseModel): (('key', 'name'), True), ) + @classmethod + def get_activos(cls): + rows = (SATUsoCfdi + .select( + SATUsoCfdi.key.alias('id'), + SATUsoCfdi.name.alias('value'), + SATUsoCfdi.fisica, + SATUsoCfdi.moral, + ) + .where(SATUsoCfdi.activo==True) + .dicts() + ) + return tuple(rows) + class Addendas(BaseModel): nombre = TextField(unique=True) @@ -344,6 +381,7 @@ class Socios(BaseModel): forma_pago = ForeignKeyField(SATFormaPago, null=True) condicion_pago = ForeignKeyField(CondicionesPago, null=True) addenda = ForeignKeyField(Addendas, null=True) + uso_cfdi = ForeignKeyField(SATUsoCfdi, null=True) tags = ManyToManyField(Tags, related_name='socios_tags') def __str__(self): diff --git a/source/static/css/app.css b/source/static/css/app.css index dc5f048..fdd73b8 100644 --- a/source/static/css/app.css +++ b/source/static/css/app.css @@ -18,6 +18,12 @@ .right { text-align: right; } +.right_footer { + text-align: right; + font-weight: bold; + font-size: 125%; + color: DarkRed; +} .cmd_close_partner div button { background-color: red !important; diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 7ac131e..9a4ad62 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -1,11 +1,80 @@ +var query = [] +var grid = null + + +function get_series(){ + webix.ajax().get('/values/series', function(text, data){ + var values = data.json() + table_series.clear() + table_series.insert(values) + pre = values[0] + $$('lst_serie').getList().parse(values) + $$('lst_serie').setValue(pre.id) + if(pre.usar_con){ + $$('lst_tipo_comprobante').setValue(pre.usar_con) + $$('lst_tipo_comprobante').config.readonly = true + $$('lst_tipo_comprobante').refresh() + } + }) +} + + +function get_forma_pago(){ + webix.ajax().get('/values/formapago', function(text, data){ + var values = data.json() + pre = values[0] + $$('lst_forma_pago').getList().parse(values) + $$('lst_forma_pago').setValue(pre.id) + }) +} + + +function get_monedas(){ + webix.ajax().get('/values/monedas', function(text, data){ + var values = data.json() + pre = values[0] + $$('lst_moneda').getList().parse(values) + $$('lst_moneda').setValue(pre.id) + }) +} + + +function get_uso_cfdi(){ + webix.ajax().get('/values/usocfdi', function(text, data){ + var values = data.json() + pre = values[0] + table_usocfdi.clear() + table_usocfdi.insert(values) + $$('lst_uso_cfdi').getList().parse(values) + $$('lst_uso_cfdi').setValue(pre.id) + }) +} + + +function default_config(){ + get_series() + get_forma_pago() + get_monedas() + get_uso_cfdi() + table_pt.clear() + table_totals.clear() +} function cmd_new_invoice_click(id, e, node){ + var form = $$('form_invoice') + var grid_totals = $$('grid_totals') + grid = $$('grid_details') - $$('form_invoice').adjust(); - $$("multi_invoices").setValue("invoices_new") - -}; + default_config() + form.adjust() + form.setValues({id: 0, id_partner: 0, lbl_partner: 'Ninguno'}) + grid.clearAll() + grid_totals.clearAll() + grid_totals.add({id: 1, concepto: 'SubTotal', importe: 0}) + $$('multi_invoices').setValue('invoices_new') + form.focus('search_partner_id') +} function cmd_edit_invoice_click(id, e, node){ @@ -22,23 +91,20 @@ function cmd_delete_invoice_click(id, e, node){ }; -function cmd_save_invoice_click(id, e, node){ - var form = this.getFormView(); +function cmd_timbrar_click(id, e, node){ + var form = this.getFormView() if (!form.validate()) { - webix.message({ type:"error", text:"Valores inválidos" }); + webix.message({type: 'error', text: 'Valores inválidos'}) return } $$('form_invoice').clear(); - $$("multi_invoices").setValue("invoices_home") - webix.message({type:"success", text: "Factura guardada correctamente"}); - -}; + $$('multi_invoices').setValue('invoices_home') + webix.message({type:"success", text: "Factura guardada correctamente"}) +} -function cmd_cancel_invoice_click(id, e, node){ - - $$("multi_invoices").setValue("invoices_home") - -}; +function cmd_close_invoice_click(id, e, node){ + $$('multi_invoices').setValue('invoices_home') +} diff --git a/source/static/js/controller/main.js b/source/static/js/controller/main.js index e1ce3b7..dbde3ba 100644 --- a/source/static/js/controller/main.js +++ b/source/static/js/controller/main.js @@ -32,8 +32,8 @@ var controllers = { $$("cmd_new_invoice").attachEvent("onItemClick", cmd_new_invoice_click); $$("cmd_edit_invoice").attachEvent("onItemClick", cmd_edit_invoice_click); $$("cmd_delete_invoice").attachEvent("onItemClick", cmd_delete_invoice_click); - $$("cmd_save_invoice").attachEvent("onItemClick", cmd_save_invoice_click); - $$("cmd_cancel_invoice").attachEvent("onItemClick", cmd_cancel_invoice_click); + $$('cmd_timbrar').attachEvent('onItemClick', cmd_timbrar_click) + $$('cmd_close_invoice').attachEvent('onItemClick', cmd_close_invoice_click) } }; diff --git a/source/static/js/controller/util.js b/source/static/js/controller/util.js index 9cd8fea..952c10b 100644 --- a/source/static/js/controller/util.js +++ b/source/static/js/controller/util.js @@ -9,6 +9,8 @@ var table_config = db.addCollection('config') var table_taxes = db.addCollection('taxes') var table_pt = db.addCollection('productstaxes') var table_totals = db.addCollection('totals', {unique: ['tax']}) +var table_series = db.addCollection('series') +var table_usocfdi = db.addCollection('usocfdi') function show(values){ diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 4b6f68c..07073be 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -7,20 +7,34 @@ var toolbar_invoices = [ autowidth: true, icon: "pencil"}, {view: "button", id: "cmd_delete_invoice", label: "Eliminar", type: "iconButton", autowidth: true, icon: "minus"}, -]; +] + + +function doc_xml(obj){ + var node = "" + return node +} var grid_invoices_cols = [ {id: "id", header:"ID", hidden:true}, - {id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data", sort:"string"}, - {id: "folio", header: ["Folio", {content: "numberFilter"}], adjust: "data", sort:"int", css: "cell_right"}, - {id: "uuid", header: ["UUID", {content: "textFilter"}], adjust: "data", sort:"string"}, + {id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data", + sort:"string"}, + {id: "folio", header: ["Folio", {content: "numberFilter"}], adjust: "data", + sort:"int", css: "cell_right"}, + {id: 'xml', header: '', adjust: 'data', template: doc_xml}, + {id: "uuid", header: ["UUID", {content: "textFilter"}], adjust: "data", + sort:"string"}, {id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort:"string"}, - {id: "tipo", header: ["Tipo", {content: "selectFilter"}], adjust: "data", sort:"string"}, - {id: "estatus", header: ["Estatus", {content: "selectFilter"}], adjust: "data", sort:"string"}, - {id: "total", header: ["Total M.N.", {content: "numberFilter"}], width: 150, sort:"int", format: webix.i18n.priceFormat, css: "cell_right"}, - {id: "partner", header: ["Razón Social", {content: "selectFilter"}], fillspace:true, sort:"string"}, -]; + {id: "tipo_comprobante", header: ["Tipo", {content: "selectFilter"}], + adjust: 'header', sort: 'string'}, + {id: "estatus", header: ["Estatus", {content: "selectFilter"}], + adjust: "data", sort:"string"}, + {id: 'total_mn', header: ['Total M.N.', {content: 'numberFilter'}], width: 150, + sort: 'int', format: webix.i18n.priceFormat, css: 'right'}, + {id: "cliente", header: ["Razón Social", {content: "selectFilter"}], + fillspace:true, sort:"string"}, +] var grid_invoices = { @@ -36,14 +50,18 @@ var grid_invoices = { var grid_details_cols = [ - {id:"id", header:"ID", hidden: true}, - {id:"key", header:{text: 'Clave', css: 'center'}, width: 100}, - {id:"description", header:{text: 'Descripción', css: 'center'}, fillspace: true}, - {id:"unidad", header:{text: 'Unidad', css: 'center'}, width: 100}, - {id:"cant", header:{text: 'Cantidad', css: 'center'}, width: 100, format: webix.i18n.priceFormat, css:'right'}, - {id:"price", header:{text: 'Valor Unitario', css: 'center'}, width: 100, format: webix.i18n.priceFormat, css:'right'}, - {id:"importe", header:{text: 'Importe', css: 'center'}, width: 150, format: webix.i18n.priceFormat, css:'right'}, -]; + {id: "id", header:"ID", hidden: true}, + {id: 'delete', header: '', width: 30, css: 'delete'}, + {id: "key", header:{text: 'Clave', css: 'center'}, width: 100}, + {id: "description", header:{text: 'Descripción', css: 'center'}, + fillspace: true}, + {id: "unit", header:{text: 'Unidad', css: 'center'}, width: 100}, + {id: 'cant', header: {text: 'Cantidad', css: 'center'}, width: 100, + format: webix.i18n.numberFormat, css:'right', editor: 'text'}, + {id: "price", header:{text: 'Valor Unitario', css: 'center'}, width: 100, + format: webix.i18n.priceFormat, css:'right', editor: 'text'}, + {id: "importe", header:{text: 'Importe', css: 'center'}, width: 150, format: webix.i18n.priceFormat, css:'right'}, +] var grid_details = { @@ -53,18 +71,181 @@ var grid_details = { adjust: true, autoheight: true, columns: grid_details_cols, - data: [ - {id:1, key:'001', description:'Uno', unidad:'Pieza', cant:1, price:100, importe:100}, - {id:2, key:'002', description:'Dos', unidad:'Pieza', cant:2, price:200, importe:400}, - ] -}; + data: [] +} + + +var grid_totals_cols = [ + {id: 'id', header: 'ID', hidden: true}, + {id: 'concepto', header: 'Concepto', width: 200, + footer: {text: 'TOTAL', css:'right_footer'}, css:'right'}, + {id: 'importe', header: 'Importe', width: 150, + footer: {content: 'summColumn', css:'right_footer'}, + format: webix.i18n.priceFormat, css:'right'}, +] + + +var grid_totals = { + view: 'datatable', + id: 'grid_totals', + select: false, + width: 350, + header: false, + footer: true, + autoheight: true, + columns: grid_totals_cols, + data: [{id: 1, concepto: 'SubTotal', importe: 0}] +} + + +var suggest_partners = { + view: 'gridsuggest', + id: 'grid_partners_found', + name: 'grid_partners_found', + body: { + autoConfig: false, + header: false, + columns: [{id:"id", hidden: true}, {id:'name', adjust:'data'}, {id:'rfc', adjust:'data'}], + dataFeed:function(text){ + if (text.length > 2){ + this.load('/values/partner?name=' + text) + }else{ + this.hide() + } + } + } +} + +var suggest_products = { + view: 'gridsuggest', + id: 'grid_products_found', + name: 'grid_products_found', + body: { + autoConfig: false, + header: true, + columns: [ + {id: 'id', hidden: true}, + {id: 'key', adjust: 'data'}, + {id: 'description', adjust: 'data'}, + {id: 'unit', adjust: 'data'}, + {id: 'price', adjust: 'data', format: webix.i18n.priceFormat} + ], + dataFeed:function(text){ + if (text.length > 2){ + this.load('/values/product?name=' + text) + }else{ + this.hide() + } + } + } +} + + +var body_comprobante = {cols: [ + { + view: 'richselect', + id: 'lst_tipo_comprobante', + label: 'Tipo', + labelPosition: 'top', + required: true, + value: 'I', + options: [ + {id: 'I', value: 'Ingreso'}, + {id: 'E', value: 'Egreso'}, + {id: 'T', value: 'Traslado'} + ] + }, + { + view: 'richselect', + id: 'lst_serie', + label: 'Serie', + labelPosition: 'top', + options: [], + //~ options: '/values/series', + //~ on: { + //~ onAfterRender: webix.once(function(){ + //~ this.getPopup().getList().waitData.then(webix.bind(function(){ + //~ this.setValue(this.getPopup().getList().getFirstId()) + //~ }, this)) + //~ }), + //~ } + } +]} + + +var opt_metodo_pago = [ + {id: 'PUE', value: 'Pago en una sola exhibición'}, + {id: 'PPD', value: 'Pago en parcialidades o diferido'} +] + + +//~ var body_serie_folio = { + //~ view: 'richselect', + //~ id: 'cbo_serie_folio', + //~ options: '/values/seriefolio' +//~ } + + +var body_opciones = {rows: [ + {view: 'richselect', id: 'lst_forma_pago', label: 'Forma de Pago', + labelPosition: 'top', required: true, options: []}, + {view: 'richselect', id: 'lst_metodo_pago', label: 'Método de Pago', + labelPosition: 'top', options: opt_metodo_pago, value: 'PUE', + required: true}, + {view: 'text', id: 'txt_condicion_pago', label: 'Condiciones de Pago', + labelPosition: 'top'}, +]} + + +var body_moneda = {cols: [ + {view: 'richselect', id: 'lst_moneda', label: 'Nombre', + labelPosition: 'top', required: true, options: []}, + {view: 'text', type: 'text', id: 'txt_tipo_cambio', value: '1.00', + label: 'Tipo de Cambio', labelPosition: 'top', required: true, + invalidMessage: 'Captura un valor númerico', inputAlign: 'right', + readonly: true} +]} + + +var body_uso_cfdi = { + view: 'richselect', + id: 'lst_uso_cfdi', + required: true, + options: [] +} var controls_generate = [ - {view: "text", id: "search_partner", name: "search_partner", label: "Buscar Cliente", required: true, labelPosition: "top"}, - {view: "text", id: "search_product", name: "search_product", label: "Buscar Producto", required: true, labelPosition: "top"}, - {view:"label", label:'Detalle', height:30, align:'left'}, + {cols: [ {rows:[ + {view: 'fieldset', label: 'Buscar Cliente', body: {rows: [ + {cols: [ + {view:"search", id:"search_partner_id", name:"search_partner_id", + label:"por Clave", labelPosition:'top', maxWidth:200, + placeholder:'Captura la clave'}, + {view:"search", id:"search_partner_name", name:"search_partner_name", label:"por Nombre o RFC", labelPosition:'top', suggest:suggest_partners, placeholder:'Captura al menos tres letras'}, + ]}, + {cols: [{view: "label", id: "lbl_partner_title", name: "lbl_partner_title", label: 'Seleccionado: ', autowidth:true}, + {view: "label", id: "lbl_partner", name: "lbl_partner", label: 'Ninguno'}, + ]} + ]}}, + {view: 'fieldset', label: 'Buscar Producto', body: {rows: [ + {cols: [{view:"search", id:"search_product_id", name:"search_product_id", label:"por Clave", labelPosition:'top', maxWidth:200, placeholder:'Captura la clave'}, + {view:"search", id:"search_product_name", name:"search_product_name", label:"por Descripción", labelPosition:'top', suggest:suggest_products, placeholder:'Captura al menos tres letras'}, + ]}, + ]}} + ]}, + {maxWidth: 10}, + {maxWidth: 300, rows: [ + {view: 'fieldset', label: 'Comprobante', body: body_comprobante}, + {view: 'fieldset', label: 'Opciones de Pago', body: body_opciones}, + {view: 'fieldset', label: 'Moneda', body: body_moneda}, + {view: 'fieldset', label: 'Uso del CFDI', body: body_uso_cfdi}, + ]} + ]}, + {view: 'label', label: 'Detalle', height: 30, align: 'left'}, grid_details, + {minHeight: 15, maxHeight: 15}, + {cols: [{}, grid_totals]} ] @@ -79,13 +260,14 @@ var controls_invoices = [ {rows: [ { template:"", type: "section" }, { margin: 10, cols: [{}, - {view: "button", id: "cmd_save_invoice", label: "Guardar" , type: "form", autowidth: true, align:"center"}, - {view: "button", id: "cmd_send_invoice", label: "Timbrar" , type: "form", autowidth: true, align:"center"}, - {view: "button", id: "cmd_cancel_invoice", label: "Cancelar" , type: "danger", autowidth: true, align:"center"}, + {view: "button", id: "cmd_timbrar", label: "Timbrar", + type: "form", autowidth: true, align:"center"}, + {view: 'button', id: 'cmd_close_invoice', label: 'Salir', + type: 'danger', autowidth: true, align: 'center'}, {}] }, ]} -]; +] var form_invoice = { @@ -93,24 +275,19 @@ var form_invoice = { cols: [{ view: "form", id: "form_invoice", - //~ width: 800, complexData: true, elements: controls_invoices, - //~ rules: { - //~ description: function(value){ return value.trim() != ""; }, - //~ unidad: function(value){ return value.trim() != ""; }, - //~ price: function(value){ return value.trim() != ""; }, - //~ } }] }; var multi_invoices = { id: "multi_invoices", + view: 'multiview', animate: true, cells:[ {id: "invoices_home", rows:[ - {view:"toolbar", elements: toolbar_invoices}, + {view: "toolbar", elements: toolbar_invoices}, grid_invoices, ]}, {id: "invoices_new", rows:[form_invoice, {}]}