diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index aa4a7dc2879..593cbf2968a 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -8,8 +8,11 @@ from collections import defaultdict from odoo import api, fields, models, _ from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_compare, float_round +from odoo.tools.float_utils import float_repr +from odoo.tools.misc import format_date from odoo.exceptions import UserError + _logger = logging.getLogger(__name__) @@ -267,6 +270,7 @@ class SaleOrderLine(models.Model): qty_to_deliver = fields.Float(compute='_compute_qty_to_deliver') is_mto = fields.Boolean(compute='_compute_is_mto') display_qty_widget = fields.Boolean(compute='_compute_qty_to_deliver') + json_forecast = fields.Char('JSON data for the forecast widget', compute='_compute_json_forecast') @api.depends('product_id', 'product_uom_qty', 'qty_delivered', 'state') def _compute_qty_to_deliver(self): @@ -354,6 +358,35 @@ class SaleOrderLine(models.Model): else: line.is_mto = False + @api.depends('move_ids', 'order_id.expected_date', 'qty_delivered') + def _compute_json_forecast(self): + self.json_forecast = False + if not any(self._ids): + # onchange + return + # compute + precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') + for so_line in self: + if any(so_line.move_ids.filtered(lambda move: move.state in ['done'])): + qty_delivered = float_repr(so_line.qty_delivered, precision) + so_line.json_forecast = json.dumps({'reservedAvailability': qty_delivered}) + else: + # For waiting deliveries, take the info from the report line. + delivery = so_line.move_ids.picking_id.filtered(lambda picking: picking.state in ['confirmed', 'waiting']) + if delivery.exists(): + moves_to_process = so_line.move_ids.filtered(lambda move: move.id in delivery.move_lines.ids and move.state not in ['cancel', 'done']) + if moves_to_process.exists(): + so_line.json_forecast = moves_to_process[0].json_forecast + else: + # For assigned deliveries, take the delivery's date. + delivery = so_line.move_ids.picking_id.filtered(lambda picking: picking.state == 'assigned') + if delivery.exists(): + date_expected = delivery.scheduled_date + so_line.json_forecast = json.dumps({ + 'expectedDate': format_date(self.env, date_expected), + 'isLate': date_expected > so_line.order_id.expected_date, + }) + @api.depends('product_id') def _compute_qty_delivered_method(self): """ Stock module compute delivered qty for product [('type', 'in', ['consu', 'product'])] diff --git a/addons/sale_stock/views/sale_order_views.xml b/addons/sale_stock/views/sale_order_views.xml index 88d5d56bb70..e4b4700def7 100644 --- a/addons/sale_stock/views/sale_order_views.xml +++ b/addons/sale_stock/views/sale_order_views.xml @@ -53,6 +53,12 @@ + + {'column_invisible': [('parent.state', 'not in', ['cancel', 'done'])]} + + + +