2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-09-23 11:00:18 +00:00

Add Expiry Date on Receive Line Item (#8867)

* Add expiry on line item receive from PO

* add backend test

* reset pre-commit

* increment inventree api version

* use None as default expiry date

* check global setting STOCK_ENABLE_EXPIRY

* check for default expiry in line item receive

* use dayjs

---------

Co-authored-by: Matthias Mair <code@mjmair.com>
This commit is contained in:
Jacob Felknor
2025-01-11 19:56:30 -07:00
committed by GitHub
parent c75630d1bd
commit e8c1417b15
7 changed files with 82 additions and 4 deletions

View File

@@ -1,13 +1,17 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 298
INVENTREE_API_VERSION = 299
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v299 - 2025-01-10 - https://github.com/inventree/InvenTree/pull/8867
- Adds 'expiry_date' field to the PurchaseOrderReceive API endpoint
- Adds 'default_expiry` field to the PartBriefSerializer, affecting API endpoints which use it
v298 - 2025-01-07 - https://github.com/inventree/InvenTree/pull/8848
- Adds 'created_by' field to PurchaseOrder API endpoints
- Adds 'created_by' field to SalesOrder API endpoints

View File

@@ -410,6 +410,7 @@ class PurchaseOrderReceive(PurchaseOrderContextMixin, CreateAPI):
- supplier_part: pk value of the supplier part
- quantity: quantity to receive
- status: stock item status
- expiry_date: stock item expiry date (optional)
- location: destination for stock item (optional)
- batch_code: the batch code for this stock item
- serial_numbers: serial numbers for this stock item

View File

@@ -819,6 +819,9 @@ class PurchaseOrder(TotalPriceMixin, Order):
# Extract optional batch code for the new stock item
batch_code = kwargs.get('batch_code', '')
# Extract optional expiry date for the new stock item
expiry_date = kwargs.get('expiry_date')
# Extract optional list of serial numbers
serials = kwargs.get('serials')
@@ -882,6 +885,7 @@ class PurchaseOrder(TotalPriceMixin, Order):
purchase_order=self,
status=status,
batch=batch_code,
expiry_date=expiry_date,
packaging=packaging,
serial=sn,
purchase_price=unit_purchase_price,

View File

@@ -717,6 +717,7 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer):
'quantity',
'status',
'batch_code',
'expiry_date',
'serial_numbers',
'packaging',
'note',
@@ -765,6 +766,13 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer):
allow_blank=True,
)
expiry_date = serializers.DateField(
label=_('Expiry Date'),
help_text=_('Enter expiry date for incoming stock items'),
required=False,
default=None,
)
serial_numbers = serializers.CharField(
label=_('Serial Numbers'),
help_text=_('Enter serial numbers for incoming stock items'),
@@ -967,6 +975,7 @@ class PurchaseOrderReceiveSerializer(serializers.Serializer):
status=item['status'],
barcode=item.get('barcode', ''),
batch_code=item.get('batch_code', ''),
expiry_date=item.get('expiry_date', None),
packaging=item.get('packaging', ''),
serials=item.get('serials', None),
notes=item.get('note', None),

View File

@@ -3,7 +3,7 @@
import base64
import io
import json
from datetime import datetime, timedelta
from datetime import date, datetime, timedelta
from django.core.exceptions import ValidationError
from django.db import connection
@@ -1061,12 +1061,20 @@ class PurchaseOrderReceiveTest(OrderTest):
self.assertEqual(line_1.received, 0)
self.assertEqual(line_2.received, 50)
one_week_from_today = date.today() + timedelta(days=7)
valid_data = {
'items': [
{'line_item': 1, 'quantity': 50, 'barcode': 'MY-UNIQUE-BARCODE-123'},
{
'line_item': 1,
'quantity': 50,
'expiry_date': one_week_from_today.strftime(r'%Y-%m-%d'),
'barcode': 'MY-UNIQUE-BARCODE-123',
},
{
'line_item': 2,
'quantity': 200,
'expiry_date': one_week_from_today.strftime(r'%Y-%m-%d'),
'location': 2, # Explicit location
'barcode': 'MY-UNIQUE-BARCODE-456',
},
@@ -1111,6 +1119,10 @@ class PurchaseOrderReceiveTest(OrderTest):
self.assertEqual(stock_1.last().location.pk, 1)
self.assertEqual(stock_2.last().location.pk, 2)
# Expiry dates should be set
self.assertEqual(stock_1.last().expiry_date, one_week_from_today)
self.assertEqual(stock_2.last().expiry_date, one_week_from_today)
# Barcodes should have been assigned to the stock items
self.assertTrue(
StockItem.objects.filter(barcode_data='MY-UNIQUE-BARCODE-123').exists()

View File

@@ -352,6 +352,7 @@ class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
'barcode_hash',
'category_default_location',
'default_location',
'default_expiry',
'name',
'revision',
'full_name',