diff --git a/source/app/main_debug.ini b/source/app/main_debug.ini index 94481fe..2196794 100644 --- a/source/app/main_debug.ini +++ b/source/app/main_debug.ini @@ -8,4 +8,4 @@ threads = 4 py-autoreload = 1 thunder-lock = true static-map = /static=../static -http-timeout = 120 \ No newline at end of file +http-timeout = 180 \ No newline at end of file diff --git a/source/app/models/main.py b/source/app/models/main.py index 3bc59fd..26e0bea 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -17,10 +17,11 @@ if __name__ == '__main__': from controllers import util from settings import log, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \ INIT_VALUES, DEFAULT_PASSWORD, DECIMALES, IMPUESTOS, DEFAULT_SAT_PRODUCTO, \ - CANCEL_SIGNATURE, PUBLIC, DEFAULT_SERIE_TICKET + CANCEL_SIGNATURE, PUBLIC, DEFAULT_SERIE_TICKET, DECIMALES_TAX FORMAT = '{0:.2f}' +FORMAT_TAX = '{0:.4f}' database_proxy = Proxy() @@ -129,8 +130,9 @@ def import_invoice(): obj = Productos.get(Productos.clave==row[0]) if obj.id in products: vu = round(row[2], 2) - cant = round(row[3], 2) - pf = products[obj.id]['valor_unitario'] - float(obj.descuento) + descuento = round(row[3], 2) + cant = round(row[4], 2) + pf = products[obj.id]['valor_unitario'] - descuento products[obj.id]['cantidad'] += cant products[obj.id]['importe'] = round( pf * products[obj.id]['cantidad'], DECIMALES) @@ -139,8 +141,9 @@ def import_invoice(): return {'ok': False, 'msg': msg} else: vu = round(row[2], 2) - cant = round(row[3], 2) - pf = vu - float(obj.descuento) + descuento = round(row[3], 2) + cant = round(row[4], 2) + pf = vu - descuento p = { 'id': obj.id, 'delete': '-', @@ -217,6 +220,7 @@ def config_timbrar(): 'cfdi_open_pdf': Configuracion.get_bool('chk_config_open_pdf'), 'cfdi_show_pedimento': Configuracion.get_bool('chk_config_show_pedimento'), 'cfdi_tax_locales': Configuracion.get_bool('chk_config_tax_locales'), + 'cfdi_tax_decimals': Configuracion.get_bool('chk_config_tax_decimals'), } return conf @@ -3069,12 +3073,12 @@ class Facturas(BaseModel): def _calculate_totals(self, invoice, products): tax_locales = Configuracion.get_bool('chk_config_tax_locales') + tax_decimals = Configuracion.get_bool('chk_config_tax_decimals') subtotal = 0 descuento_cfdi = 0 totals_tax = {} total_trasladados = None total_retenciones = None - # ~ total_iva = 0 locales_traslados = 0 locales_retenciones = 0 @@ -3112,7 +3116,10 @@ class Facturas(BaseModel): for tax in p.impuestos: if tax_locales and tax.tipo == 'R' and tax.key == '000': base = product['importe'] - impuesto_producto = round(float(tax.tasa) * base, DECIMALES) + if tax_decimals: + impuesto_producto = round(float(tax.tasa) * base, DECIMALES_TAX) + else: + impuesto_producto = round(float(tax.tasa) * base, DECIMALES) if tax.tipo == 'T' and tax.key != '000': total_trasladados = (total_trasladados or 0) + impuesto_producto elif tax.tipo == 'R' and tax.key != '000': @@ -3134,7 +3141,6 @@ class Facturas(BaseModel): if tax.tipo == 'E': continue - invoice_tax = { 'factura': invoice.id, 'impuesto': tax.id, @@ -3229,6 +3235,8 @@ class Facturas(BaseModel): return data def _make_xml(self, invoice, auth): + tax_decimals = Configuracion.get_bool('chk_config_tax_decimals') + tmp = 0 emisor = Emisor.select()[0] certificado = Certificado.select()[0] @@ -3317,7 +3325,13 @@ class Facturas(BaseModel): continue base = row.importe - row.descuento - import_tax = round(impuesto.tasa * base, DECIMALES) + if tax_decimals: + import_tax = round(impuesto.tasa * base, DECIMALES_TAX) + tmp += import_tax + xml_importe = FORMAT_TAX.format(import_tax) + else: + import_tax = round(impuesto.tasa * base, DECIMALES) + xml_importe = FORMAT.format(import_tax) tipo_factor = 'Tasa' if impuesto.factor != 'T': tipo_factor = 'Cuota' @@ -3326,7 +3340,7 @@ class Facturas(BaseModel): "Impuesto": impuesto.key, "TipoFactor": tipo_factor, "TasaOCuota": str(impuesto.tasa), - "Importe": FORMAT.format(import_tax), + "Importe": xml_importe, } if impuesto.tipo == 'T': traslados.append(tax) @@ -3347,6 +3361,7 @@ class Facturas(BaseModel): total_locales_retenciones = 0 locales_trasladados = [] locales_retenciones = [] + if not invoice.total_trasladados is None: impuestos['TotalImpuestosTrasladados'] = \ FORMAT.format(invoice.total_trasladados) @@ -3382,12 +3397,18 @@ class Facturas(BaseModel): tipo_factor = 'Tasa' if tax.impuesto.factor != 'T': tipo_factor = 'Cuota' + + if tax_decimals: + xml_importe = FORMAT_TAX.format(tax.importe) + else: + xml_importe = FORMAT.format(tax.importe) + if tax.impuesto.tipo == 'T': traslado = { "Impuesto": tax.impuesto.key, "TipoFactor": tipo_factor, "TasaOCuota": str(tax.impuesto.tasa), - "Importe": FORMAT.format(tax.importe), + "Importe": xml_importe, } traslados.append(traslado) else: @@ -3811,12 +3832,16 @@ class PreFacturas(BaseModel): return inicio def _calculate_totals(self, invoice, products): + tax_locales = Configuracion.get_bool('chk_config_tax_locales') + tax_decimals = Configuracion.get_bool('chk_config_tax_decimals') + tax_decimals = True subtotal = 0 descuento_cfdi = 0 totals_tax = {} total_trasladados = None total_retenciones = None - # ~ total_iva = 0 + locales_traslados = 0 + locales_retenciones = 0 for product in products: id_product = product.pop('id') @@ -3846,47 +3871,47 @@ class PreFacturas(BaseModel): subtotal += importe PreFacturasDetalle.create(**product) + + base = product['importe'] - product['descuento'] for tax in p.impuestos: - if tax.id in totals_tax: - totals_tax[tax.id].importe += importe + if tax_locales and tax.tipo == 'R' and tax.key == '000': + base = product['importe'] + if tax_decimals: + impuesto_producto = round(float(tax.tasa) * base, DECIMALES_TAX) else: - tax.importe = importe + impuesto_producto = round(float(tax.tasa) * base, DECIMALES) + if tax.tipo == 'T' and tax.key != '000': + total_trasladados = (total_trasladados or 0) + impuesto_producto + elif tax.tipo == 'R' and tax.key != '000': + total_retenciones = (total_retenciones or 0) + impuesto_producto + elif tax.tipo == 'T' and tax.key == '000': + locales_traslados += impuesto_producto + elif tax.tipo == 'R' and tax.key == '000': + locales_retenciones += impuesto_producto + + if tax.id in totals_tax: + totals_tax[tax.id].base += base + totals_tax[tax.id].suma_impuestos += impuesto_producto + else: + tax.base = base + tax.suma_impuestos = impuesto_producto totals_tax[tax.id] = tax for tax in totals_tax.values(): - if tax.tipo == 'E' or tax.tipo == 'R': + if tax.tipo == 'E': continue - 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 invoice_tax = { 'factura': invoice.id, 'impuesto': tax.id, - 'base': tax.importe, - 'importe': import_tax, + 'base': tax.base, + 'importe': tax.suma_impuestos, } PreFacturasImpuestos.create(**invoice_tax) - for tax in totals_tax.values(): - 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, DECIMALES) - # ~ else: - import_tax = round(float(tax.tasa) * tax.importe, DECIMALES) - total_retenciones = (total_retenciones or 0) + import_tax - - invoice_tax = { - 'factura': invoice.id, - 'impuesto': tax.id, - 'base': tax.importe, - 'importe': import_tax, - } - PreFacturasImpuestos.create(**invoice_tax) - - total = subtotal + (total_trasladados or 0) - (total_retenciones or 0) + total = subtotal - descuento_cfdi + \ + (total_trasladados or 0) - (total_retenciones or 0) \ + + locales_traslados - locales_retenciones total_mn = round(total * invoice.tipo_cambio, DECIMALES) data = { 'subtotal': subtotal + descuento, @@ -4090,9 +4115,6 @@ class PreFacturasDetalle(BaseModel): @classmethod def can_open(cls, id): c = cls.count(id) - # ~ result = c < 300 - # ~ if result: - # ~ return True PreFacturas.get_pdf_in_thread(id) return c < 300 diff --git a/source/app/settings.py b/source/app/settings.py index 415d381..061ecdd 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -111,6 +111,7 @@ PRE = { CURRENT_CFDI = '3.3' DECIMALES = 2 +DECIMALES_TAX = 4 IMPUESTOS = { 'ISR': '001', 'IVA': '002', diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index db54fe8..3881758 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -163,6 +163,7 @@ function default_config(){ } cfg_invoice['open_pdf'] = values.cfdi_open_pdf cfg_invoice['tax_locales'] = values.cfdi_tax_locales + cfg_invoice['tax_decimals'] = values.cfdi_tax_decimals if(values.cfdi_show_pedimento){ $$('grid_details').showColumn('pedimento') } @@ -796,7 +797,11 @@ function calcular_impuestos(){ base = (base * -1).round(DECIMALES) } - impuesto_producto = (impuesto.tasa * base).round(DECIMALES) + if(cfg_invoice.tax_decimals){ + impuesto_producto = (impuesto.tasa * base).round(DECIMALES_TAX) + }else{ + impuesto_producto = (impuesto.tasa * base).round(DECIMALES) + } tmp = table_totals.findOne({'tax': tax.tax}) if(tmp === null){ diff --git a/source/static/js/controller/util.js b/source/static/js/controller/util.js index 0373ee7..0081054 100644 --- a/source/static/js/controller/util.js +++ b/source/static/js/controller/util.js @@ -3,6 +3,7 @@ var RFC_PUBLICO = "XAXX010101000"; var RFC_EXTRANJERO = "XEXX010101000"; var PAIS = "México"; var DECIMALES = 2; +var DECIMALES_TAX = 4; var CLAVE_ANTICIPOS = '84111506';