Skip to content
Snippets Groups Projects
Commit 3317249d authored by Guewen Baconnier's avatar Guewen Baconnier Committed by Sébastien Alix
Browse files

[FIX] stock: fix check of package all in move lines


The `groupby` function is used to builds groups of(product, lot) keys
and their corresponding move lines / quants. `groupby` groups
*consecutive* keys, which is why the input is sorted by the keys.

`sorted` on recordsets keys will not sort as we would expect in this
particular situation, as the comparison operators on records act as
Set Comparison operators on the record ids, i.e. to compare the sets
superset/subset relationships:

```
>>> env["product.product"].browse(1) < env["product.product"].browse(2)
False
>>> env["product.product"].browse(1) < env["product.product"].browse([1, 2])
True
```

Example of sorted on stock.move.line records, where the product id 7313
is both in the slots 4 and 12 instead of being consecutive:

```
>>> [l.product_id.id for l in sorted(lines, key=itemgetter('product_id'))]
[7436, 7437, 7352, 7423, 7313, 7351, 7423, 7424, 7320, 7398, 7312, 7352, 7313, 7436, 7437, 7442, 7443, 7320, 7423, 7424, 7318, 7396, 7368, 7355, 7316]
```

Now when we group by id the 2 ids 7313 are correctly placed together in
slots 1 and 2:

```
>>> [l.product_id.id for l in sorted(lines, key=attrgetter('product_id.id'))]
[7312, 7313, 7313, 7316, 7318, 7320, 7320, 7351, 7352, 7352, 7355, 7368, 7396, 7398, 7423, 7423, 7423, 7424, 7424, 7436, 7436, 7437, 7437, 7442, 7443]
```

This commit aims to sort by "id" of the related records, to ensure the
same (product, lot) couples are consecutive.

closes odoo/odoo#63541

Signed-off-by: default avatarArnold Moyaux <amoyaux@users.noreply.github.com>
parent 3e8b930b
Branches
Tags
No related merge requests found
......@@ -4,7 +4,7 @@
from ast import literal_eval
from datetime import date
from itertools import groupby
from operator import itemgetter
from operator import attrgetter, itemgetter
import time
from odoo import api, fields, models, SUPERUSER_ID, _
......@@ -771,14 +771,15 @@ class Picking(models.Model):
all_in = True
pack_move_lines = self.move_line_ids.filtered(lambda ml: ml.package_id == package)
keys = ['product_id', 'lot_id']
keys_ids = ["{}.id".format(fname) for fname in keys]
precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure')
grouped_quants = {}
for k, g in groupby(sorted(package.quant_ids, key=itemgetter(*keys)), key=itemgetter(*keys)):
for k, g in groupby(sorted(package.quant_ids, key=attrgetter(*keys_ids)), key=itemgetter(*keys)):
grouped_quants[k] = sum(self.env['stock.quant'].concat(*list(g)).mapped('quantity'))
grouped_ops = {}
for k, g in groupby(sorted(pack_move_lines, key=itemgetter(*keys)), key=itemgetter(*keys)):
for k, g in groupby(sorted(pack_move_lines, key=attrgetter(*keys_ids)), key=itemgetter(*keys)):
grouped_ops[k] = sum(self.env['stock.move.line'].concat(*list(g)).mapped('product_qty'))
if any(not float_is_zero(grouped_quants.get(key, 0) - grouped_ops.get(key, 0), precision_digits=precision_digits) for key in grouped_quants) \
or any(not float_is_zero(grouped_ops.get(key, 0) - grouped_quants.get(key, 0), precision_digits=precision_digits) for key in grouped_ops):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment