如何让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适配原有货币关联逻辑,需注意维护双向同步的准确性。
关键注意事项
- 不要修改Odoo核心
Monetary字段逻辑,避免后续版本升级出现兼容问题 - 使用
Float字段时,需手动处理货币转换逻辑,确保业务计算的准确性 - 视图widget的精度设置要与字段存储精度保持一致,避免显示与存储值不匹配
内容的提问来源于stack exchange,提问作者H 19
相关产品推荐
相关产品推荐

