Adds some more API filters for the StockItem endpoint

This commit is contained in:
Oliver 2021-07-08 17:44:52 +10:00
parent 81010994e7
commit f0e7826fdc
2 changed files with 47 additions and 68 deletions

View File

@ -8,7 +8,7 @@ from __future__ import unicode_literals
from django.conf.urls import url, include from django.conf.urls import url, include
from django.urls import reverse from django.urls import reverse
from django.http import JsonResponse from django.http import JsonResponse
from django.db.models import Q, F, Count, Min, Max, Avg, query from django.db.models import Q, F, Count, Min, Max, Avg
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import status from rest_framework import status

View File

@ -343,20 +343,62 @@ class StockLocationList(generics.ListCreateAPIView):
class StockFilter(rest_filters.FilterSet): class StockFilter(rest_filters.FilterSet):
""" FilterSet for advanced stock filtering.
Allows greater-than / less-than filtering for stock quantity
""" """
FilterSet for StockItem LIST API
"""
# Part name filters
name = rest_filters.CharFilter(label='Part name (case insensitive)', field_name='part__name', lookup_expr='iexact')
name_regex = rest_filters.CharFilter(label='Part name (regex)', field_name='part__name', lookup_expr='iregex')
# Part IPN filters
ipn = rest_filters.CharFilter(label='Part IPN (case insensitive)', field_name='part__IPN', lookup_expr='iexact')
ipn_regex = rest_filters.CharFilter(label='Part IPN (regex)', field_name='part__IPN', lookup_expr='iregex')
# Part attribute filters
assembly = rest_filters.BooleanFilter(label="Assembly", field_name='part__assembly')
active = rest_filters.BooleanFilter(label="Active", field_name='part__active')
min_stock = rest_filters.NumberFilter(label='Minimum stock', field_name='quantity', lookup_expr='gte') min_stock = rest_filters.NumberFilter(label='Minimum stock', field_name='quantity', lookup_expr='gte')
max_stock = rest_filters.NumberFilter(label='Maximum stock', field_name='quantity', lookup_expr='lte') max_stock = rest_filters.NumberFilter(label='Maximum stock', field_name='quantity', lookup_expr='lte')
in_stock = rest_filters.BooleanFilter(label='In Stock', method='filter_in_stock')
def filter_in_stock(self, queryset, name, value):
value = str2bool(value)
if value:
queryset = queryset.filter(StockItem.IN_STOCK_FILTER)
else:
queryset = queryset.exclude(StockItem.IN_STOCK_FILTER)
return queryset
batch = rest_filters.CharFilter(label="Batch code filter (case insensitive)", lookup_expr='iexact') batch = rest_filters.CharFilter(label="Batch code filter (case insensitive)", lookup_expr='iexact')
batch_regex = rest_filters.CharFilter(label="Batch code filter (regex)", field_name='batch', lookup_expr='iregex') batch_regex = rest_filters.CharFilter(label="Batch code filter (regex)", field_name='batch', lookup_expr='iregex')
is_building = rest_filters.BooleanFilter(label="In production") is_building = rest_filters.BooleanFilter(label="In production")
# Serial number filtering
serial_gte = rest_filters.NumberFilter(label='Serial number GTE', field_name='serial', lookup_expr='gte')
serial_lte = rest_filters.NumberFilter(label='Serial number LTE', field_name='serial', lookup_expr='lte')
serial = rest_filters.NumberFilter(label='Serial number', field_name='serial', lookup_expr='exact')
serialized = rest_filters.BooleanFilter(label='Has serial number', method='filter_serialized')
def filter_serialized(self, queryset, name, value):
value = str2bool(value)
if value:
queryset = queryset.exclude(serial=None)
else:
queryset = queryset.filter(serial=None)
return queryset
class StockList(generics.ListCreateAPIView): class StockList(generics.ListCreateAPIView):
""" API endpoint for list view of Stock objects """ API endpoint for list view of Stock objects
@ -629,50 +671,7 @@ class StockList(generics.ListCreateAPIView):
else: else:
queryset = queryset.filter(customer=None) queryset = queryset.filter(customer=None)
# Filter by "serialized" status? # Filter by 'allocated' parts?
serialized = params.get('serialized', None)
if serialized is not None:
serialized = str2bool(serialized)
if serialized:
queryset = queryset.exclude(serial=None)
else:
queryset = queryset.filter(serial=None)
# Filter by serial number?
serial_number = params.get('serial', None)
if serial_number is not None:
queryset = queryset.filter(serial=serial_number)
# Filter by range of serial numbers?
serial_number_gte = params.get('serial_gte', None)
serial_number_lte = params.get('serial_lte', None)
if serial_number_gte is not None or serial_number_lte is not None:
queryset = queryset.exclude(serial=None)
if serial_number_gte is not None:
queryset = queryset.filter(serial__gte=serial_number_gte)
if serial_number_lte is not None:
queryset = queryset.filter(serial__lte=serial_number_lte)
# Filter by "in_stock" status
in_stock = params.get('in_stock', None)
if in_stock is not None:
in_stock = str2bool(in_stock)
if in_stock:
# Filter out parts which are not actually "in stock"
queryset = queryset.filter(StockItem.IN_STOCK_FILTER)
else:
# Only show parts which are not in stock
queryset = queryset.exclude(StockItem.IN_STOCK_FILTER)
# Filter by 'allocated' patrs?
allocated = params.get('allocated', None) allocated = params.get('allocated', None)
if allocated is not None: if allocated is not None:
@ -685,20 +684,6 @@ class StockList(generics.ListCreateAPIView):
# Filter StockItem without build allocations or sales order allocations # Filter StockItem without build allocations or sales order allocations
queryset = queryset.filter(Q(sales_order_allocations__isnull=True) & Q(allocations__isnull=True)) queryset = queryset.filter(Q(sales_order_allocations__isnull=True) & Q(allocations__isnull=True))
# Do we wish to filter by "active parts"
active = params.get('active', None)
if active is not None:
active = str2bool(active)
queryset = queryset.filter(part__active=active)
# Do we wish to filter by "assembly parts"
assembly = params.get('assembly', None)
if assembly is not None:
assembly = str2bool(assembly)
queryset = queryset.filter(part__assembly=assembly)
# Filter by 'depleted' status # Filter by 'depleted' status
depleted = params.get('depleted', None) depleted = params.get('depleted', None)
@ -710,12 +695,6 @@ class StockList(generics.ListCreateAPIView):
else: else:
queryset = queryset.exclude(quantity__lte=0) queryset = queryset.exclude(quantity__lte=0)
# Filter by internal part number
ipn = params.get('IPN', None)
if ipn is not None:
queryset = queryset.filter(part__IPN=ipn)
# Does the client wish to filter by the Part ID? # Does the client wish to filter by the Part ID?
part_id = params.get('part', None) part_id = params.get('part', None)