Conociendo los impuestos de los pedidos o de las facturas. El campo tax_totals

16 de agosto de 2025 por
Gustavo Orrillo
| Sin comentarios aún
 

Una necesidad frecuente es poder conocer (o modificar) a nivel documento (factura o pedido de venta, por ejemplo) los impuestos involucrados en el mismo. Es algo necesario en Argentina donde por ejemplo, necesitamos discriminar los impuestos que se agregan según el cliente (en el caso de las percepciones) o agregar impuestos de manera arbitraria (como sucede con las facturas de proveedores, donde la lista de impuestos aplicados es una verdadera murga).

Para manejar ello Odoo introdujo (anda a saber cuando) un campo binario llamado tax_totals, y en este campo binario se almacena un json con los totales del documento por impuesto. Por ejemplo, debajo tenemos un una factura de ventas de Argentina con IVA del 21%, IVA del 10.5% y percepciones de IIBB de Buenos Aires con una alícuota del 3% para el cliente. 

{'currency_id': 19,
'currency_pd': 0.01,
'company_currency_id': 19,
'company_currency_pd': 0.01,
'has_tax_groups': True,
'subtotals': [{'tax_groups': [{'id': 81,
'involved_tax_ids': [390],
'tax_amount_currency': 8097.08,
'tax_amount': 8097.08,
'base_amount_currency': 38557.5,
'base_amount': 38557.5,
'display_base_amount_currency': 38557.5,
'display_base_amount': 38557.5,
'group_name': 'VAT 21%',
'group_label': False},
{'id': 83,
'involved_tax_ids': [388],
'tax_amount_currency': 12145.61,
'tax_amount': 12145.61,
'base_amount_currency': 115672.5,
'base_amount': 115672.5,
'display_base_amount_currency': 115672.5,
'display_base_amount': 115672.5,
'group_name': 'VAT 10.5%',
'group_label': False},
{'id': 93,
'involved_tax_ids': [356],
'tax_amount_currency': 4626.9,
'tax_amount': 4626.9,
'base_amount_currency': 154230.0,
'base_amount': 154230.0,
'display_base_amount_currency': None,
'display_base_amount': None,
'group_name': 'P. IIBB CABA (s) - 3.0%',
'group_label': False},
{'id': 111,
'involved_tax_ids': [374],
'tax_amount_currency': 0,
'tax_amount': 0.0,
'base_amount_currency': 154230.0,
'base_amount': 154230.0,
'display_base_amount_currency': None,
'display_base_amount': None,
'group_name': 'Perc IIBB Misiones',
'group_label': False}],
'tax_amount_currency': 24869.590000000004,
'tax_amount': 24869.590000000004,
'base_amount_currency': 154230.0,
'base_amount': 154230.0,
'name': 'Untaxed Amount'}],
'base_amount_currency': 154230.0,
'base_amount': 154230.0,
'tax_amount_currency': 49739.18000000001,
'tax_amount': 54366.08,
'same_tax_base': False,
'total_amount_currency': 179099.59,
'total_amount': 183726.49,
'display_in_company_currency': False}

El campo lo pueden tratar como un diccionario de Python y se accede mediante el ORM como cualquier otro campo. Verán que tenemos campos con los totales del documento, los totales de los impuestos, los totales en la moneda del documento y la moneda de la empresa. Y una lista con cada impuesto, su base imponible y los totales.

Y aquí lo interesante, puede ser manipulado. Los valores del campo puede ser manipulado. Supongamos que tenemos un pedido de venta y queremos agregarle a ciertos clientes un impuesto que es un porcentaje del importe neto de la factura. Para ello podemos extender el método _get_tax_totals_summary donde podemos extenderlo y modificar el contenido de los impuestos que querramos.

El método get_tax_totals_summary recibe como parámetro un campo denominado base_lines que contiene el que esta involucrado en el cálculo de los impuestos (por ejemplo sale.order.line para pedidos de venta). Si hacemos

            if base_lines:
for base_line in base_lines:
variable = base_line.get('record')
if variable._name not in['sale.order.line','account.move.line']:
return res
if variable._name == 'sale.order.line':

Ahi nos aseguramos que estamos trabajando con un pedido de venta o una factura. Y si luego recorremos cada uno de los tax groups para conocer el impuesto involucrado

            for i,subtotal in enumerate(res.get('subtotals')):
for t,tax_group in enumerate(subtotal.get('tax_groups')):
if tax_group.get('involved_tax_ids'):
tax_id = tax_group.get('involved_tax_ids')[0]

Y ya sabiendo el impuesto y conociendo el monto al que se desea cambiar, lo podemos cambiar de la siguiente manera (por ejemplo)

        tax = self.env['account.tax'].browse(tax_id)
if tax_id in taxes:
res['subtotals'][i]['tax_groups'][t]['group_name'] = tax.name + ' - %s%%'%(taxes[tax_id])
perception_amount = tax_group.get('base_amount_currency') * taxes[tax_id] / 10
res['subtotals'][i]['tax_groups'][t]['tax_amount_currency'] = perception_amount
res['subtotals'][i]['tax_groups'][t]['tax_amount'] = perception_amount * currency_rate
tax_amount_currency = tax_amount_currency + perception_amount
tax_amount = tax_amount_currency + perception_amount * currency_rate

Que es lo que necesitariamos hacer si queremos agregarle soporte de percepciones a los pedidos de venta. De nada

Gustavo Orrillo 16 de agosto de 2025
Compartir
Archivar
Identificarse dejar un comentario