[IMP] sale_stock: forecast widget
Add the forecast widget for the sale order line's delivered quantity. task-2058495
This commit is contained in:
@@ -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'])]
|
||||
|
||||
@@ -53,6 +53,12 @@
|
||||
<xpath expr="//field[@name='order_line']/tree/field[@name='analytic_tag_ids']" position="after">
|
||||
<field name="route_id" groups="stock.group_adv_location" options="{'no_create': True}" optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='order_line']/tree/field[@name='qty_delivered']" position="attributes">
|
||||
<attribute name="attrs">{'column_invisible': [('parent.state', 'not in', ['cancel', 'done'])]}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='order_line']/tree/field[@name='qty_delivered']" position="after">
|
||||
<field name="json_forecast" string="Delivered" widget="forecast_widget" attrs="{'column_invisible': [('parent.state', 'in', ['cancel', 'done'])]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user