diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py
index 56f10c3352..477023226e 100644
--- a/InvenTree/order/serializers.py
+++ b/InvenTree/order/serializers.py
@@ -5,8 +5,6 @@ JSON serializers for the Order API
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
-from datetime import datetime
-
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError as DjangoValidationError
@@ -138,11 +136,10 @@ class POLineItemSerializer(InvenTreeModelSerializer):
)
)
- # Add an annotated 'overdue' field
queryset = queryset.annotate(
overdue=Case(
- When(Q(order__status__in=PurchaseOrderStatus.OPEN) & order.models.OrderLineItem.OVERDUE_FILTER,
- then=Value(True, output_field=BooleanField()),
+ When(
+ Q(order__status__in=PurchaseOrderStatus.OPEN) & order.models.OrderLineItem.OVERDUE_FILTER, then=Value(True, output_field=BooleanField())
),
default=Value(False, output_field=BooleanField()),
)
@@ -566,6 +563,23 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
class SOLineItemSerializer(InvenTreeModelSerializer):
""" Serializer for a SalesOrderLineItem object """
+ @staticmethod
+ def annotate_queryset(queryset):
+ """
+ Add some extra annotations to this queryset:
+
+ - "Overdue" status (boolean field)
+ """
+
+ queryset = queryset.annotate(
+ overdue=Case(
+ When(
+ Q(order__status__in=SalesOrderStatus.OPEN) & order.models.OrderLineItem.OVERDUE_FILTER, then=Value(True, output_field=BooleanField()),
+ ),
+ default=Value(False, output_field=BooleanField()),
+ )
+ )
+
def __init__(self, *args, **kwargs):
part_detail = kwargs.pop('part_detail', False)
@@ -587,6 +601,8 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True)
+ overdue = serializers.BooleanField(required=False, read_only=True)
+
quantity = InvenTreeDecimalField()
allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
@@ -616,6 +632,7 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
'notes',
'order',
'order_detail',
+ 'overdue',
'part',
'part_detail',
'sale_price',
diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html
index 48b2542752..3676268f5c 100644
--- a/InvenTree/order/templates/order/sales_order_detail.html
+++ b/InvenTree/order/templates/order/sales_order_detail.html
@@ -238,6 +238,7 @@
reference: {},
sale_price: {},
sale_price_currency: {},
+ target_date: {},
notes: {},
},
method: 'POST',
diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js
index 3dfe112381..83d6b92103 100644
--- a/InvenTree/templates/js/translated/order.js
+++ b/InvenTree/templates/js/translated/order.js
@@ -2235,6 +2235,28 @@ function loadSalesOrderLineItemTable(table, options={}) {
return formatter.format(total);
}
},
+ {
+ field: 'target_date',
+ title: '{% trans "Target Date" %}',
+ sortable: true,
+ switchable: true,
+ formatter: function(value, row) {
+ if (row.target_date) {
+ var html = row.target_date;
+
+ if (row.overdue) {
+ html += ``;
+ }
+
+ return html;
+
+ } else if (row.order_detail && row.order_detail.target_date) {
+ return `${row.order_detail.target_date}`;
+ } else {
+ return '-';
+ }
+ }
+ }
];
if (pending) {
@@ -2378,6 +2400,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
reference: {},
sale_price: {},
sale_price_currency: {},
+ target_date: {},
notes: {},
},
title: '{% trans "Edit Line Item" %}',