Saltar al contenido
Todos los posts
23 de mayo de 2025·2 min de lectura·Diogo Hudson

El precio en una cotización es un snapshot, no un query

Los precios de catálogo cambian. Las cotizaciones que ya mandaste no deberían. Una decisión arquitectural de una línea que evita meses de disputas.

El precio en una cotización es un snapshot, no un query

Bug común en sistemas caseros de cotización: el PDF muestra el precio del momento en que el cliente lo abre. Ajustas el catálogo el martes, el cliente abre la cotización el jueves, el precio impreso está mal, el cliente se enoja, y nadie sabe explicar qué pasó.

Este bug es insidioso porque no parece un bug. El sistema está funcionando correctamente — está mostrando el precio actual. El problema es que 'precio actual' es la respuesta equivocada para un documento que fue creado la semana pasada. La cotización es un snapshot de un acuerdo comercial en un punto en el tiempo. El catálogo es un documento vivo. Confundir los dos es un error de categoría, y es uno que cuesta dinero real cuando un cliente te exige cumplir una cotización que no puedes honrar al precio original.

Snapshot en la creación de la línea Cada QuoteItem lleva un unit_price capturado del Product al momento de crear la línea. Las actualizaciones de catálogo nunca reescriben el historial. D2 y D11 en el decision log son explícitas: snapshot es el contrato.

La implementación es directa: cuando se crea una línea de cotización, el service lee el unit_price actual del producto y lo escribe en QuoteItem.unit_price. Después de ese momento, los dos valores son independientes. El precio del producto puede cambiar cien veces — la línea de la cotización mantiene el precio que estaba vigente cuando la línea fue creada. Si el comercial quiere usar el precio actualizado, debe explícitamente re-preciar la línea.

¿Por qué no simplemente re-consultar? Re-consultar hace que cada reload muestre un total sutilmente diferente. Tu PDF impreso y la base de datos están en desacuerdo. Dos clientes distintos terminan con precios distintos por la misma cotización histórica. El snapshot elimina todo eso.

La dimensión legal hace esto no negociable. En la mayoría de las jurisdicciones, una cotización es una oferta. Una vez aceptada, se convierte en contrato al precio cotizado. Si tu sistema silenciosamente cambia el precio entre el momento en que enviaste la cotización y el momento en que el cliente la aceptó, o absorbes la diferencia o discutes con un cliente que tiene un PDF con un número distinto. Ninguno de los dos resultados es bueno para el negocio.

El descuento también vive en la línea discount_pct es por línea, capturado al mismo tiempo. line_total es una propiedad computada — cantidad × unit_price × (1 − discount_pct / 100). Toda la matemática es reproducible desde la fila.

Como cada input del total de línea está almacenado en la fila, el total es determinístico. Dos personas diferentes viendo la misma cotización, con seis meses de diferencia, verán los mismos números. Un auditor puede recalcular cada línea desde los campos almacenados y verificar que el total coincide. No hay fórmula oculta, no hay lookup dinámico, no hay datos de referencia que puedan haber cambiado desde que se creó la cotización. La fila es autocontenida y autodemostrable.

Cómo una cotización va de borrador a entrega.

Todos los posts
Textos cortos sobre cotizar, inventario, IA y cómo los distribuidores pequeños despachan mucho volumen sin tanto rodeo.