mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
[MIG] sale_sourced_by_line: to Odoo 14.0
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
'name': 'Sale Sourced by Line',
|
'name': 'Sale Sourced by Line',
|
||||||
'summary': 'Multiple warehouse source locations for Sale order',
|
'summary': 'Multiple warehouse source locations for Sale order',
|
||||||
'version': '13.0.1.0.0',
|
'version': '14.0.1.0.0',
|
||||||
'author': "Hibou Corp.,Odoo Community Association (OCA)",
|
'author': "Hibou Corp.,Odoo Community Association (OCA)",
|
||||||
'category': 'Warehouse',
|
'category': 'Warehouse',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ class SaleOrder(models.Model):
|
|||||||
class SaleOrderLine(models.Model):
|
class SaleOrderLine(models.Model):
|
||||||
_inherit = 'sale.order.line'
|
_inherit = 'sale.order.line'
|
||||||
|
|
||||||
# In 13, this field exists, but isn't stored and is computed during
|
# In 14, this field exists, but isn't stored and is merely related to the
|
||||||
# computation for available inventory (set to order's warehouse)
|
# order's warehouse_id, it is only used in computation of availability
|
||||||
warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse',
|
warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse',
|
||||||
compute=None, store=True)
|
compute=None, related=None, store=True)
|
||||||
date_planned = fields.Datetime('Planned Date')
|
date_planned = fields.Datetime('Planned Date')
|
||||||
|
|
||||||
def _prepare_procurement_values(self, group_id=False):
|
def _prepare_procurement_values(self, group_id=False):
|
||||||
@@ -29,30 +29,41 @@ class SaleOrderLine(models.Model):
|
|||||||
return vals
|
return vals
|
||||||
|
|
||||||
# Needs modifications to not actually set a warehouse on the line as it is now stored
|
# Needs modifications to not actually set a warehouse on the line as it is now stored
|
||||||
@api.depends('product_id', 'customer_lead', 'product_uom_qty', 'product_uom', 'order_id.warehouse_id', 'order_id.commitment_date')
|
@api.depends(
|
||||||
|
'product_id', 'customer_lead', 'product_uom_qty', 'product_uom', 'order_id.commitment_date',
|
||||||
|
'move_ids', 'move_ids.forecast_expected_date', 'move_ids.forecast_availability')
|
||||||
def _compute_qty_at_date(self):
|
def _compute_qty_at_date(self):
|
||||||
""" Compute the quantity forecasted of product at delivery date. There are
|
""" Compute the quantity forecasted of product at delivery date. There are
|
||||||
two cases:
|
two cases:
|
||||||
1. The quotation has a commitment_date, we take it as delivery date
|
1. The quotation has a commitment_date, we take it as delivery date
|
||||||
2. The quotation hasn't commitment_date, we compute the estimated delivery
|
2. The quotation hasn't commitment_date, we compute the estimated delivery
|
||||||
date based on lead time"""
|
date based on lead time"""
|
||||||
|
treated = self.browse()
|
||||||
|
# If the state is already in sale the picking is created and a simple forecasted quantity isn't enough
|
||||||
|
# Then used the forecasted data of the related stock.move
|
||||||
|
for line in self.filtered(lambda l: l.state == 'sale'):
|
||||||
|
if not line.display_qty_widget:
|
||||||
|
continue
|
||||||
|
moves = line.move_ids
|
||||||
|
line.forecast_expected_date = max(moves.filtered("forecast_expected_date").mapped("forecast_expected_date"), default=False)
|
||||||
|
line.qty_available_today = 0
|
||||||
|
line.virtual_available_at_date = 0
|
||||||
|
for move in moves:
|
||||||
|
line.qty_available_today += move.product_uom._compute_quantity(move.reserved_availability, line.product_uom)
|
||||||
|
line.virtual_available_at_date += move.product_id.uom_id._compute_quantity(move.forecast_availability, line.product_uom)
|
||||||
|
line.scheduled_date = line.order_id.commitment_date or line._expected_date()
|
||||||
|
line.free_qty_today = False
|
||||||
|
treated |= line
|
||||||
|
|
||||||
qty_processed_per_product = defaultdict(lambda: 0)
|
qty_processed_per_product = defaultdict(lambda: 0)
|
||||||
grouped_lines = defaultdict(lambda: self.env['sale.order.line'])
|
grouped_lines = defaultdict(lambda: self.env['sale.order.line'])
|
||||||
# We first loop over the SO lines to group them by warehouse and schedule
|
# We first loop over the SO lines to group them by warehouse and schedule
|
||||||
# date in order to batch the read of the quantities computed field.
|
# date in order to batch the read of the quantities computed field.
|
||||||
for line in self:
|
for line in self.filtered(lambda l: l.state in ('draft', 'sent')):
|
||||||
if not (line.product_id and line.display_qty_widget):
|
if not (line.product_id and line.display_qty_widget):
|
||||||
continue
|
continue
|
||||||
# use warehouse from line or order
|
grouped_lines[(line.warehouse_id.id or line.order_id.warehouse_id.id, line.order_id.commitment_date or line._expected_date())] |= line
|
||||||
warehouse = line.warehouse_id or line.order_id.warehouse_id
|
|
||||||
# line.warehouse_id = line.order_id.warehouse_id
|
|
||||||
if line.order_id.commitment_date:
|
|
||||||
date = line.order_id.commitment_date
|
|
||||||
else:
|
|
||||||
date = line._expected_date()
|
|
||||||
grouped_lines[(warehouse, date)] |= line
|
|
||||||
|
|
||||||
treated = self.browse()
|
|
||||||
for (warehouse, scheduled_date), lines in grouped_lines.items():
|
for (warehouse, scheduled_date), lines in grouped_lines.items():
|
||||||
product_qties = lines.mapped('product_id').with_context(to_date=scheduled_date, warehouse=warehouse).read([
|
product_qties = lines.mapped('product_id').with_context(to_date=scheduled_date, warehouse=warehouse).read([
|
||||||
'qty_available',
|
'qty_available',
|
||||||
@@ -69,6 +80,7 @@ class SaleOrderLine(models.Model):
|
|||||||
line.qty_available_today = qty_available_today - qty_processed_per_product[line.product_id.id]
|
line.qty_available_today = qty_available_today - qty_processed_per_product[line.product_id.id]
|
||||||
line.free_qty_today = free_qty_today - qty_processed_per_product[line.product_id.id]
|
line.free_qty_today = free_qty_today - qty_processed_per_product[line.product_id.id]
|
||||||
line.virtual_available_at_date = virtual_available_at_date - qty_processed_per_product[line.product_id.id]
|
line.virtual_available_at_date = virtual_available_at_date - qty_processed_per_product[line.product_id.id]
|
||||||
|
line.forecast_expected_date = False
|
||||||
if line.product_uom and line.product_id.uom_id and line.product_uom != line.product_id.uom_id:
|
if line.product_uom and line.product_id.uom_id and line.product_uom != line.product_id.uom_id:
|
||||||
line.qty_available_today = line.product_id.uom_id._compute_quantity(line.qty_available_today, line.product_uom)
|
line.qty_available_today = line.product_id.uom_id._compute_quantity(line.qty_available_today, line.product_uom)
|
||||||
line.free_qty_today = line.product_id.uom_id._compute_quantity(line.free_qty_today, line.product_uom)
|
line.free_qty_today = line.product_id.uom_id._compute_quantity(line.free_qty_today, line.product_uom)
|
||||||
@@ -78,7 +90,6 @@ class SaleOrderLine(models.Model):
|
|||||||
remaining = (self - treated)
|
remaining = (self - treated)
|
||||||
remaining.virtual_available_at_date = False
|
remaining.virtual_available_at_date = False
|
||||||
remaining.scheduled_date = False
|
remaining.scheduled_date = False
|
||||||
|
remaining.forecast_expected_date = False
|
||||||
remaining.free_qty_today = False
|
remaining.free_qty_today = False
|
||||||
remaining.qty_available_today = False
|
remaining.qty_available_today = False
|
||||||
# don't unset warehouse as it may be set by hand
|
|
||||||
# remaining.warehouse_id = False
|
|
||||||
|
|||||||
Reference in New Issue
Block a user