diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index b9d7e71c86..099d5ab6cd 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from django.utils.translation import ugettext as _ from django.db import models from django.db.models import Sum +from django.core.validators import MinValueValidator from InvenTree.models import InvenTreeTree @@ -35,7 +36,7 @@ class Part(models.Model): category = models.ForeignKey(PartCategory, on_delete=models.CASCADE) # Minimum "allowed" stock level - minimum_stock = models.PositiveIntegerField(default=0) + minimum_stock = models.PositiveIntegerField(default=0, validators=[MinValueValidator(0)]) # Units of quantity for this part. Default is "pcs" units = models.CharField(max_length=20, default="pcs", blank=True) @@ -112,7 +113,8 @@ class PartParameterTemplate(models.Model): format = models.PositiveIntegerField( default=PARAM_NUMERIC, - choices=PARAM_TYPE_CODES.items()) + choices=PARAM_TYPE_CODES.items(), + validators=[MinValueValidator(0)]) def __str__(self): return "{name} ({units})".format( diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 40c7134860..d2a1e9f55d 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -1,5 +1,4 @@ from django_filters.rest_framework import FilterSet, DjangoFilterBackend -from django_filters import NumberFilter from rest_framework import generics, permissions @@ -31,8 +30,6 @@ class PartDetail(generics.RetrieveUpdateDestroyAPIView): class PartParamFilter(FilterSet): - part = NumberFilter(name='part', lookup_expr='exact') - class Meta: model = PartParameter fields = ['part'] @@ -75,7 +72,6 @@ class PartParamDetail(generics.RetrieveUpdateDestroyAPIView): class PartFilter(FilterSet): - category = NumberFilter(name='category', lookup_expr='exact') class Meta: model = Part diff --git a/InvenTree/project/models.py b/InvenTree/project/models.py index 8038184215..99228deb22 100644 --- a/InvenTree/project/models.py +++ b/InvenTree/project/models.py @@ -5,6 +5,7 @@ from django.db import models from InvenTree.models import InvenTreeTree from part.models import Part +from django.core.validators import MinValueValidator class ProjectCategory(InvenTreeTree): @@ -46,7 +47,7 @@ class ProjectPart(models.Model): part = models.ForeignKey(Part, on_delete=models.CASCADE) project = models.ForeignKey(Project, on_delete=models.CASCADE) - quantity = models.PositiveIntegerField(default=1) + quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) class Meta: unique_together = ('part', 'project') @@ -66,7 +67,8 @@ class ProjectPart(models.Model): overage = models.FloatField(default=0) overage_type = models.PositiveIntegerField( default=OVERAGE_ABSOLUTE, - choices=OVARAGE_CODES.items()) + choices=OVARAGE_CODES.items(), + validators=[MinValueValidator(0)]) """ # Set if the part is generated by the project, @@ -89,6 +91,6 @@ class ProjectRun(models.Model): """ project = models.ForeignKey(Project, on_delete=models.CASCADE) - quantity = models.PositiveIntegerField(default=1) + quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) run_date = models.DateField(auto_now_add=True) diff --git a/InvenTree/project/views.py b/InvenTree/project/views.py index 2a293a0cca..593407ae63 100644 --- a/InvenTree/project/views.py +++ b/InvenTree/project/views.py @@ -1,5 +1,6 @@ -from rest_framework import generics, permissions +from django_filters.rest_framework import FilterSet, DjangoFilterBackend +from rest_framework import generics, permissions from InvenTree.models import FilterChildren from .models import ProjectCategory, Project, ProjectPart from .serializers import ProjectSerializer @@ -26,6 +27,13 @@ class ProjectDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) +class ProjectFilter(FilterSet): + + class Meta: + model = Project + fields = ['category'] + + class ProjectList(generics.ListCreateAPIView): """ @@ -38,19 +46,11 @@ class ProjectList(generics.ListCreateAPIView): """ - def get_queryset(self): - projects = Project.objects.all() - params = self.request.query_params - - cat_id = params.get('category', None) - - if cat_id: - projects = projects.filter(category=cat_id) - - return projects - + queryset = Project.objects.all() serializer_class = ProjectSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + filter_backends = (DjangoFilterBackend,) + filter_class = ProjectFilter class ProjectCategoryDetail(generics.RetrieveUpdateAPIView): @@ -136,7 +136,7 @@ class ProjectPartDetail(generics.RetrieveUpdateDestroyAPIView): delete: Remove a ProjectPart - + """ queryset = ProjectPart.objects.all() diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 9984d1d74a..0c847e80d5 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from django.utils.translation import ugettext as _ from django.db import models +from django.core.validators import MinValueValidator from supplier.models import SupplierPart from part.models import Part @@ -21,7 +22,7 @@ class StockItem(models.Model): part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='locations') supplier_part = models.ForeignKey(SupplierPart, blank=True, null=True, on_delete=models.SET_NULL) location = models.ForeignKey(StockLocation, on_delete=models.CASCADE) - quantity = models.PositiveIntegerField() + quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)]) updated = models.DateField(auto_now=True) # last time the stock was checked / counted @@ -50,7 +51,8 @@ class StockItem(models.Model): status = models.PositiveIntegerField( default=ITEM_IN_STOCK, - choices=ITEM_STATUS_CODES.items()) + choices=ITEM_STATUS_CODES.items(), + validators=[MinValueValidator(0)]) notes = models.CharField(max_length=100, blank=True) @@ -73,5 +75,4 @@ class StockTracking(models.Model): item = models.ForeignKey(StockItem, on_delete=models.CASCADE, related_name='tracking') quantity = models.IntegerField() - pending = models.BooleanField(default=False) when = models.DateTimeField(auto_now=True) diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index c7e958e4e9..f0ba1c805d 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -11,6 +11,7 @@ class StockItemSerializer(serializers.HyperlinkedModelSerializer): model = StockItem fields = ('url', 'part', + 'supplier_part', 'location', 'quantity', 'status', @@ -41,5 +42,4 @@ class StockTrackingSerializer(serializers.HyperlinkedModelSerializer): fields = ('url', 'item', 'quantity', - 'pending', 'when') diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 026c9084ab..a0a9cf4beb 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -29,8 +29,6 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView): class StockFilter(FilterSet): min_stock = NumberFilter(name='quantity', lookup_expr='gte') max_stock = NumberFilter(name='quantity', lookup_expr='lte') - part = NumberFilter(name='part', lookup_expr='exact') - location = NumberFilter(name='location', lookup_expr='exact') class Meta: model = StockItem @@ -76,8 +74,6 @@ class LocationDetail(generics.RetrieveUpdateDestroyAPIView): class StockLocationFilter(FilterSet): - parent = NumberFilter(name='parent', lookup_expr='exact') - class Meta: model = StockLocation fields = ['parent'] @@ -123,8 +119,6 @@ class StockTrackingDetail(generics.RetrieveUpdateDestroyAPIView): class StockTrackingFilter(FilterSet): - item = NumberFilter(name='item', lookup_expr='exact') - class Meta: model = StockTracking fields = ['item'] diff --git a/InvenTree/supplier/models.py b/InvenTree/supplier/models.py index 9f5067caf8..13393bb4ad 100644 --- a/InvenTree/supplier/models.py +++ b/InvenTree/supplier/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from django.db import models +from django.core.validators import MinValueValidator from InvenTree.models import Company from part.models import Part @@ -54,10 +55,10 @@ class SupplierPart(models.Model): packaging = models.CharField(max_length=50, blank=True) # multiple that the part is provided in - multiple = models.PositiveIntegerField(default=1) + multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) # Mimumum number required to order - minimum = models.PositiveIntegerField(default=1) + minimum = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) # lead time for parts that cannot be delivered immediately lead_time = models.DurationField(blank=True, null=True) @@ -75,7 +76,7 @@ class SupplierPriceBreak(models.Model): """ part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='price_breaks') - quantity = models.PositiveIntegerField() + quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)]) cost = models.DecimalField(max_digits=10, decimal_places=3) class Meta: diff --git a/InvenTree/supplier/views.py b/InvenTree/supplier/views.py index ac8995de48..8f9b43e03a 100644 --- a/InvenTree/supplier/views.py +++ b/InvenTree/supplier/views.py @@ -1,5 +1,4 @@ from django_filters.rest_framework import FilterSet, DjangoFilterBackend -from django_filters import NumberFilter from rest_framework import generics, permissions @@ -138,12 +137,6 @@ class SupplierPartDetail(generics.RetrieveUpdateDestroyAPIView): class SupplierPartFilter(FilterSet): - supplier = NumberFilter(name='supplier', lookup_expr='exact') - - part = NumberFilter(name='part', lookup_expr='exact') - - manufacturer = NumberFilter(name='manufacturer', lookup_expr='exact') - class Meta: model = SupplierPart fields = ['supplier', 'part', 'manufacturer'] @@ -190,8 +183,6 @@ class SupplierPriceBreakDetail(generics.RetrieveUpdateDestroyAPIView): class PriceBreakFilter(FilterSet): - part = NumberFilter(name='part', lookup_expr='exact') - class Meta: model = SupplierPriceBreak fields = ['part'] diff --git a/InvenTree/track/serializers.py b/InvenTree/track/serializers.py index c2c097c28d..34f15e227d 100644 --- a/InvenTree/track/serializers.py +++ b/InvenTree/track/serializers.py @@ -5,8 +5,6 @@ from .models import UniquePart, PartTrackingInfo class UniquePartSerializer(serializers.HyperlinkedModelSerializer): - tracking_info = serializers.PrimaryKeyRelatedField(many=True, read_only=True) - class Meta: model = UniquePart fields = ['url', @@ -15,8 +13,7 @@ class UniquePartSerializer(serializers.HyperlinkedModelSerializer): 'serial', # 'createdBy', 'customer', - 'status', - 'tracking_info'] + 'status'] class PartTrackingInfoSerializer(serializers.HyperlinkedModelSerializer): diff --git a/InvenTree/track/views.py b/InvenTree/track/views.py index f45205993d..c36f710e0d 100644 --- a/InvenTree/track/views.py +++ b/InvenTree/track/views.py @@ -31,10 +31,6 @@ class UniquePartFilter(FilterSet): min_sn = NumberFilter(name='serial', lookup_expr='gte') max_sn = NumberFilter(name='serial', lookup_expr='lte') - sn = NumberFilter(name='serial', lookup_expr='exact') - part = NumberFilter(name='part', lookup_expr='exact') - customer = NumberFilter(name='customer', lookup_expr='exact') - class Meta: model = UniquePart fields = ['serial', 'part', 'customer'] @@ -77,7 +73,6 @@ class PartTrackingDetail(generics.RetrieveUpdateDestroyAPIView): class PartTrackingFilter(FilterSet): - part = NumberFilter(name='part', lookup_expr='exact') class Meta: model = PartTrackingInfo