-2

While editing notes and saving, I got error as:

 self[a[0]] = a[1] 
 RecursionError: maximum recursion depth exceeded

Code:

    notes = fields.Text('Terms', compute="_default_terms",inverse="_inverse_terms")

    @api.multi
    def _default_terms(self):
        terms = "\n\nPayment Terms:\nThis LPO is on the goods / services named and is governed by the below mentioned Terms and Conditions\n\
LPO is a must in order to start with the Job \n\
If the supplier fails to deliver on time and thereby resulting on the rejection or cancellation of job, MAI BLUE has the right to cancel the job and has no financial obligation towards the supplier, and if MN BLUE has already paid any down payment; the supplier must return it to the company immediately.\n\
MAI BLUE can demand an amendment / modification due to sub-standard / low quality products / services provided, at supplier's cost. if the supplier is unable to rectify the product before final delivery MAI BLUE has the right not to pay the balance amount and demand back any advance payments made for the job.\n\
Delays in delivery and/or delivering the goods not as per agreed quality / specifications will lead to job cancellation and/or 50% reduction in payment from MAI BLUE towards the supplier.\n\
Once the supplier submits their final Quotation, no changes in materials or specification will be accepted after the supplier confirms or submit his quotation. Any changes will be under the supplier's responsibility/cost.\n\
"
        self.notes = terms


    @api.multi
    def _inverse_terms(self):
        terms = "\n\nPayment Terms:\nThis LPO is on the goods / services named and is governed by the below mentioned Terms and Conditions\n\
    LPO is a must in order to start with the Job \n\
    If the supplier fails to deliver on time and thereby resulting on the rejection or cancellation of job, MAI BLUE has the right to cancel the job and has no financial obligation towards the supplier, and if MN BLUE has already paid any down payment; the supplier must return it to the company immediately.\n\
    MAI BLUE can demand an amendment / modification due to sub-standard / low quality products / services provided, at supplier's cost. if the supplier is unable to rectify the product before final delivery MAI BLUE has the right not to pay the balance amount and demand back any advance payments made for the job.\n\
    Delays in delivery and/or delivering the goods not as per agreed quality / specifications will lead to job cancellation and/or 50% reduction in payment from MAI BLUE towards the supplier.\n\
    Once the supplier submits their final Quotation, no changes in materials or specification will be accepted after the supplier confirms or submit his quotation. Any changes will be under the supplier's responsibility/cost.\n\
    "
        self.notes= terms

Kenly
  • 24,317
  • 7
  • 44
  • 60
Shahal
  • 115
  • 1
  • 12

2 Answers2

2

The inverse function is used for reversing the computation and setting the relevant fields. In your example above, it does not reverse the computation but set the value of the field itself, which is not possible using the inverse function.

There are plenty of examples in Odoo source code, for example in project model, is_favorite field is set to True when the current user is in project favorite_user_ids and to inverse the calculation we check if the current user is a favorite user and remove it from the set and if not add it to the project favorite users.

What you are trying to achieve is the same as setting a default value for the text field.

Default values are defined as parameters on fields, either a value:

notes = fields.Text('Terms', default="Payment Terms:...")

Or a function called to compute the default value, which should return that value:

def compute_default_value(self):
    return self.get_value()

notes = fields.Text('Terms', default=compute_default_value)

The best way to do this is by defining a system parameter and a field in the company that can be edited later by users.

The following code adds a parameter to control the use of the default payment terms in the sale order, and a related field to define the current user company default payment terms.

Python Code:

class ResCompany(models.Model):
    _inherit = 'res.company'

    payment_terms = fields.Text(string='Payment Terms', translate=True)


class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    payment_terms = fields.Text(related='company_id.payment_terms', string="Terms", readonly=False)
    use_payment_terms = fields.Boolean(
        string='Payment Terms',
        config_parameter='sale.use_payment_terms')


class SaleOrder(models.Model):
    _inherit = 'sale.order'

    @api.model
    def compute_default_value(self):
        return self.env['ir.config_parameter'].sudo().get_param('sale.use_payment_terms') and self.env.user.company_id.payment_terms or ''

    notes = fields.Text('Terms', default=compute_default_value)

XML: (Add the payment terms inside the Quotations & Orders configuration)

<record id="res_config_settings_view_form" model="ir.ui.view">
    <field name="name">res.config.settings.view.form.inherit.sale</field>
    <field name="model">res.config.settings</field>
    <field name="inherit_id" ref="base.res_config_settings_view_form"/>
    <field name="arch" type="xml">
        <xpath expr="//div[@id='sale_config_online_confirmation_pay']/parent::div" position="inside">
            <div class="col-6 col-lg-6 o_setting_box">
                <div class="o_setting_left_pane">
                    <field name="use_payment_terms"/>
                </div>
                <div class="o_setting_right_pane">
                    <label for="use_payment_terms"/>
                    <span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific."
                          groups="base.group_multi_company" role="img"/>
                    <div class="text-muted">
                        Show payment terms on orders
                    </div>
                    <div class="content-group" attrs="{'invisible': [('use_payment_terms','=',False)]}">
                        <div class="mt16">
                            <field name="payment_terms" placeholder="Insert your terms here..."/>
                        </div>
                    </div>
                </div>
            </div>
        </xpath>
    </field>
</record>  
Kenly
  • 24,317
  • 7
  • 44
  • 60
2

If you want to use an inverse method to change values of computed fields, the computed field should be computed on persistent and changeable values.

Otherwise, you get the effect/error you're seeing right now: Your field is computed on a string in code. So the inverse method should change the value on that string, which isn't possible (or very, very difficult).

Just define a default value or default method, like in Kenly's answer:

@api.model
def _default_terms(self):
    return "terms..."

notes = fields.Text('Terms', default=_default_terms)

Another good way would be defining a system parameter or configurable field on the company, which could be configured on a settings page, like a lot of other things in Odoo.

You can then get that value as default from that parameter or company field as default. That way, the default is changeable in Odoo itself.

Kenly
  • 24,317
  • 7
  • 44
  • 60
CZoellner
  • 13,553
  • 3
  • 25
  • 38