Muchas veces necesitamos actualizar en las transacciones de Odoo atributos relacionados con los productos o clientes. Supongamos que tenemos órdenes de venta; muchas veces le agregamos a las líneas de las mismas atributos de los productos. Por ejemplo la marca. Tenemos en el producto un campo llamado marca y necesitamos que el mismo este replicado en la línea de venta. Y muchas veces resolvemos esto con un campo computado que se almacena de la siguiente manera:
marca = fields.Char('Marca',store=True,compute='_compute_marca')
@api.depends('product_tmpl_id')
def _compute_marca(self):
self.marca = self.product_tmpl_id.marca
Lo cual está bien y nos resuelve la actualización del atributo en el momento de la creación de la línea de la orden de venta. Ahora, que sucede cuando el usuario se equivocó y quiere actualizar la marca del producto? Como se actualizan las líneas de venta ya creadas? Hay dos opciones, uno lo hace con el ORM, lo cual esta bien... Otra opción es dejarle la tarea de PostgreSQL para que lo haga mediante triggers.
Que es un trigger de una base de datos? Es un objeto de la base de datos que se ejecuta cada vez que sucede un evento en la misma (por ejemplo se actualiza una columna en una tabla). Es muy util para muchas tareas y permite realizar acciones por fuera de Odoo (por ejemplo logging.
En este caso vamos a querer detectar cada cambio al campo marca en un producto, y actualizar mediante un trigger la tabla sale_order_line. Para ello primero tenemos que definir la función que se ejecutará cuando ocurra el evento:
CREATE OR REPLACE FUNCTION update_sol_marca()
RETURNS TRIGGER AS
$$
BEGIN
-- Solo ejecutar cuando cambie el marca
IF NEW.marca IS DISTINCT FROM OLD.marca THEN
UPDATE sale_order_line
SET marca = NEW.marca
WHERE product_id = (select product_tmpl_id from product_product where id = NEW.id);
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Como pueden ver es una función en PLPGSQL (un lenguaje para trabajar con PostgreSQL) pero tambien podemos utilizar Python. Y en esta función tenemos dos variables, NEW (por el nuevo resgitro) y OLD (por el viejo registro). Nos aseguramos que el campo marca en los dos registros sean diferentes y si es así, se procede a actualizar el campo sale_order_line.
Solo nos queda crear el trigger que se ejecute cada vez que se actualiza la tabla product_template
CREATE TRIGGER trg_update_sol_marca
AFTER UPDATE OF marca
ON product_template
FOR EACH ROW
EXECUTE FUNCTION update_sol_marca();
Lo que hace este trigger es; cada vez que se actualiza el campo marca de product_template, actualiza las filas relacionadas en sale_order_line.
Muchos dirán; eso puedo hacerlo con el ORM! Seguro... pero el ORM tiene problemas cuando llega el momento de trabajar con decenas de miles de registros. Y en ese momento tenemos que recurrir a las herramientas que nos brinda la base de datos.
Bueno, espero que esta vieja herramienta de postgresql les resulte de utilidad,