diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 19723bb6bb..d750b6388c 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -1,8 +1,21 @@ from django.conf.urls import url, include from django.contrib import admin +from rest_framework import status +from rest_framework.response import Response +from rest_framework.decorators import api_view + admin.site.site_header = "InvenTree Admin" + +@api_view() +def Inventree404(self): + """ Supplied URL is invalid + """ + content = {'detail': 'Malformed API URL'} + return Response(content, status=status.HTTP_404_NOT_FOUND) + + urlpatterns = [ url(r'^stock/', include('stock.urls')), url(r'^part/', include('part.urls')), @@ -10,5 +23,8 @@ urlpatterns = [ 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'^auth/', include('rest_framework.urls', namespace='rest_framework')), + + # Any other URL + url(r'', Inventree404) ] diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html deleted file mode 100644 index 8e999ea96c..0000000000 --- a/InvenTree/part/templates/part/category.html +++ /dev/null @@ -1,21 +0,0 @@ -{# Construct the category path #} -Category/ -{% for path_item in category.parentpath %} -{{ path_item.name }}/ -{% endfor %} - -{{ category.name }} - -

Children:
-{% for child in children %} -{{ child.name }}
-{% endfor %} - -
-
-Parts: -
- -{% for part in category.part_set.all %} -{{ part.name }}
-{% endfor %} diff --git a/InvenTree/part/templates/part/categorylist.html b/InvenTree/part/templates/part/categorylist.html deleted file mode 100644 index c4c62ba58b..0000000000 --- a/InvenTree/part/templates/part/categorylist.html +++ /dev/null @@ -1,8 +0,0 @@ -Top Level Part Categories: - -{% for category in categories %} - -
-{{ category.name }} - -{% endfor %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html deleted file mode 100644 index 8055f46023..0000000000 --- a/InvenTree/part/templates/part/detail.html +++ /dev/null @@ -1,4 +0,0 @@ -{{part}} - -
-Category:
{{ part.category }} \ No newline at end of file diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 711df899f8..da9cb5ab4a 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -61,10 +61,7 @@ class PartFilter(django_filters.rest_framework.FilterSet): class PartList(generics.ListCreateAPIView): - """ Display a list of parts, with optional filters - Filters are specified in the url, e.g. - /part/?category=127 - /part/?min_stock=100 + """ List of parts, with optional filters """ def get_queryset(self): diff --git a/InvenTree/stock/templates/stock/index.html b/InvenTree/stock/templates/stock/index.html deleted file mode 100644 index 234cd000dc..0000000000 --- a/InvenTree/stock/templates/stock/index.html +++ /dev/null @@ -1,8 +0,0 @@ -Warehouses: - -{% for warehouse in warehouse %} - -
-{{ warehouse.name }} - -{% endfor %} \ No newline at end of file diff --git a/InvenTree/supplier/serializers.py b/InvenTree/supplier/serializers.py new file mode 100644 index 0000000000..3635a93a72 --- /dev/null +++ b/InvenTree/supplier/serializers.py @@ -0,0 +1,42 @@ +from rest_framework import serializers + +from .models import Supplier, SupplierPart, SupplierPriceBreak + + +class SupplierSerializer(serializers.ModelSerializer): + + class Meta: + model = Supplier + fields = '__all__' + + +class SupplierPartSerializer(serializers.ModelSerializer): + + price_breaks = serializers.PrimaryKeyRelatedField(many=True, read_only=True) + + class Meta: + model = SupplierPart + fields = ['pk', + 'part', + 'supplier', + 'SKU', + 'manufacturer', + 'MPN', + 'URL', + 'description', + 'single_price', + 'packaging', + 'multiple', + 'minimum', + 'price_breaks', + 'lead_time'] + + +class SupplierPriceBreakSerializer(serializers.ModelSerializer): + + class Meta: + model = SupplierPriceBreak + fields = ['pk', + 'part', + 'quantity', + 'cost'] diff --git a/InvenTree/supplier/templates/supplier/detail.html b/InvenTree/supplier/templates/supplier/detail.html deleted file mode 100644 index 709ba79248..0000000000 --- a/InvenTree/supplier/templates/supplier/detail.html +++ /dev/null @@ -1 +0,0 @@ -{{ supplier }} \ No newline at end of file diff --git a/InvenTree/supplier/urls.py b/InvenTree/supplier/urls.py index 5490b22d87..10fbe8f230 100644 --- a/InvenTree/supplier/urls.py +++ b/InvenTree/supplier/urls.py @@ -1,11 +1,30 @@ -from django.conf.urls import url +from django.conf.urls import url, include from . import views -urlpatterns = [ - - # Display details of a supplier - url(r'^(?P[0-9]+)/$', views.supplierDetail, name='detail'), - - url(r'^$', views.index, name='index') +partpatterns = [ + url(r'^(?P[0-9]+)/?$', views.SupplierPartDetail.as_view()), + + url(r'^\?*[^/]*/?$', views.SupplierPartList.as_view()) +] + +pricepatterns = [ + url(r'^(?P[0-9]+)/?$', views.SupplierPriceBreakDetail.as_view()), + + url(r'^\?*[^/]*/?$', views.SupplierPriceBreakList.as_view()) +] + +urlpatterns = [ + + # Supplier part information + url(r'part/?', include(partpatterns)), + + # Supplier price information + url(r'price/?', include(pricepatterns)), + + # Display details of a supplier + url(r'^(?P[0-9]+)/?$', views.SupplierDetail.as_view()), + + # List suppliers + url(r'^\?*[^/]*/?$', views.SupplierList.as_view()) ] diff --git a/InvenTree/supplier/views.py b/InvenTree/supplier/views.py index edfd3883be..e6fa2e628b 100644 --- a/InvenTree/supplier/views.py +++ b/InvenTree/supplier/views.py @@ -1,15 +1,74 @@ -from django.shortcuts import render, get_object_or_404 -from django.http import HttpResponse +from rest_framework import generics, permissions -from .models import Supplier +from .models import Supplier, SupplierPart, SupplierPriceBreak +from .serializers import SupplierSerializer +from .serializers import SupplierPartSerializer +from .serializers import SupplierPriceBreakSerializer -def index(request): - return HttpResponse("This is the suppliers page") +class SupplierDetail(generics.RetrieveUpdateDestroyAPIView): + + queryset = Supplier.objects.all() + serializer_class = SupplierSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) -def supplierDetail(request, supplier_id): - supplier = get_object_or_404(Supplier, pk=supplier_id) - - return render(request, 'supplier/detail.html', - {'supplier': supplier}) +class SupplierList(generics.ListCreateAPIView): + + queryset = Supplier.objects.all() + serializer_class = SupplierSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class SupplierPartDetail(generics.RetrieveUpdateDestroyAPIView): + + queryset = SupplierPart.objects.all() + serializer_class = SupplierPartSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class SupplierPartList(generics.ListCreateAPIView): + + serializer_class = SupplierPartSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + def get_queryset(self): + parts = SupplierPart.objects.all() + params = self.request.query_params + + supplier_id = params.get('supplier', None) + if supplier_id: + parts = parts.filter(supplier=supplier_id) + + part_id = params.get('part', None) + if part_id: + parts = parts.filter(part=part_id) + + manu_id = params.get('manufacturer', None) + if manu_id: + parts = parts.filter(manufacturer=manu_id) + + return parts + + +class SupplierPriceBreakDetail(generics.RetrieveUpdateDestroyAPIView): + + queryset = SupplierPriceBreak.objects.all() + serializer_class = SupplierPriceBreakSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class SupplierPriceBreakList(generics.ListCreateAPIView): + + def get_queryset(self): + prices = SupplierPriceBreak.objects.all() + params = self.request.query_params + + part_id = params.get('part', None) + if part_id: + prices = prices.filter(part=part_id) + + return prices + + serializer_class = SupplierPriceBreakSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,)