diff --git a/addons/mrp/models/stock_rule.py b/addons/mrp/models/stock_rule.py
index 1c7373c8c1a..9fc2ce20bdd 100644
--- a/addons/mrp/models/stock_rule.py
+++ b/addons/mrp/models/stock_rule.py
@@ -119,16 +119,19 @@ class StockRule(models.Model):
and cumulative description.
"""
delay, delay_description = super()._get_lead_days(product)
+ bypass_delay_description = self.env.context.get('bypass_delay_description')
manufacture_rule = self.filtered(lambda r: r.action == 'manufacture')
if not manufacture_rule:
return delay, delay_description
manufacture_rule.ensure_one()
manufacture_delay = product.produce_delay
delay += manufacture_delay
- delay_description += '
| %s | + %d %s |
' % (_('Manufacturing Lead Time'), manufacture_delay, _('day(s)'))
+ if not bypass_delay_description:
+ delay_description += '| %s | + %d %s |
' % (_('Manufacturing Lead Time'), manufacture_delay, _('day(s)'))
security_delay = manufacture_rule.picking_type_id.company_id.manufacturing_lead
delay += security_delay
- delay_description += '| %s | + %d %s |
' % (_('Manufacture Security Lead Time'), security_delay, _('day(s)'))
+ if not bypass_delay_description:
+ delay_description += '| %s | + %d %s |
' % (_('Manufacture Security Lead Time'), security_delay, _('day(s)'))
return delay, delay_description
def _push_prepare_move_copy_values(self, move_to_copy, new_date):
diff --git a/addons/product/models/product.py b/addons/product/models/product.py
index 91920e7c00b..1250c5cc0f7 100644
--- a/addons/product/models/product.py
+++ b/addons/product/models/product.py
@@ -598,9 +598,7 @@ class ProductProduct(models.Model):
'target': 'new'}
def _prepare_sellers(self, params=False):
- # This search is made to avoid retrieving seller_ids from the cache.
- return self.env['product.supplierinfo'].search([('product_tmpl_id', '=', self.product_tmpl_id.id),
- ('name.active', '=', True)]).sorted(lambda s: (s.sequence, -s.min_qty, s.price, s.id))
+ return self.seller_ids.filtered(lambda s: s.name.active).sorted(lambda s: (s.sequence, -s.min_qty, s.price, s.id))
def _select_seller(self, partner_id=False, quantity=0.0, date=None, uom_id=False, params=False):
self.ensure_one()
@@ -776,7 +774,7 @@ class ProductPackaging(models.Model):
class SupplierInfo(models.Model):
_name = "product.supplierinfo"
_description = "Supplier Pricelist"
- _order = 'sequence, min_qty desc, price'
+ _order = 'sequence, min_qty DESC, price, id'
name = fields.Many2one(
'res.partner', 'Vendor',
diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py
index aec908eede4..fd9217256f4 100644
--- a/addons/product/models/product_template.py
+++ b/addons/product/models/product_template.py
@@ -110,7 +110,7 @@ class ProductTemplate(models.Model):
packaging_ids = fields.One2many(
'product.packaging', string="Product Packages", compute="_compute_packaging_ids", inverse="_set_packaging_ids",
help="Gives the different ways to package the same product.")
- seller_ids = fields.One2many('product.supplierinfo', 'product_tmpl_id', 'Vendors', help="Define vendor pricelists.")
+ seller_ids = fields.One2many('product.supplierinfo', 'product_tmpl_id', 'Vendors', depends_context=('company',), help="Define vendor pricelists.")
variant_seller_ids = fields.One2many('product.supplierinfo', 'product_tmpl_id')
active = fields.Boolean('Active', default=True, help="If unchecked, it will allow you to hide the product without removing it.")
diff --git a/addons/purchase_stock/models/stock_rule.py b/addons/purchase_stock/models/stock_rule.py
index 51c68706d31..2064f76b6e8 100644
--- a/addons/purchase_stock/models/stock_rule.py
+++ b/addons/purchase_stock/models/stock_rule.py
@@ -148,17 +148,21 @@ class StockRule(models.Model):
purpose in order to indicate that those options are available.
"""
delay, delay_description = super()._get_lead_days(product)
+ bypass_delay_description = self.env.context.get('bypass_delay_description')
buy_rule = self.filtered(lambda r: r.action == 'buy')
- if not buy_rule or not product._prepare_sellers():
+ seller = product._prepare_sellers()
+ if not buy_rule or not seller:
return delay, delay_description
buy_rule.ensure_one()
- supplier_delay = product._prepare_sellers()[0].delay
- if supplier_delay:
+ supplier_delay = seller[0].delay
+ if supplier_delay and not bypass_delay_description:
delay_description += '| %s | + %d %s |
' % (_('Vendor Lead Time'), supplier_delay, _('day(s)'))
security_delay = buy_rule.picking_type_id.company_id.po_lead
- delay_description += '| %s | + %d %s |
' % (_('Purchase Security Lead Time'), security_delay, _('day(s)'))
+ if not bypass_delay_description:
+ delay_description += '| %s | + %d %s |
' % (_('Purchase Security Lead Time'), security_delay, _('day(s)'))
days_to_purchase = buy_rule.company_id.days_to_purchase
- delay_description += '| %s | + %d %s |
' % (_('Days to Purchase'), days_to_purchase, _('day(s)'))
+ if not bypass_delay_description:
+ delay_description += '| %s | + %d %s |
' % (_('Days to Purchase'), days_to_purchase, _('day(s)'))
return delay + supplier_delay + security_delay + days_to_purchase, delay_description
@api.model
diff --git a/addons/stock/models/stock_orderpoint.py b/addons/stock/models/stock_orderpoint.py
index 6918a6b5d89..6b02cdfbe95 100644
--- a/addons/stock/models/stock_orderpoint.py
+++ b/addons/stock/models/stock_orderpoint.py
@@ -318,6 +318,8 @@ class StockWarehouseOrderpoint(models.Model):
to_remove.unlink()
orderpoints = orderpoints - to_remove
to_refill = defaultdict(float)
+ all_product_ids = []
+ all_warehouse_ids = []
qty_by_product_warehouse = self.env['report.stock.quantity'].read_group(
[('date', '=', fields.date.today()), ('state', '=', 'forecast')],
['product_id', 'product_qty', 'warehouse_id'],
@@ -326,6 +328,8 @@ class StockWarehouseOrderpoint(models.Model):
warehouse_id = group.get('warehouse_id') and group['warehouse_id'][0]
if group['product_qty'] >= 0.0 or not warehouse_id:
continue
+ all_product_ids.append(group['product_id'][0])
+ all_warehouse_ids.append(warehouse_id)
to_refill[(group['product_id'][0], warehouse_id)] = group['product_qty']
if not to_refill:
return action
@@ -333,19 +337,27 @@ class StockWarehouseOrderpoint(models.Model):
# Recompute the forecasted quantity for missing product today but at this time
# with their real lead days.
key_to_remove = []
+ pwh_per_day = defaultdict(list)
for (product, warehouse) in to_refill.keys():
- product = self.env['product.product'].browse(product)
- warehouse = self.env['stock.warehouse'].browse(warehouse)
+ product = self.env['product.product'].browse(product).with_prefetch(all_product_ids)
+ warehouse = self.env['stock.warehouse'].browse(warehouse).with_prefetch(all_warehouse_ids)
rules = product._get_rules_from_location(warehouse.lot_stock_id)
- lead_days = rules._get_lead_days(product)[0]
- virtual_available = product.with_context(
+ lead_days = rules.with_context(bypass_delay_description=True)._get_lead_days(product)[0]
+ pwh_per_day[(lead_days, warehouse)].append(product.id)
+ # group product by lead_days and warehouse in order to read virtual_available
+ # in batch
+ for (days, warehouse), p_ids in pwh_per_day.items():
+ products = self.env['product.product'].browse(p_ids)
+ qties = products.with_context(
warehouse=warehouse.id,
- to_date=fields.datetime.now() + relativedelta.relativedelta(days=lead_days)
- ).virtual_available
- if float_compare(virtual_available, 0, precision_rounding=product.uom_id.rounding) >= 0:
- key_to_remove.append((product.id, warehouse.id))
- else:
- to_refill[(product.id, warehouse.id)] = virtual_available
+ to_date=fields.datetime.now() + relativedelta.relativedelta(days=days)
+ ).read(['virtual_available'])
+ for qty in qties:
+ if float_compare(qty['virtual_available'], 0, precision_rounding=product.uom_id.rounding) >= 0:
+ key_to_remove.append((qty['id'], warehouse.id))
+ else:
+ to_refill[(qty['id'], warehouse.id)] = qty['virtual_available']
+
for key in key_to_remove:
del to_refill[key]
if not to_refill:
diff --git a/addons/stock/models/stock_rule.py b/addons/stock/models/stock_rule.py
index cd78f978567..006415f9303 100644
--- a/addons/stock/models/stock_rule.py
+++ b/addons/stock/models/stock_rule.py
@@ -330,7 +330,10 @@ class StockRule(models.Model):
:rtype: tuple
"""
delay = sum(self.filtered(lambda r: r.action in ['pull', 'pull_push']).mapped('delay'))
- delay_description = ''.join(['| %s %s | + %d %s |
' % (_('Delay on'), html_escape(rule.name), rule.delay, _('day(s)')) for rule in self if rule.action in ['pull', 'pull_push'] and rule.delay])
+ if self.env.context.get('bypass_delay_description'):
+ delay_description = ""
+ else:
+ delay_description = ''.join(['| %s %s | + %d %s |
' % (_('Delay on'), html_escape(rule.name), rule.delay, _('day(s)')) for rule in self if rule.action in ['pull', 'pull_push'] and rule.delay])
return delay, delay_description