Introduction
In Odoo, models define how data is structured and stored in the database. Every piece of business data you work with, from sales orders to invoices to contacts, lives in a model.
Understanding Odoo models is essential for both developers and functional consultants. Models are the foundation of the Odoo data architecture. They define fields, relationships, and business logic.
This article focuses on one of the most important models in Odoo: sales.order. Whether you are building custom modules, integrating external systems, or configuring sales workflows, you will work with this model.
What is the sales.order Model
The sales.order model represents quotations and sales orders in Odoo. It is the central place where all sales transactions are captured before they become invoiced or delivered.
This model in Odoo is used by the Sales module.
When a salesperson creates a quotation, they create a sales.order record. When the customer confirms, the order moves from draft to confirmed. The same model in Odoo holds both draft quotations and confirmed orders. The state field tracks the lifecycle.
Other modules extend this model through Odoo model inheritance. CRM links opportunities to orders. Accounting adds invoice fields. Inventory adds delivery and commitment dates. Each module adds what it needs without duplicating the core structure.
Key Fields in the Model
Here are the most important Odoo fields in the sales.order model. Understanding these will help you work effectively with quotations and orders.
1. name
Type: Char. This field stores the order reference or quotation number. It is typically auto-generated (e.g. S00042) and displayed in list views and on documents. It is the primary identifier for the order.
2. state
Type: Selection. Tracks the order lifecycle. Values: draft (quotation), sent (quotation sent to customer), sale (confirmed order), done (fully delivered and invoiced), cancel (cancelled). The state drives which actions are available.
3. partner_id
Type: Many2one (res.partner). The customer. Required. This is the main contact or company for the order. Used for all customer-related logic and reporting.
4. partner_invoice_id
Type: Many2one (res.partner). The billing address. If not set, it defaults to the partner_id. Use this when the invoice address differs from the main contact (e.g. central billing).
5. partner_shipping_id
Type: Many2one (res.partner). The delivery address. If not set, defaults to partner_id. Used for delivery orders and shipping calculations.
6. user_id
Type: Many2one (res.users). The salesperson or responsible user. Used for CRM, commissions, and activity assignment. Often set from the sales team or opportunity.
7. team_id
Type: Many2one (crm.team). The sales team. Groups salespeople and drives reporting. Used for team-based dashboards and quotas.
8. date_order
Type: Datetime. The order date. For draft orders: creation date. For confirmed orders: confirmation date. Used for reporting and sorting.
9. validity_date
Type: Date. The expiration date of the quotation. After this date, the quotation may become invalid. Useful for time-limited offers.
10. commitment_date
Type: Datetime. The promised delivery date. When set, delivery orders are scheduled based on this date rather than product lead times. Important for customer commitments.
11. order_line
Type: One2many (sale.order.line). The order lines. Each line contains product, quantity, price, and tax. This is the core detail of the order.
12. amount_untaxed
Type: Float. The subtotal before tax. Computed from order lines. Used for reporting and display.
13. amount_tax
Type: Float. The total tax amount. Computed from order lines based on tax configuration. Displayed on the order and invoice.
14. amount_total
Type: Float. The total amount including tax. The main amount for invoicing and reporting.
15. currency_id
Type: Many2one (res.currency). The currency. Usually inherited from the company or pricelist. All monetary fields use this currency.
16. pricelist_id
Type: Many2one (product.pricelist). The price list used for the order. Determines unit prices on lines. Can be set from the partner or manually.
17. payment_term_id
Type: Many2one (account.payment.term). Payment terms (e.g. Net 30, 50% advance). Used when creating invoices.
18. fiscal_position_id
Type: Many2one (account.fiscal.position). The fiscal position for tax mapping. Applied when the customer is in a different country or has special tax regime.
19. client_order_ref
Type: Char. The customer reference or PO number. Used when the customer provides their own order reference. Displayed on documents and in reports.
20. origin
Type: Char. The source document. For example, when an order is created from an opportunity, the opportunity name is stored here. Used for traceability.
21. create_date
Type: Datetime. Stores the date and time when the record was created. Automatically managed by Odoo. Useful for reporting and auditing.
22. write_date
Type: Datetime. Stores the date and time of the last modification. Also automatically managed. Helps track when data was last updated.
23. note
Type: Text. Terms and conditions or internal notes. Can be displayed on the quotation and invoice. Used for legal text or special instructions.
24. require_signature
Type: Boolean. When True, the customer must sign online before the order is confirmed. Used for e-commerce and portal flows.
25. require_payment
Type: Boolean. When True, payment is required before confirmation. Used for prepaid or deposit-based orders.
26. invoice_status
Type: Selection. Tracks invoicing: no (not invoiced), to invoice (ready to invoice), invoiced (fully invoiced), or upsell (additional lines to invoice).
27. locked
Type: Boolean. When True, the order cannot be modified. Set automatically when the order is confirmed or when related documents are posted.
28. company_id
Type: Many2one (res.company). In multi-company setups, this indicates which Odoo company the order belongs to. Affects record visibility and access.
29. tag_ids
Type: Many2many (crm.tag). Tags for categorization. Used for filtering, reporting, and segmentation. Flexible for custom workflows.
30. signed_by
Type: Char. Name of the person who signed the order when require_signature is used. Stored for audit.
31. signed_on
Type: Datetime. Date and time of signature. Used when signature is required for confirmation.
32. prepayment_percent
Type: Float. The percentage of the order that must be paid as prepayment. Used with require_payment for deposit-based orders.
How This Model Is Used in Business Workflows
1. Quotation to Order
Salesperson creates a quotation (draft). Adds lines, sets prices, sends to customer. Customer confirms. The order is confirmed (state = sale). Invoices and delivery orders can be created.
2. E-commerce and Portal
Customers place orders on the website. Orders are created as sales.order records. require_signature and require_payment can enforce online payment or signature before confirmation.
3. CRM to Sales
When an opportunity is won, a quotation is created from it. The origin field links back to the opportunity. user_id and team_id drive sales reporting and commissions.
4. Invoicing
From a confirmed order, users create invoices. Invoice lines are pulled from order lines. payment_term_id and fiscal_position_id come from the order. invoice_status tracks progress.
5. Delivery and Commitment
commitment_date drives delivery scheduling. When set, delivery orders are planned around it. partner_shipping_id defines the delivery address.
How Developers Extend This Model
Developers extend sales.order using several patterns. Odoo model inheritance is the main mechanism.
Model Inheritance
Use _inherit = 'sale.order' to extend the model. Add new Odoo fields, override methods, or add constraints. The inherit model in Odoo keeps your changes in a separate module for easy upgrades.
Adding Fields
Define new Odoo fields in your inherited model. Use the right field type: Char, Many2one, Boolean, Integer, Text, Selection. Consider company-dependent fields for multi-company.
Python Extensions
Override action_confirm, create, or write to add logic. Use super() to call the original. Be careful with computed fields and their dependencies.
Odoo Studio
Odoo Studio lets you add fields without code. Good for quick customizations. For complex logic or upgrades, custom modules are more maintainable.
Best Practices
- Use the correct state for each stage. Do not skip states or bypass confirmation logic.
- Set commitment_date when the customer has a promised date. It improves delivery planning.
- Use commercial_partner_id when you need the top-level entity for grouping (e.g. for credit or reporting).
- When building API integrations, use the XML-RPC or JSON-RPC API. The sales.order model is fully exposed. Map external IDs carefully.
- For custom fields, use the
x_prefix or a module prefix to avoid conflicts with future Odoo versions.
Common Mistakes
- Modifying confirmed orders without checking locked. Locked orders cannot be edited. Create a new revision or use the proper workflow.
- Mixing up partner_id, partner_invoice_id, and partner_shipping_id. Each has a distinct purpose. Set all three when addresses differ.
- Overriding action_confirm without calling super(). This can break other modules or future upgrades.
- Adding required custom fields without defaults. Existing orders will fail validation on upgrade.
- Forgetting to set pricelist_id when the currency or pricing differs from the default. Wrong prices can lead to incorrect invoicing.
Conclusion
The sales.order model is central to Odoo Sales. It stores quotations and confirmed orders. Understanding its fields and how modules extend it will help you configure, customize, and integrate Odoo effectively.
Whether you are a functional consultant mapping sales processes or a developer building custom modules, a solid grasp of sales.order will save time and prevent errors.
Need Help With Your Odoo Implementation?
Dasolo helps companies implement, customize, and optimize Odoo. We specialize in API integrations and Odoo development. Our team has deep experience with the Odoo data architecture and models like sales.order.
If you need help with your Odoo implementation, custom modules, or integrations, we are here to help. Book a demo to discuss your project.