mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
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:
parent
397419f365
commit
98d87c84e3
@ -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
|
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
|
v113 -> 2023-05-13 : https://github.com/inventree/InvenTree/pull/4800
|
||||||
- Adds API endpoints for scrapping a build output
|
- Adds API endpoints for scrapping a build output
|
||||||
|
|
||||||
|
@ -1020,6 +1020,15 @@ class SalesOrderShipmentFilter(rest_filters.FilterSet):
|
|||||||
else:
|
else:
|
||||||
return queryset.filter(shipment_date=None)
|
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):
|
class SalesOrderShipmentList(ListCreateAPI):
|
||||||
"""API list endpoint for SalesOrderShipment model."""
|
"""API list endpoint for SalesOrderShipment model."""
|
||||||
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
@ -1406,6 +1406,12 @@ class SalesOrderShipment(InvenTreeNotesMixin, MetadataMixin, models.Model):
|
|||||||
help_text=_('Date of shipment'),
|
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(
|
checked_by = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
on_delete=models.SET_NULL,
|
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 True if this shipment has already been completed"""
|
||||||
return self.shipment_date is not None
|
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):
|
def check_can_complete(self, raise_error=True):
|
||||||
"""Check if this shipment is able to be completed"""
|
"""Check if this shipment is able to be completed"""
|
||||||
try:
|
try:
|
||||||
@ -1508,6 +1518,12 @@ class SalesOrderShipment(InvenTreeNotesMixin, MetadataMixin, models.Model):
|
|||||||
if link is not None:
|
if link is not None:
|
||||||
self.link = link
|
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()
|
self.save()
|
||||||
|
|
||||||
trigger_event('salesordershipment.completed', id=self.pk)
|
trigger_event('salesordershipment.completed', id=self.pk)
|
||||||
|
@ -965,6 +965,7 @@ class SalesOrderShipmentSerializer(InvenTreeModelSerializer):
|
|||||||
'order_detail',
|
'order_detail',
|
||||||
'allocations',
|
'allocations',
|
||||||
'shipment_date',
|
'shipment_date',
|
||||||
|
'delivery_date',
|
||||||
'checked_by',
|
'checked_by',
|
||||||
'reference',
|
'reference',
|
||||||
'tracking_number',
|
'tracking_number',
|
||||||
@ -988,6 +989,7 @@ class SalesOrderShipmentCompleteSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
'shipment_date',
|
'shipment_date',
|
||||||
|
'delivery_date',
|
||||||
'tracking_number',
|
'tracking_number',
|
||||||
'invoice_number',
|
'invoice_number',
|
||||||
'link',
|
'link',
|
||||||
@ -1034,6 +1036,7 @@ class SalesOrderShipmentCompleteSerializer(serializers.ModelSerializer):
|
|||||||
invoice_number=data.get('invoice_number', shipment.invoice_number),
|
invoice_number=data.get('invoice_number', shipment.invoice_number),
|
||||||
link=data.get('link', shipment.link),
|
link=data.get('link', shipment.link),
|
||||||
shipment_date=shipment_date,
|
shipment_date=shipment_date,
|
||||||
|
delivery_date=data.get('delivery_date', shipment.delivery_date),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1829,6 +1829,7 @@ class SalesOrderAllocateTest(OrderTest):
|
|||||||
'link': 'http://test.com/link.html',
|
'link': 'http://test.com/link.html',
|
||||||
'tracking_number': 'TRK12345',
|
'tracking_number': 'TRK12345',
|
||||||
'shipment_date': '2020-12-05',
|
'shipment_date': '2020-12-05',
|
||||||
|
'delivery_date': '2023-12-05',
|
||||||
},
|
},
|
||||||
expected_code=201,
|
expected_code=201,
|
||||||
)
|
)
|
||||||
@ -1839,6 +1840,48 @@ class SalesOrderAllocateTest(OrderTest):
|
|||||||
self.assertEqual(self.shipment.tracking_number, 'TRK12345')
|
self.assertEqual(self.shipment.tracking_number, 'TRK12345')
|
||||||
self.assertEqual(self.shipment.invoice_number, 'INV01234')
|
self.assertEqual(self.shipment.invoice_number, 'INV01234')
|
||||||
self.assertEqual(self.shipment.link, 'http://test.com/link.html')
|
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):
|
def test_sales_order_shipment_list(self):
|
||||||
"""Test the SalesOrderShipment list API endpoint"""
|
"""Test the SalesOrderShipment list API endpoint"""
|
||||||
|
@ -257,6 +257,13 @@ class SalesOrderTest(TestCase):
|
|||||||
# Shipment should have default reference of '1'
|
# Shipment should have default reference of '1'
|
||||||
self.assertEqual('1', order_2.pending_shipments()[0].reference)
|
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):
|
def test_overdue_notification(self):
|
||||||
"""Test overdue sales order notification"""
|
"""Test overdue sales order notification"""
|
||||||
|
|
||||||
|
@ -209,6 +209,9 @@ function salesOrderShipmentFields(options={}) {
|
|||||||
},
|
},
|
||||||
link: {
|
link: {
|
||||||
icon: 'fa-link',
|
icon: 'fa-link',
|
||||||
|
},
|
||||||
|
delivery_date: {
|
||||||
|
icon: 'fa-calendar-check',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -298,7 +301,11 @@ function completeSalesOrderShipment(shipment_id, options={}) {
|
|||||||
link: {
|
link: {
|
||||||
value: shipment.link,
|
value: shipment.link,
|
||||||
icon: 'fa-link',
|
icon: 'fa-link',
|
||||||
}
|
},
|
||||||
|
delivery_date: {
|
||||||
|
value: shipment.delivery_date,
|
||||||
|
icon: 'fa-calendar-check',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
preFormContent: html,
|
preFormContent: html,
|
||||||
confirm: true,
|
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',
|
field: 'tracking_number',
|
||||||
title: '{% trans "Tracking" %}',
|
title: '{% trans "Tracking" %}',
|
||||||
|
Loading…
Reference in New Issue
Block a user