mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #739 from SchrodingersGat/api-consolidation
Api consolidation
This commit is contained in:
commit
85e20041c7
@ -104,21 +104,23 @@ function removePurchaseOrderLineItem(e) {
|
||||
function loadPurchaseOrderTable(table, options) {
|
||||
/* Create a purchase-order table */
|
||||
|
||||
var params = options.params || {};
|
||||
options.params = options.params || {};
|
||||
|
||||
options.params['supplier_detail'] = true;
|
||||
|
||||
var filters = loadTableFilters("order");
|
||||
|
||||
for (var key in params) {
|
||||
filters[key] = params[key];
|
||||
for (var key in options.params) {
|
||||
filters[key] = options.params[key];
|
||||
}
|
||||
|
||||
setupFilterList("order", table);
|
||||
setupFilterList("order", $(table));
|
||||
|
||||
$(table).inventreeTable({
|
||||
url: options.url,
|
||||
queryParams: filters,
|
||||
groupBy: false,
|
||||
original: params,
|
||||
original: options.params,
|
||||
formatNoMatches: function() { return "No purchase orders found"; },
|
||||
columns: [
|
||||
{
|
||||
@ -131,15 +133,15 @@ function loadPurchaseOrderTable(table, options) {
|
||||
field: 'reference',
|
||||
title: 'Purchase Order',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, "/order/purchase-order/" + row.pk + "/");
|
||||
return renderLink(value, `/order/purchase-order/${row.pk}/`);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'supplier',
|
||||
field: 'supplier_detail',
|
||||
title: 'Supplier',
|
||||
formatter: function(value, row, index, field) {
|
||||
return imageHoverIcon(row.supplier__image) + renderLink(row.supplier__name, '/company/' + value + '/purchase-orders/');
|
||||
return imageHoverIcon(row.supplier_detail.image) + renderLink(row.supplier_detail.name, `/company/${row.supplier}/purchase-orders/`);
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -162,7 +164,7 @@ function loadPurchaseOrderTable(table, options) {
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'lines',
|
||||
field: 'line_items',
|
||||
title: 'Items'
|
||||
},
|
||||
],
|
||||
|
@ -8,14 +8,10 @@ from __future__ import unicode_literals
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import generics, permissions
|
||||
from rest_framework import filters
|
||||
from rest_framework.response import Response
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url
|
||||
|
||||
from InvenTree.status_codes import OrderStatus
|
||||
|
||||
import os
|
||||
from InvenTree.helpers import str2bool
|
||||
|
||||
from part.models import Part
|
||||
from company.models import SupplierPart
|
||||
@ -34,66 +30,66 @@ class POList(generics.ListCreateAPIView):
|
||||
queryset = PurchaseOrder.objects.all()
|
||||
serializer_class = POSerializer
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
queryset = self.get_queryset().prefetch_related('supplier', 'lines')
|
||||
|
||||
queryset = self.filter_queryset(queryset)
|
||||
|
||||
# Special filtering for 'status' field
|
||||
if 'status' in request.GET:
|
||||
status = request.GET['status']
|
||||
|
||||
# First attempt to filter by integer value
|
||||
try:
|
||||
status = int(status)
|
||||
queryset = queryset.filter(status=status)
|
||||
except ValueError:
|
||||
try:
|
||||
value = OrderStatus.value(status)
|
||||
queryset = queryset.filter(status=value)
|
||||
except ValueError:
|
||||
kwargs['supplier_detail'] = str2bool(self.request.query_params.get('supplier_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Ensure the request context is passed through
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
|
||||
queryset = queryset.prefetch_related(
|
||||
'supplier',
|
||||
'lines',
|
||||
)
|
||||
|
||||
queryset = POSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
|
||||
# Perform basic filtering
|
||||
queryset = super().filter_queryset(queryset)
|
||||
|
||||
params = self.request.query_params
|
||||
|
||||
# Special filtering for 'status' field
|
||||
status = params.get('status', None)
|
||||
|
||||
if status is not None:
|
||||
# First attempt to filter by integer value
|
||||
queryset = queryset.filter(status=status)
|
||||
|
||||
# Attempt to filter by part
|
||||
if 'part' in request.GET:
|
||||
part = params.get('part', None)
|
||||
|
||||
if part is not None:
|
||||
try:
|
||||
part = Part.objects.get(pk=request.GET['part'])
|
||||
part = Part.objects.get(pk=part)
|
||||
queryset = queryset.filter(id__in=[p.id for p in part.purchase_orders()])
|
||||
except (Part.DoesNotExist, ValueError):
|
||||
pass
|
||||
|
||||
# Attempt to filter by supplier part
|
||||
if 'supplier_part' in request.GET:
|
||||
supplier_part = params.get('supplier_part', None)
|
||||
|
||||
if supplier_part is not None:
|
||||
try:
|
||||
supplier_part = SupplierPart.objects.get(pk=request.GET['supplier_part'])
|
||||
supplier_part = SupplierPart.objects.get(pk=supplier_part)
|
||||
queryset = queryset.filter(id__in=[p.id for p in supplier_part.purchase_orders()])
|
||||
except (ValueError, SupplierPart.DoesNotExist):
|
||||
pass
|
||||
|
||||
data = queryset.values(
|
||||
'pk',
|
||||
'supplier',
|
||||
'supplier_reference',
|
||||
'supplier__name',
|
||||
'supplier__image',
|
||||
'reference',
|
||||
'description',
|
||||
'link',
|
||||
'status',
|
||||
'notes',
|
||||
'creation_date',
|
||||
)
|
||||
|
||||
for item in data:
|
||||
|
||||
order = queryset.get(pk=item['pk'])
|
||||
|
||||
item['supplier__image'] = os.path.join(settings.MEDIA_URL, item['supplier__image'])
|
||||
item['status_text'] = OrderStatus.label(item['status'])
|
||||
item['lines'] = order.lines.count()
|
||||
|
||||
return Response(data)
|
||||
return queryset
|
||||
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated,
|
||||
@ -123,6 +119,31 @@ class PODetail(generics.RetrieveUpdateAPIView):
|
||||
queryset = PurchaseOrder.objects.all()
|
||||
serializer_class = POSerializer
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
try:
|
||||
kwargs['supplier_detail'] = str2bool(self.request.query_params.get('supplier_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Ensure the request context is passed through
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
|
||||
queryset = queryset.prefetch_related(
|
||||
'supplier',
|
||||
'lines',
|
||||
)
|
||||
|
||||
queryset = POSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated
|
||||
]
|
||||
|
@ -5,7 +5,12 @@ JSON serializers for the Order API
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from django.db.models import Count
|
||||
|
||||
from InvenTree.serializers import InvenTreeModelSerializer
|
||||
from company.serializers import CompanyBriefSerializer
|
||||
|
||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||
|
||||
@ -13,17 +18,48 @@ from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||
class POSerializer(InvenTreeModelSerializer):
|
||||
""" Serializes an Order object """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
supplier_detail = kwargs.pop('supplier_detail', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if supplier_detail is not True:
|
||||
self.fields.pop('supplier_detail')
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
"""
|
||||
Add extra information to the queryset
|
||||
"""
|
||||
|
||||
return queryset.annotate(
|
||||
line_items=Count('lines'),
|
||||
)
|
||||
|
||||
supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True)
|
||||
|
||||
line_items = serializers.IntegerField(read_only=True)
|
||||
|
||||
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = PurchaseOrder
|
||||
|
||||
fields = [
|
||||
'pk',
|
||||
'supplier',
|
||||
'supplier_reference',
|
||||
'reference',
|
||||
'issue_date',
|
||||
'complete_date',
|
||||
'creation_date',
|
||||
'description',
|
||||
'line_items',
|
||||
'link',
|
||||
'reference',
|
||||
'supplier',
|
||||
'supplier_detail',
|
||||
'supplier_reference',
|
||||
'status',
|
||||
'status_text',
|
||||
'notes',
|
||||
]
|
||||
|
||||
|
@ -135,10 +135,40 @@ class PartDetail(generics.RetrieveUpdateAPIView):
|
||||
queryset = Part.objects.all()
|
||||
serializer_class = part_serializers.PartSerializer
|
||||
|
||||
starred_parts = None
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
|
||||
queryset = part_serializers.PartSerializer.prefetch_queryset(queryset)
|
||||
queryset = part_serializers.PartSerializer.annotate_queryset(queryset)
|
||||
return queryset
|
||||
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated,
|
||||
]
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
try:
|
||||
cat_detail = str2bool(self.request.query_params.get('category_detail', False))
|
||||
except AttributeError:
|
||||
cat_detail = None
|
||||
|
||||
# Ensure the request context is passed through
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
||||
kwargs['category_detail'] = cat_detail
|
||||
|
||||
# Pass a list of "starred" parts fo the current user to the serializer
|
||||
# We do this to reduce the number of database queries required!
|
||||
if self.starred_parts is None and self.request is not None:
|
||||
self.starred_parts = [star.part for star in self.request.user.starred_parts.all()]
|
||||
|
||||
kwargs['starred_parts'] = self.starred_parts
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
|
||||
class PartList(generics.ListCreateAPIView):
|
||||
""" API endpoint for accessing a list of Part objects
|
||||
|
@ -58,20 +58,28 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
serializer_class = StockItemSerializer
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
queryset = StockItemSerializer.prefetch_queryset(queryset)
|
||||
queryset = StockItemSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
try:
|
||||
kwargs['part_detail'] = str2bool(self.request.GET.get('part_detail', False))
|
||||
kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
kwargs['location_detail'] = str2bool(self.request.GET.get('location_detail', False))
|
||||
kwargs['location_detail'] = str2bool(self.request.query_params.get('location_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
kwargs['supplier_detail'] = str2bool(self.request.GET.get('supplier_detail', False))
|
||||
kwargs['supplier_part_detail'] = str2bool(self.request.query_params.get('supplier_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@ -321,14 +329,19 @@ class StockList(generics.ListCreateAPIView):
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
try:
|
||||
part_detail = str2bool(self.request.query_params.get('part_detail', None))
|
||||
location_detail = str2bool(self.request.query_params.get('location_detail', None))
|
||||
kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', None))
|
||||
except AttributeError:
|
||||
part_detail = None
|
||||
location_detail = None
|
||||
pass
|
||||
|
||||
kwargs['part_detail'] = part_detail
|
||||
kwargs['location_detail'] = location_detail
|
||||
try:
|
||||
kwargs['location_detail'] = str2bool(self.request.query_params.get('location_detail', None))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
kwargs['supplier_part_detail'] = str2bool(self.request.query_params.get('supplier_part_detail', None))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Ensure the request context is passed through
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
@ -7,6 +7,7 @@ from rest_framework import serializers
|
||||
from .models import StockItem, StockLocation
|
||||
from .models import StockItemTracking
|
||||
|
||||
from company.serializers import SupplierPartSerializer
|
||||
from part.serializers import PartBriefSerializer
|
||||
from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer
|
||||
|
||||
@ -78,13 +79,14 @@ class StockItemSerializer(InvenTreeModelSerializer):
|
||||
performing database queries as efficiently as possible.
|
||||
"""
|
||||
|
||||
# TODO
|
||||
pass
|
||||
# TODO - Add custom annotated fields
|
||||
return queryset
|
||||
|
||||
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
||||
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)
|
||||
supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True)
|
||||
|
||||
tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True)
|
||||
|
||||
@ -92,6 +94,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
|
||||
|
||||
part_detail = kwargs.pop('part_detail', False)
|
||||
location_detail = kwargs.pop('location_detail', False)
|
||||
supplier_part_detail = kwargs.pop('supplier_part_detail', False)
|
||||
|
||||
super(StockItemSerializer, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -101,6 +104,9 @@ class StockItemSerializer(InvenTreeModelSerializer):
|
||||
if location_detail is not True:
|
||||
self.fields.pop('location_detail')
|
||||
|
||||
if supplier_part_detail is not True:
|
||||
self.fields.pop('supplier_part_detail')
|
||||
|
||||
class Meta:
|
||||
model = StockItem
|
||||
fields = [
|
||||
@ -116,6 +122,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
|
||||
'quantity',
|
||||
'serial',
|
||||
'supplier_part',
|
||||
'supplier_part_detail',
|
||||
'status',
|
||||
'status_text',
|
||||
'tracking_items',
|
||||
|
Loading…
Reference in New Issue
Block a user