From f915073acd514425219ff5124b1ce313b24a6107 Mon Sep 17 00:00:00 2001 From: Iryna Vushnevska Date: Thu, 23 Apr 2020 16:10:14 +0300 Subject: [PATCH] [IMP] add posibility to move only not reserved quantity --- stock_move_location/__manifest__.py | 10 +- stock_move_location/models/stock_picking.py | 39 +++--- .../tests/test_stock_fillwithstock.py | 111 ++++++++++-------- stock_move_location/views/stock_picking.xml | 13 +- .../wizard/stock_move_location.py | 68 ++++++++--- 5 files changed, 152 insertions(+), 89 deletions(-) diff --git a/stock_move_location/__manifest__.py b/stock_move_location/__manifest__.py index d5bbe1a87..006513358 100644 --- a/stock_move_location/__manifest__.py +++ b/stock_move_location/__manifest__.py @@ -7,9 +7,9 @@ "name": "Move Stock Location", "version": "15.0.1.0.0", "author": "Julius Network Solutions, " - "BCIM," - "Camptocamp," - "Odoo Community Association (OCA)", + "BCIM," + "Camptocamp," + "Odoo Community Association (OCA)", "summary": "This module allows to move all stock " "in a stock location to an other one.", "website": "https://github.com/OCA/stock-logistics-warehouse", @@ -20,8 +20,8 @@ "data/stock_quant_view.xml", "security/ir.model.access.csv", "views/stock_picking_type_views.xml", - 'views/stock_picking.xml', - 'wizard/stock_move_location.xml', + "views/stock_picking.xml", + "wizard/stock_move_location.xml", ], "post_init_hook": "enable_multi_locations", } diff --git a/stock_move_location/models/stock_picking.py b/stock_move_location/models/stock_picking.py index 3b8733472..f1f203db3 100644 --- a/stock_move_location/models/stock_picking.py +++ b/stock_move_location/models/stock_picking.py @@ -4,11 +4,10 @@ from odoo import _, models from odoo.exceptions import UserError -from itertools import groupby class StockPicking(models.Model): - _inherit = 'stock.picking' + _inherit = "stock.picking" def button_fillwithstock(self): # check source location has no children, i.e. we scanned a bin @@ -16,31 +15,37 @@ class StockPicking(models.Model): self.ensure_one() self._validate_picking() context = { - 'active_ids': self._get_movable_quants().ids, - 'active_model': 'stock.quant', - 'only_reserved_qty': True, - 'planned': True, + "active_ids": self._get_movable_quants().ids, + "active_model": "stock.quant", + "only_reserved_qty": True, + "planned": True, } - move_wizard = self.env['wiz.stock.move.location'].with_context(context).create({ - 'destination_location_id' : self.location_dest_id.id, - 'origin_location_id': self.location_id.id, - 'picking_type_id': self.picking_type_id.id, - 'picking_id': self.id, - }) + move_wizard = ( + self.env["wiz.stock.move.location"] + .with_context(**context) + .create( + { + "destination_location_id": self.location_dest_id.id, + "origin_location_id": self.location_id.id, + "picking_type_id": self.picking_type_id.id, + "picking_id": self.id, + } + ) + ) move_wizard._onchange_destination_location_id() move_wizard.action_move_location() return True def _validate_picking(self): if self.location_id.child_ids: - raise UserError(_('Please choose a source end location')) + raise UserError(_("Please choose a source end location")) if self.move_lines: - raise UserError(_('Moves lines already exists')) + raise UserError(_("Moves lines already exists")) def _get_movable_quants(self): - return self.env['stock.quant'].search( + return self.env["stock.quant"].search( [ - ('location_id', '=', self.location_id.id), - ('quantity', '>', 0.0), + ("location_id", "=", self.location_id.id), + ("quantity", ">", 0.0), ] ) diff --git a/stock_move_location/tests/test_stock_fillwithstock.py b/stock_move_location/tests/test_stock_fillwithstock.py index 5546daa2b..c6b6d4845 100644 --- a/stock_move_location/tests/test_stock_fillwithstock.py +++ b/stock_move_location/tests/test_stock_fillwithstock.py @@ -6,68 +6,85 @@ import odoo.tests.common as common class TestFillwithStock(common.TransactionCase): - def setUp(self): super(TestFillwithStock, self).setUp() - self.env = self.env(context=dict( - self.env.context, - tracking_disable=True, - )) + self.env = self.env( + context=dict( + self.env.context, + tracking_disable=True, + ) + ) - self.stock_location = self.env.ref('stock.stock_location_stock') - self.pack_location = self.env.ref('stock.location_pack_zone') + self.stock_location = self.env.ref("stock.stock_location_stock") + self.pack_location = self.env.ref("stock.location_pack_zone") - self.shelf1_location = self.env["stock.location"].create({ - "name": "Test location", - "usage": "internal", - "location_id": self.stock_location.id - }) + self.shelf1_location = self.env["stock.location"].create( + { + "name": "Test location", + "usage": "internal", + "location_id": self.stock_location.id, + } + ) - self.product1 = self.env['product.product'].create({ - 'name': 'Product A', - 'type': 'product', - }) - self.product2 = self.env['product.product'].create({ - 'name': 'Product B', - 'type': 'product', - }) + self.product1 = self.env["product.product"].create( + { + "name": "Product A", + "type": "product", + } + ) + self.product2 = self.env["product.product"].create( + { + "name": "Product B", + "type": "product", + } + ) - self.env['stock.quant'].create({ - 'product_id': self.product1.id, - 'location_id': self.shelf1_location.id, - 'quantity': 5.0, - 'reserved_quantity': 0.0, - }) - self.env['stock.quant'].create({ - 'product_id': self.product1.id, - 'location_id': self.shelf1_location.id, - 'quantity': 10.0, - 'reserved_quantity': 5.0, - }) - self.env['stock.quant'].create({ - 'product_id': self.product2.id, - 'location_id': self.shelf1_location.id, - 'quantity': 5.0, - 'reserved_quantity': 0.0, - }) + self.env["stock.quant"].create( + { + "product_id": self.product1.id, + "location_id": self.shelf1_location.id, + "quantity": 5.0, + "reserved_quantity": 0.0, + } + ) + self.env["stock.quant"].create( + { + "product_id": self.product1.id, + "location_id": self.shelf1_location.id, + "quantity": 10.0, + "reserved_quantity": 5.0, + } + ) + self.env["stock.quant"].create( + { + "product_id": self.product2.id, + "location_id": self.shelf1_location.id, + "quantity": 5.0, + "reserved_quantity": 0.0, + } + ) def test_fillwithstock(self): - picking_stock_pack = self.env['stock.picking'].create({ - 'location_id': self.shelf1_location.id, - 'location_dest_id': self.pack_location.id, - 'picking_type_id': self.env.ref('stock.picking_type_internal').id, - }) + picking_stock_pack = self.env["stock.picking"].create( + { + "location_id": self.shelf1_location.id, + "location_dest_id": self.pack_location.id, + "picking_type_id": self.env.ref("stock.picking_type_internal").id, + } + ) self.assertFalse(picking_stock_pack.move_lines) picking_stock_pack.button_fillwithstock() # picking filled with quants in bin self.assertEqual(len(picking_stock_pack.move_lines), 2) self.assertEqual( picking_stock_pack.move_lines.filtered( - lambda m: m.product_id == self.product1).product_uom_qty, - 10.0 + lambda m: m.product_id == self.product1 + ).product_uom_qty, + 10.0, ) self.assertEqual( picking_stock_pack.move_lines.filtered( - lambda m: m.product_id == self.product2).product_uom_qty, - 5.0 + lambda m: m.product_id == self.product2 + ).product_uom_qty, + 5.0, ) diff --git a/stock_move_location/views/stock_picking.xml b/stock_move_location/views/stock_picking.xml index 052a76184..8f0849d2a 100644 --- a/stock_move_location/views/stock_picking.xml +++ b/stock_move_location/views/stock_picking.xml @@ -1,13 +1,20 @@ - + stock.picking.form.fillwithstock stock.picking - + diff --git a/stock_move_location/wizard/stock_move_location.py b/stock_move_location/wizard/stock_move_location.py index a7208227d..a8f221749 100644 --- a/stock_move_location/wizard/stock_move_location.py +++ b/stock_move_location/wizard/stock_move_location.py @@ -3,6 +3,8 @@ # Copyright 2019 Sergio Teruel - Tecnativa # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from itertools import groupby + from odoo import api, fields, models from odoo.fields import first @@ -82,26 +84,58 @@ class StockMoveLocationWizard(models.TransientModel): quants = self.env["stock.quant"].browse( self.env.context.get("active_ids", False) ) - res["stock_move_location_line_ids"] = [ - ( - 0, - 0, - { - "product_id": quant.product_id.id, - "move_quantity": quant.quantity, - "max_quantity": quant.quantity, - "reserved_quantity": quant.reserved_quantity, - "origin_location_id": quant.location_id.id, - "lot_id": quant.lot_id.id, - "product_uom_id": quant.product_uom_id.id, - "custom": False, - }, - ) - for quant in quants - ] + res["stock_move_location_line_ids"] = self._prepare_wizard_move_lines(quants) res["origin_location_id"] = first(quants).location_id.id return res + @api.model + def _prepare_wizard_move_lines(self, quants): + res = [] + exclude_reserved_qty = self.env.context.get("only_reserved_qty", False) + if not exclude_reserved_qty: + res = [ + ( + 0, + 0, + { + "product_id": quant.product_id.id, + "move_quantity": quant.quantity, + "max_quantity": quant.quantity, + "origin_location_id": quant.location_id.id, + "lot_id": quant.lot_id.id, + "product_uom_id": quant.product_uom_id.id, + "custom": False, + }, + ) + for quant in quants + ] + else: + # if need move only available qty per product on location + for _product, quant in groupby(quants, lambda r: r.product_id): + # we need only one quant per product + quant = list(quant)[0] + qty = quant._get_available_quantity( + quant.product_id, + quant.location_id, + ) + if qty: + res.append( + ( + 0, + 0, + { + "product_id": quant.product_id.id, + "move_quantity": qty, + "max_quantity": qty, + "origin_location_id": quant.location_id.id, + "lot_id": quant.lot_id.id, + "product_uom_id": quant.product_uom_id.id, + "custom": False, + }, + ) + ) + return res + @api.onchange("origin_location_id") def _onchange_origin_location_id(self): if not self.env.context.get("origin_location_disable", False):