Shipment delivery date (#4825)

* Add delivery date setting to Shipment model

* Add delivery_date to serializer

* Correct test for is_delivered

* Add relevant fields to API and forms

* Add test

* Increment API version

* Move migration file because of conflict
This commit is contained in:
miggland 2023-05-16 13:28:09 +02:00 committed by GitHub
parent 397419f365
commit 98d87c84e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 1 deletions

View File

@ -7,6 +7,9 @@ INVENTREE_API_VERSION = 113
"""
Increment this API version number whenever there is a significant change to the API that any clients need to know about
v114 -> 2023-05-16 : https://github.com/inventree/InvenTree/pull/4825
- Adds "delivery_date" to shipments
v113 -> 2023-05-13 : https://github.com/inventree/InvenTree/pull/4800
- Adds API endpoints for scrapping a build output

View File

@ -1020,6 +1020,15 @@ class SalesOrderShipmentFilter(rest_filters.FilterSet):
else:
return queryset.filter(shipment_date=None)
delivered = rest_filters.BooleanFilter(label='delivered', method='filter_delivered')
def filter_delivered(self, queryset, name, value):
"""Filter SalesOrder list by 'delivered' status (boolean)"""
if str2bool(value):
return queryset.exclude(delivery_date=None)
else:
return queryset.filter(delivery_date=None)
class SalesOrderShipmentList(ListCreateAPI):
"""API list endpoint for SalesOrderShipment model."""

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.19 on 2023-05-13 06:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('order', '0094_auto_20230514_2331'),
]
operations = [
migrations.AddField(
model_name='salesordershipment',
name='delivery_date',
field=models.DateField(blank=True, help_text='Date of delivery of shipment', null=True, verbose_name='Delivery Date'),
),
]

View File

@ -1406,6 +1406,12 @@ class SalesOrderShipment(InvenTreeNotesMixin, MetadataMixin, models.Model):
help_text=_('Date of shipment'),
)
delivery_date = models.DateField(
null=True, blank=True,
verbose_name=_('Delivery Date'),
help_text=_('Date of delivery of shipment'),
)
checked_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
@ -1449,6 +1455,10 @@ class SalesOrderShipment(InvenTreeNotesMixin, MetadataMixin, models.Model):
"""Return True if this shipment has already been completed"""
return self.shipment_date is not None
def is_delivered(self):
"""Return True if this shipment has already been delivered"""
return self.delivery_date is not None
def check_can_complete(self, raise_error=True):
"""Check if this shipment is able to be completed"""
try:
@ -1508,6 +1518,12 @@ class SalesOrderShipment(InvenTreeNotesMixin, MetadataMixin, models.Model):
if link is not None:
self.link = link
# Was a delivery date provided?
delivery_date = kwargs.get('delivery_date', None)
if delivery_date is not None:
self.delivery_date = delivery_date
self.save()
trigger_event('salesordershipment.completed', id=self.pk)

View File

@ -965,6 +965,7 @@ class SalesOrderShipmentSerializer(InvenTreeModelSerializer):
'order_detail',
'allocations',
'shipment_date',
'delivery_date',
'checked_by',
'reference',
'tracking_number',
@ -988,6 +989,7 @@ class SalesOrderShipmentCompleteSerializer(serializers.ModelSerializer):
fields = [
'shipment_date',
'delivery_date',
'tracking_number',
'invoice_number',
'link',
@ -1034,6 +1036,7 @@ class SalesOrderShipmentCompleteSerializer(serializers.ModelSerializer):
invoice_number=data.get('invoice_number', shipment.invoice_number),
link=data.get('link', shipment.link),
shipment_date=shipment_date,
delivery_date=data.get('delivery_date', shipment.delivery_date),
)

View File

@ -1829,6 +1829,7 @@ class SalesOrderAllocateTest(OrderTest):
'link': 'http://test.com/link.html',
'tracking_number': 'TRK12345',
'shipment_date': '2020-12-05',
'delivery_date': '2023-12-05',
},
expected_code=201,
)
@ -1839,6 +1840,48 @@ class SalesOrderAllocateTest(OrderTest):
self.assertEqual(self.shipment.tracking_number, 'TRK12345')
self.assertEqual(self.shipment.invoice_number, 'INV01234')
self.assertEqual(self.shipment.link, 'http://test.com/link.html')
self.assertEqual(self.shipment.delivery_date, datetime(2023, 12, 5).date())
self.assertTrue(self.shipment.is_delivered())
def test_shipment_deliverydate(self):
"""Test delivery date functions via API."""
url = reverse('api-so-shipment-detail', kwargs={'pk': self.shipment.pk})
# Attempt remove delivery_date from shipment
response = self.patch(
url,
{
'delivery_date': None,
},
expected_code=200,
)
# Shipment should not be marked as delivered
self.assertFalse(self.shipment.is_delivered())
# Attempt to set delivery date
response = self.patch(
url,
{
'delivery_date': 'asfasd',
},
expected_code=400,
)
self.assertIn('Date has wrong format', str(response.data))
response = self.patch(
url,
{
'delivery_date': '2023-05-15',
},
expected_code=200,
)
self.shipment.refresh_from_db()
# Shipment should now be marked as delivered
self.assertTrue(self.shipment.is_delivered())
self.assertEqual(self.shipment.delivery_date, datetime(2023, 5, 15).date())
def test_sales_order_shipment_list(self):
"""Test the SalesOrderShipment list API endpoint"""

View File

@ -257,6 +257,13 @@ class SalesOrderTest(TestCase):
# Shipment should have default reference of '1'
self.assertEqual('1', order_2.pending_shipments()[0].reference)
def test_shipment_delivery(self):
"""Test the shipment delivery settings"""
# Shipment delivery date should be empty before setting date
self.assertIsNone(self.shipment.delivery_date)
self.assertFalse(self.shipment.is_delivered())
def test_overdue_notification(self):
"""Test overdue sales order notification"""

View File

@ -209,6 +209,9 @@ function salesOrderShipmentFields(options={}) {
},
link: {
icon: 'fa-link',
},
delivery_date: {
icon: 'fa-calendar-check',
}
};
@ -298,7 +301,11 @@ function completeSalesOrderShipment(shipment_id, options={}) {
link: {
value: shipment.link,
icon: 'fa-link',
}
},
delivery_date: {
value: shipment.delivery_date,
icon: 'fa-calendar-check',
},
},
preFormContent: html,
confirm: true,
@ -979,6 +986,18 @@ function loadSalesOrderShipmentTable(table, options={}) {
}
}
},
{
field: 'delivery_date',
title: '{% trans "Delivery Date" %}',
sortable: true,
formatter: function(value, row) {
if (value) {
return renderDate(value);
} else {
return '<em>{% trans "Unknown" %}</em>';
}
}
},
{
field: 'tracking_number',
title: '{% trans "Tracking" %}',