From 76c86e7b2f54ed9ba2ee3ff88d7ceb35f3765f43 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 7 Jan 2021 23:04:00 +1100 Subject: [PATCH] Calendar view for purchase orders --- InvenTree/InvenTree/urls.py | 1 + InvenTree/order/api.py | 9 +- InvenTree/order/models.py | 43 ++++++- .../templates/order/purchase_orders.html | 112 ++++++++++++++++++ .../order/templates/order/sales_orders.html | 24 +--- InvenTree/templates/base.html | 1 + InvenTree/templates/js/calendar.js | 25 ++++ 7 files changed, 193 insertions(+), 22 deletions(-) create mode 100644 InvenTree/templates/js/calendar.js diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 944c6432b5..79c662182e 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -93,6 +93,7 @@ dynamic_javascript_urls = [ url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'), url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'), url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'), + url(r'^calendar.js', DynamicJsView.as_view(template_name='js/calendar.js'), name='calendar.js'), url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'), url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'), url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'), diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index e240c69861..972ff16f9c 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -107,6 +107,13 @@ class POList(generics.ListCreateAPIView): except (ValueError, SupplierPart.DoesNotExist): pass + # Filter by 'date range' + min_date = params.get('min_date', None) + max_date = params.get('max_date', None) + + if min_date is not None and max_date is not None: + queryset = PurchaseOrder.filterByDate(queryset, min_date, max_date) + return queryset filter_backends = [ @@ -298,7 +305,7 @@ class SOList(generics.ListCreateAPIView): max_date = params.get('max_date', None) if min_date is not None and max_date is not None: - queryset = SalesOrder.filter_interesting_orders(queryset, min_date, max_date) + queryset = SalesOrder.filterByDate(queryset, min_date, max_date) return queryset diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 27bcd4acca..08b88264ae 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -121,6 +121,44 @@ class PurchaseOrder(Order): received_by: User that received the goods """ + @staticmethod + def filterByDate(queryset, min_date, max_date): + """ + Filter by 'minimum and maximum date range' + + - Specified as min_date, max_date + - Both must be specified for filter to be applied + - Determine which "interesting" orders exist bewteen these dates + + To be "interesting": + - A "received" order where the received date lies within the date range + - TODO: A "pending" order where the target date lies within the date range + - TODO: An "overdue" order where the target date is in the past + """ + + date_fmt = '%Y-%m-%d' # ISO format date string + + # Ensure that both dates are valid + try: + min_date = datetime.strptime(str(min_date), date_fmt).date() + max_date = datetime.strptime(str(max_date), date_fmt).date() + except (ValueError, TypeError): + # Date processing error, return queryset unchanged + return queryset + + # Construct a queryset for "received" orders within the range + received = Q(status=PurchaseOrderStatus.COMPLETE) & Q(complete_date__gte=min_date) & Q(complete_date__lte=max_date) + + # TODO - Construct a queryset for "pending" orders within the range + + # TODO - Construct a queryset for "overdue" orders within the range + + flt = received + + queryset = queryset.filter(flt) + + return queryset + def __str__(self): prefix = getSetting('PURCHASEORDER_REFERENCE_PREFIX') @@ -302,7 +340,7 @@ class SalesOrder(Order): OVERDUE_FILTER = Q(status__in=SalesOrderStatus.OPEN) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date()) @staticmethod - def filter_interesting_orders(queryset, min_date, max_date): + def filterByDate(queryset, min_date, max_date): """ Filter by "minimum and maximum date range" @@ -332,7 +370,8 @@ class SalesOrder(Order): # Construct a queryset for "pending" orders within the range pending = Q(status__in=SalesOrderStatus.OPEN) & ~Q(target_date=None) & Q(target_date__gte=min_date) & Q(target_date__lte=max_date) - # Construct a queryset for "overdue" orders within the range + # TODO: Construct a queryset for "overdue" orders within the range + flt = completed | pending queryset = queryset.filter(flt) diff --git a/InvenTree/order/templates/order/purchase_orders.html b/InvenTree/order/templates/order/purchase_orders.html index 347033a888..53502376cb 100644 --- a/InvenTree/order/templates/order/purchase_orders.html +++ b/InvenTree/order/templates/order/purchase_orders.html @@ -1,5 +1,6 @@ {% extends "base.html" %} +{% load inventree_extras %} {% load static %} {% load i18n %} @@ -18,6 +19,12 @@ InvenTree | {% trans "Purchase Orders" %} {% endif %} + +
@@ -27,11 +34,116 @@ InvenTree | {% trans "Purchase Orders" %}
+
+ +{% endblock %} + +{% block js_load %} +{{ block.super }} + + + {% endblock %} {% block js_ready %} {{ block.super }} +$('#purchase-order-calendar').hide(); +$('#view-list').hide(); + +$('#view-calendar').click(function() { + // Hide the list view, show the calendar view + $("#purchase-order-table").hide(); + $("#view-calendar").hide(); + $(".fixed-table-pagination").hide(); + $(".columns-right").hide(); + $(".search").hide(); + $('#filter-list-salesorder').hide(); + + $("#purchase-order-calendar").show(); + $("#view-list").show(); +}); + +$("#view-list").click(function() { + // Hide the calendar view, show the list view + $("#purchase-order-calendar").hide(); + $("#view-list").hide(); + + $(".fixed-table-pagination").show(); + $(".columns-right").show(); + $(".search").show(); + $("#purchase-order-table").show(); + $('#filter-list-salesorder').show(); + $("#view-calendar").show(); +}); + $("#po-create").click(function() { launchModalForm("{% url 'po-create' %}", { diff --git a/InvenTree/order/templates/order/sales_orders.html b/InvenTree/order/templates/order/sales_orders.html index f75f9fa36b..257ee13887 100644 --- a/InvenTree/order/templates/order/sales_orders.html +++ b/InvenTree/order/templates/order/sales_orders.html @@ -12,7 +12,6 @@ InvenTree | {% trans "Sales Orders" %}

{% trans "Sales Orders" %}


-
@@ -34,10 +33,9 @@ InvenTree | {% trans "Sales Orders" %}
+
- - {% endblock %} {% block js_load %} @@ -45,25 +43,12 @@ InvenTree | {% trans "Sales Orders" %} + diff --git a/InvenTree/templates/js/calendar.js b/InvenTree/templates/js/calendar.js new file mode 100644 index 0000000000..861bbe1727 --- /dev/null +++ b/InvenTree/templates/js/calendar.js @@ -0,0 +1,25 @@ +{% load i18n %} + +/** + * Helper functions for calendar display + */ + +function startDate(calendar) { + // Extract the first displayed date on the calendar + return calendar.currentData.dateProfile.activeRange.start.toISOString().split("T")[0]; +} + +function endDate(calendar) { + // Extract the last display date on the calendar + return calendar.currentData.dateProfile.activeRange.end.toISOString().split("T")[0]; +} + +function clearEvents(calendar) { + // Remove all events from the calendar + + var events = calendar.getEvents(); + + events.forEach(function(event) { + event.remove(); + }) +} \ No newline at end of file