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" %}',