Skip to Content

The purchase.order Model: Understanding Odoo's Purchase Order Architecture

A complete guide to Odoo's purchase order model for developers and functional consultants
March 11, 2026 by
The purchase.order Model: Understanding Odoo's Purchase Order Architecture
Dasolo
| No comments yet

Introduction


In Odoo, models define how data is structured and stored in the database. Every piece of business data you work with, from purchase orders to invoices to inventory, 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 Odoo fields, relationships, and business logic.


This article focuses on one of the most important models in Odoo: purchase.order. Whether you are building custom modules, integrating external systems, or configuring procurement workflows, you will work with this model.

What is the purchase.order Model


The purchase.order model represents purchase orders and requests for quotation (RFQs) in Odoo. It is the central place where all procurement transactions are captured before they become receipts or vendor bills.


This model in Odoo is used by the Purchase module. When a buyer creates an RFQ, they create a purchase.order record. When the vendor confirms or the buyer approves, the order moves from draft to confirmed. The same model in Odoo holds both draft RFQs and confirmed purchase orders. The state field tracks the lifecycle.


Other modules extend this model through Odoo model inheritance. Inventory adds receipt and picking logic. Accounting adds vendor bill fields. Manufacturing can create purchase orders from bills of materials. 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 purchase.order model. Understanding these will help you work effectively with purchase orders.


1. name

Type: Char. This field stores the order reference (e.g. PO00042). It is typically auto-generated and displayed in list views and on documents. It is the primary identifier for the purchase order.


2. state

Type: Selection. Tracks the order lifecycle. Values: draft (RFQ), sent (sent to vendor), to approve (awaiting approval), purchase (confirmed), done (fully received and invoiced), cancel (cancelled). The state drives which actions are available.


3. partner_id

Type: Many2one (res.partner). The vendor or supplier. Required. This is the main contact or company for the order. Used for all vendor-related logic and reporting.


4. partner_ref

Type: Char. The vendor reference or supplier PO number. Used when the vendor provides their own order reference. Displayed on documents and helps match receipts and bills.


5. date_order

Type: Datetime. The order date. For draft orders: creation date. For confirmed orders: confirmation date. Used for reporting, sorting, and as the default expected date for order lines.


6. date_approve

Type: Datetime. The approval or confirmation date. Set when the order moves to purchase state. Read-only. Used for reporting and audit trails.


7. order_line

Type: One2many (purchase.order.line). The order lines. Each line contains product, quantity, price, and tax. This is the core detail of the purchase order.


8. amount_untaxed

Type: Float. The subtotal before tax. Computed from order lines. Used for reporting and display.


9. amount_tax

Type: Float. The total tax amount. Computed from order lines based on tax configuration. Displayed on the order and vendor bill.


10. amount_total

Type: Float. The total amount including tax. The main amount for invoicing and reporting.


11. currency_id

Type: Many2one (res.currency). The currency. Usually inherited from the company or vendor. All monetary fields use this currency.


12. origin

Type: Char. The source document. For example, when an order is created from a sale order (dropship) or manufacturing order, the source name is stored here. Used for traceability.


13. dest_address_id

Type: Many2one (res.partner). The delivery address. If not set, defaults to the company address. Used for dropshipping when goods go directly to the customer.


14. priority

Type: Selection. Order priority: Normal or Urgent. Used for sorting and highlighting. Urgent orders may get special handling in workflows.


15. invoice_status

Type: Selection. Tracks invoicing: no (not invoiced), to invoice (ready to invoice), invoiced (fully invoiced). Drives the Create Bill action visibility.


16. invoice_count

Type: Integer. Number of related vendor bills. Computed. Used for display and to open the list of bills.


17. invoice_ids

Type: One2many (account.move). The related vendor bills. Links purchase orders to accounting. Used for three-way matching and payment tracking.


18. picking_ids

Type: One2many (stock.picking). The related delivery orders or receipts. Used when the Purchase module is installed with Inventory.


19. picking_count

Type: Integer. Number of related pickings. Computed. Used for display and to open the list of receipts.


20. create_date

Type: Datetime. Stores the date and time when the record was created. Automatically managed by Odoo. Useful for reporting and auditing.


21. write_date

Type: Datetime. Stores the date and time of the last modification. Also automatically managed. Helps track when data was last updated.


22. notes

Type: Text. Terms and conditions or internal notes. Can be displayed on the purchase order. Used for special instructions to the vendor.


23. company_id

Type: Many2one (res.company). In multi-company setups, this indicates which Odoo company the order belongs to. Affects record visibility and access.


24. user_id

Type: Many2one (res.users). The buyer or responsible user. Used for approval workflows and activity assignment.


25. fiscal_position_id

Type: Many2one (account.fiscal.position). The fiscal position for tax mapping. Applied when the vendor is in a different country or has special tax regime.


26. payment_term_id

Type: Many2one (account.payment.term). Payment terms (e.g. Net 30, 50% advance). Used when creating vendor bills.


27. display_name

Type: Char. Computed display name. Combines name with vendor info. Used in many2one dropdowns and search results. Read-only.


28. active

Type: Boolean. Soft delete flag. When False, the record is archived and hidden from default views. Purchase orders are not physically deleted to preserve history.

How This Model Is Used in Business Workflows


1. RFQ to Purchase Order

Buyer creates a request for quotation (draft). Adds lines, sends to vendor. Vendor confirms or buyer manually confirms. The order is confirmed (state = purchase). Receipts and vendor bills can be created.


2. Vendor Receipt

When goods arrive, the user creates a receipt from the purchase order. The picking_ids are linked. Quantities received update stock. Product costs are updated from the purchase price.


3. Vendor Bill

From a confirmed order, users create vendor bills. Invoice lines are pulled from order lines. payment_term_id and fiscal_position_id come from the order. invoice_status tracks progress.


4. Dropshipping

When a sale order triggers a purchase, the origin links back to the sale. dest_address_id is set to the customer address so the vendor ships directly. The purchase.order model is the bridge between sales and procurement.



5. Manufacturing and MRP

When a manufacturing order needs components, it can create purchase orders for raw materials. The origin field links to the manufacturing order. This model is central to the procure-to-pay cycle.

How Developers Extend This Model


Developers extend purchase.order using several patterns. Odoo model inheritance is the main mechanism.


Model Inheritance

Use _inherit = 'purchase.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 button_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. The API model in Odoo (purchase.order) is fully exposed via XML-RPC and JSON-RPC for integrations.

Best Practices


  • Use the correct state for each stage. Do not skip states or bypass confirmation logic.
  • Set partner_ref when the vendor provides a reference. It helps match receipts and bills.
  • Use origin to trace the source of purchase orders. Essential for dropshipping and manufacturing.
  • When building API integrations, use the XML-RPC or JSON-RPC API. The purchase.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 state. Confirmed orders have restricted fields. Create a new order or use the proper workflow.
  • Mixing up partner_id and dest_address_id. partner_id is the vendor; dest_address_id is where goods go (for dropshipping).
  • Overriding button_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 currency_id when dealing with multi-currency vendors. Wrong currency can lead to incorrect costs and invoicing.

Conclusion


The purchase.order model is central to Odoo Purchase. It stores RFQs and confirmed purchase orders. Understanding its Odoo fields and how modules extend it will help you configure, customize, and integrate Odoo effectively.


Whether you are a functional consultant mapping procurement processes or a developer building custom modules, a solid grasp of purchase.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 purchase.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.

The purchase.order Model: Understanding Odoo's Purchase Order Architecture
Dasolo March 11, 2026
Share this post
Sign in to leave a comment