From 6f31e3447c803611bbd677d7decd652b16d2f92a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 14 Apr 2017 15:49:10 +1000 Subject: [PATCH] Added /track/ API --- InvenTree/InvenTree/urls.py | 14 +++---- InvenTree/track/models.py | 5 +-- InvenTree/track/serializers.py | 27 ++++++++++++ InvenTree/track/urls.py | 18 ++++++-- InvenTree/track/views.py | 75 ++++++++++++++++++++++++++++++++-- 5 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 InvenTree/track/serializers.py diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index d750b6388c..5ab4076fad 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -17,13 +17,13 @@ def Inventree404(self): urlpatterns = [ - url(r'^stock/', include('stock.urls')), - url(r'^part/', include('part.urls')), - url(r'^supplier/', include('supplier.urls')), - url(r'^track/', include('track.urls')), - url(r'^project/', include('project.urls')), - url(r'^admin/', admin.site.urls), - url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')), + url(r'^stock/?', include('stock.urls')), + url(r'^part/?', include('part.urls')), + url(r'^supplier/?', include('supplier.urls')), + url(r'^track/?', include('track.urls')), + url(r'^project/?', include('project.urls')), + url(r'^admin/?', admin.site.urls), + url(r'^auth/?', include('rest_framework.urls', namespace='rest_framework')), # Any other URL url(r'', Inventree404) diff --git a/InvenTree/track/models.py b/InvenTree/track/models.py index 4fed0fdd60..389a0bea09 100644 --- a/InvenTree/track/models.py +++ b/InvenTree/track/models.py @@ -57,7 +57,6 @@ class PartTrackingInfo(models.Model): a new PartTrackingInfo object should be created. """ - part = models.ForeignKey(UniquePart, on_delete=models.CASCADE) - date = models.DateField(auto_now_add=True, - editable=False) + part = models.ForeignKey(UniquePart, on_delete=models.CASCADE, related_name='tracking_info') + date = models.DateField(auto_now_add=True, editable=False) notes = models.CharField(max_length=500) diff --git a/InvenTree/track/serializers.py b/InvenTree/track/serializers.py new file mode 100644 index 0000000000..6e958acbf3 --- /dev/null +++ b/InvenTree/track/serializers.py @@ -0,0 +1,27 @@ +from rest_framework import serializers + +from .models import UniquePart, PartTrackingInfo + + +class UniquePartSerializer(serializers.ModelSerializer): + + tracking_info = serializers.PrimaryKeyRelatedField(many=True, read_only=True) + + class Meta: + model = UniquePart + fields = ['pk', + 'part', + 'revision', + 'creation_date', + 'serial', + 'createdBy', + 'customer', + 'status', + 'tracking_info'] + + +class PartTrackingInfoSerializer(serializers.ModelSerializer): + + class Meta: + model = PartTrackingInfo + fields = '__all__' diff --git a/InvenTree/track/urls.py b/InvenTree/track/urls.py index 9cb3403af4..447c1c3d38 100644 --- a/InvenTree/track/urls.py +++ b/InvenTree/track/urls.py @@ -1,7 +1,19 @@ -from django.conf.urls import url +from django.conf.urls import url, include from . import views -urlpatterns = [ - url(r'^$', views.index, name='index') +infopatterns = [ + url(r'^(?P[0-9]+)/?$', views.PartTrackingDetail.as_view()), + + url(r'^\?*[^/]*/?$', views.PartTrackingList.as_view()) +] + +urlpatterns = [ + url(r'info/?', include(infopatterns)), + + # Detail for a single unique part + url(r'^(?P[0-9]+)$', views.UniquePartDetail.as_view()), + + # List all unique parts, with optional filters + url(r'^\?*[^/]*/?$', views.UniquePartList.as_view()), ] diff --git a/InvenTree/track/views.py b/InvenTree/track/views.py index 0a26c7bf12..0d4a94eed8 100644 --- a/InvenTree/track/views.py +++ b/InvenTree/track/views.py @@ -1,5 +1,74 @@ -from django.http import HttpResponse +import django_filters + +from rest_framework import generics, permissions + +from .models import UniquePart, PartTrackingInfo +from .serializers import UniquePartSerializer, PartTrackingInfoSerializer -def index(request): - return HttpResponse("This is the Tracking page") +class UniquePartDetail(generics.RetrieveUpdateDestroyAPIView): + + queryset = UniquePart.objects.all() + serializer_class = UniquePartSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class UniquePartFilter(django_filters.rest_framework.FilterSet): + # Filter based on serial number + min_sn = django_filters.NumberFilter(name='serial', lookup_expr='gte') + max_sn = django_filters.NumberFilter(name='serial', lookup_expr='lte') + + class Meta: + model = UniquePart + fields = ['serial',] + +class UniquePartList(generics.ListCreateAPIView): + + serializer_class = UniquePartSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) + filter_class = UniquePartFilter + + def get_queryset(self): + parts = UniquePart.objects.all() + query = self.request.query_params + + # Filter by associated part + part_id = query.get('part', None) + if part_id: + parts = parts.filter(part=part_id) + + # Filter by serial number + sn = query.get('sn', None) + if sn: + parts = parts.filter(serial=sn) + + # Filter by customer + customer = query.get('customer', None) + if customer: + parts = parts.filter(customer=customer) + + return parts + + +class PartTrackingDetail(generics.RetrieveUpdateDestroyAPIView): + + queryset = PartTrackingInfo.objects.all() + serializer_class = PartTrackingInfoSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class PartTrackingList(generics.ListCreateAPIView): + + serializer_class = PartTrackingInfoSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + def get_queryset(self): + tracking = PartTrackingInfo.objects.all() + query = self.request.query_params + + part_id = query.get('part', None) + if part_id: + tracking = tracking.filter(part=part_id) + + return tracking