diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index e32e9f3694e..54873be048e 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -509,7 +509,7 @@ class MrpProduction(models.Model): @api.depends('product_uom_qty', 'date_planned_start') def _compute_forecasted_issue(self): for order in self: - warehouse = order.location_dest_id.get_warehouse() + warehouse = order.location_dest_id.warehouse_id order.forecasted_issue = False if order.product_id: virtual_available = order.product_id.with_context(warehouse=warehouse.id, to_date=order.date_planned_start).virtual_available @@ -631,7 +631,7 @@ class MrpProduction(models.Model): def _onchange_location(self): source_location = self.location_src_id self.move_raw_ids.update({ - 'warehouse_id': source_location.get_warehouse().id, + 'warehouse_id': source_location.warehouse_id.id, 'location_id': source_location.id, }) @@ -641,7 +641,7 @@ class MrpProduction(models.Model): update_value_list = [] for move in self.move_finished_ids: update_value_list += [(1, move.id, ({ - 'warehouse_id': destination_location.get_warehouse().id, + 'warehouse_id': destination_location.warehouse_id.id, 'location_dest_id': destination_location.id, }))] self.move_finished_ids = update_value_list @@ -834,7 +834,7 @@ class MrpProduction(models.Model): 'location_dest_id': self.location_dest_id.id, 'company_id': self.company_id.id, 'production_id': self.id, - 'warehouse_id': self.location_dest_id.get_warehouse().id, + 'warehouse_id': self.location_dest_id.warehouse_id.id, 'origin': self.name, 'group_id': self.procurement_group_id.id, 'propagate_cancel': self.propagate_cancel, @@ -895,7 +895,7 @@ class MrpProduction(models.Model): 'procure_method': 'make_to_stock', 'origin': self.name, 'state': 'draft', - 'warehouse_id': source_location.get_warehouse().id, + 'warehouse_id': source_location.warehouse_id.id, 'group_id': self.procurement_group_id.id, 'propagate_cancel': self.propagate_cancel, } diff --git a/addons/mrp/models/mrp_unbuild.py b/addons/mrp/models/mrp_unbuild.py index c0343dea40d..1b0ca5e9dcc 100644 --- a/addons/mrp/models/mrp_unbuild.py +++ b/addons/mrp/models/mrp_unbuild.py @@ -257,7 +257,7 @@ class MrpUnbuild(models.Model): 'procure_method': 'make_to_stock', 'location_dest_id': location_dest_id.id, 'location_id': location_id.id, - 'warehouse_id': location_dest_id.get_warehouse().id, + 'warehouse_id': location_dest_id.warehouse_id.id, 'unbuild_id': self.id, 'company_id': move.company_id.id, }) @@ -266,7 +266,7 @@ class MrpUnbuild(models.Model): product_prod_location = product.with_company(self.company_id).property_stock_production location_id = bom_line_id and product_prod_location or self.location_id location_dest_id = bom_line_id and self.location_dest_id or product_prod_location - warehouse = location_dest_id.get_warehouse() + warehouse = location_dest_id.warehouse_id return self.env['stock.move'].create({ 'name': self.name, 'date': self.create_date, diff --git a/addons/purchase_stock/models/product.py b/addons/purchase_stock/models/product.py index 66bfb199b3a..4c201c07ba0 100644 --- a/addons/purchase_stock/models/product.py +++ b/addons/purchase_stock/models/product.py @@ -67,5 +67,5 @@ class ProductProduct(models.Model): uom = self.env['uom.uom'].browse(group['product_uom'][0]) product_qty = uom._compute_quantity(group['product_qty'], product.uom_id, round=False) qty_by_product_location[(product.id, location.id)] += product_qty - qty_by_product_wh[(product.id, location.get_warehouse().id)] += product_qty + qty_by_product_wh[(product.id, location.warehouse_id.id)] += product_qty return qty_by_product_location, qty_by_product_wh diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index a96cab737d6..ebc3dd9fd94 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -574,7 +574,7 @@ class Product(models.Model): seen_rules = self.env['stock.rule'] rule = self.env['procurement.group']._get_rule(self, location, { 'route_ids': route_ids, - 'warehouse_id': location.get_warehouse() + 'warehouse_id': location.warehouse_id }) if not rule: return seen_rules diff --git a/addons/stock/models/stock_location.py b/addons/stock/models/stock_location.py index 3c44faeff3b..e158a287699 100644 --- a/addons/stock/models/stock_location.py +++ b/addons/stock/models/stock_location.py @@ -6,6 +6,7 @@ from datetime import timedelta from odoo import _, api, fields, models from odoo.exceptions import UserError from odoo.osv import expression +from collections import OrderedDict class Location(models.Model): @@ -65,6 +66,8 @@ class Location(models.Model): cyclic_inventory_frequency = fields.Integer("Inventory Frequency (Days)", default=0, help=" When different than 0, inventory adjustments for products stored at this location will be created automatically at the defined frequency.") last_inventory_date = fields.Datetime("Last Effective Inventory", readonly=True, help="Date of the last inventory at this location.") next_inventory_date = fields.Date("Next Expected Inventory", compute="_compute_next_inventory_date", store=True, help="Date for next planned inventory based on cyclic schedule.") + warehouse_view_ids = fields.One2many('stock.warehouse', 'view_location_id', readonly=True) + warehouse_id = fields.Many2one('stock.warehouse', compute='_compute_warehouse_id') _sql_constraints = [('barcode_company_uniq', 'unique (barcode,company_id)', 'The barcode for a location must be unique per company !'), ('inventory_freq_nonneg', 'check(cyclic_inventory_frequency >= 0)', 'The inventory frequency (days) for a location must be non-negative')] @@ -95,6 +98,18 @@ class Location(models.Model): else: location.next_inventory_date = False + @api.depends('location_id.warehouse_id', 'warehouse_view_ids') + def _compute_warehouse_id(self): + warehouses = self.env['stock.warehouse'].search([('view_location_id', 'parent_of', self.ids)]) + view_by_wh = OrderedDict((wh.view_location_id.id, wh.id) for wh in warehouses) + self.warehouse_id = False + for loc in self: + path = set(int(loc_id) for loc_id in loc.parent_path.split('/')[:-1]) + for view_location_id in view_by_wh: + if view_location_id in path: + loc.warehouse_id = view_by_wh[view_location_id] + break + @api.onchange('usage') def _onchange_usage(self): if self.usage not in ('internal', 'inventory'): @@ -177,12 +192,6 @@ class Location(models.Model): current_location = current_location.location_id return putaway_location - @api.returns('stock.warehouse', lambda value: value.id) - def get_warehouse(self): - """ Returns warehouse id of warehouse that contains location """ - domain = [('view_location_id', 'parent_of', self.ids)] - return self.env['stock.warehouse'].search(domain, limit=1) - def should_bypass_reservation(self): self.ensure_one() return self.usage in ('supplier', 'customer', 'inventory', 'production') or self.scrap_location or (self.usage == 'transit' and not self.company_id) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index ba5218e2694..2cb41b1b54e 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -409,7 +409,7 @@ class StockMove(models.Model): move.forecast_availability = move.product_qty product_moves = (self - not_product_moves) - warehouse_by_location = {loc: loc.get_warehouse() for loc in product_moves.location_id} + warehouse_by_location = {loc: loc.warehouse_id for loc in product_moves.location_id} outgoing_unreserved_moves_per_warehouse = defaultdict(lambda: self.env['stock.move']) for move in product_moves: @@ -670,9 +670,9 @@ class StockMove(models.Model): 'move_to_match_ids': self.ids, } if self.picking_type_id.code == 'outgoing': - warehouse = self.location_id.get_warehouse() + warehouse = self.location_id.warehouse_id else: - warehouse = self.location_dest_id.get_warehouse() + warehouse = self.location_dest_id.warehouse_id if warehouse: action['context']['warehouse'] = warehouse.id @@ -883,7 +883,7 @@ class StockMove(models.Model): def _get_forecast_availability_incoming(self): self.ensure_one() - warehouse = self.location_dest_id.get_warehouse() + warehouse = self.location_dest_id.warehouse_id self.forecast_availability = self.product_id.with_context(warehouse=warehouse.id, to_date=self.date).virtual_available if self.state == 'draft': self.forecast_availability += self.product_uom_qty diff --git a/addons/stock/models/stock_orderpoint.py b/addons/stock/models/stock_orderpoint.py index 2a69085a93b..2f5245c8bbb 100644 --- a/addons/stock/models/stock_orderpoint.py +++ b/addons/stock/models/stock_orderpoint.py @@ -176,7 +176,7 @@ class StockWarehouseOrderpoint(models.Model): @api.onchange('location_id') def _onchange_location_id(self): - warehouse = self.location_id.get_warehouse().id + warehouse = self.location_id.warehouse_id.id if warehouse: self.warehouse_id = warehouse diff --git a/addons/stock/populate/stock.py b/addons/stock/populate/stock.py index 65a351a6119..25a4665eed0 100644 --- a/addons/stock/populate/stock.py +++ b/addons/stock/populate/stock.py @@ -380,7 +380,7 @@ class PickingType(models.Model): locations_company = locations_by_company[values['company_id']] # TODO : choice only location child of warehouse.lot_stock_id inter_location = random.choice(locations_company) - values['warehouse_id'] = inter_location.get_warehouse().id + values['warehouse_id'] = inter_location.warehouse_id.id if values['code'] == 'internal': values['default_location_src_id'] = inter_location.id values['default_location_dest_id'] = random.choice(locations_company - inter_location).id diff --git a/addons/stock/report/report_stock_rule.py b/addons/stock/report/report_stock_rule.py index f45b909fe7d..003a152e918 100644 --- a/addons/stock/report/report_stock_rule.py +++ b/addons/stock/report/report_stock_rule.py @@ -96,7 +96,7 @@ class ReportStockRule(models.AbstractModel): ordered_locations = self.env['stock.location'] locations = all_locations.filtered(lambda l: l.usage in ('supplier', 'production')) for warehouse_id in warehouses: - all_warehouse_locations = all_locations.filtered(lambda l: l.get_warehouse() == warehouse_id) + all_warehouse_locations = all_locations.filtered(lambda l: l.warehouse_id == warehouse_id) starting_rules = [d for d in rules_and_loc if d['source'] not in all_warehouse_locations] if starting_rules: start_locations = self.env['stock.location'].concat(*([r['destination'] for r in starting_rules])) @@ -116,7 +116,7 @@ class ReportStockRule(models.AbstractModel): def _sort_locations_by_warehouse(self, rules_and_loc, used_rules, start_locations, ordered_locations, warehouse_id): """ We order locations by putting first the locations that are not the destination of others and do it recursively. """ - start_locations = start_locations.filtered(lambda l: l.get_warehouse() == warehouse_id) + start_locations = start_locations.filtered(lambda l: l.warehouse_id == warehouse_id) ordered_locations |= start_locations rules_start = [] for rule in rules_and_loc: