diff --git a/InvenTree/order/migrations/0053_salesordershipment.py b/InvenTree/order/migrations/0053_salesordershipment.py index e20a95e3f8..b137e2dea8 100644 --- a/InvenTree/order/migrations/0053_salesordershipment.py +++ b/InvenTree/order/migrations/0053_salesordershipment.py @@ -3,6 +3,9 @@ from django.conf import settings from django.db import migrations, models import django.db.models.deletion + +import order.models + import markdownx.models @@ -19,7 +22,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('shipment_date', models.DateField(blank=True, help_text='Date of shipment', null=True, verbose_name='Shipment Date')), - ('reference', models.CharField(blank=True, help_text='Shipment reference', max_length=100, verbose_name='Reference')), + ('reference', models.CharField(default=order.models.get_next_shipment_number, unique=True, help_text='Shipment reference', max_length=100, verbose_name='Reference')), ('notes', markdownx.models.MarkdownxField(blank=True, help_text='Shipment notes', verbose_name='Notes')), ('checked_by', models.ForeignKey(blank=True, help_text='User who checked this shipment', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Checked By')), ('order', models.ForeignKey(help_text='Sales Order', on_delete=django.db.models.deletion.CASCADE, related_name='shipments', to='order.salesorder', verbose_name='Order')), diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index c6ff6dc5bd..b0b0d82221 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -37,7 +37,7 @@ def get_next_po_number(): """ if PurchaseOrder.objects.count() == 0: - return + return "001" order = PurchaseOrder.objects.exclude(reference=None).last() @@ -66,7 +66,7 @@ def get_next_so_number(): """ if SalesOrder.objects.count() == 0: - return + return "001" order = SalesOrder.objects.exclude(reference=None).last() @@ -107,45 +107,6 @@ class Order(ReferenceIndexingMixin): responsible: User (or group) responsible for managing the order """ - @classmethod - def getNextOrderNumber(cls): - """ - Try to predict the next order-number - """ - - if cls.objects.count() == 0: - return None - - # We will assume that the latest pk has the highest PO number - order = cls.objects.last() - ref = order.reference - - if not ref: - return None - - tries = set() - - tries.add(ref) - - while 1: - new_ref = increment(ref) - - print("Reference:", new_ref) - - if new_ref in tries: - # We are in a looping situation - simply return the original one - return ref - - # Check that the new ref does not exist in the database - if cls.objects.filter(reference=new_ref).exists(): - tries.add(new_ref) - new_ref = increment(new_ref) - - else: - break - - return new_ref - def save(self, *args, **kwargs): self.rebuild_reference_field() @@ -903,6 +864,35 @@ class SalesOrderLineItem(OrderLineItem): return self.allocated_quantity() > self.quantity +def get_next_shipment_number(): + """ + Returns the next available SalesOrderShipment reference number" + """ + + if SalesOrderShipment.objects.count() == 0: + return "001" + + shipment = SalesOrderShipment.objects.exclude(reference=None).last() + + attempts = set([shipment.reference]) + + reference = shipment.reference + + while 1: + reference = increment(reference) + + if reference in attempts: + # Escape infinite recursion + return reference + + if SalesOrderShipment.objects.filter(reference=reference).exists(): + attempts.add(reference) + else: + break + + return reference + + class SalesOrderShipment(models.Model): """ The SalesOrderShipment model represents a physical shipment made against a SalesOrder. @@ -946,9 +936,11 @@ class SalesOrderShipment(models.Model): reference = models.CharField( max_length=100, - blank=True, + blank=False, + unique=True, verbose_name=('Reference'), help_text=_('Shipment reference'), + default=get_next_shipment_number, ) notes = MarkdownxField(