Skip to Content

The Monetary Field in Odoo: How It Works and When to Use It

A practical guide to handling currency values correctly in the Odoo data model
March 6, 2026 by
The Monetary Field in Odoo: How It Works and When to Use It
Dasolo
| No comments yet

Introduction


The Monetary field is one of the most useful and most frequently misused field types in Odoo. It looks like a number, stores like a float, but behaves like neither. Once you understand what makes it different, you will never use a plain Float for a financial value again.


If you have ever looked at a sales order total, an invoice amount, or a product price in Odoo, you have already used a Monetary field. They are everywhere in the Odoo data model, and they quietly do a lot of the heavy lifting around currency formatting, rounding, and precision.

This guide is for Odoo developers, consultants, and technically-minded business users who want to understand how the Monetary field actually works. Whether you are following an odoo field tutorial, building a custom module, or just trying to understand why your amounts are rounding differently than expected, this is the reference you need.

What Is the Monetary Field in Odoo


The fields.Monetary type is one of the core odoo field types in the Odoo framework. It is designed specifically to store currency-denominated values: prices, amounts, totals, budgets, or any number that represents money.


What makes it distinct from a regular Float is the mandatory relationship with a currency. A Monetary field always knows what currency it is working with, and it uses that currency to determine how many decimal places to display and how to round stored values.


How It Appears in the Interface

In the Odoo UI, a Monetary field displays the value formatted according to the associated currency. If the currency is Euro, you see something like € 1,234.50. If it is the US Dollar, you see $ 1,234.50. The number of decimal places follows the configuration of the currency record.


The field is fully editable in form views, displays cleanly in list views, and integrates naturally into pivot tables and financial reports. End users do not have to think about formatting at all. Odoo handles it transparently.


The Underlying Data Type

At the database level, a Monetary field is stored as a double precision float in PostgreSQL. The currency information is not stored in the same column. It comes from a related res.currency record, linked through a separate Many2one field on the same model.


This separation of value and currency is intentional. It keeps the odoo database fields clean and makes it possible to change a record's currency independently of its stored amounts.


How the Field Works


Understanding the mechanics behind the Monetary field will help you use it correctly and avoid the kind of rounding or display issues that are surprisingly common in custom Odoo development.


The currency_field Parameter

Every Monetary field must be paired with a Many2one field pointing to res.currency. By default, Odoo looks for a field named currency_id on the same model. You can override this with the currency_field parameter:


amount = fields.Monetary(string='Amount', currency_field='currency_id')

If the currency field is missing or not set on a given record, Odoo falls back to the company currency. This prevents hard errors, but in a multi-currency environment it will produce incorrect formatting. Always declare the currency field explicitly.


Rounding and Precision

One of the key differences between Monetary and Float is how rounding works. The res.currency model defines the number of decimal places and the rounding factor for each currency. When Odoo reads or displays a Monetary value, it applies those rules automatically.

This means a value stored as 1.2349999 for a EUR field will display as 1.23, not 1.235 or 1.23499. This is critical for tax calculations, invoice totals, and any financial reconciliation process. Using a plain Float in those contexts will eventually produce rounding discrepancies that are difficult to trace.


Interaction with the Odoo ORM

In the odoo orm, reading a Monetary field always returns a Python float. The currency context comes from the paired currency field on the same record. When doing calculations in Python that involve Monetary fields, use the currency's round() method to preserve precision:


rounded_value = self.currency_id.round(self.amount)

This avoids floating-point accumulation errors that can appear in multi-line totals or iterative computations.


Monetary Fields in QWeb Reports

In QWeb report templates, Monetary fields integrate with a dedicated widget that formats the value correctly in PDFs and web reports:


<span t-esc="record.amount"
      t-options='{"widget": "monetary", "display_currency": record.currency_id}'/>

This ensures the correct currency symbol and decimal formatting in every generated document, regardless of the currency on the record.

Business Use Cases


Monetary fields are used throughout standard Odoo modules. Here are five concrete examples that illustrate where and why they matter in real business workflows.


1. Sales: Product Prices and Order Totals

Fields like price_unit, price_subtotal, and amount_total on sale orders and order lines are all Monetary fields. They automatically respect the currency selected on the customer order, which may differ from the company's operating currency.


When a sales rep creates an order in USD for a company that operates in EUR, Odoo handles the display, rounding, and conversion correctly because the Monetary field always works in the context of the record's currency, not the system currency.


2. Accounting: Invoice Amounts and Tax Lines

In the accounting module, every amount column on an invoice is a Monetary field: amount_untaxed, amount_tax, amount_total. The currency set on the invoice drives the rounding of all these values.


This is not a detail. Incorrect rounding on tax lines creates journal entry imbalances that are painful to reconcile. The Monetary field's currency-aware rounding is what prevents those issues at the data level.


3. CRM: Expected Revenue on Opportunities

The expected_revenue field on a CRM opportunity is a Monetary field. Sales teams can capture pipeline values in the prospect's currency, while dashboards and reports convert everything to the company currency for pipeline analysis and forecasting.


This setup works cleanly precisely because Monetary fields carry currency information alongside their numeric value.


4. Purchase: Vendor Prices and Purchase Orders

Purchase orders use Monetary fields for unit prices and totals, linked to the vendor's agreed currency. A vendor invoice in Japanese Yen is handled the same way as one in Euro. The Monetary field takes care of precision and display without any manual handling from the purchasing team.


5. Custom Fields: Budget and Target Tracking

A very common customization request is adding a budget amount, a revenue target, or a cost ceiling to a project, department, or custom model. In all these cases, a Monetary field is the right choice. It naturally integrates with the company currency, displays correctly in forms and lists, and behaves predictably in reports and exports.

Using a Float for this kind of field is technically possible but leads to formatting inconsistencies and rounding issues as soon as multi-currency scenarios arise.


Creating or Customizing the Field


There are two main ways to add a Monetary field to an Odoo model: through Odoo Studio for a no-code approach, or through a custom Python module for full control.


Using Odoo Studio

Odoo Studio includes a Monetary type in its field creation panel. When you use odoo studio fields to add a Monetary field to a model, Studio automatically adds a currency_id field if one does not already exist on that model. This covers the most common use cases without writing any code.


One thing to be aware of: Studio-created fields use the x_ prefix (for example, x_studio_budget). If your model already has a currency_id field, the new Monetary field will use it. If not, Studio will create a new one. When you have several Monetary fields on the same model with potentially different currencies, this shared currency field is worth reviewing carefully before going live.


For straightforward scenarios, Studio is the fastest way to create fields in Odoo and works well for business users who do not have development access.


Technical Approach: Python Fields

In a custom Odoo module, creating a Monetary field requires two declarations: the field itself and the associated currency field. This is the standard pattern in odoo python fields development:


from odoo import fields, models

class ProjectTask(models.Model):
    _inherit = 'project.task'

    x_budget = fields.Monetary(
        string='Budget',
        currency_field='x_budget_currency_id',
    )
    x_budget_currency_id = fields.Many2one(
        comodel_name='res.currency',
        string='Budget Currency',
        default=lambda self: self.env.company.currency_id,
    )

Setting the company currency as the default is a practical choice for most internal fields. It prevents the currency field from appearing empty when a user first opens a record, which would break the Monetary field's formatting.


Computed Monetary Fields

Monetary fields work well as odoo computed fields. If you need to total line amounts or apply a formula that produces a monetary result, this is the standard pattern:


x_total_budget = fields.Monetary(
    string='Total Budget',
    currency_field='currency_id',
    compute='_compute_total_budget',
    store=True,
)

@api.depends('x_line_ids.x_amount')
def _compute_total_budget(self):
    for record in self:
        record.x_total_budget = sum(record.x_line_ids.mapped('x_amount'))

The store=True attribute is important if you plan to filter, sort, or aggregate on this field in list views or reports. Non-stored computed fields cannot be used in ORM domain filters.


Adding a Monetary Field via the API

If you need to create fields in Odoo programmatically via XML-RPC (for example, as part of a remote configuration script), you can create the Monetary field through ir.model.fields:


models.execute_kw(ODOO_DB, uid, ODOO_API_KEY,
    'ir.model.fields', 'create',
    [{
        'name': 'x_budget',
        'field_description': 'Budget',
        'model_id': model_id,
        'ttype': 'monetary',
        'currency_field': 'currency_id',
        'state': 'manual',
    }]
)

This is part of the broader odoo customization toolkit available through the XML-RPC API, which is covered in more detail in other articles in this blog collection.

Best Practices


The Monetary field is straightforward to use once you know the patterns. Here are the practices that will keep your implementation clean and prevent issues down the line.


1. Never Use Float for Financial Values

This is the most important rule in odoo development when it comes to money. If a field represents a price, an amount, a total, a budget, or any currency-denominated number, use fields.Monetary. A Float field has no currency awareness and will not round correctly across different currencies. The Monetary field exists precisely to solve this problem.


2. Always Declare the Currency Field Explicitly

Do not rely on Odoo's fallback to currency_id unless that field actually exists on your model. Explicitly set the currency_field parameter and always declare the corresponding Many2one to res.currency. This makes the relationship clear and prevents silent fallback behavior in multi-currency environments.


3. Set a Default Currency

For internal fields that will almost always use the company currency, set a default on the currency field: default=lambda self: self.env.company.currency_id. This prevents the field from appearing blank on new records, which would strip out the currency symbol and formatting in the UI.


4. Use store=True on Computed Monetary Fields You Plan to Search

If you define a computed Monetary field and expect users or reports to filter or sort by it, set store=True. Non-stored computed fields cannot appear in ORM domains or SQL-based views. This is a common source of confusion when building custom dashboards in Odoo.


5. Use Currency Round() for Intermediate Calculations

When writing Python code that performs multiple arithmetic steps on Monetary values, apply self.currency_id.round(value) at each meaningful step rather than only at the end. Floating-point errors compound over multiple operations, and applying rounding early prevents discrepancies in totals.


6. Be Intentional in Multi-Currency Reports

When aggregating Monetary values across records with different currencies, do not simply sum the raw numbers. Convert all values to a common currency first using res.currency.compute(), or make the report currency-specific. Mixing currencies in a sum produces numbers that are technically correct at the field level but financially meaningless.

Common Pitfalls


Even experienced Odoo developers run into issues with Monetary fields. Here are the most common mistakes and how to avoid them.


Pitfall 1: Missing Currency Field

The most frequent issue when adding a Monetary field is forgetting to create the associated currency Many2one field. If currency_id does not exist on the model, Odoo will fall back to the company currency silently in some contexts and raise an error in others. Always create the currency field alongside the Monetary field, even if you never expect users to change it.


Pitfall 2: Two Monetary Fields Sharing One Currency Field with Different Intended Currencies

If you have two Monetary fields on the same model that are meant to hold values in different currencies (for example, a customer price in EUR and a vendor cost in USD), they cannot safely share a single currency_id field. Each needs its own currency reference. Failing to do this means one currency setting overrides both fields, which will produce incorrect data and confusing UI behavior.


Pitfall 3: Rounding Discrepancies When Aggregating Across Currencies

Summing Monetary field values across records with different currencies will produce totals that look wrong, because you are adding EUR amounts to USD amounts as if they were the same unit. This is a common source of reporting errors in companies that operate in multiple currencies. Always normalize to a single currency before aggregating.


Pitfall 4: Floating-Point Comparisons in ORM Searches

Searching a Monetary field with an exact equality check (for example, looking for records where amount = 10.0) can miss records due to how floats are stored in the database. Use >= and <= with a small tolerance, or apply currency rounding before comparing values in Python logic. This is a general odoo orm issue with float-based fields, not specific to Monetary, but it matters more when money is involved.


Pitfall 5: Ignoring Currency Rounding During Data Import

When importing records via CSV or XML-RPC that include Monetary field values, the imported numbers are stored as provided without automatic rounding. If your source data has more decimal places than the target currency allows, the stored value will be technically correct but will display differently than expected, and may cause small discrepancies in totals. Apply currency rounding in your import scripts or data preparation steps before sending values to Odoo.


Conclusion


The Monetary field is one of those Odoo field types that looks simple on the surface but carries a lot of important behavior underneath. Its tight relationship with the currency record is what makes it reliable for financial data: correct rounding, consistent formatting, and currency-aware display across the entire Odoo interface and report engine.


Using it correctly, which means always pairing it with an explicit currency field and never substituting a Float for financial values, will save you from a whole category of subtle bugs that are notoriously hard to track down in production. The odoo data model is built around this field type for good reason.


Whether you are following an odoo developer guide, customizing a standard module, or building something new from scratch, getting your Monetary fields right is one of the foundational decisions that shapes how reliably your Odoo implementation handles money.

Need Help with Your Odoo Implementation?


At Dasolo, we help companies implement, customize, and optimize Odoo across all scales and configurations. Whether you need a clean data model, a custom field strategy, multi-currency support, or a full Odoo rollout, our team has the technical and functional depth to get it right.


If you have questions about Monetary fields or any other aspect of your Odoo implementation, we are happy to help. Reach out to us and let's talk about what you are building.

The Monetary Field in Odoo: How It Works and When to Use It
Dasolo March 6, 2026
Share this post
Sign in to leave a comment