Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix secondary and split move lines #491

Open
wants to merge 2 commits into
base: 16.0
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 89 additions & 9 deletions stock_ux/models/stock_move_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,93 @@ def create(self, vals_list):
return recs

def _get_aggregated_product_quantities(self, **kwargs):
aggregated_move_lines = super()._get_aggregated_product_quantities(**kwargs)
if bool(self.env['ir.config_parameter'].sudo().get_param('stock_ux.delivery_slip_use_origin', 'False')) == True:
for line in aggregated_move_lines:
moves = self.filtered(
lambda sml: sml.product_id == aggregated_move_lines[line]['product']
).mapped('move_id').filtered(lambda m: m.origin_description)
if moves:
aggregated_move_lines[line]['description'] = False
aggregated_move_lines[line]['name'] =', '.join(moves.mapped('origin_description'))
""" Returns a dictionary of products (key = id+name+description+uom) and corresponding values of interest.

Allows aggregation of data across separate move lines for the same product. This is expected to be useful
in things such as delivery reports. Dict key is made as a combination of values we expect to want to group
the products by (i.e. so data is not lost). This function purposely ignores lots/SNs because these are
expected to already be properly grouped by line.

returns: dictionary {product_id+name+description+uom: {product, name, description, qty_done, product_uom}, ...}
"""
aggregated_move_lines = {}

def get_aggregated_properties(move_line=False, move=False):
move = move or move_line.move_id
uom = move.product_uom or move_line.product_uom_id
name = move.product_id.display_name
secondary_uom_qty = move.secondary_uom_qty
secondary_uom_id = move.secondary_uom_id
description = move.description_picking
if description == name or description == move.product_id.name:
description = False
product = move.product_id
line_key = f'{product.id}_{product.display_name}_{description or ""}_{uom.id}_{move_line.id}'
return (line_key, name, description, uom, secondary_uom_qty, secondary_uom_id)

# Loops to get backorders, backorders' backorders, and so and so...
backorders = self.env['stock.picking']
pickings = self.picking_id
while pickings.backorder_ids:
backorders |= pickings.backorder_ids
pickings = pickings.backorder_ids

for move_line in self:
if kwargs.get('except_package') and move_line.result_package_id:
continue
line_key, name, description, uom, secondary_uom_qty, secondary_uom_id = get_aggregated_properties(move_line=move_line)
qty_done = move_line.product_uom_id._compute_quantity(move_line.qty_done, uom)
if line_key not in aggregated_move_lines:
qty_ordered = None
if backorders and not kwargs.get('strict'):
qty_ordered = move_line.move_id.product_uom_qty
# Filters on the aggregation key (product, description and uom) to add the
# quantities delayed to backorders to retrieve the original ordered qty.
following_move_lines = backorders.move_line_ids.filtered(
lambda ml: get_aggregated_properties(move=ml.move_id)[0] == line_key
)
qty_ordered += sum(following_move_lines.move_id.mapped('product_uom_qty'))
# Remove the done quantities of the other move lines of the stock move
previous_move_lines = move_line.move_id.move_line_ids.filtered(
lambda ml: get_aggregated_properties(move=ml.move_id)[0] == line_key and ml.id != move_line.id
)
qty_ordered -= sum(map(lambda m: m.product_uom_id._compute_quantity(m.qty_done, uom), previous_move_lines))
aggregated_move_lines[line_key] = {'name': name,
'description': description,
'qty_done': qty_done,
'qty_ordered': qty_ordered or qty_done,
'product_uom': uom,
'product': move_line.product_id,
'secondary_uom_qty' : secondary_uom_qty,
'secondary_uom_id' : secondary_uom_id}
else:
aggregated_move_lines[line_key]['qty_ordered'] += qty_done
aggregated_move_lines[line_key]['qty_done'] += qty_done

# Does the same for empty move line to retrieve the ordered qty. for partially done moves
# (as they are splitted when the transfer is done and empty moves don't have move lines).
if kwargs.get('strict'):
return aggregated_move_lines
pickings = (self.picking_id | backorders)
for empty_move in pickings.move_ids:
if not (empty_move.state == "cancel" and empty_move.product_uom_qty
and float_is_zero(empty_move.quantity_done, precision_rounding=empty_move.product_uom.rounding)):
continue
line_key, name, description, uom, secondary_uom_qty, secondary_uom_id = get_aggregated_properties(move=empty_move)

if line_key not in aggregated_move_lines:
qty_ordered = empty_move.product_uom_qty
aggregated_move_lines[line_key] = {
'name': name,
'description': description,
'qty_done': False,
'qty_ordered': qty_ordered,
'product_uom': uom,
'product': empty_move.product_id,
'secondary_uom_qty' : secondary_uom_qty,
'secondary_uom_id' : secondary_uom_id,
}
else:
aggregated_move_lines[line_key]['qty_ordered'] += empty_move.product_uom_qty
return aggregated_move_lines