2

I am migrating a module to version 13.0, which uses continue in a loop inside a compute method, and an error was driving me crazy for a while.

I simplified the code to the minimum until I had this kind of nosense:

@api.depends('move_lines', 'move_lines.price_subtotal')
def _compute_subtotal(self):
    for picking in self:
        if picking.picking_type_id.code not in ['incoming', 'outgoing']:
            continue
        picking.update({
            'amount_untaxed': 3.0,
        })

But I was still receiving the error, which by the way was this (and only was shown when creating new pickings):

stock.picking(<NewId 0x7f5404ba5eb8>,).amount_untaxed

So I realised that the problem was the continue statement, if I removed it, it worked. And I tried to use continue in several loops of other compute methods of standard Odoo modules, with same result.

Until now, if you did not assign a value for a field in a computed method, it automatically took False, so continue was not a problem.

Does anyone experience this problem with continue too?

forvas
  • 9,801
  • 7
  • 62
  • 158

2 Answers2

3

It is required to set value for each record set. If we use continue and don't set value for that specific recordset, will get issue as you mentioned.

Try with following code:

@api.depends('move_lines', 'move_lines.price_subtotal')
def _compute_subtotal(self):
    for picking in self:
        amount_untaxed = 0.0
        if picking.picking_type_id.code == 'internal':
            amount_untaxed = 3.0
        picking.update({
            'amount_untaxed': amount_untaxed,
        })

Continue will work if we do code something like:

@api.depends('move_lines', 'move_lines.price_subtotal')
def _compute_subtotal(self):
    for picking in self:
        picking.update({
            'amount_untaxed': 0.0,
        })
        if picking.picking_type_id.code not in ['incoming', 'outgoing']:
            continue
        picking.update({
            'amount_untaxed': 3.0,
        })
Bhavesh Odedra
  • 10,990
  • 12
  • 33
  • 58
2

The problem is not the continue statement itself but is that Odoo expect you to set the the value for your computed field because if you check the code of __get__ of Field class:

def __get__(self):
     ....
     .....
        elif self.compute:
            ........
            ........
            else:
                recs = record if self.recursive or not record.id else record._in_cache_without(self)
                try:
                    # Here it's computing the value for this record
                    self.compute_value(recs)
                except AccessError:
                    self.compute_value(record)
                # after computation they try the get the value from the environment cache
                value = env.cache.get(record, self)

And because you didn't set the value for this record, this will raise this error odoo.exceptions.CacheMiss: ('stock.picking(ID_OF_RECORD,).amount_untaxed', None). You need to set a value for each compute field that is computed in that method.

Charif DZ
  • 14,415
  • 3
  • 21
  • 40
  • 1
    Thank you for your useful help Charif, but giving the valid answer to Odedra because he was faster. – forvas Feb 19 '20 at 09:35
  • 1
    The difference between our answer is that I explained why are you having the problem. The solution that he wrote to use continue is bad because he is triggering a update query (if the field is storable of curse) two time for some records. And thanks for the up vote and the awesome question as always – Charif DZ Feb 19 '20 at 09:46
  • 1
    You are right, your solution is deeper and in fact I used the `continue` solution but wrote the update to 0.0 inside the `if` statement, just before the `continue`, to avoid the doble query for some records (the field is stored). – forvas Feb 19 '20 at 11:32
  • 1
    @forvas exaclty, and why are you using update? it's just one field use normal assignment, `picking.amount_untaxed = value`. – Charif DZ Feb 19 '20 at 13:13
  • Actually I am updating three fields in the same compute method, but here I removed the other to simplify the question's code. But it's good to know that tip, the code of this example should be computed as you write. – forvas Feb 19 '20 at 13:41