parent_store computation is wrong when parent_id was null before (may corrupt accounting and stock!)
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Odoo Server (MOVED TO GITHUB) |
Fix Released
|
High
|
Unassigned |
Bug Description
When setting the parent for an object, that previously had no parent, the parent_right and parent_left are not recomputed!
This means that if a ("parent_id", "child_of", parent_id) search is performed, the object is not considered as a child (wrong), but if a ("parent_id", "=", parent_id) is used then the object is considered a child (right).
Please, set this bug priority to High, as it is pretty dangerous (the "totals" reports, like accounting balances, and the calculations performed, like stock operations, may be wrong!!) and affects any object using parent_store (account_account, stock_location, res_company...).
--- HOW TO REPRODUCE -------
- Create one account (for example an account with code "57200001" [id 1])
- Import one chart of accounts (for example, create the Spanish chart of accounts from its template)
- Set a parent for the first account (for example use the account with code "572" and [id 822] as parent for the "57200001")
=> PROBLEM: The parent_left and parent_right aren't updated!!!
- Create an account move using the child account (57200001)
- Go to the chart of accounts: The child account has balance, the parent account balance is 0!!!!!
=> PROBLEM: The children account is being ignored cause its parent_left and parent_right are wrong
--- DETAILS / DEBUGGING -------
We have a chart like this:
id code parent_id
1 57200001 Null
2 57200002 Null
822 572 817
823 57200000 822
If we set the parent for the accounts 1 and 2:
id code parent_id
1 57200001 822
2 57200002 822
822 572 817
823 57200000 822
And call the account_account object search method, the child_of search fails:
ipdb> self.search(cr, 1, [('parent_id', 'child_of', [822])])
[822, 823]
ipdb> self.search(cr, 1, [('parent_id', '=', 822)])
[823, 1, 2]
As you can see, 823, 1 and 2 are children of 822; but child_of only returns 823 as a child!!
If we debug the parent_left & parent_right values for the accounts, you can see that account 1 values are wrong:
ipdb> self.browse(cr, 1, 1).parent_left
2896
ipdb> self.browse(cr, 1, 1).parent_right
2897
ipdb> self.browse(cr, 1, 822).parent_left
1681
ipdb> self.browse(cr, 1, 822).parent_right
1684
ipdb> self.browse(cr, 1, 823).parent_left
1682
ipdb> self.browse(cr, 1, 823).parent_right
1683
If you take a look at the ORM code, you can see that, when writing a record (like the account 1), this query is performed to decide whether the parent_
"SELECT id FROM account_account WHERE id IN (1) AND parent_id != 822"
That query is wrong: it does not return any record (so parent_left/right are not recomputed) if the previous parent_id was NULL!
It should be:
"SELECT id FROM account_account WHERE id IN (1) AND (parent_id != 822 OR parent_id IS NULL)"
that returns the id 1, in the case parent_id was NULL
--- HOW TO FIX -------
This buggy code:
if self._parent_store and (self._parent_name in vals):
# The parent_left/right computation may take up to
# 5 seconds. No need to recompute the values if the
# parent is the same. Get the current value of the parent
params = (tuple(ids),)
if parent_val:
else:
Should be replaced with something like this:
if self._parent_store and (self._parent_name in vals):
# The parent_left/right computation may take up to
# 5 seconds. No need to recompute the values if the
# parent is the same. Get the current value of the parent
ids_str = ','.join(map(str, map(int, ids)))
if parent_val:
else:
Related branches
- Olivier Dony (Odoo): Pending requested
-
Diff: 24 lines (+6/-5)1 file modifiedbin/osv/orm.py (+6/-5)
description: | updated |
Changed in openobject-server: | |
status: | New → Confirmed |
importance: | Undecided → High |
milestone: | none → 5.0.11 |
Changed in openobject-server: | |
milestone: | 5.0.11 → 5.0.12 |
good to know