Added update endpoints for StockItem

- Stocktake
- Take-Stock
This commit is contained in:
Oliver Walters 2017-04-20 22:08:27 +10:00
parent 7efb4c21d3
commit 2c28ef6b3c
4 changed files with 118 additions and 6 deletions

View File

@ -7,6 +7,8 @@ from supplier.models import SupplierPart
from part.models import Part
from InvenTree.models import InvenTreeTree
from datetime import datetime
class StockLocation(InvenTreeTree):
""" Organization tree for StockItem objects
@ -26,7 +28,7 @@ class StockItem(models.Model):
updated = models.DateField(auto_now=True)
# last time the stock was checked / counted
last_checked = models.DateField(blank=True, null=True)
stocktake_date = models.DateField(blank=True, null=True)
review_needed = models.BooleanField(default=False)
@ -59,6 +61,65 @@ class StockItem(models.Model):
# If stock item is incoming, an (optional) ETA field
expected_arrival = models.DateField(null=True, blank=True)
infinite = models.BooleanField(default=False)
def stocktake(self, count):
""" Perform item stocktake.
When the quantity of an item is counted,
record the date of stocktake
"""
count = int(count)
if count < 0 or self.infinite:
return
self.quantity = count
self.stocktake_date = datetime.now().date()
self.save()
def take_stock(self, amount):
""" Take items from stock
This function can be called by initiating a ProjectRun,
or by manually taking the items from the stock location
"""
if self.infinite:
return
amount = int(amount)
if amount < 0:
raise ValueError("Stock amount must be positive")
q = self.quantity - amount
if q < 0:
q = 0
self.quantity = q
self.save()
def add_stock(self, amount):
""" Add items to stock
This function can be called by initiating a ProjectRun,
or by manually adding the items to the stock location
"""
amount = int(amount)
if self.infinite or amount == 0:
return
amount = int(amount)
q = self.quantity + amount
if q < 0:
q = 0
self.quantity = q
self.save()
def __str__(self):
return "{n} x {part} @ {loc}".format(
n=self.quantity,

View File

@ -17,10 +17,22 @@ class StockItemSerializer(serializers.HyperlinkedModelSerializer):
'status',
'notes',
'updated',
'last_checked',
'stocktake_date',
'review_needed',
'expected_arrival')
""" These fields are read-only in this context.
They can be updated by accessing the appropriate API endpoints
"""
read_only_fields = ('stocktake_date', 'quantity',)
class StockQuantitySerializer(serializers.ModelSerializer):
class Meta:
model = StockItem
fields = ('quantity',)
class LocationSerializer(serializers.HyperlinkedModelSerializer):
""" Detailed information about a stock location

View File

@ -1,10 +1,18 @@
from django.conf.urls import url
from django.conf.urls import url, include
from . import views
stock_endpoints = [
url(r'^$', views.StockDetail.as_view(), name='stockitem-detail'),
url(r'^stocktake/?$', views.StockStocktakeEndpoint.as_view(), name='stockitem-stocktake'),
url(r'^add-stock/?$', views.AddStockEndpoint.as_view(), name='stockitem-add-stock'),
]
stock_urls = [
# Detail for a single stock item
url(r'^(?P<pk>[0-9]+)/?$', views.StockDetail.as_view(), name='stockitem-detail'),
url(r'^(?P<pk>[0-9]+)/', include(stock_endpoints)),
# List all stock items, with optional filters
url(r'^\?.*/?$', views.StockList.as_view()),

View File

@ -1,11 +1,12 @@
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
from django_filters import NumberFilter
from rest_framework import generics, permissions
from rest_framework import generics, permissions, response
# from InvenTree.models import FilterChildren
from .models import StockLocation, StockItem, StockTracking
from .serializers import StockItemSerializer, LocationSerializer, StockTrackingSerializer
from .serializers import StockItemSerializer, StockQuantitySerializer
from .serializers import LocationSerializer, StockTrackingSerializer
class StockDetail(generics.RetrieveUpdateDestroyAPIView):
@ -53,6 +54,36 @@ class StockList(generics.ListCreateAPIView):
filter_class = StockFilter
class StockStocktakeEndpoint(generics.UpdateAPIView):
queryset = StockItem.objects.all()
serializer_class = StockQuantitySerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def update(self, request, *args, **kwargs):
object = self.get_object()
object.stocktake(request.data['quantity'])
serializer = self.get_serializer(object)
return response.Response(serializer.data)
class AddStockEndpoint(generics.UpdateAPIView):
queryset = StockItem.objects.all()
serializer_class = StockQuantitySerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def update(self, request, *args, **kwargs):
object = self.get_object()
object.add_stock(request.data['quantity'])
serializer = self.get_serializer(object)
return response.Response(serializer.data)
class LocationDetail(generics.RetrieveUpdateDestroyAPIView):
"""