diff --git a/stock_move_location/README.rst b/stock_move_location/README.rst index 197dc5ffd..78619f4c5 100644 --- a/stock_move_location/README.rst +++ b/stock_move_location/README.rst @@ -62,8 +62,8 @@ If you want to transfer a full quant: - Select the quantities which you want move to another location If you go to the Inventory Dashboard you can see the button "Move from -location" in each of the picking types (only applicable to internal -transfers). Press it and you will be directed to the wizard. +location" in each of the picking types (only applicable to internal and +outgoing transfers). Press it and you will be directed to the wizard. |image1| @@ -143,6 +143,8 @@ Contributors - Aung Ko Ko Lin +- Laurent Mignon + Maintainers ----------- diff --git a/stock_move_location/readme/CONTRIBUTORS.md b/stock_move_location/readme/CONTRIBUTORS.md index fece6339c..7bb7732a3 100644 --- a/stock_move_location/readme/CONTRIBUTORS.md +++ b/stock_move_location/readme/CONTRIBUTORS.md @@ -13,3 +13,4 @@ - Abraham Anes \<\> - Quartile \<\> - Aung Ko Ko Lin +- Laurent Mignon \<\> diff --git a/stock_move_location/readme/USAGE.md b/stock_move_location/readme/USAGE.md index a772a0a56..a61d944cb 100644 --- a/stock_move_location/readme/USAGE.md +++ b/stock_move_location/readme/USAGE.md @@ -1,43 +1,37 @@ -- A new menu item Operations \> Move from location... opens a wizard - where 2 locations can be specified. -- Select origin and destination locations and press "IMMEDIATE TRANSFER" - or "PLANNED TRANSFER" +- A new menu item Operations \> Move from location... opens a wizard where 2 locations + can be specified. +- Select origin and destination locations and press "IMMEDIATE TRANSFER" or "PLANNED + TRANSFER" - Press ADD ALL button to add all products available -- Those lines can be edited. Move quantity can't be more than a max - available quantity +- Those lines can be edited. Move quantity can't be more than a max available quantity - Move doesn't care about the reservations and will move stuff anyway -- If during your operation with the wizard the real quantity will change - it will move only the available quantity at the button press -- Products will be moved and a form view of picking that did that will - show up -- If "PLANNED TRANSFER" is used - the picking won't be validated - automatically +- If during your operation with the wizard the real quantity will change it will move + only the available quantity at the button press +- Products will be moved and a form view of picking that did that will show up +- If "PLANNED TRANSFER" is used - the picking won't be validated automatically If you want to transfer a full quant: -- Go to Inventory \> Products \> Products and click "On hand" smart - button or Inventory \> Reporting \> Inventory, the quants view will be - opened. +- Go to Inventory \> Products \> Products and click "On hand" smart button or Inventory + \> Reporting \> Inventory, the quants view will be opened. - Select the quantities which you want move to another location -If you go to the Inventory Dashboard you can see the button "Move from -location" in each of the picking types (only applicable to internal -transfers). Press it and you will be directed to the wizard. +If you go to the Inventory Dashboard you can see the button "Move from location" in each +of the picking types (only applicable to internal and outgoing transfers). Press it and +you will be directed to the wizard. ![](https://user-images.githubusercontent.com/147538094/281480833-208ea309-0bad-43e7-bd6f-8384520afe00.png) -To enable this option, check "Show Move On Hand Stock" in the Picking Type configuration. +To enable this option, check "Show Move On Hand Stock" in the Picking Type +configuration. ![](https://user-images.githubusercontent.com/147538094/281479487-45fa4bde-36be-4ba1-8d54-8e707b89459e.png) If you want transfer everything from stock.location -On a draft picking, add a button to fill with moves lines for all -products in the source destination. This allows to create a picking to -move all the content of a location. The Origin Location must have stock. -The Destination Location has to be a final location. -If some quants are not available -(i.e. reserved) the picking will be in partially available state and -reserved moves won't be listed in the operations. Use barcode interface -to scan a location and create an empty picking. Then use the fill with -stock button. +On a draft picking, add a button to fill with moves lines for all products in the source +destination. This allows to create a picking to move all the content of a location. The +Origin Location must have stock. The Destination Location has to be a final location. If +some quants are not available (i.e. reserved) the picking will be in partially available +state and reserved moves won't be listed in the operations. Use barcode interface to +scan a location and create an empty picking. Then use the fill with stock button. diff --git a/stock_move_location/static/description/index.html b/stock_move_location/static/description/index.html index bcd253d49..6a5f342df 100644 --- a/stock_move_location/static/description/index.html +++ b/stock_move_location/static/description/index.html @@ -412,8 +412,8 @@ opened.
  • Select the quantities which you want move to another location
  • If you go to the Inventory Dashboard you can see the button “Move from -location” in each of the picking types (only applicable to internal -transfers). Press it and you will be directed to the wizard.

    +location” in each of the picking types (only applicable to internal and +outgoing transfers). Press it and you will be directed to the wizard.

    image1

    To enable this option, check “Show Move On Hand Stock” in the Picking Type configuration.

    @@ -483,6 +483,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
  • Aung Ko Ko Lin
  • +
  • Laurent Mignon <laurent.mignon@acsone.eu>
  • diff --git a/stock_move_location/tests/test_common.py b/stock_move_location/tests/test_common.py index e476f7281..761cd07ce 100644 --- a/stock_move_location/tests/test_common.py +++ b/stock_move_location/tests/test_common.py @@ -92,46 +92,49 @@ class TestsCommon(common.TransactionCase): ) cls.package = cls.env["stock.quant.package"].create({}) cls.package1 = cls.env["stock.quant.package"].create({}) + cls.package2 = cls.env["stock.quant.package"].create({}) - def setup_product_amounts(self): - self.set_product_amount(self.product_no_lots, self.internal_loc_1, 123) - self.set_product_amount( - self.product_lots, self.internal_loc_1, 1.0, lot_id=self.lot1 + @classmethod + def setup_product_amounts(cls): + cls.set_product_amount(cls.product_no_lots, cls.internal_loc_1, 123) + cls.set_product_amount( + cls.product_lots, cls.internal_loc_1, 1.0, lot_id=cls.lot1 ) - self.set_product_amount( - self.product_lots, self.internal_loc_1, 1.0, lot_id=self.lot2 + cls.set_product_amount( + cls.product_lots, cls.internal_loc_1, 1.0, lot_id=cls.lot2 ) - self.set_product_amount( - self.product_lots, self.internal_loc_1, 1.0, lot_id=self.lot3 + cls.set_product_amount( + cls.product_lots, cls.internal_loc_1, 1.0, lot_id=cls.lot3 ) - self.set_product_amount( - self.product_package, - self.internal_loc_1, + cls.set_product_amount( + cls.product_package, + cls.internal_loc_1, 1.0, - lot_id=self.lot4, - package_id=self.package, + lot_id=cls.lot4, + package_id=cls.package, ) - self.set_product_amount( - self.product_package, - self.internal_loc_1, + cls.set_product_amount( + cls.product_package, + cls.internal_loc_1, 1.0, - lot_id=self.lot4, - package_id=self.package1, + lot_id=cls.lot4, + package_id=cls.package1, ) - self.set_product_amount( - self.product_package, - self.internal_loc_1, + cls.set_product_amount( + cls.product_package, + cls.internal_loc_1, 1.0, - lot_id=self.lot5, - package_id=self.package2, - owner_id=self.partner, + lot_id=cls.lot5, + package_id=cls.package2, + owner_id=cls.partner, ) + @classmethod def set_product_amount( - self, product, location, amount, lot_id=None, package_id=None, owner_id=None + cls, product, location, amount, lot_id=None, package_id=None, owner_id=None ): - self.env["stock.quant"]._update_available_quantity( + cls.env["stock.quant"]._update_available_quantity( product, location, amount, diff --git a/stock_move_location/tests/test_move_location.py b/stock_move_location/tests/test_move_location.py index 87de962f9..0421134eb 100644 --- a/stock_move_location/tests/test_move_location.py +++ b/stock_move_location/tests/test_move_location.py @@ -8,9 +8,10 @@ from .test_common import TestsCommon class TestMoveLocation(TestsCommon): - def setUp(self): - super().setUp() - self.setup_product_amounts() + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.setup_product_amounts() def test_move_location_wizard(self): """Test a simple move.""" diff --git a/stock_move_location/views/stock_picking_type_views.xml b/stock_move_location/views/stock_picking_type_views.xml index ed0a6d6db..1f3045b74 100644 --- a/stock_move_location/views/stock_picking_type_views.xml +++ b/stock_move_location/views/stock_picking_type_views.xml @@ -8,7 +8,7 @@ diff --git a/stock_move_location/wizard/stock_move_location.py b/stock_move_location/wizard/stock_move_location.py index ac2854f99..e04201e1d 100644 --- a/stock_move_location/wizard/stock_move_location.py +++ b/stock_move_location/wizard/stock_move_location.py @@ -71,7 +71,7 @@ class StockMoveLocationWizard(models.TransientModel): for rec in self: picking_type = self.env["stock.picking.type"] base_domain = [ - ("code", "=", "internal"), + ("code", "in", ("internal", "outgoing")), ("warehouse_id.company_id", "=", company_id), ] if rec.origin_location_id: @@ -303,25 +303,32 @@ class StockMoveLocationWizard(models.TransientModel): ) return action + def _get_quants_domain(self): + return [("location_id", "=", self.origin_location_id.id)] + def _get_group_quants(self): - location_id = self.origin_location_id - # Using sql as search_group doesn't support aggregation functions - # leading to overhead in queries to DB - query = """ - SELECT product_id, lot_id, package_id, owner_id, SUM(quantity) AS quantity, - SUM(reserved_quantity) AS reserved_quantity - FROM stock_quant - WHERE location_id = %s - GROUP BY product_id, lot_id, package_id, owner_id - """ - self.env.cr.execute(query, (location_id.id,)) - return self.env.cr.dictfetchall() + domain = self._get_quants_domain() + result = self.env["stock.quant"].read_group( + domain=domain, + fields=[ + "product_id", + "lot_id", + "package_id", + "owner_id", + "quantity:sum", + "reserved_quantity:sum", + ], + groupby=["product_id", "lot_id", "package_id", "owner_id"], + orderby="id", + lazy=False, + ) + return result def _get_stock_move_location_lines_values(self): product_obj = self.env["product.product"] product_data = [] for group in self._get_group_quants(): - product = product_obj.browse(group.get("product_id")).exists() + product = product_obj.browse(group["product_id"][0]).exists() # Apply the putaway strategy location_dest_id = ( self.apply_putaway_strategy @@ -337,15 +344,33 @@ class StockMoveLocationWizard(models.TransientModel): "origin_location_id": self.origin_location_id.id, "destination_location_id": location_dest_id, # cursor returns None instead of False - "lot_id": group.get("lot_id") or False, - "package_id": group.get("package_id") or False, - "owner_id": group.get("owner_id") or False, + "lot_id": group["lot_id"][0] if group.get("lot_id") else False, + "package_id": group["package_id"][0] + if group.get("package_id") + else False, + "owner_id": group["owner_id"][0] + if group.get("owner_id") + else False, "product_uom_id": product.uom_id.id, "custom": False, } ) return product_data + def _reset_stock_move_location_lines(self): + lines = [] + line_model = self.env["wiz.stock.move.location.line"] + for line_val in self._get_stock_move_location_lines_values(): + if line_val.get("max_quantity") <= 0: + continue + line = line_model.create(line_val) + line.max_quantity = line.get_max_quantity() + line.reserved_quantity = line.reserved_quantity + lines.append(line) + self.update( + {"stock_move_location_line_ids": [(6, 0, [line.id for line in lines])]} + ) + @api.onchange("origin_location_id") def onchange_origin_location(self): # Get origin_location_disable context key to prevent load all origin @@ -355,18 +380,7 @@ class StockMoveLocationWizard(models.TransientModel): not self.env.context.get("origin_location_disable") and self.origin_location_id ): - lines = [] - line_model = self.env["wiz.stock.move.location.line"] - for line_val in self._get_stock_move_location_lines_values(): - if line_val.get("max_quantity") <= 0: - continue - line = line_model.create(line_val) - line.max_quantity = line.get_max_quantity() - line.reserved_quantity = line.reserved_quantity - lines.append(line) - self.update( - {"stock_move_location_line_ids": [(6, 0, [line.id for line in lines])]} - ) + self._reset_stock_move_location_lines() def clear_lines(self): self._clear_lines() diff --git a/stock_move_location/wizard/stock_move_location.xml b/stock_move_location/wizard/stock_move_location.xml index 060504d38..30101eceb 100644 --- a/stock_move_location/wizard/stock_move_location.xml +++ b/stock_move_location/wizard/stock_move_location.xml @@ -10,18 +10,15 @@
    -
    - + -
    -
    - - -
    + + @@ -37,6 +34,8 @@ attrs="{'readonly': [('destination_location_disable', '=', True)]}" /> + +