From 0d462389b9472d40448543ffd45beb5b1a014a35 Mon Sep 17 00:00:00 2001 From: Daniel Pervan Date: Tue, 19 Jan 2021 12:00:30 +0100 Subject: [PATCH 1/3] Fix misspelled query filter method name --- InvenTree/order/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 84f6aeb6f0..ff159fce0c 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -455,7 +455,7 @@ class SalesOrder(Order): """ query = SalesOrder.objects.filter(pk=self.pk) - query = query.filer(SalesOrder.OVERDUE_FILTER) + query = query.filter(SalesOrder.OVERDUE_FILTER) return query.exists() From 82e6b87e1cac21436c195cd77943e30b6ff2caee Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 20 Jan 2021 07:49:14 +1100 Subject: [PATCH 2/3] Adds unit testing for order overdue status --- InvenTree/build/models.py | 15 ++++++--------- InvenTree/build/tests.py | 19 +++++++++++++++++++ InvenTree/order/models.py | 1 + InvenTree/order/test_sales_order.py | 22 ++++++++++++++++++++++ InvenTree/order/tests.py | 22 ++++++++++++++++++++++ 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 10b3b00259..c1d4aa8026 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -225,22 +225,19 @@ class Build(MPTTModel): blank=True, help_text=_('Extra build notes') ) + @property def is_overdue(self): """ Returns true if this build is "overdue": - - Not completed - - Target date is "in the past" + Makes use of the OVERDUE_FILTER to avoid code duplication """ - # Cannot be deemed overdue if target_date is not set - if self.target_date is None: - return False - - today = datetime.now().date() - - return self.active and self.target_date < today + query = Build.objects.filter(pk=self.pk) + query = query.filter(Build.OVERDUE_FILTER) + return query.exists() + @property def active(self): """ diff --git a/InvenTree/build/tests.py b/InvenTree/build/tests.py index cb1881e507..2ac571a726 100644 --- a/InvenTree/build/tests.py +++ b/InvenTree/build/tests.py @@ -10,6 +10,7 @@ from rest_framework.test import APITestCase from rest_framework import status import json +from datetime import datetime, timedelta from .models import Build from stock.models import StockItem @@ -70,6 +71,24 @@ class BuildTestSimple(TestCase): self.assertEqual(b2.status, BuildStatus.COMPLETE) + def test_overdue(self): + """ + Test overdue status functionality + """ + + today = datetime.now().date() + + build = Build.objects.get(pk=1) + self.assertFalse(build.is_overdue) + + build.target_date = today - timedelta(days=1) + build.save() + self.assertTrue(build.is_overdue) + + build.target_date = today + timedelta(days=80) + build.save() + self.assertFalse(build.is_overdue) + def test_is_active(self): b1 = Build.objects.get(pk=1) b2 = Build.objects.get(pk=2) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index ff159fce0c..32f25a78cc 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -272,6 +272,7 @@ class PurchaseOrder(Order): self.complete_date = datetime.now().date() self.save() + @property def is_overdue(self): """ Returns True if this PurchaseOrder is "overdue" diff --git a/InvenTree/order/test_sales_order.py b/InvenTree/order/test_sales_order.py index 5eb350575e..c619aec5bc 100644 --- a/InvenTree/order/test_sales_order.py +++ b/InvenTree/order/test_sales_order.py @@ -5,6 +5,8 @@ from django.test import TestCase from django.core.exceptions import ValidationError from django.db.utils import IntegrityError +from datetime import datetime, timedelta + from company.models import Company from stock.models import StockItem from order.models import SalesOrder, SalesOrderLineItem, SalesOrderAllocation @@ -40,6 +42,26 @@ class SalesOrderTest(TestCase): # Create a line item self.line = SalesOrderLineItem.objects.create(quantity=50, order=self.order, part=self.part) + def test_overdue(self): + """ + Tests for overdue functionality + """ + + today = datetime.now().date() + + # By default, order is *not* overdue as the target date is not set + self.assertFalse(self.order.is_overdue) + + # Set target date in the past + self.order.target_date = today - timedelta(days=5) + self.order.save() + self.assertTrue(self.order.is_overdue) + + # Set target date in the future + self.order.target_date = today + timedelta(days=5) + self.order.save() + self.assertFalse(self.order.is_overdue) + def test_empty_order(self): self.assertEqual(self.line.quantity, 50) self.assertEqual(self.line.allocated_quantity(), 0) diff --git a/InvenTree/order/tests.py b/InvenTree/order/tests.py index 7f60b1445b..ed6a4ebb6a 100644 --- a/InvenTree/order/tests.py +++ b/InvenTree/order/tests.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime, timedelta + from django.test import TestCase import django.core.exceptions as django_exceptions @@ -37,6 +41,24 @@ class OrderTest(TestCase): self.assertEqual(str(line), "100 x ACME0001 from ACME (for PO0001 - ACME)") + def test_overdue(self): + """ + Test overdue status functionality + """ + + today = datetime.now().date() + + order = PurchaseOrder.objects.get(pk=1) + self.assertFalse(order.is_overdue) + + order.target_date = today - timedelta(days=5) + order.save() + self.assertTrue(order.is_overdue) + + order.target_date = today + timedelta(days=1) + order.save() + self.assertFalse(order.is_overdue) + def test_increment(self): next_ref = PurchaseOrder.getNextOrderNumber() From 69362ab960f26ae97e083d3b832f8ff6388da61d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 20 Jan 2021 18:04:08 +1100 Subject: [PATCH 3/3] Display link column in part table --- .../static/script/inventree/tables.js | 26 +++++++++++++++++-- InvenTree/templates/js/part.js | 14 ++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/static/script/inventree/tables.js b/InvenTree/InvenTree/static/script/inventree/tables.js index a40eb37285..21f9160758 100644 --- a/InvenTree/InvenTree/static/script/inventree/tables.js +++ b/InvenTree/InvenTree/static/script/inventree/tables.js @@ -8,11 +8,33 @@ function deleteButton(url, text='Delete') { } -function renderLink(text, url) { - if (text === '' || url === '') { +function renderLink(text, url, options={}) { + if (url == null || url === '') { return text; } + var max_length = options.max_length || -1; + + var remove_http = options.remove_http || false; + + if (remove_http) { + if (text.startsWith('http://')) { + text = text.slice(7); + } else if (text.startsWith('https://')) { + text = text.slice(8); + } + } + + // Shorten the displayed length if required + if ((max_length > 0) && (text.length > max_length)) { + var slice_length = (max_length - 3) / 2; + + var text_start = text.slice(0, slice_length); + var text_end = text.slice(-slice_length); + + text = `${text_start}...${text_end}`; + } + return '' + text + ''; } diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index e0f6a491f6..c9f59ab4eb 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -446,6 +446,20 @@ function loadPartTable(table, url, options={}) { } }); + columns.push({ + field: 'link', + title: '{% trans "Link" %}', + formatter: function(value, row, index, field) { + return renderLink( + value, value, + { + max_length: 32, + remove_http: true, + } + ); + } + }); + $(table).inventreeTable({ url: url, sortName: 'name',