Aplicando descuentos globales en ordenes de venta

Gustavo Orrillo
- 27/06/2022 - 3 min. de lectura

Odoo brinda con la opción de aplicar descuentos en las ventas. Eso se establece en la configuración del módulo de Ventas.


Eso habilita la posibilidad de agregar descuentos por línea del pedido de venta. Al crear un pedido, se podrá ingresar por línea el descuento a aplicarse:


Como muchas ideas que surgen de Odoo SA, los descuentos por línea son una buena idea cuando la cantidad de líneas son pocas. Cuando tenemos pedidos con decenas de líneas (como sucede a menudo) no es practicable esta idea.

Módulo sale_global_discount de OCA

En el repositorio sale-workflow de OCA, hay un módulo llamado sale_global_discount el cual permite aplicar descuentos en forma global a los pedidos de venta. Forma parte de un pack de tres módulos (base_global_discount, account_global_discount y sale_global_discount) que permiten definir descuentos en forma global y luego aplicarlos en los pedidos de venta.

Lo primero que se debe hacer luego de instalar los módulos, debe ser crear los descuentos globales que se van a poder utilizar en el sistema:


Y establecer descuentos globales es una buena idea. Esto fuerza a la gerencia de Ventas a pensar los niveles de descuentos que se van a ofrecer en el sistema, al tiempo que facilita la validación que los descuentos aplicados sean los correctos (al tiempo que se evita situaciones como, descuento de 100%). Dichos descuentos pueden ser accedidos por el vendedor siempre y cuando el mismo tenga habilitada la opción de "Aplicar descuentos globales", lo cual es bueno también porque facilita la gestión de un grupo de ventas. Uno verá el grupo "Manage global discounts" en el perfil del usuario.



También por cliente o proveedor, se pueden establecer cuales son los descuentos globales que se pueden aplicar.


Acto seguido, uno podrá notar que en el pedido de venta se puede seleccionar que descuento global se va a aplicar. Tambien se notará que en la sección de los totales del pedido de venta, se detalla el porcentaje de descuento global aplicado.


Al confirmarse el pedido, se podrá crear la factura donde se notará que también se aplican los descuentos globales.


Notas técnicas

Para aplicar los descuentos globales, se necesitan tener instalados tres módulos: base_global_discount, account_global_discount y sale_global_discount. El módulo base_global_discount crea el modelo global.discount el cual puede ser accedido por parte del administrador del sistema en el menu Ajustes > Técnicos. Establece las reglas de seguridad para un entorno multi-compañía y crea un grupo para aplicar los descuentos globales.

<record model="ir.rule" id="global_discount_comp_rule">
    <field name="name">Global Discount multi-company</field>
    <field name="model_id" ref="base_global_discount.model_global_discount" />
    <field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
    <field name="perm_read" eval="1" />
    <field name="perm_create" eval="1" />
    <field name="perm_write" eval="1" />
    <field name="perm_unlink" eval="1" />
</record>
<record id="group_global_discount" model="res.groups">
    <field name="name">Manage Global Discounts</field>
    <field name="category_id" ref="base.module_category_hidden" />
</record>

Es interesante que el modelo global.discount tiene un método que devuelve un diccionario en el cual se tiene un valor para el monto base y otro valor para el descuento

def _get_global_discount_vals(self, base, **kwargs):
    """Prepare the dict of values to create to obtain the discounted
        amount
        :param float base: the amount to discount
        :return: dict with the discounted amount
    """
    self.ensure_one()
    return {
        "global_discount": self,
        "base": base,
        "base_discounted": base * (1 - (self.discount / 100)),
        }

que puede invocarse para un monto de 100$ como

res = res_dto._get_global_discount_vals(100)

El módulo sale_global_discount agrega un método interesante para cuando se cambia el partner_id del pedido de venta

@api.onchange("partner_id")
def onchange_partner_id(self):
    res = super().onchange_partner_id()
    self.global_discount_ids = self.partner_id.customer_global_discount_ids.filtered(
        lambda d: d.company_id == self.company_id
        ) or self.partner_id.commercial_partner_id.customer_global_discount_ids.filtered(
            lambda d: d.company_id == self.company_id
        )
    return res

Tiene dos cosas interesantes: por una parte que existe ya en el core un onchange_partner_id para el modelo sale.order. Por otra parte, el uso del método filtered en el recordset. Y los montos del pedido de ventas se calculan por medio del método amount_all.

Por último, en otro post vamos a hablar del módulo account_global_discount ya que en el mismo se extienden los métodos que calculan los totales por descuento e impuesto. Y dichos métodos merecen un capítulo aparte.

Acerca de:

Gustavo Orrillo

Apasionado de la programación, implementa Odoo para distintos tipos de negocios desde el año 2010. En Moldeo Interactive es Socio fundador y Programador; además de escribir en el Blog sobre distintos temas relacionados a los desarrollos que realiza.