You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Odoo 18的fields.Monetary字段保留5位小数?

问题:Odoo 18.0企业版Monetary字段保留5位小数的实现需求

我需要让一个Monetary字段保留5位小数(例如12.34567),但Odoo 18.0企业版会按照公司货币的精度(我司货币为2位小数)进行四舍五入。

当前代码

class AccountPaymentRegister(models.TransientModel):
    _inherit = 'account.payment.register'

    bank_charges = fields.Monetary(
        string='Bank Charges',
        currency_field='currency_id',
    )

class AccountJournal(models.Model):
    _inherit = 'account.journal'

    default_bank_charge_amount = fields.Monetary(
        string='Default Bank Charge Amount',
        currency_field='company_currency_id',
        help='Default bank charge amount to prefill in the Pay wizard.',
    )

已尝试方案

  • 在字段上设置digits=(16, 5) → 似乎被Monetary字段忽略
  • 仅修改视图中的widget

预期与实际结果

  • 预期结果:存储并显示5位小数
  • 实际结果:值被四舍五入至货币精度

疑问

是否有受支持的方法可让Monetary字段保留5位小数,且无需全局修改公司货币设置?如果没有,推荐的实现模式是什么?


解决方案

核心问题说明

Odoo的Monetary字段会强制关联指定货币的全局精度设置,无法通过字段参数直接绕过,因此必须调整实现思路。

推荐实现方案

方案1:使用Float字段替代(优先推荐)

放弃Monetary字段,改用带自定义精度的Float字段,同时保留货币字段用于业务关联,既满足5位小数存储需求,又不破坏原有业务逻辑:

class AccountPaymentRegister(models.TransientModel):
    _inherit = 'account.payment.register'

    bank_charges = fields.Float(
        string='Bank Charges',
        digits=(16, 5),  # 强制设置5位小数精度
    )
    # 保留原货币字段用于业务关联
    currency_id = fields.Many2one('res.currency', related='journal_id.currency_id')

class AccountJournal(models.Model):
    _inherit = 'account.journal'

    default_bank_charge_amount = fields.Float(
        string='Default Bank Charge Amount',
        digits=(16, 5),
        help='Default bank charge amount to prefill in the Pay wizard.',
    )
    company_currency_id = fields.Many2one('res.currency', related='company_id.currency_id')

视图层可使用monetary widget保持货币显示风格,同时指定精度:

<field name="bank_charges" widget="monetary" options="{'decimal_precision': 5}"/>
<field name="default_bank_charge_amount" widget="monetary" options="{'decimal_precision': 5}"/>

方案2:自定义双字段同步(兼容多精度场景)

如果需要同时兼容全局货币精度和自定义精度,可添加一个Float字段存储5位小数,搭配Monetary字段做双向同步,适配不同业务场景:

from odoo import fields, models, api

class AccountPaymentRegister(models.TransientModel):
    _inherit = 'account.payment.register'

    bank_charges = fields.Float(
        string='Bank Charges',
        digits=(16, 5),
    )
    bank_charges_monetary = fields.Monetary(
        string='Bank Charges (Monetary)',
        currency_field='currency_id',
        compute='_compute_bank_charges_monetary',
        inverse='_inverse_bank_charges_monetary'
    )

    @api.depends('bank_charges')
    def _compute_bank_charges_monetary(self):
        for rec in self:
            rec.bank_charges_monetary = rec.bank_charges

    def _inverse_bank_charges_monetary(self):
        for rec in self:
            rec.bank_charges = rec.bank_charges_monetary

这种方式用bank_charges存储5位小数,bank_charges_monetary适配原有货币关联逻辑,需注意维护双向同步的准确性。

关键注意事项

  1. 不要修改Odoo核心Monetary字段逻辑,避免后续版本升级出现兼容问题
  2. 使用Float字段时,需手动处理货币转换逻辑,确保业务计算的准确性
  3. 视图widget的精度设置要与字段存储精度保持一致,避免显示与存储值不匹配

内容的提问来源于stack exchange,提问作者H 19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 04:02:43