diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index bc7a47a..18ce108 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -82,6 +82,8 @@ class AppValues(object): req.context['result'] = self._db.send_email(values, session) elif table == 'enviarprefac': req.context['result'] = self._db.enviar_prefac(values) + elif table == 'addunidad': + req.context['result'] = self._db.add_unidad(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 a82ca4a..3efda83 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -176,6 +176,25 @@ def get_sat_key(table, key): return {'ok': True, 'text': data[1]} +def get_sat_unidades(key): + con = sqlite3.connect(DB_SAT) + con.row_factory = sqlite3.Row + cursor = con.cursor() + + filtro = '%{}%'.format(key) + sql = "SELECT * FROM unidades WHERE key LIKE ? OR name LIKE ?" + + cursor.execute(sql, [filtro, filtro]) + data = cursor.fetchall() + cursor.close() + con.close() + if data is None: + return {'ok': False, 'text': 'No se encontró la unidad'} + + data = [dict(r) for r in data] + return tuple(data) + + def now(): return datetime.datetime.now().replace(microsecond=0) diff --git a/source/app/models/db.py b/source/app/models/db.py index d3fab7e..fecd237 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -82,6 +82,9 @@ class StorageEngine(object): def _get_unidades(self, values): return main.SATUnidades.get_activos() + def add_unidad(self, values): + return main.SATUnidades.add(values) + def _get_taxes(self, values): return main.SATImpuestos.get_activos() @@ -115,6 +118,9 @@ class StorageEngine(object): def _get_satkey(self, values): return main.get_sat_key(values['key']) + def _get_satunidades(self, values): + return main.get_sat_unidades(values['key']) + def _get_series(self, values): return main.Folios.get_all() diff --git a/source/app/models/main.py b/source/app/models/main.py index db6c618..c8567a2 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 + INIT_VALUES, DEFAULT_PASSWORD, DECIMALES FORMAT = '{0:.2f}' @@ -579,6 +579,14 @@ class SATUnidades(BaseModel): rows = SATUnidades.select().dicts() return tuple(rows) + @classmethod + def add(self, values): + try: + SATUnidades.create(**values) + return {'ok': True} + except: + return {'ok': False} + @classmethod def actualizar(self, values): id = int(values['id']) @@ -1742,13 +1750,13 @@ class Facturas(BaseModel): valor_unitario = float(product['valor_unitario']) descuento = float(product['descuento']) precio_final = valor_unitario - descuento - importe = round(cantidad * precio_final, 2) + importe = round(cantidad * precio_final, DECIMALES) product['cantidad'] = cantidad product['valor_unitario'] = valor_unitario product['descuento'] = descuento product['precio_final'] = precio_final - product['importe'] = round(cantidad * valor_unitario, 2) + product['importe'] = round(cantidad * valor_unitario, DECIMALES) descuento_cfdi += descuento subtotal += importe @@ -1768,7 +1776,7 @@ class Facturas(BaseModel): if tax.tipo == 'E' or tax.tipo == 'R': continue - import_tax = round(float(tax.tasa) * tax.importe, 2) + import_tax = round(float(tax.tasa) * tax.importe, DECIMALES) total_trasladados = (total_trasladados or 0) + import_tax if tax.name == 'IVA': total_iva += import_tax @@ -1785,9 +1793,9 @@ class Facturas(BaseModel): if tax.tipo == 'E' or tax.tipo == 'T': continue if tax.tasa == round(Decimal(2/3), 6): - import_tax = round(float(tax.tasa) * total_iva, 2) + import_tax = round(float(tax.tasa) * total_iva, DECIMALES) else: - import_tax = round(float(tax.tasa) * tax.importe, 2) + import_tax = round(float(tax.tasa) * tax.importe, DECIMALES) total_retenciones = (total_retenciones or 0) + import_tax invoice_tax = { @@ -1799,7 +1807,7 @@ class Facturas(BaseModel): FacturasImpuestos.create(**invoice_tax) total = subtotal + (total_trasladados or 0) - (total_retenciones or 0) - total_mn = round(total * invoice.tipo_cambio, 2) + total_mn = round(total * invoice.tipo_cambio, DECIMALES) data = { 'subtotal': subtotal + descuento, 'descuento': descuento_cfdi, @@ -1930,7 +1938,7 @@ class Facturas(BaseModel): if impuesto.tipo == 'E': continue base = row.importe - row.descuento - import_tax = round(impuesto.tasa * base, 2) + import_tax = round(impuesto.tasa * base, DECIMALES) tipo_factor = 'Tasa' if impuesto.factor != 'T': tipo_factor = 'Cuota' @@ -2341,13 +2349,13 @@ class PreFacturas(BaseModel): valor_unitario = float(product['valor_unitario']) descuento = float(product['descuento']) precio_final = valor_unitario - descuento - importe = round(cantidad * precio_final, 2) + importe = round(cantidad * precio_final, DECIMALES) product['cantidad'] = cantidad product['valor_unitario'] = valor_unitario product['descuento'] = descuento product['precio_final'] = precio_final - product['importe'] = round(cantidad * valor_unitario, 2) + product['importe'] = round(cantidad * valor_unitario, DECIMALES) descuento_cfdi += descuento subtotal += importe @@ -2363,7 +2371,7 @@ class PreFacturas(BaseModel): for tax in totals_tax.values(): if tax.tipo == 'E' or tax.tipo == 'R': continue - import_tax = round(float(tax.tasa) * tax.importe, 2) + import_tax = round(float(tax.tasa) * tax.importe, DECIMALES) total_trasladados = (total_trasladados or 0) + import_tax if tax.name == 'IVA': total_iva += import_tax @@ -2380,9 +2388,9 @@ class PreFacturas(BaseModel): if tax.tipo == 'E' or tax.tipo == 'T': continue if tax.tasa == round(Decimal(2/3), 6): - import_tax = round(float(tax.tasa) * total_iva, 2) + import_tax = round(float(tax.tasa) * total_iva, DECIMALES) else: - import_tax = round(float(tax.tasa) * tax.importe, 2) + import_tax = round(float(tax.tasa) * tax.importe, DECIMALES) total_retenciones = (total_retenciones or 0) + import_tax invoice_tax = { @@ -2394,7 +2402,7 @@ class PreFacturas(BaseModel): PreFacturasImpuestos.create(**invoice_tax) total = subtotal + (total_trasladados or 0) - (total_retenciones or 0) - total_mn = round(total * invoice.tipo_cambio, 2) + total_mn = round(total * invoice.tipo_cambio, DECIMALES) data = { 'subtotal': subtotal + descuento, 'descuento': descuento_cfdi, @@ -2552,7 +2560,9 @@ class PreFacturasDetalle(BaseModel): row['unidad'] = p.producto.unidad.name row['cantidad'] = p.cantidad row['valor_unitario'] = p.valor_unitario - row['importe'] = p.importe + row['descuento'] = p.descuento + pf = p.valor_unitario - p.descuento + row['importe'] = round(pf * p.cantidad, DECIMALES) impuestos = cls._get_impuestos(cls, row['id']) data.append({'row': row, 'taxes': impuestos}) @@ -2687,7 +2697,11 @@ def get_cp(cp): def get_sat_key(key): - return util.get_sat_key('products', key) + return util.get_sat_key('productos', key) + + +def get_sat_unidades(key): + return util.get_sat_unidades(key) def test_correo(values): diff --git a/source/app/settings.py b/source/app/settings.py index 7880a4c..a2e008d 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -92,3 +92,4 @@ PRE = { CURRENT_CFDI = '3.3' DEFAULT_PASSWORD = 'blades3.3' +DECIMALES = 2 diff --git a/source/db/sat.db b/source/db/sat.db index f86398d..8bc71a8 100644 Binary files a/source/db/sat.db and b/source/db/sat.db differ diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index 187d6c9..b09f472 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -30,6 +30,7 @@ var controllers = { $$('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) //~ Opciones tb_options = $$('tab_options').getTabbar() tb_options.attachEvent('onChange', tab_options_change) @@ -983,3 +984,44 @@ function cmd_emisor_agregar_cuenta_click(){ }) } + + +function agregar_nueva_unidad(obj){ + var grid = $$('grid_admin_unidades') + var values = {key: obj.key, name: obj.name} + + webix.ajax().post('/values/addunidad', values, { + error: function(text, data, xhr) { + webix.message({type: 'error', text: 'Error al consultar'}) + }, + success: function(text, data, xhr){ + var values = data.json() + if (values.ok){ + grid.add(obj) + } + } + }) +} + + +function grid_unidad_found_click(obj){ + + + msg = '¿Estás seguro de agregar la siguiente unidad?' + msg += '(' + obj.key + ')
' + msg += obj.name + + webix.confirm({ + title: 'Agregar Unidad', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + agregar_nueva_unidad(obj) + } + } + }) + $$('buscar_nueva_unidad').setValue('') +} diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index ddf2a1b..d23b1c1 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -633,7 +633,10 @@ function set_product(values){ grid.add(values) } else { values['cantidad'] = parseFloat(row.cantidad) + 1 - values['importe'] = values['valor_unitario'] * values['cantidad'] + values['descuento'] = parseFloat(row.descuento) + values['valor_unitario'] = parseFloat(row.valor_unitario) + var precio_final = values['valor_unitario'] - values['descuento'] + values['importe'] = (precio_final * values['cantidad']).round(DECIMALES) grid.updateItem(row.id, values) } form.setValues({search_product_id:'', search_product_name:''}, true) @@ -1173,7 +1176,10 @@ function agregar_preproducto(values){ grid.add(values) } else { values['cantidad'] = parseFloat(row.cantidad) + parseFloat(values['cantidad']) - values['importe'] = values['valor_unitario'] * values['cantidad'] + values['valor_unitario'] = parseFloat(row.valor_unitario) + values['descuento'] = parseFloat(row.descuento) + var precio_final = values['valor_unitario'] - values['descuento'] + values['importe'] = (precio_final * values['cantidad']).round(DECIMALES) grid.updateItem(row.id, values) } diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index 00d5a26..da7ab85 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -562,11 +562,49 @@ var sat_bancos = [ ] +var suggest_sat_unidad = { + view: 'gridsuggest', + id: 'grid_unidad_found', + name: 'grid_unidad_found', + body: { + autoConfig: false, + scroll:true, + autoheight:false, + header: true, + yCount: 10, + columns: [ + {id: 'id', hidden: true}, + {id: 'key', adjust: 'data', header: 'Clave'}, + {id: 'name', adjust: 'data', header: 'Unidad'}, + ], + dataFeed:function(text){ + if (text.length > 2){ + this.load('/values/satunidades?key=' + text) + }else{ + this.hide() + } + } + } +} + + +var buscar_nueva_unidad = { + view: 'search', + id: 'buscar_nueva_unidad', + label: 'Buscar Unidad en el catálogo del SAT', + labelPosition: 'top', + suggest: suggest_sat_unidad, + placeholder: 'Por clave o descripción. Captura al menos tres letras', +} + + var msg_unidades = 'Activar las unidades necesarias' var sat_unidades = [ {maxHeight: 20}, {cols: [{maxWidth: 15}, {view: 'label', label: msg_unidades}, {}]}, {maxHeight: 20}, + {cols: [{maxWidth: 15}, buscar_nueva_unidad, {}]}, + {maxHeight: 20}, {cols: [{maxWidth: 15}, grid_admin_unidades, {}]}, {}, ]