diff --git a/InvenTree/label/admin.py b/InvenTree/label/admin.py index 2e4967ffc2..8fee2b1f8f 100644 --- a/InvenTree/label/admin.py +++ b/InvenTree/label/admin.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from django.contrib import admin -from .models import StockItemLabel, StockLocationLabel +from .models import StockItemLabel, StockLocationLabel, PartLabel class LabelAdmin(admin.ModelAdmin): @@ -13,3 +13,4 @@ class LabelAdmin(admin.ModelAdmin): admin.site.register(StockItemLabel, LabelAdmin) admin.site.register(StockLocationLabel, LabelAdmin) +admin.site.register(PartLabel, LabelAdmin) diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py index 8522857e30..13f737057d 100644 --- a/InvenTree/label/api.py +++ b/InvenTree/label/api.py @@ -15,9 +15,10 @@ import InvenTree.helpers import common.models from stock.models import StockItem, StockLocation +from part.models import Part -from .models import StockItemLabel, StockLocationLabel -from .serializers import StockItemLabelSerializer, StockLocationLabelSerializer +from .models import StockItemLabel, StockLocationLabel, PartLabel +from .serializers import StockItemLabelSerializer, StockLocationLabelSerializer, PartLabelSerializer class LabelListView(generics.ListAPIView): @@ -132,6 +133,7 @@ class StockItemLabelMixin: for key in ['item', 'item[]', 'items', 'items[]']: if key in params: items = params.getlist(key, []) + break valid_ids = [] @@ -376,6 +378,112 @@ class StockLocationLabelPrint(generics.RetrieveAPIView, StockLocationLabelMixin, return self.print(request, locations) +class PartLabelMixin: + """ + Mixin for extracting Part objects from query parameters + """ + + def get_parts(self): + """ + Return a list of requested Part objects + """ + + parts = [] + + params = self.request.query_params + + for key in ['part', 'part[]', 'parts', 'parts[]']: + if key in params: + parts = parts.getlist(key, []) + break + + valid_ids = [] + + for part in parts: + try: + valid_ids.append(int(part)) + except (ValueError): + pass + + # List of Part objects which match provided values + return Part.objects.filter(pk__in=valid_ids) + + +class PartLabelList(LabelListView, PartLabelMixin): + """ + API endpoint for viewing list of PartLabel objects + """ + + queryset = PartLabel.objects.all() + serializer_class = PartLabelSerializer + + def filter_queryset(self, queryset): + + queryset = super().filter_queryset(queryset) + + parts = self.get_parts() + + if len(parts) > 0: + + valid_label_ids = set() + + for label in queryset.all(): + + matches = True + + try: + filters = InvenTree.helpers.validateFilterString(label.filters) + except ValidationError: + continue + + for part in parts: + + part_query = Part.objects.filter(pk=part.pk) + + try: + if not part_query.filter(**filters).exists(): + matches = False + break + except FieldError: + matches = False + break + + if matches: + valid_label_ids.add(label.pk) + + # Reduce queryset to only valid matches + queryset = queryset.filter(pk__in=[pk for pk in valid_label_ids]) + + return queryset + + +class PartLabelDetail(generics.RetrieveUpdateDestroyAPIView): + """ + API endpoint for a single PartLabel object + """ + + queryset = PartLabel.objects.all() + serializer_class = PartLabelSerializer + + +class PartLabelPrint(generics.RetrieveAPIView, PartLabelMixin, LabelPrintMixin): + """ + API endpoint for printing a PartLabel object + """ + + queryset = PartLabel.objects.all() + serializer_class = PartLabelSerializer + + def get(self, request, *args, **kwargs): + """ + Check if valid part(s) have been provided + """ + + parts = self.get_parts() + + return self.print(request, parts) + + label_api_urls = [ # Stock item labels @@ -401,4 +509,16 @@ label_api_urls = [ # List view url(r'^.*$', StockLocationLabelList.as_view(), name='api-stocklocation-label-list'), ])), + + # Part labels + url(r'^part/', include([ + # Detail views + url(r'^(?P\d+)/', include([ + url(r'^print/', PartLabelPrint.as_view(), name='api-part-label-print'), + url(r'^.*$', PartLabelDetail.as_view(), name='api-part-label-detail'), + ])), + + # List view + url(r'^.*$', PartLabelList.as_view(), name='api-part-label-list'), + ])), ] diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index cfa658914d..b558f10e73 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -12,7 +12,6 @@ import datetime from django.conf import settings from django.db import models -from django.db.models.fields import Field from django.urls import reverse from django.core.validators import FileExtensionValidator, MinValueValidator from django.core.exceptions import ValidationError, FieldError diff --git a/InvenTree/label/serializers.py b/InvenTree/label/serializers.py index c9d487af23..47ccd51ba1 100644 --- a/InvenTree/label/serializers.py +++ b/InvenTree/label/serializers.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals from InvenTree.serializers import InvenTreeModelSerializer from InvenTree.serializers import InvenTreeAttachmentSerializerField -from .models import StockItemLabel, StockLocationLabel +from .models import StockItemLabel, StockLocationLabel, PartLabel class StockItemLabelSerializer(InvenTreeModelSerializer): @@ -43,3 +43,22 @@ class StockLocationLabelSerializer(InvenTreeModelSerializer): 'filters', 'enabled', ] + + +class PartLabelSerializer(InvenTreeModelSerializer): + """ + Serializes a PartLabel object + """ + + label = InvenTreeAttachmentSerializerField(required=True) + + class Meta: + model = PartLabel + fields = [ + 'pk', + 'name', + 'description', + 'label', + 'filters', + 'enabled', + ]