2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-05 13:10:57 +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

@ -372,6 +372,7 @@ class Part(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel):
creation_date: Date that this part was added to the database
creation_user: User who added this part to the database
responsible: User who is responsible for this part (optional)
last_stocktake: Date at which last stocktake was performed for this Part
"""
objects = PartManager()
@ -1004,6 +1005,11 @@ class Part(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel):
responsible = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True, verbose_name=_('Responsible'), related_name='parts_responible')
last_stocktake = models.DateField(
blank=True, null=True,
verbose_name=_('Last Stocktake'),
)
@property
def category_path(self):
"""Return the category path of this Part instance"""
@ -2161,6 +2167,12 @@ class Part(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel):
return params
@property
def latest_stocktake(self):
"""Return the latest PartStocktake object associated with this part (if one exists)"""
return self.stocktakes.order_by('-pk').first()
@property
def has_variants(self):
"""Check if this Part object has variants underneath it."""
@ -2878,6 +2890,66 @@ class PartPricing(models.Model):
)
class PartStocktake(models.Model):
"""Model representing a 'stocktake' entry for a particular Part.
A 'stocktake' is a representative count of available stock:
- Performed on a given date
- Records quantity of part in stock (across multiple stock items)
- Records user information
"""
part = models.ForeignKey(
Part,
on_delete=models.CASCADE,
related_name='stocktakes',
verbose_name=_('Part'),
help_text=_('Part for stocktake'),
)
quantity = models.DecimalField(
max_digits=19, decimal_places=5,
validators=[MinValueValidator(0)],
verbose_name=_('Quantity'),
help_text=_('Total available stock at time of stocktake'),
)
date = models.DateField(
verbose_name=_('Date'),
help_text=_('Date stocktake was performed'),
auto_now_add=True
)
note = models.CharField(
max_length=250,
blank=True,
verbose_name=_('Notes'),
help_text=_('Additional notes'),
)
user = models.ForeignKey(
User, blank=True, null=True,
on_delete=models.SET_NULL,
related_name='part_stocktakes',
verbose_name=_('User'),
help_text=_('User who performed this stocktake'),
)
@receiver(post_save, sender=PartStocktake, dispatch_uid='post_save_stocktake')
def update_last_stocktake(sender, instance, created, **kwargs):
"""Callback function when a PartStocktake instance is created / edited"""
# When a new PartStocktake instance is create, update the last_stocktake date for the Part
if created:
try:
part = instance.part
part.last_stocktake = instance.date
part.save()
except Exception:
pass
class PartAttachment(InvenTreeAttachment):
"""Model for storing file attachments against a Part object."""