diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index e3c3924..03b46d8 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -140,6 +140,7 @@ class AppPartners(object): def on_get(self, req, resp): values = req.params + #~ print ('VALUES', values) req.context['result'] = self._db.get_partners(values) resp.status = falcon.HTTP_200 diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 5ff3ddc..fce597b 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -767,9 +767,8 @@ class LIBO(object): #~ Si no se encuentra, copia las celdas hacia abajo de #~ {subtotal.titulo} y {subtotal} - print (data['descuento']) + #~ print (data['descuento']) if 'descuento' in data: - self._copy_cell(cell_title) self._copy_cell(cell_value) cell_title = self._set_cell(v='Descuento', cell=cell_title) @@ -1534,6 +1533,8 @@ class ImportFacturaLibre(object): data = [] for row in rows: new = {t: row[s] for s, t in fields} + if not new['uuid']: + new['uuid'] = None if row['estatus'] == 'Pagada': new['pagada'] = True elif row['estatus'] == 'Cancelada': diff --git a/source/app/models/main.py b/source/app/models/main.py index 3c85a35..0fb1e0b 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -747,6 +747,11 @@ class SATImpuestos(BaseModel): (('key', 'factor', 'tipo', 'tasa'), True), ) + @classmethod + def get_o_crea(self, values): + obj, _ = SATImpuestos.get_or_create(**values) + return obj + @classmethod def add(self, values): tasa = float(values['tasa']) @@ -1083,7 +1088,9 @@ class Socios(BaseModel): @classmethod def get_(cls, values): - if values: + print ('values', values) + id = values.get('id', 0) + if id: id = int(values['id']) row = Socios.select().where(Socios.id==id).dicts()[0] row['uso_cfdi_socio'] = row.pop('uso_cfdi') @@ -1092,6 +1099,18 @@ class Socios(BaseModel): str(CondicionesPago.get(id=row['condicion_pago'])) return row + #~ return {'data': data['rows'][:100], 'pos':0, 'total_count': 1300} + #~ start = 0 + #~ count = 0 + #~ end = 100 + #~ if values: + #~ {'start': '100', 'count': '100', 'continue': 'true'} + #~ start = int(values['start']) + #~ cont = int(values['count']) + #~ end = start + count + + total = Socios.select().count() + rows = (Socios .select( Socios.id, @@ -1100,7 +1119,7 @@ class Socios(BaseModel): Socios.saldo_cliente) .dicts() ) - return {'ok': True, 'rows': tuple(rows)} + return {'pos': 0, 'total_count': total, 'data': tuple(rows)} @classmethod def get_by_client(cls, values): @@ -3074,7 +3093,7 @@ def _importar_facturas(rows): } FacturasImpuestos.create(**new) except IntegrityError: - msg = '\tFactura: id: {}'.format(row['serie'] + row['folio']) + msg = '\tFactura: id: {}'.format(row['serie'] + str(row['folio'])) log.error(msg) log.info('\tFacturas importadas...') return @@ -3210,7 +3229,83 @@ def _importar_factura_libre(archivo): _importar_socios(data['Socios']) _importar_facturas(data['Facturas']) _importar_categorias(data['Categorias']) - #~ _generar_archivo_productos(data['Productos'], archivo) + + log.info('Importación terminada...') + return + + +def _importar_productos(archivo): + rfc = input('Introduce el RFC: ').strip().upper() + if not rfc: + msg = 'El RFC es requerido' + log.error(msg) + return + + args = util.get_con(rfc) + if not args: + return + + conectar(args) + log.info('Importando productos...') + + fields = ( + 'clave', + 'clave_sat', + 'unidad', + 'categoria', + 'descripcion', + 'valor_unitario', + 'existencia', + 'inventario', + 'codigo_barras', + 'cuenta_predial', + 'ultimo_precio', + 'minimo', + ) + + rows = util.read_file(archivo, 'r').split('\n') + for i, row in enumerate(rows): + if i == 0: + continue + data = row.split('|') + + new = {} + for i, f in enumerate(fields): + if not len(data[0]): + continue + + if i in (2, 3): + try: + new[f] = int(data[i]) + except ValueError: + continue + elif i in (5, 6, 10, 11): + new[f] = float(data[i]) + elif i == 7: + new[f] = bool(data[i]) + else: + new[f] = data[i] + + impuestos = data[i + 1:] + if not impuestos: + taxes = [SATImpuestos.select().where(SATImpuestos.id==6)] + else: + taxes = [] + for i in range(0, len(impuestos), 4): + w = { + 'key': impuestos[i], + 'name': impuestos[i+1], + 'tipo': impuestos[i+2], + 'tasa': float(impuestos[i+3]), + } + taxes.append(SATImpuestos.get_o_crea(w)) + + with database_proxy.transaction(): + try: + obj = Productos.create(**new) + obj.impuestos = taxes + except IntegrityError: + pass log.info('Importación terminada...') return diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index d23b1c1..593cab9 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -953,6 +953,8 @@ function get_invoices(rango){ } var grid = $$('grid_invoices') + grid.showProgress({type: 'icon'}) + webix.ajax().get('/invoices', rango, { error: function(text, data, xhr) { webix.message({type: 'error', text: 'Error al consultar'}) diff --git a/source/static/js/controller/main.js b/source/static/js/controller/main.js index ab9fcdb..f7c287e 100644 --- a/source/static/js/controller/main.js +++ b/source/static/js/controller/main.js @@ -63,6 +63,8 @@ var controllers = { $$('cmd_delete_preinvoice').attachEvent('onItemClick', cmd_delete_preinvoice_click) $$('cmd_facturar_preinvoice').attachEvent('onItemClick', cmd_facturar_preinvoice_click) $$('grid_preinvoices').attachEvent('onItemClick', grid_preinvoices_click) + + webix.extend($$('grid_invoices'), webix.ProgressBar) } } @@ -77,18 +79,18 @@ function get_uso_cfdi_to_table(){ function get_partners(){ - webix.ajax().get("/partners", {}, { + webix.ajax().get('/partners', {}, { error: function(text, data, xhr) { - webix.message({ type:"error", text: "Error al consultar"}); + webix.message({type: 'error', text: 'Error al consultar'}); }, success: function(text, data, xhr) { var values = data.json(); - $$("grid_partners").clearAll(); - if (values.ok){ - $$("grid_partners").parse(values.rows, 'json'); + $$('grid_partners').clearAll(); + if (values.data){ + $$('grid_partners').parse(values.data, 'json'); }; } - }); + }) } diff --git a/source/static/js/ui/partners.js b/source/static/js/ui/partners.js index 2ae0df8..3c399c3 100644 --- a/source/static/js/ui/partners.js +++ b/source/static/js/ui/partners.js @@ -11,10 +11,10 @@ var toolbar_partners = [ var grid_partners_cols = [ - {id: 'index', header:'#', adjust:'data', css: 'right', + {id: 'index', header:'#', css: 'right', footer: {content: 'rowCount', colspan: 2, css: 'right'}}, - {id: 'id', header: 'Clave', adjust:'data', sort: 'int', css: 'right'}, - {id: 'rfc', header: ['RFC', {content: 'textFilter'}], adjust:'data', + {id: 'id', header: 'Clave', sort: 'int', css: 'right'}, + {id: 'rfc', header: ['RFC', {content: 'textFilter'}], sort: 'string', footer: {text: 'Clientes y Proveedores', colspan: 2}}, {id: 'nombre', header: ['Razón Social', {content: 'textFilter'}], fillspace:true, sort: 'string'}, @@ -32,6 +32,15 @@ var grid_partners = { resizeColumn: true, headermenu: true, columns: grid_partners_cols, + pager: 'pager_clientes', + //~ datafetch: 100, + //~ loadahead: 100, + //~ url: '/partners', + ready:function(){ + this.adjustColumn('index'); + this.adjustColumn('id'); + this.adjustColumn('rfc'); + }, on:{ 'data->onStoreUpdated':function(){ this.data.each(function(obj, i){ @@ -300,6 +309,15 @@ var form_partner = { } +var pager_clientes = { + view: "pager", + id: "pager_clientes", + template: "{common.prev()} {common.pages()} {common.next()}", + size: 100, + group: 10, +} + + var multi_partners = { id: 'multi_partners', animate: true, @@ -307,6 +325,7 @@ var multi_partners = { {id: 'partners_home', rows:[ {view: 'toolbar', elements: toolbar_partners}, grid_partners, + pager_clientes, ]}, {id: 'partners_new', rows:[form_partner]} ] diff --git a/source/static/js/ui/products.js b/source/static/js/ui/products.js index 6650587..e2bbdaf 100644 --- a/source/static/js/ui/products.js +++ b/source/static/js/ui/products.js @@ -13,9 +13,9 @@ var toolbar_products = [ var grid_products_cols = [ { id: "id", header: "ID", width: 75}, { id: "clave", header: ["Clave", {content: "textFilter"}], width: 100, - sort:"string" }, + sort: 'string', footer: {content: 'rowCount', css: 'right'}}, { id: "descripcion", header: ["Descripción", {content: "textFilter"}], - fillspace:true, sort:"string" }, + fillspace:true, sort: 'string', footer: 'Productos y Servicios'}, { id: "unidad", header: ["Unidad", {content: "selectFilter"}], width: 150, sort:"string" }, { id: "valor_unitario", header: ["Precio", {content: "numberFilter"}], width: 150,