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

Odoo如何根据选择器切换实现固定金额/百分比折扣适配显示

Odoo 折扣模式切换控件适配方案

问题背景

Odoo开发中需要实现双模式折扣功能,通过选择器切换固定货币金额折扣、百分比折扣两种计算与展示逻辑。

原有后端计算代码(.py)

@api.depends('discount_type', 'discount_rate', 'amount_total')
def _compute_amount_discount(self):
    for act in self:
        amount_untaxed = amount_discount = discount_rate = 0.0
        for line in act.reconciliation_act_line_ids:
            amount_untaxed += line.price_subtotal
        if self.discount_type == 'percent':
            amount_discount = amount_untaxed * self.discount_rate / 100
        else:
            amount_discount = self.discount_rate

        act.update({
            'amount_total_with_discount': amount_untaxed - amount_discount,
            'amount_discount': - amount_discount,
            'amount_total': amount_untaxed,
        })

原有前端视图代码(.xml)

<div class="container">
    <div class="row justify-content-between">
        <div class="col-4">
            <group name="discount"
                 attrs="{'invisible': [('apply_discount', '=', False)]}">
             <field name="discount_type"/>
             <field name="discount_rate"/>
             </group>
         </div>
         <div class="col-4">
             <group>
                 <field name="amount_total"  nolabel="0" widget='monetary'
                                                 options="{'currency_field': 'currency_id'}"/>
                 <field name="amount_discount" widget='monetary'
                                                 attrs="{'invisible': [('apply_discount', '=', False)]}"/>
                 <field name="amount_total_with_discount" widget='monetary'
                                                 attrs="{'invisible': [('apply_discount', '=', False)]}"/>
                 <field name="amount_total_executors" nolabel="0" widget='monetary'
                                                 options="{'currency_field': 'currency_id'}"/>
                </group>
            </div>
       </div>
</div>

异常表现

固定金额折扣模式运行正常,切换到百分比折扣模式时,discount_rate字段绑定的monetary货币控件会强制显示货币符号,无法适配百分比数值的展示要求,异常效果如下:
固定金额模式效果
百分比模式异常效果

修复方案

不要尝试用单个字段动态切换widget,Odoo原生视图框架不支持运行时直接修改字段绑定的控件类型,最稳定的实现方式是拆分字段+动态显隐:

  1. 模型层调整:新增两个独立字段分别承载两类折扣值,同步修改计算逻辑
    # 新增字段定义
    discount_fixed = fields.Monetary(string='折扣金额', currency_field='currency_id')
    discount_percent = fields.Float(string='折扣比例(%)')
    
    # 调整后的计算方法
    @api.depends('discount_type', 'discount_fixed', 'discount_percent', 'reconciliation_act_line_ids.price_subtotal')
    def _compute_amount_discount(self):
        for act in self:
            amount_untaxed = sum(act.reconciliation_act_line_ids.mapped('price_subtotal'))
            if act.discount_type == 'percent':
                amount_discount = amount_untaxed * act.discount_percent / 100
            else:
                amount_discount = act.discount_fixed
    
            act.write({
                'amount_total': amount_untaxed,
                'amount_discount': -amount_discount,
                'amount_total_with_discount': amount_untaxed - amount_discount,
            })
    
  2. 视图层调整:替换原有单个discount_rate字段,通过attrs属性根据折扣类型控制两个字段的显隐,分别绑定对应适配的控件
    <group name="discount" attrs="{'invisible': [('apply_discount', '=', False)]}">
        <field name="discount_type"/>
        <!-- 固定金额模式:显示货币控件 -->
        <field name="discount_fixed" widget="monetary"
               options="{'currency_field': 'currency_id'}"
               attrs="{'required': [('discount_type', '=', 'fixed')], 'invisible': [('discount_type', '!=', 'fixed')]}"/>
        <!-- 百分比模式:显示浮点数百分比控件 -->
        <field name="discount_percent" widget="float"
               options="{'type': 'percent'}"
               attrs="{'required': [('discount_type', '=', 'percent')], 'invisible': [('discount_type', '!=', 'percent')]}"/>
    </group>
    

该方案无需编写自定义JS组件,兼容Odoo所有主流版本(12.0~17.0),表单加载、编辑、保存时不会出现控件渲染异常,是Odoo生态内同类需求的标准实现方式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:45:25