2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 12:35:46 +00:00

Feature: Supplier part pack size (#3644)

* Adds 'pack_size' field to SupplierPart model

* Edit pack_size for SupplierPart via API

* Display pack size in supplier part page template

* Improve table ordering for SupplierPart table

* Fix for API filtering

- Need to use custom filter class

* Adds functionality to duplicate an existing SupplierPart

* Bump API version number

* Display annotation of pack size in purchase order line item table

* Display additional information in part purchase order table

* Add UOM to purchase order table

* Improve receive items functionality

* Indicate quantity which will be received in modal form

* Update the received quantity as the user changes the value

* Take  the pack_size into account when receiving line items

* Take supplierpart pack size into account when receiving line items

* Add "pack size" column to purchase order line item table

* Tweak supplier part table

* Update 'on_order' queryset annotation to take pack_size into account

- May god have mercy on my soul

* Adds a unit test to validate that the on_order queryset annotation is working as expected

* Update Part.on_order method to take pack_size into account

- Check in existing unit test also

* Fix existing unit tests

- Previous unit test was actually in error
- Logic for calculating "on_order" was broked

* More unit tests for receiving items against a purchase order

* Allow pack_size < 1

* Display pack size when adding / editing PurchaseOrderLineItem

* Fix bug in part purchase order table

* Update part purchase order table again

* Exclude notificationmessage when exporting dataset

* Also display pack size when ordering parts from secondary form

* javascript linting

* Change user facing strings to "Pack Quantity"
This commit is contained in:
Oliver
2022-09-08 09:49:14 +10:00
committed by GitHub
parent 890c998420
commit 198ac9b275
17 changed files with 567 additions and 60 deletions

View File

@ -1,5 +1,7 @@
"""Unit tests for the various part API endpoints"""
from random import randint
from django.urls import reverse
import PIL
@ -9,7 +11,7 @@ from rest_framework.test import APIClient
import build.models
import order.models
from common.models import InvenTreeSetting
from company.models import Company
from company.models import Company, SupplierPart
from InvenTree.api_tester import InvenTreeAPITestCase
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
StockStatus)
@ -1676,6 +1678,110 @@ class PartAPIAggregationTest(InvenTreeAPITestCase):
self.assertEqual(part.total_stock, 91)
self.assertEqual(part.available_stock, 56)
def test_on_order(self):
"""Test that the 'on_order' queryset annotation works as expected.
This queryset annotation takes into account any outstanding line items for active orders,
and should also use the 'pack_size' of the supplier part objects.
"""
supplier = Company.objects.create(
name='Paint Supplies',
description='A supplier of paints',
is_supplier=True
)
# First, create some parts
paint = PartCategory.objects.create(
parent=None,
name="Paint",
description="Paints and such",
)
for color in ['Red', 'Green', 'Blue', 'Orange', 'Yellow']:
p = Part.objects.create(
category=paint,
units='litres',
name=f"{color} Paint",
description=f"Paint which is {color} in color"
)
# Create multiple supplier parts in different sizes
for pk_sz in [1, 10, 25, 100]:
sp = SupplierPart.objects.create(
part=p,
supplier=supplier,
SKU=f"PNT-{color}-{pk_sz}L",
pack_size=pk_sz,
)
self.assertEqual(p.supplier_parts.count(), 4)
# Check that we have the right base data to start with
self.assertEqual(paint.parts.count(), 5)
self.assertEqual(supplier.supplied_parts.count(), 20)
supplier_parts = supplier.supplied_parts.all()
# Create multiple orders
for _ii in range(5):
po = order.models.PurchaseOrder.objects.create(
supplier=supplier,
description='ordering some paint',
)
# Order an assortment of items
for sp in supplier_parts:
# Generate random quantity to order
quantity = randint(10, 20)
# Mark up to half of the quantity as received
received = randint(0, quantity // 2)
# Add a line item
item = order.models.PurchaseOrderLineItem.objects.create(
part=sp,
order=po,
quantity=quantity,
received=received,
)
# Now grab a list of parts from the API
response = self.get(
reverse('api-part-list'),
{
'category': paint.pk,
},
expected_code=200,
)
# Check that the correct number of items have been returned
self.assertEqual(len(response.data), 5)
for item in response.data:
# Calculate the 'ordering' quantity from first principles
p = Part.objects.get(pk=item['pk'])
on_order = 0
for sp in p.supplier_parts.all():
for line_item in sp.purchase_order_line_items.all():
po = line_item.order
if po.status in PurchaseOrderStatus.OPEN:
remaining = line_item.quantity - line_item.received
if remaining > 0:
on_order += remaining * sp.pack_size
# The annotated quantity must be equal to the hand-calculated quantity
self.assertEqual(on_order, item['ordering'])
# The annotated quantity must also match the part.on_order quantity
self.assertEqual(on_order, p.on_order)
class BomItemTest(InvenTreeAPITestCase):
"""Unit tests for the BomItem API."""