Introducción
En Odoo, los modelos son las plantillas que determinan cómo se guarda cada dato en la base: desde contactos hasta facturas. Cada registro de negocio se almacena dentro de un modelo concreto que organiza campos, relaciones y reglas.
Comprender los modelos de Odoo es imprescindible tanto para implementadores funcionales como para desarrolladores. Son la columna vertebral de la arquitectura de datos: definen qué información existe, cómo se relaciona y qué lógica aplica sobre esos datos.
Este artículo se centra en uno de los modelos más relevantes de Odoo: sales.order. Si vas a desarrollar módulos a medida, integrar sistemas externos o parametrizar ventas, acabarás manipulando este modelo con frecuencia.
¿Qué es el modelo sales.order?
El modelo sales.order agrupa las presupuestos y pedidos de venta. Es el punto central donde se registran las transacciones comerciales antes de pasar a facturación o entrega.
Este modelo forma parte del módulo de Ventas de Odoo.
Un vendedor crea un presupuesto que genera un registro sales.order en estado borrador; al confirmar el cliente, ese mismo registro pasa a pedido confirmado. sales.order aloja tanto presupuestos como pedidos; el campo state refleja en qué fase del ciclo está cada registro.
Otros módulos amplían este modelo mediante herencia: CRM puede enlazar oportunidades con pedidos, Contabilidad añade campos de facturación e Inventario incorpora fechas de entrega y compromiso. Cada módulo aporta lo necesario sin duplicar la estructura base.
Campos clave del modelo
A continuación presentamos los campos más relevantes de sales.order. Conocerlos facilita trabajar con presupuestos y pedidos dentro de Odoo.
1. name
Tipo: Char. Referencia del pedido o número de presupuesto. Suele generarse automáticamente (por ejemplo S00042) y se muestra en listados y documentos como identificador principal.
2. state
Tipo: Selection. Indica la fase del pedido. Valores habituales: draft (presupuesto), sent (presupuesto enviado), sale (pedido confirmado), done (entregado/facturado), cancel (anulado). El estado condiciona qué acciones están disponibles.
3. partner_id
Tipo: Many2one (res.partner). Cliente principal. Campo obligatorio que identifica la empresa o contacto vinculados al pedido, y alimenta la lógica comercial y los informes.
4. partner_invoice_id
Tipo: Many2one (res.partner). Dirección de facturación. Si no se completa, toma por defecto partner_id; se usa cuando la factura debe emitirse a otra entidad (p. ej. facturación centralizada).
5. partner_shipping_id
Tipo: Many2one (res.partner). Dirección de entrega. Si no se especifica, por defecto es partner_id; se emplea para planificar salidas y calcular gastos de envío.
6. user_id
Tipo: Many2one (res.users). Comercial o usuario responsable. Se utiliza en comisiones, asignación de actividades y reporting; suele heredarse del equipo de ventas u oportunidad asociada.
7. team_id
Tipo: Many2one (crm.team). Equipo de ventas. Agrupa vendedores para cuadros de mando y objetivos; influye en informes y políticas comerciales.
8. date_order
Tipo: Datetime. Fecha del pedido: para borradores suele ser la fecha de creación; para pedidos confirmados, la fecha de confirmación. Es clave en informes y ordenación.
9. validity_date
Tipo: Date. Fecha de caducidad del presupuesto. Tras esa fecha la oferta puede considerarse inválida; útil para controles de validez temporal en promociones.
10. commitment_date
Tipo: Datetime. Fecha comprometida de entrega. Si se rellena, las órdenes de salida se planifican en función de esta fecha en lugar de los plazos estándar; esencial para gestionar compromisos con clientes.
11. order_line
Tipo: One2many (sale.order.line). Líneas del pedido. Cada línea contiene producto, cantidad, precio y impuestos; conforman el detalle esencial del pedido.
12. amount_untaxed
Tipo: Float. Subtotal sin impuestos. Calculado a partir de las líneas del pedido; se usa en visualizaciones e informes.
13. amount_tax
Tipo: Float. Total de impuestos. Calculado según las líneas y la configuración fiscal; se muestra en pedido y factura.
14. amount_total
Tipo: Float. Importe total con impuestos. Es el importe principal para facturación y análisis financiero.
15. currency_id
Tipo: Many2one (res.currency). Moneda del pedido. Normalmente proviene de la compañía o la lista de precios; todos los importes monetarios se interpretan en esta moneda.
16. pricelist_id
Tipo: Many2one (product.pricelist). Lista de precios aplicada. Determina los precios unitarios en las líneas; puede heredarse desde el cliente o fijarse manualmente.
17. payment_term_id
Tipo: Many2one (account.payment.term). Condiciones de pago (p. ej. 30 días, 50% al pedido). Se aplica al generar facturas.
18. fiscal_position_id
Tipo: Many2one (account.fiscal.position). Posición fiscal para mapear impuestos. Se utiliza cuando el cliente tiene tratamiento fiscal distinto o es de otro país.
19. client_order_ref
Tipo: Char. Referencia del cliente o número de PO. Se emplea cuando el cliente facilita su propio identificador; aparece en documentos e informes.
20. origin
Tipo: Char. Documento origen. Permite trazar de dónde proviene el pedido, por ejemplo el nombre de la oportunidad que lo generó.
21. create_date
Tipo: Datetime. Fecha y hora de creación del registro. Gestionada automáticamente por Odoo; útil para auditorías y métricas temporales.
22. write_date
Tipo: Datetime. Fecha y hora de la última modificación. También gestionada automáticamente; ayuda a saber cuándo se actualizó por última vez.
23. note
Tipo: Text. Notas o condiciones. Se usa para textos legales, instrucciones internas o cláusulas que aparecerán en presupuestos y facturas.
24. require_signature
Tipo: Boolean. Si es True, requiere firma electrónica del cliente antes de confirmar. Muy usado en ventas online y portales de cliente.
25. require_payment
Tipo: Boolean. Si es True, exige pago antes de confirmar. Adecuado para pedidos con prepago o depósitos.
26. invoice_status
Tipo: Selection. Estado de facturación: no (sin facturar), to invoice (pendiente de facturar), invoiced (facturado), upsell (líneas adicionales por facturar).
27. locked
Tipo: Boolean. Si es True, el pedido no es modificable. Suele activarse al confirmar o cuando documentos vinculados están registrados.
28. company_id
Tipo: Many2one (res.company). En entornos multiempresa indica a qué compañía pertenece el pedido, condicionando visibilidad y permisos.
29. tag_ids
Tipo: Many2many (crm.tag). Etiquetas para segmentación. Útiles para filtros rápidos, informes y flujos personalizados.
30. signed_by
Tipo: Char. Nombre de la persona que firmó el pedido cuando se requiere firma; se conserva para auditoría.
31. signed_on
Tipo: Datetime. Fecha y hora de la firma. Pertinente cuando la confirmación exige firma del cliente.
32. prepayment_percent
Tipo: Float. Porcentaje de pedido que debe pagarse como anticipo. Se combina con require_payment para gestionar pedidos con depósito.
Cómo se usa este modelo en los procesos comerciales
1. De presupuesto a pedido
El flujo típico: un comercial crea un presupuesto en estado borrador, añade líneas y precios y lo envía al cliente; al aceptar, el presupuesto pasa a pedido confirmado (state = sale) y a partir de ahí se generan facturas y albaranes.
2. Comercio electrónico y portal
Las ventas desde la web crean registros sales.order automáticamente. En portales se pueden forzar parámetros como require_payment o require_signature para validar pagos o firmas antes de confirmar el pedido.
3. De CRM a Ventas
Al ganar una oportunidad en CRM se puede generar un presupuesto que referencia la oportunidad en origin. Los campos user_id y team_id mantienen la trazabilidad para comisiones e informes de equipo.
4. Facturación
Desde un pedido confirmado se generan facturas: las líneas se trasladan desde order_line y condiciones como payment_term_id o fiscal_position_id se heredan. invoice_status refleja el avance del proceso de cobro.
5. Entregas y compromisos
La commitment_date sirve para programar las salidas: cuando existe, los albaranes se planifican en torno a esa fecha y partner_shipping_id define el destino de la entrega.
Cómo amplían los desarrolladores este modelo
Los desarrolladores amplían sales.order mediante patrones de herencia y extensiones propias: Odoo ofrece mecanismos claros para añadir campos, modificar comportamientos o integrar lógica adicional.
Herencia de modelo
Emplea _inherit = 'sale.order' para extender el modelo: incorpora campos nuevos, redefine métodos o añade restricciones. Mantener las modificaciones en un módulo separado facilita actualizaciones posteriores.
Añadir campos
Declara nuevos campos en el modelo heredado usando tipos adecuados: Char, Many2one, Boolean, Integer, Text, Selection. En entornos multiempresa valora si los campos han de ser dependientes de la compañía.
Extensiones en Python
Sobrescribe métodos como action_confirm, create o write para incorporar lógica propia, llamando a super() cuando corresponda. Presta atención a los campos computados y sus dependencias para evitar inconsistencias.
Odoo Studio
Odoo Studio permite añadir campos sin programar, ideal para cambios rápidos. Para lógica compleja o proyectos mantenibles a largo plazo, los módulos personalizados siguen siendo la mejor opción.
Buenas prácticas
- Asigna estados correctamente: no saltes etapas ni omitas la lógica de confirmación nativa del sistema.
- Rellena commitment_date cuando haya una fecha de entrega comprometida con el cliente para mejorar la planificación logística.
- Usa commercial_partner_id cuando necesites la entidad de nivel superior (por ejemplo, para análisis de crédito o consolidación de informes).
- Para integraciones con APIs, utiliza XML-RPC o JSON-RPC. El modelo sales.order está expuesto y debes mapear IDs externos con cuidado para evitar colisiones.
- Para campos personalizados, usa prefijos (x_ o el prefijo de tu módulo) para reducir riesgo de conflictos en futuras versiones de Odoo.
Errores frecuentes
- No modifiques pedidos confirmados sin comprobar el flag locked. Si es necesario, crea una revisión o sigue el flujo correcto para mantener trazabilidad.
- No confundas partner_id con partner_invoice_id y partner_shipping_id: cada uno tiene un propósito distinto; completa los tres si las direcciones difieren.
- No sobreescribas action_confirm sin llamar a super(): hacerlo puede romper integraciones y otras extensiones.
- Evita añadir campos obligatorios sin proporcionar valores por defecto: las migraciones o upgrades pueden fallar si existen pedidos previos sin esos valores.
- Asegúrate de fijar pricelist_id si la moneda o reglas de precio difieren del comportamiento por defecto; errores aquí generan facturas incorrectas.
Conclusión
El modelo sales.order es el eje del módulo de Ventas en Odoo, almacenando presupuestos y pedidos. Conocer sus campos y cómo se amplía es clave para configurar, personalizar e integrar con éxito Odoo.
Tanto si eres consultor funcional diseñando procesos de venta como desarrollador creando módulos, dominar sales.order te ahorrará tiempo y reducirá errores en la implantación.
¿Necesitas ayuda con tu implementación de Odoo?
Dasolo acompaña a empresas en la implantación, personalización y optimización de Odoo. Nos especializamos en integraciones API y desarrollo a medida, con experiencia profunda en la arquitectura de datos y modelos como sales.order.
Si necesitas apoyo con tu implantación de Odoo, desarrollo de módulos o integraciones, podemos ayudarte. Solicita una demo para hablar sobre tu proyecto.