[IMP] stock_move_location: black, isort

This commit is contained in:
Joan Sisquella
2020-01-10 12:28:30 +01:00
committed by Alex Cuellar
parent e3131c7325
commit 50ddacfe53
7 changed files with 228 additions and 274 deletions

View File

@@ -5,19 +5,16 @@
{
"name": "Move Stock Location",
"version": "12.0.1.2.0",
"author": "Julius Network Solutions, "
"Odoo Community Association (OCA)",
"author": "Julius Network Solutions, " "Odoo Community Association (OCA)",
"summary": "This module allows to move all stock "
"in a stock location to an other one.",
"in a stock location to an other one.",
"website": "https://github.com/OCA/stock-logistics-warehouse",
'license': 'AGPL-3',
"depends": [
"stock",
],
"license": "AGPL-3",
"depends": ["stock"],
"category": "Stock",
"data": [
'data/stock_quant_view.xml',
'views/stock_picking_type_views.xml',
'wizard/stock_move_location.xml',
"data/stock_quant_view.xml",
"views/stock_picking_type_views.xml",
"wizard/stock_move_location.xml",
],
}

View File

@@ -7,19 +7,20 @@ class StockPickingType(models.Model):
_inherit = "stock.picking.type"
show_move_onhand = fields.Boolean(
string='Show Move On hand stock',
string="Show Move On hand stock",
help="Show a button 'Move On Hand' in the Inventory Dashboard "
"to initiate the process to move the products in stock "
"at the origin location.")
"to initiate the process to move the products in stock "
"at the origin location.",
)
def action_move_location(self):
action = self.env.ref(
'stock_move_location.wiz_stock_move_location_action').read()[0]
action['context'] = {
'default_origin_location_id': self.default_location_src_id.id,
'default_destination_location_id':
self.default_location_dest_id.id,
'default_picking_type_id': self.id,
'default_edit_locations': False,
"stock_move_location.wiz_stock_move_location_action"
).read()[0]
action["context"] = {
"default_origin_location_id": self.default_location_src_id.id,
"default_destination_location_id": self.default_location_dest_id.id,
"default_picking_type_id": self.id,
"default_edit_locations": False,
}
return action

View File

@@ -19,4 +19,4 @@ If you want to transfer a full quant:
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.
and you will be directed to the wizard.

View File

@@ -6,7 +6,6 @@ from odoo.tests import common
class TestsCommon(common.SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
@@ -17,83 +16,65 @@ class TestsCommon(common.SavepointCase):
cls.quant_obj = cls.env["stock.quant"]
# Enable multi-locations:
wizard = cls.env['res.config.settings'].create({
'group_stock_multi_locations': True,
})
wizard = cls.env["res.config.settings"].create(
{"group_stock_multi_locations": True}
)
wizard.execute()
cls.internal_loc_1 = cls.location_obj.create({
"name": "INT_1",
"usage": "internal",
"active": True,
})
cls.internal_loc_2 = cls.location_obj.create({
"name": "INT_2",
"usage": "internal",
"active": True,
})
cls.uom_unit = cls.env.ref('uom.product_uom_unit')
cls.product_no_lots = product_obj.create({
"name": "Pineapple",
"type": "product",
"tracking": "none",
'category_id': cls.env.ref('product.product_category_all').id,
})
cls.product_lots = product_obj.create({
"name": "Pineapple",
"type": "product",
"tracking": "lot",
'category_id': cls.env.ref('product.product_category_all').id,
})
cls.lot1 = cls.env['stock.production.lot'].create({
'product_id': cls.product_lots.id,
})
cls.lot2 = cls.env['stock.production.lot'].create({
'product_id': cls.product_lots.id,
})
cls.lot3 = cls.env['stock.production.lot'].create({
'product_id': cls.product_lots.id,
})
cls.internal_loc_1 = cls.location_obj.create(
{"name": "INT_1", "usage": "internal", "active": True}
)
cls.internal_loc_2 = cls.location_obj.create(
{"name": "INT_2", "usage": "internal", "active": True}
)
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
cls.product_no_lots = product_obj.create(
{
"name": "Pineapple",
"type": "product",
"tracking": "none",
"category_id": cls.env.ref("product.product_category_all").id,
}
)
cls.product_lots = product_obj.create(
{
"name": "Pineapple",
"type": "product",
"tracking": "lot",
"category_id": cls.env.ref("product.product_category_all").id,
}
)
cls.lot1 = cls.env["stock.production.lot"].create(
{"product_id": cls.product_lots.id}
)
cls.lot2 = cls.env["stock.production.lot"].create(
{"product_id": cls.product_lots.id}
)
cls.lot3 = cls.env["stock.production.lot"].create(
{"product_id": cls.product_lots.id}
)
def setup_product_amounts(self):
self.set_product_amount(self.product_no_lots, self.internal_loc_1, 123)
self.set_product_amount(
self.product_no_lots,
self.internal_loc_1,
123,
self.product_lots, self.internal_loc_1, 1, lot_id=self.lot1
)
self.set_product_amount(
self.product_lots,
self.internal_loc_1,
1,
lot_id=self.lot1,
self.product_lots, self.internal_loc_1, 1, lot_id=self.lot2
)
self.set_product_amount(
self.product_lots,
self.internal_loc_1,
1,
lot_id=self.lot2,
)
self.set_product_amount(
self.product_lots,
self.internal_loc_1,
1,
lot_id=self.lot3,
self.product_lots, self.internal_loc_1, 1, lot_id=self.lot3
)
def set_product_amount(self, product, location, amount, lot_id=None):
self.env['stock.quant']._update_available_quantity(
product,
location,
amount,
lot_id=lot_id,
self.env["stock.quant"]._update_available_quantity(
product, location, amount, lot_id=lot_id
)
def check_product_amount(self, product, location, amount, lot_id=None):
self.assertEqual(
self.env['stock.quant']._get_available_quantity(
product,
location,
lot_id=lot_id,
self.env["stock.quant"]._get_available_quantity(
product, location, lot_id=lot_id
),
amount,
)

View File

@@ -2,51 +2,37 @@
# Copyright 2018 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from .test_common import TestsCommon
from odoo.exceptions import ValidationError
from .test_common import TestsCommon
class TestMoveLocation(TestsCommon):
def setUp(self):
super().setUp()
self.setup_product_amounts()
def _create_wizard(self, origin_location, destination_location):
return self.wizard_obj.create({
"origin_location_id": origin_location.id,
"destination_location_id": destination_location.id,
})
return self.wizard_obj.create(
{
"origin_location_id": origin_location.id,
"destination_location_id": destination_location.id,
}
)
def test_move_location_wizard(self):
"""Test a simple move."""
wizard = self._create_wizard(self.internal_loc_1, self.internal_loc_2)
wizard.onchange_origin_location()
wizard.action_move_location()
self.check_product_amount(
self.product_no_lots, self.internal_loc_1, 0,
)
self.check_product_amount(
self.product_lots, self.internal_loc_1, 0, self.lot1,
)
self.check_product_amount(
self.product_lots, self.internal_loc_1, 0, self.lot2,
)
self.check_product_amount(
self.product_lots, self.internal_loc_1, 0, self.lot3,
)
self.check_product_amount(
self.product_no_lots, self.internal_loc_2, 123,
)
self.check_product_amount(
self.product_lots, self.internal_loc_2, 1, self.lot1,
)
self.check_product_amount(
self.product_lots, self.internal_loc_2, 1, self.lot2,
)
self.check_product_amount(
self.product_lots, self.internal_loc_2, 1, self.lot3,
)
self.check_product_amount(self.product_no_lots, self.internal_loc_1, 0)
self.check_product_amount(self.product_lots, self.internal_loc_1, 0, self.lot1)
self.check_product_amount(self.product_lots, self.internal_loc_1, 0, self.lot2)
self.check_product_amount(self.product_lots, self.internal_loc_1, 0, self.lot3)
self.check_product_amount(self.product_no_lots, self.internal_loc_2, 123)
self.check_product_amount(self.product_lots, self.internal_loc_2, 1, self.lot1)
self.check_product_amount(self.product_lots, self.internal_loc_2, 1, self.lot2)
self.check_product_amount(self.product_lots, self.internal_loc_2, 1, self.lot3)
def test_move_location_wizard_amount(self):
"""Can't move more than exists."""
@@ -61,27 +47,16 @@ class TestMoveLocation(TestsCommon):
wizard.onchange_origin_location()
# reserve some quants
self.quant_obj._update_reserved_quantity(
self.product_no_lots,
self.internal_loc_1,
50,
self.product_no_lots, self.internal_loc_1, 50
)
self.quant_obj._update_reserved_quantity(
self.product_lots,
self.internal_loc_1,
1,
lot_id=self.lot1,
self.product_lots, self.internal_loc_1, 1, lot_id=self.lot1
)
# doesn't care about reservations, everything is moved
wizard.action_move_location()
self.check_product_amount(
self.product_no_lots, self.internal_loc_1, 0,
)
self.check_product_amount(
self.product_no_lots, self.internal_loc_2, 123,
)
self.check_product_amount(
self.product_lots, self.internal_loc_2, 1, self.lot1,
)
self.check_product_amount(self.product_no_lots, self.internal_loc_1, 0)
self.check_product_amount(self.product_no_lots, self.internal_loc_2, 123)
self.check_product_amount(self.product_lots, self.internal_loc_2, 1, self.lot1)
def test_wizard_clear_lines(self):
"""Test lines getting cleared properly."""
@@ -91,7 +66,8 @@ class TestMoveLocation(TestsCommon):
wizard._onchange_destination_location_id()
self.assertEqual(len(wizard.stock_move_location_line_ids), 4)
dest_location_line = wizard.stock_move_location_line_ids.mapped(
'destination_location_id')
"destination_location_id"
)
self.assertEqual(dest_location_line, wizard.destination_location_id)
wizard._onchange_origin_location_id()
self.assertEqual(len(wizard.stock_move_location_line_ids), 0)
@@ -100,33 +76,33 @@ class TestMoveLocation(TestsCommon):
"""Test planned transfer."""
wizard = self._create_wizard(self.internal_loc_1, self.internal_loc_2)
wizard.onchange_origin_location()
wizard = wizard.with_context({'planned': True})
wizard = wizard.with_context({"planned": True})
wizard.action_move_location()
picking = wizard.picking_id
self.assertEqual(picking.state, 'assigned')
self.assertEqual(picking.state, "assigned")
self.assertEqual(len(picking.move_line_ids), 4)
self.assertEqual(
sorted(picking.move_line_ids.mapped("product_uom_qty")),
[1, 1, 1, 123],
sorted(picking.move_line_ids.mapped("product_uom_qty")), [1, 1, 1, 123]
)
def test_quant_transfer(self):
"""Test quants transfer."""
quants = self.product_lots.stock_quant_ids
wizard = self.wizard_obj.with_context(
active_model='stock.quant',
active_model="stock.quant",
active_ids=quants.ids,
origin_location_disable=True
).create({
"origin_location_id": quants[:1].location_id.id,
"destination_location_id": self.internal_loc_2.id,
})
origin_location_disable=True,
).create(
{
"origin_location_id": quants[:1].location_id.id,
"destination_location_id": self.internal_loc_2.id,
}
)
lines = wizard.stock_move_location_line_ids
self.assertEqual(len(lines), 3)
wizard.destination_location_id = self.internal_loc_1
wizard._onchange_destination_location_id()
self.assertEqual(
lines.mapped('destination_location_id'), self.internal_loc_1)
self.assertEqual(lines.mapped("destination_location_id"), self.internal_loc_1)
wizard.origin_location_id = self.internal_loc_2
wizard._onchange_destination_location_id()
self.assertEqual(len(lines), 3)

View File

@@ -9,56 +9,60 @@ from odoo.fields import first
class StockMoveLocationWizard(models.TransientModel):
_name = "wiz.stock.move.location"
_description = 'Wizard move location'
_description = "Wizard move location"
@api.multi
def _get_default_picking_type_id(self):
company_id = self.env.context.get('company_id') or \
self.env.user.company_id.id
return self.env['stock.picking.type'].search(
[('code', '=', 'internal'),
('warehouse_id.company_id', '=', company_id)], limit=1).id
company_id = self.env.context.get("company_id") or self.env.user.company_id.id
return (
self.env["stock.picking.type"]
.search(
[
("code", "=", "internal"),
("warehouse_id.company_id", "=", company_id),
],
limit=1,
)
.id
)
origin_location_disable = fields.Boolean(
compute="_compute_readonly_locations",
help="technical field to disable the edition of origin location."
help="technical field to disable the edition of origin location.",
)
origin_location_id = fields.Many2one(
string='Origin Location',
comodel_name='stock.location',
string="Origin Location",
comodel_name="stock.location",
required=True,
domain=lambda self: self._get_locations_domain(),
)
destination_location_disable = fields.Boolean(
compute="_compute_readonly_locations",
help="technical field to disable the edition of destination location."
help="technical field to disable the edition of destination location.",
)
destination_location_id = fields.Many2one(
string='Destination Location',
comodel_name='stock.location',
string="Destination Location",
comodel_name="stock.location",
required=True,
domain=lambda self: self._get_locations_domain(),
)
stock_move_location_line_ids = fields.Many2many(
string="Move Location lines",
comodel_name="wiz.stock.move.location.line",
string="Move Location lines", comodel_name="wiz.stock.move.location.line"
)
picking_type_id = fields.Many2one(
comodel_name='stock.picking.type',
default=_get_default_picking_type_id,
comodel_name="stock.picking.type", default=_get_default_picking_type_id
)
picking_id = fields.Many2one(
string="Connected Picking",
comodel_name="stock.picking",
string="Connected Picking", comodel_name="stock.picking"
)
edit_locations = fields.Boolean(string='Edit Locations',
default=True)
edit_locations = fields.Boolean(string="Edit Locations", default=True)
@api.depends('edit_locations')
@api.depends("edit_locations")
def _compute_readonly_locations(self):
for rec in self:
rec.origin_location_disable = self.env.context.get(
'origin_location_disable', False)
"origin_location_disable", False
)
if not rec.edit_locations:
rec.origin_location_disable = True
rec.destination_location_disable = True
@@ -66,29 +70,37 @@ class StockMoveLocationWizard(models.TransientModel):
@api.model
def default_get(self, fields):
res = super().default_get(fields)
if self.env.context.get('active_model', False) != 'stock.quant':
if self.env.context.get("active_model", False) != "stock.quant":
return res
# Load data directly from quants
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,
'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['origin_location_id'] = first(quants).location_id.id
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,
"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["origin_location_id"] = first(quants).location_id.id
return res
@api.onchange('origin_location_id')
@api.onchange("origin_location_id")
def _onchange_origin_location_id(self):
if not self.env.context.get('origin_location_disable', False):
if not self.env.context.get("origin_location_disable", False):
self._clear_lines()
@api.onchange('destination_location_id')
@api.onchange("destination_location_id")
def _onchange_destination_location_id(self):
for line in self.stock_move_location_line_ids:
line.destination_location_id = self.destination_location_id
@@ -97,22 +109,23 @@ class StockMoveLocationWizard(models.TransientModel):
self.stock_move_location_line_ids = False
def _get_locations_domain(self):
return [('usage', '=', 'internal')]
return [("usage", "=", "internal")]
def _create_picking(self):
return self.env['stock.picking'].create({
'picking_type_id': self.picking_type_id.id,
'location_id': self.origin_location_id.id,
'location_dest_id': self.destination_location_id.id,
})
return self.env["stock.picking"].create(
{
"picking_type_id": self.picking_type_id.id,
"location_id": self.origin_location_id.id,
"location_dest_id": self.destination_location_id.id,
}
)
@api.multi
def group_lines(self):
lines_grouped = {}
for line in self.stock_move_location_line_ids:
lines_grouped.setdefault(
line.product_id.id,
self.env["wiz.stock.move.location.line"].browse(),
line.product_id.id, self.env["wiz.stock.move.location.line"].browse()
)
lines_grouped[line.product_id.id] |= line
return lines_grouped
@@ -148,9 +161,7 @@ class StockMoveLocationWizard(models.TransientModel):
@api.multi
def _create_move(self, picking, lines):
self.ensure_one()
move = self.env["stock.move"].create(
self._get_move_values(picking, lines),
)
move = self.env["stock.move"].create(self._get_move_values(picking, lines))
if not self.env.context.get("planned"):
for line in lines:
line.create_move_lines(picking, move)
@@ -172,18 +183,14 @@ class StockMoveLocationWizard(models.TransientModel):
def _get_picking_action(self, pickinig_id):
action = self.env.ref("stock.action_picking_tree_all").read()[0]
form_view = self.env.ref("stock.view_picking_form").id
action.update({
"view_mode": "form",
"views": [(form_view, "form")],
"res_id": pickinig_id,
})
action.update(
{"view_mode": "form", "views": [(form_view, "form")], "res_id": pickinig_id}
)
return action
def _get_group_quants(self):
location_id = self.origin_location_id.id
company = self.env['res.company']._company_default_get(
'stock.inventory',
)
company = self.env["res.company"]._company_default_get("stock.inventory")
# Using sql as search_group doesn't support aggregation functions
# leading to overhead in queries to DB
query = """
@@ -197,44 +204,46 @@ class StockMoveLocationWizard(models.TransientModel):
return self.env.cr.dictfetchall()
def _get_stock_move_location_lines_values(self):
product_obj = self.env['product.product']
product_obj = self.env["product.product"]
product_data = []
for group in self._get_group_quants():
product = product_obj.browse(group.get("product_id")).exists()
# Apply the putaway strategy
location_dest_id = \
self.destination_location_id.get_putaway_strategy(
product).id or self.destination_location_id.id
product_data.append({
'product_id': product.id,
'move_quantity': group.get("sum"),
'max_quantity': group.get("sum"),
'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,
'product_uom_id': product.uom_id.id,
'custom': False,
})
location_dest_id = (
self.destination_location_id.get_putaway_strategy(product).id
or self.destination_location_id.id
)
product_data.append(
{
"product_id": product.id,
"move_quantity": group.get("sum"),
"max_quantity": group.get("sum"),
"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,
"product_uom_id": product.uom_id.id,
"custom": False,
}
)
return product_data
@api.onchange('origin_location_id')
@api.onchange("origin_location_id")
def onchange_origin_location(self):
lines = []
if self.origin_location_id:
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:
if line_val.get("max_quantity") <= 0:
continue
line = line_model.create(line_val)
line.max_quantity = line.get_max_quantity()
lines.append(line)
# self.stock_move_location_line_ids = [(4, line.id)]
self.update({'stock_move_location_line_ids': [
(6, 0, [line.id for line in lines])]})
self.update(
{"stock_move_location_line_ids": [(6, 0, [line.id for line in lines])]}
)
def clear_lines(self):
self._clear_lines()
return {
"type": "ir.action.do_nothing",
}
return {"type": "ir.action.do_nothing"}

View File

@@ -3,99 +3,88 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo import _, api, fields, models
from odoo.addons import decimal_precision as dp
from odoo.exceptions import ValidationError
from odoo.tools import float_compare
from odoo.addons import decimal_precision as dp
class StockMoveLocationWizardLine(models.TransientModel):
_name = "wiz.stock.move.location.line"
_description = 'Wizard move location line'
_description = "Wizard move location line"
product_id = fields.Many2one(
string="Product",
comodel_name="product.product",
required=True,
string="Product", comodel_name="product.product", required=True
)
origin_location_id = fields.Many2one(
string='Origin Location',
comodel_name='stock.location',
string="Origin Location", comodel_name="stock.location"
)
destination_location_id = fields.Many2one(
string='Destination Location',
comodel_name='stock.location',
string="Destination Location", comodel_name="stock.location"
)
product_uom_id = fields.Many2one(
string='Product Unit of Measure',
comodel_name='uom.uom',
string="Product Unit of Measure", comodel_name="uom.uom"
)
lot_id = fields.Many2one(
string='Lot/Serial Number',
comodel_name='stock.production.lot',
domain="[('product_id','=',product_id)]"
string="Lot/Serial Number",
comodel_name="stock.production.lot",
domain="[('product_id','=',product_id)]",
)
move_quantity = fields.Float(
string="Quantity to move",
digits=dp.get_precision('Product Unit of Measure'),
string="Quantity to move", digits=dp.get_precision("Product Unit of Measure")
)
max_quantity = fields.Float(
string="Maximum available quantity",
digits=dp.get_precision('Product Unit of Measure'),
)
custom = fields.Boolean(
string="Custom line",
default=True,
digits=dp.get_precision("Product Unit of Measure"),
)
custom = fields.Boolean(string="Custom line", default=True)
@staticmethod
def _compare(qty1, qty2, precision_rounding):
return float_compare(
qty1, qty2,
precision_rounding=precision_rounding)
return float_compare(qty1, qty2, precision_rounding=precision_rounding)
@api.constrains("max_quantity", "move_quantity")
def _constraint_max_move_quantity(self):
for record in self:
rounding = record.product_uom_id.rounding
move_qty_gt_max_qty = self._compare(
record.move_quantity, record.max_quantity, rounding) == 1
move_qty_lt_0 = self._compare(
record.move_quantity, 0.0, rounding) == -1
if (move_qty_gt_max_qty or move_qty_lt_0):
raise ValidationError(_(
"Move quantity can not exceed max quantity or be negative"
))
move_qty_gt_max_qty = (
self._compare(record.move_quantity, record.max_quantity, rounding) == 1
)
move_qty_lt_0 = self._compare(record.move_quantity, 0.0, rounding) == -1
if move_qty_gt_max_qty or move_qty_lt_0:
raise ValidationError(
_("Move quantity can not exceed max quantity or be negative")
)
def get_max_quantity(self):
self.product_uom_id = self.product_id.uom_id
search_args = [
('location_id', '=', self.origin_location_id.id),
('product_id', '=', self.product_id.id),
("location_id", "=", self.origin_location_id.id),
("product_id", "=", self.product_id.id),
]
if self.lot_id:
search_args.append(('lot_id', '=', self.lot_id.id))
search_args.append(("lot_id", "=", self.lot_id.id))
else:
search_args.append(('lot_id', '=', False))
res = self.env['stock.quant'].read_group(search_args, ['quantity'], [])
max_quantity = res[0]['quantity']
search_args.append(("lot_id", "=", False))
res = self.env["stock.quant"].read_group(search_args, ["quantity"], [])
max_quantity = res[0]["quantity"]
return max_quantity
def create_move_lines(self, picking, move):
for line in self:
values = line._get_move_line_values(picking, move)
if not self.env.context.get("planned") and \
values.get("qty_done") <= 0:
if not self.env.context.get("planned") and values.get("qty_done") <= 0:
continue
self.env["stock.move.line"].create(
values
)
self.env["stock.move.line"].create(values)
return True
@api.multi
def _get_move_line_values(self, picking, move):
self.ensure_one()
location_dest_id = self.destination_location_id.get_putaway_strategy(
self.product_id).id or self.destination_location_id.id
location_dest_id = (
self.destination_location_id.get_putaway_strategy(self.product_id).id
or self.destination_location_id.id
)
qty_todo, qty_done = self._get_available_quantity()
return {
"product_id": self.product_id.id,
@@ -121,22 +110,23 @@ class StockMoveLocationWizardLine(models.TransientModel):
# for planned transfer we don't care about the amounts at all
return self.move_quantity, 0
search_args = [
('location_id', '=', self.origin_location_id.id),
('product_id', '=', self.product_id.id),
("location_id", "=", self.origin_location_id.id),
("product_id", "=", self.product_id.id),
]
if self.lot_id:
search_args.append(('lot_id', '=', self.lot_id.id))
search_args.append(("lot_id", "=", self.lot_id.id))
else:
search_args.append(('lot_id', '=', False))
res = self.env['stock.quant'].read_group(search_args, ['quantity'], [])
available_qty = res[0]['quantity']
search_args.append(("lot_id", "=", False))
res = self.env["stock.quant"].read_group(search_args, ["quantity"], [])
available_qty = res[0]["quantity"]
if not available_qty:
# if it is immediate transfer and product doesn't exist in that
# location -> make the transfer of 0.
return 0
rounding = self.product_uom_id.rounding
available_qty_lt_move_qty = self._compare(
available_qty, self.move_quantity, rounding) == -1
available_qty_lt_move_qty = (
self._compare(available_qty, self.move_quantity, rounding) == -1
)
if available_qty_lt_move_qty:
return available_qty
return 0, self.move_quantity