mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 07:05:41 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		@@ -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 '<a href="' + url + '">' + text + '</a>';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
@@ -455,7 +456,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()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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',
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user