From 04374c71c211046e09e381f666f35f6b56a9ac0d Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 25 Jun 2021 00:17:58 +1000 Subject: [PATCH] Annotate models with their API list view - It will make sense, trust me --- InvenTree/build/models.py | 8 ++++ InvenTree/company/api.py | 2 +- InvenTree/company/models.py | 20 ++++++++++ .../company/supplier_part_pricing.html | 2 +- InvenTree/label/models.py | 9 +++++ InvenTree/order/models.py | 29 +++++++++++++++ InvenTree/part/models.py | 37 +++++++++++++++++++ InvenTree/part/serializers.py | 6 ++- InvenTree/report/models.py | 21 +++++++++++ InvenTree/stock/api.py | 2 +- InvenTree/stock/models.py | 20 ++++++++++ InvenTree/stock/templates/stock/item.html | 2 +- 12 files changed, 153 insertions(+), 5 deletions(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index fad5a2934d..848d774d1c 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -60,6 +60,10 @@ class Build(MPTTModel): responsible: User (or group) responsible for completing the build """ + @staticmethod + def get_api_url(): + return reverse('api-build-list') + OVERDUE_FILTER = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date()) class Meta: @@ -1117,6 +1121,10 @@ class BuildItem(models.Model): quantity: Number of units allocated """ + @staticmethod + def get_api_url(): + return reverse('api-build-item-list') + def get_absolute_url(self): # TODO - Fix! return '/build/item/{pk}/'.format(pk=self.id) diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index 6cd1e83dfa..16887414de 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -424,7 +424,7 @@ company_api_urls = [ url(r'^part/', include(supplier_part_api_urls)), - url(r'^price-break/', SupplierPriceBreakList.as_view(), name='api-part-supplier-price'), + url(r'^price-break/', SupplierPriceBreakList.as_view(), name='api-part-supplier-price-list'), url(r'^(?P\d+)/?', CompanyDetail.as_view(), name='api-company-detail'), diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 093d545f78..1c2306fc6a 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -84,6 +84,10 @@ class Company(models.Model): currency_code: Specifies the default currency for the company """ + @staticmethod + def get_api_url(): + return reverse('api-company-list') + class Meta: ordering = ['name', ] constraints = [ @@ -297,6 +301,10 @@ class ManufacturerPart(models.Model): description: Descriptive notes field """ + @staticmethod + def get_api_url(): + return reverse('api-manufacturer-part-list') + class Meta: unique_together = ('part', 'manufacturer', 'MPN') @@ -380,6 +388,10 @@ class ManufacturerPartParameter(models.Model): Each parameter is a simple string (text) value. """ + @staticmethod + def get_api_url(): + return reverse('api-manufacturer-part-parameter-list') + class Meta: unique_together = ('manufacturer_part', 'name') @@ -432,6 +444,10 @@ class SupplierPart(models.Model): packaging: packaging that the part is supplied in, e.g. "Reel" """ + @staticmethod + def get_api_url(): + return reverse('api-supplier-part-list') + def get_absolute_url(self): return reverse('supplier-part-detail', kwargs={'pk': self.id}) @@ -660,6 +676,10 @@ class SupplierPriceBreak(common.models.PriceBreak): currency: Reference to the currency of this pricebreak (leave empty for base currency) """ + @staticmethod + def get_api_url(): + return reverse('api-part-supplier-price-list') + part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='pricebreaks', verbose_name=_('Part'),) class Meta: diff --git a/InvenTree/company/templates/company/supplier_part_pricing.html b/InvenTree/company/templates/company/supplier_part_pricing.html index 9da3f3df7e..89b33049c6 100644 --- a/InvenTree/company/templates/company/supplier_part_pricing.html +++ b/InvenTree/company/templates/company/supplier_part_pricing.html @@ -39,7 +39,7 @@ $('#price-break-table').inventreeTable({ queryParams: { part: {{ part.id }}, }, - url: "{% url 'api-part-supplier-price' %}", + url: "{% url 'api-part-supplier-price-list' %}", onPostBody: function() { var table = $('#price-break-table'); diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index a5d8314193..8a6684d7e3 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -12,6 +12,7 @@ import datetime from django.conf import settings from django.db import models +from django.urls import reverse from django.core.validators import FileExtensionValidator, MinValueValidator from django.core.exceptions import ValidationError, FieldError @@ -237,6 +238,10 @@ class StockItemLabel(LabelTemplate): Template for printing StockItem labels """ + @staticmethod + def get_api_url(): + return reverse('api-stockitem-label-list') + SUBDIR = "stockitem" filters = models.CharField( @@ -290,6 +295,10 @@ class StockLocationLabel(LabelTemplate): Template for printing StockLocation labels """ + @staticmethod + def get_api_url(): + return reverse('api-stocklocation-label-list') + SUBDIR = "stocklocation" filters = models.CharField( diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index c150331f94..1aa34838b7 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -136,6 +136,10 @@ class PurchaseOrder(Order): target_date: Expected delivery target date for PurchaseOrder completion (optional) """ + @staticmethod + def get_api_url(): + return reverse('api-po-list') + OVERDUE_FILTER = Q(status__in=PurchaseOrderStatus.OPEN) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date()) @staticmethod @@ -407,6 +411,10 @@ class SalesOrder(Order): target_date: Target date for SalesOrder completion (optional) """ + @staticmethod + def get_api_url(): + return reverse('api-so-list') + OVERDUE_FILTER = Q(status__in=SalesOrderStatus.OPEN) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date()) @staticmethod @@ -585,6 +593,10 @@ class PurchaseOrderAttachment(InvenTreeAttachment): Model for storing file attachments against a PurchaseOrder object """ + @staticmethod + def get_api_url(): + return reverse('api-po-attachment-list') + def getSubdir(self): return os.path.join("po_files", str(self.order.id)) @@ -596,6 +608,10 @@ class SalesOrderAttachment(InvenTreeAttachment): Model for storing file attachments against a SalesOrder object """ + @staticmethod + def get_api_url(): + return reverse('api-so-attachment-list') + def getSubdir(self): return os.path.join("so_files", str(self.order.id)) @@ -629,6 +645,11 @@ class PurchaseOrderLineItem(OrderLineItem): """ + @staticmethod + def get_api_url(): + return reverse('api-po-line-list') + + class Meta: unique_together = ( ('order', 'part') @@ -712,6 +733,10 @@ class SalesOrderLineItem(OrderLineItem): sale_price: The unit sale price for this OrderLineItem """ + @staticmethod + def get_api_url(): + return reverse('api-so-line-list') + order = models.ForeignKey(SalesOrder, on_delete=models.CASCADE, related_name='lines', verbose_name=_('Order'), help_text=_('Sales Order')) part = models.ForeignKey('part.Part', on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, verbose_name=_('Part'), help_text=_('Part'), limit_choices_to={'salable': True}) @@ -774,6 +799,10 @@ class SalesOrderAllocation(models.Model): """ + @staticmethod + def get_api_url(): + return reverse('api-so-allocation-list') + class Meta: unique_together = [ # Cannot allocate any given StockItem to the same line more than once diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 8ddf049216..b979f7ece5 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -75,6 +75,10 @@ class PartCategory(InvenTreeTree): default_keywords = models.CharField(null=True, blank=True, max_length=250, verbose_name=_('Default keywords'), help_text=_('Default keywords for parts in this category')) + @staticmethod + def get_api_url(): + return reverse('api-part-category-list') + def get_absolute_url(self): return reverse('category-detail', kwargs={'pk': self.id}) @@ -329,6 +333,11 @@ class Part(MPTTModel): # For legacy reasons the 'variant_of' field is used to indicate the MPTT parent parent_attr = 'variant_of' + @staticmethod + def get_api_url(): + + return reverse('api-part-list') + def get_context_data(self, request, **kwargs): """ Return some useful context data about this part for template rendering @@ -1966,6 +1975,10 @@ class PartAttachment(InvenTreeAttachment): Model for storing file attachments against a Part object """ + @staticmethod + def get_api_url(): + return reverse('api-part-attachment-list') + def getSubdir(self): return os.path.join("part_files", str(self.part.id)) @@ -1977,6 +1990,10 @@ class PartSellPriceBreak(common.models.PriceBreak): """ Represents a price break for selling this part """ + + @staticmethod + def get_api_url(): + return reverse('api-part-sale-price-list') part = models.ForeignKey( Part, on_delete=models.CASCADE, @@ -1994,6 +2011,10 @@ class PartInternalPriceBreak(common.models.PriceBreak): Represents a price break for internally selling this part """ + @staticmethod + def get_api_url(): + return reverse('api-part-internal-price-list') + part = models.ForeignKey( Part, on_delete=models.CASCADE, related_name='internalpricebreaks', @@ -2038,6 +2059,10 @@ class PartTestTemplate(models.Model): run on the model (refer to the validate_unique function). """ + @staticmethod + def get_api_url(): + return reverse('api-part-test-template-list') + def save(self, *args, **kwargs): self.clean() @@ -2136,6 +2161,10 @@ class PartParameterTemplate(models.Model): units: The units of the Parameter [string] """ + @staticmethod + def get_api_url(): + return reverse('api-part-param-template-list') + def __str__(self): s = str(self.name) if self.units: @@ -2173,6 +2202,10 @@ class PartParameter(models.Model): data: The data (value) of the Parameter [string] """ + @staticmethod + def get_api_url(): + return reverse('api-part-param-list') + def __str__(self): # String representation of a PartParameter (used in the admin interface) return "{part} : {param} = {data}{units}".format( @@ -2264,6 +2297,10 @@ class BomItem(models.Model): allow_variants: Stock for part variants can be substituted for this BomItem """ + @staticmethod + def get_api_url(): + return reverse('api-bom-list') + def save(self, *args, **kwargs): self.clean() diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 6c47f1310f..e73ff54c25 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -4,6 +4,7 @@ JSON serializers for Part app import imghdr from decimal import Decimal +from django.urls import reverse_lazy from django.db import models from django.db.models import Q from django.db.models.functions import Coalesce @@ -187,6 +188,9 @@ class PartSerializer(InvenTreeModelSerializer): Used when displaying all details of a single component. """ + def get_api_url(self): + return reverse_lazy('api-part-list') + def __init__(self, *args, **kwargs): """ Custom initialization method for PartSerializer, @@ -305,7 +309,7 @@ class PartSerializer(InvenTreeModelSerializer): image = InvenTreeImageSerializerField(required=False, allow_null=True) thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True) - starred = serializers.SerializerMethodField() + starred = serializers.BooleanField() # PrimaryKeyRelated fields (Note: enforcing field type here results in much faster queries, somehow...) category = serializers.PrimaryKeyRelatedField(queryset=PartCategory.objects.all()) diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index ecb4d91492..c33347f643 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -11,6 +11,7 @@ import logging import datetime +from django.urls import reverse from django.db import models from django.conf import settings from django.core.exceptions import ValidationError, FieldError @@ -307,6 +308,10 @@ class TestReport(ReportTemplateBase): Render a TestReport against a StockItem object. """ + @staticmethod + def get_api_url(): + return reverse('api-stockitem-testreport-list') + @classmethod def getSubdir(cls): return 'test' @@ -361,6 +366,10 @@ class BuildReport(ReportTemplateBase): Build order / work order report """ + @staticmethod + def get_api_url(): + return reverse('api-build-report-list') + @classmethod def getSubdir(cls): return 'build' @@ -400,6 +409,10 @@ class BillOfMaterialsReport(ReportTemplateBase): Render a Bill of Materials against a Part object """ + @staticmethod + def get_api_url(): + return reverse('api-bom-report-list') + @classmethod def getSubdir(cls): return 'bom' @@ -430,6 +443,10 @@ class PurchaseOrderReport(ReportTemplateBase): Render a report against a PurchaseOrder object """ + @staticmethod + def get_api_url(): + return reverse('api-po-report-list') + @classmethod def getSubdir(cls): return 'purchaseorder' @@ -464,6 +481,10 @@ class SalesOrderReport(ReportTemplateBase): Render a report against a SalesOrder object """ + @staticmethod + def get_api_url(): + return reverse('api-so-report-list') + @classmethod def getSubdir(cls): return 'salesorder' diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 3fc440cae4..d1add67d9d 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -1148,7 +1148,7 @@ stock_api_urls = [ url(r'^$', StockItemTestResultList.as_view(), name='api-stock-test-result-list'), ])), - url(r'track/?', StockTrackingList.as_view(), name='api-stock-track'), + url(r'track/?', StockTrackingList.as_view(), name='api-stock-tracking-list'), url(r'^tree/?', StockCategoryTree.as_view(), name='api-stock-tree'), diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 9786b360d9..a29630b4d7 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -52,6 +52,10 @@ class StockLocation(InvenTreeTree): Stock locations can be heirarchical as required """ + @staticmethod + def get_api_url(): + return reverse('api-location-list') + owner = models.ForeignKey(Owner, on_delete=models.SET_NULL, blank=True, null=True, verbose_name=_('Owner'), help_text=_('Select Owner'), @@ -161,6 +165,10 @@ class StockItem(MPTTModel): packaging: Description of how the StockItem is packaged (e.g. "reel", "loose", "tape" etc) """ + @staticmethod + def get_api_url(): + return reverse('api-stock-list') + # A Query filter which will be re-used in multiple places to determine if a StockItem is actually "in stock" IN_STOCK_FILTER = Q( quantity__gt=0, @@ -1608,6 +1616,10 @@ class StockItemAttachment(InvenTreeAttachment): Model for storing file attachments against a StockItem object. """ + @staticmethod + def get_api_url(): + return reverse('api-stock-attachment-list') + def getSubdir(self): return os.path.join("stock_files", str(self.stock_item.id)) @@ -1639,6 +1651,10 @@ class StockItemTracking(models.Model): deltas: The changes associated with this history item """ + @staticmethod + def get_api_url(): + return reverse('api-stock-tracking-list') + def get_absolute_url(self): return '/stock/track/{pk}'.format(pk=self.id) @@ -1697,6 +1713,10 @@ class StockItemTestResult(models.Model): date: Date the test result was recorded """ + @staticmethod + def get_api_url(): + return reverse('api-stock-test-result-list') + def save(self, *args, **kwargs): super().clean() diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html index 5d551c29fb..7564e7864e 100644 --- a/InvenTree/stock/templates/stock/item.html +++ b/InvenTree/stock/templates/stock/item.html @@ -57,7 +57,7 @@ item: {{ item.pk }}, user_detail: true, }, - url: "{% url 'api-stock-track' %}", + url: "{% url 'api-stock-tracking-list' %}", }); {% endblock %} \ No newline at end of file