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

Part stocktake (#4069)

* Remove stat context variables

* Revert "Remove stat context variables"

This reverts commit 0989c308d0.

* Allow longer timeout for image download tests

* Create PartStocktake model

Model for representing stocktake entries against any given part

* Admin interface support for new model

* Adds API endpoint for listing stocktake information

* Bump API version

* Enable filtering and ordering for API endpoint

* Add model to permission group

* Add UI hooks for displaying stocktake data for a particular part

* Fix encoded type for 'quantity' field

* Load stocktake table for part

* Add "stocktake" button

* Add "note" field for stocktake

* Add user information when performing stocktake

* First pass at UI elements for performing stocktake

* Add user information to stocktake table

* Auto-calculate quantity based on available stock items

* add stocktake data as tabular inline (admin)

* js linting

* Add indication that a stock item has not been updated recently

* Display last stocktake information on part page

* js style fix

* Test fix for ongoing CI issues

* Add configurable option for controlling default "delete_on_deplete" behaviour

* Add id values to cells

* Hide action buttons (at least for now)

* Adds refresh button to table

* Add API endpoint to delete or edit stocktake entries

* Adds unit test for API list endpoint

* javascript linting

* More unit testing

* Add Part API filter for stocktake

* Add 'last_stocktake' field to Part model

- Gets filled out automatically when a new PartStocktake instance is created

* Update part table to include last_stocktake date

* Add simple unit test

* Fix test
This commit is contained in:
Oliver
2022-12-31 23:14:43 +11:00
committed by GitHub
parent 4ae278d119
commit ab4e2aa8bb
23 changed files with 803 additions and 22 deletions

View File

@ -20,7 +20,7 @@ from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
StockStatus)
from part.models import (BomItem, BomItemSubstitute, Part, PartCategory,
PartCategoryParameterTemplate, PartParameterTemplate,
PartRelated)
PartRelated, PartStocktake)
from stock.models import StockItem, StockLocation
@ -2779,3 +2779,141 @@ class PartInternalPriceBreakTest(InvenTreeAPITestCase):
with self.assertRaises(Part.DoesNotExist):
p.refresh_from_db()
class PartStocktakeTest(InvenTreeAPITestCase):
"""Unit tests for the part stocktake functionality"""
superuser = False
is_staff = False
fixtures = [
'category',
'part',
'location',
]
def test_list_endpoint(self):
"""Test the list endpoint for the stocktake data"""
url = reverse('api-part-stocktake-list')
self.assignRole('part.view')
# Initially, no stocktake entries
response = self.get(url, expected_code=200)
self.assertEqual(len(response.data), 0)
total = 0
# Create some entries
for p in Part.objects.all():
for n in range(p.pk):
PartStocktake.objects.create(
part=p,
quantity=(n + 1) * 100,
)
total += p.pk
response = self.get(
url,
{
'part': p.pk,
},
expected_code=200,
)
# List by part ID
self.assertEqual(len(response.data), p.pk)
# List all entries
response = self.get(url, {}, expected_code=200)
self.assertEqual(len(response.data), total)
def test_create_stocktake(self):
"""Test that stocktake entries can be created via the API"""
url = reverse('api-part-stocktake-list')
self.assignRole('part.add')
self.assignRole('part.view')
for p in Part.objects.all():
# Initially no stocktake information available
self.assertIsNone(p.latest_stocktake)
note = f"Note {p.pk}"
quantity = p.pk + 5
self.post(
url,
{
'part': p.pk,
'quantity': quantity,
'note': note,
},
expected_code=201,
)
p.refresh_from_db()
stocktake = p.latest_stocktake
self.assertIsNotNone(stocktake)
self.assertEqual(stocktake.quantity, quantity)
self.assertEqual(stocktake.part, p)
self.assertEqual(stocktake.note, note)
def test_edit_stocktake(self):
"""Test that a Stoctake instance can be edited and deleted via the API.
Note that only 'staff' users can perform these actions.
"""
p = Part.objects.all().first()
st = PartStocktake.objects.create(part=p, quantity=10)
url = reverse('api-part-stocktake-detail', kwargs={'pk': st.pk})
self.assignRole('part.view')
# Test we can retrieve via API
self.get(url, expected_code=403)
# Assign staff permission
self.user.is_staff = True
self.user.save()
self.get(url, expected_code=200)
# Try to edit data
self.patch(
url,
{
'note': 'Another edit',
},
expected_code=403
)
# Assign 'edit' role permission
self.assignRole('part.change')
# Try again
self.patch(
url,
{
'note': 'Editing note field again',
},
expected_code=200,
)
# Try to delete
self.delete(url, expected_code=403)
self.assignRole('part.delete')
self.delete(url, expected_code=204)