Skip to content

Commit

Permalink
Merge PR #1451 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by rousseldenis
  • Loading branch information
OCA-git-bot committed Oct 15, 2024
2 parents e200acd + 5a13075 commit 1cf57d7
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 5 deletions.
2 changes: 1 addition & 1 deletion stock_picking_group_by_max_weight/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Stock Picking Group By Max Weight
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:a80e538459c481d69cbbc746b4dde01e52c5034473a44491aa11edf2e8a79918
!! source digest: sha256:90d60c02dfe3ddafa506ad96c05d12b923ba4c2ce7a93ca6d41d407b3eb86905
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down
4 changes: 4 additions & 0 deletions stock_picking_group_by_max_weight/models/stock_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ def _search_picking_for_assignation_domain(self):
]
)
return domain

def _assign_picking_post_process(self, new=False):
self.picking_id._split_for_max_weight()
return super()._assign_picking_post_process(new=new)
69 changes: 66 additions & 3 deletions stock_picking_group_by_max_weight/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from collections import defaultdict

from odoo import api, fields, models
from odoo.tools import float_compare
Expand All @@ -18,11 +19,13 @@ class StockPicking(models.Model):
states={"done": [("readonly", True)], "cancel": [("readonly", True)]},
)

@property
def _assignation_max_weight_precision(self):
return self._fields["assignation_max_weight"].get_digits(self.env)[1]

@api.depends("picking_type_id.group_pickings_maxweight", "weight", "state")
def _compute_assignation_max_weight(self):
precision_digits = self._fields["assignation_max_weight"].get_digits(self.env)[
1
]
precision_digits = self._assignation_max_weight_precision
for picking in self:
max_weight = (
picking.picking_type_id.group_pickings_maxweight - picking.weight
Expand Down Expand Up @@ -54,3 +57,63 @@ def init(self):
This has to be called in every overriding module
"""
self._create_index_for_grouping()

def _should_be_split_for_max_weight(self):
"""
Return True if the picking should be split
"""
self.ensure_one()
return (
self.state not in ["done", "cancel"]
and not self.printed
and self.picking_type_id.group_pickings_maxweight
and float_compare(
self.weight,
self.picking_type_id.group_pickings_maxweight,
precision_digits=self._assignation_max_weight_precision,
)
> 0
)

def _split_for_max_weight(self):
"""
Split the picking in several pickings if the total weight is
greater than the max weight of the picking type
"""
precision_digits = self._assignation_max_weight_precision
for picking in self:
if not picking._should_be_split_for_max_weight():
continue
# we create batch of move's ids to reassign. To do so, we
# iterate over the move lines and we add the move to the current
# batch while the total weight of the batch is less than the max
# weight of the picking type. When the total weight of the batch
# is exceeded, we create a new batch of ids to reassign.
ids_to_reassign_by_batch = defaultdict(list)
batch_id = 0
total_weight = 0
# we must ignore the first batch of ids to reassign because it
# will be the current picking
max_weight = picking.picking_type_id.group_pickings_maxweight
for move in picking.move_ids:
total_weight += move.weight
if (
float_compare(
total_weight,
max_weight,
precision_digits=precision_digits,
)
> 0
):
batch_id += 1
total_weight = move.weight
ids_to_reassign_by_batch[batch_id].append(move.id)
# we create the new pickings for each batch except the first one
# which is the current picking
first = True
for ids_to_reassign in ids_to_reassign_by_batch.values():
if first:
first = False
continue
moves = self.env["stock.move"].browse(ids_to_reassign)
moves._assign_picking()
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Split moves into different pickings at assignment time if the total weight
of the picking is greater than the maximum weight allowed on the picking type.

Prior to this release only new moves created after the creation of an open picking
were put into a new picking upon assignment if the total weight of the picking
would exceed the maximum weight allowed on the picking type. This release improves
this behavior by also splitting existing moves into different pickings after the
moves have been assigned to a picking. IOW, in a post-assignment step, the system
will split picking lines into different pickings when the total weight is exceeded.
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ <h1 class="title">Stock Picking Group By Max Weight</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:a80e538459c481d69cbbc746b4dde01e52c5034473a44491aa11edf2e8a79918
!! source digest: sha256:90d60c02dfe3ddafa506ad96c05d12b923ba4c2ce7a93ca6d41d407b3eb86905
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_picking_group_by_max_weight"><img alt="OCA/stock-logistics-workflow" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-workflow-16-0/stock-logistics-workflow-16-0-stock_picking_group_by_max_weight"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-workflow&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows to filter picking candidates for moves assignation based
Expand Down
37 changes: 37 additions & 0 deletions stock_picking_group_by_max_weight/tests/test_group_maxweight.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,40 @@ def test_group_max_weight_several_quantities(self):
self._set_line(sale_form, self.product_3, 1.0)

self.assertEqual(2, len(sale.picking_ids))

def test_split_at_creation(self):
"""Test that a SO with 2 lines that will exceed the max weight if set into
the same picking, will be split"""
self.product.weight = 6.0
self.product_2.weight = 3.0
# the max weight is 8.0
# we create a SO with 2 lines of 1.0 each ->
# 2 pickings will be created since the weight is 9.0
# the first picking will have a weight of 6.0
sale = self._get_new_sale_order(amount=1.0)
with Form(sale) as sale_form:
self._set_line(sale_form, self.product_2, 1.0)
sale.action_confirm()
self.assertEqual(2, len(sale.picking_ids))

def test_no_split_if_one_move_exceed(self):
"""
If the picking contains a move that exceed the max weight, the picking
is not split
"""
self.product.weight = 6.0
sale = self._get_new_sale_order(amount=3.0)
sale.action_confirm()
self.assertEqual(1, len(sale.picking_ids))

def test_multi_split_at_creation(self):
self.product.weight = 6.0
self.product_2.weight = 3.0
self.product_3.weight = 3.0
sale = self._get_new_sale_order(amount=1.0)
with Form(sale) as sale_form:
self._set_line(sale_form, self.product_2, 2.0)
self._set_line(sale_form, self.product_3, 2.0)

sale.action_confirm()
self.assertEqual(3, len(sale.picking_ids))

0 comments on commit 1cf57d7

Please sign in to comment.