[REF] stock: cache the get_warehouse of stock.location
To avoid multiple search of the get_warehouse for the same location and extra SQL request (it happens a lot for complicate flow, e.g. mrp_mps, replenishment report). Translate it into a standard compute to use the cache of the ORM for no-store compute field (`warehouse_id`) and put some depends to be always correct (even if `warehouse_id` shouldn't change in the same request). task-2439019
This commit is contained in:
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user