mirror of
https://github.com/inventree/InvenTree.git
synced 2025-08-09 21:30:54 +00:00
Move Meta class to top of class definition (#4363)
This commit is contained in:
@@ -41,6 +41,13 @@ class CompanyAdmin(ImportExportModelAdmin):
|
||||
class SupplierPartResource(InvenTreeResource):
|
||||
"""Class for managing SupplierPart data import/export."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra admin options"""
|
||||
model = SupplierPart
|
||||
skip_unchanged = True
|
||||
report_skipped = True
|
||||
clean_model_instances = True
|
||||
|
||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||
|
||||
part_name = Field(attribute='part__full_name', readonly=True)
|
||||
@@ -49,13 +56,6 @@ class SupplierPartResource(InvenTreeResource):
|
||||
|
||||
supplier_name = Field(attribute='supplier__name', readonly=True)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra admin options"""
|
||||
model = SupplierPart
|
||||
skip_unchanged = True
|
||||
report_skipped = True
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class SupplierPriceBreakInline(admin.TabularInline):
|
||||
"""Inline for supplier-part pricing"""
|
||||
@@ -87,6 +87,13 @@ class SupplierPartAdmin(ImportExportModelAdmin):
|
||||
class ManufacturerPartResource(InvenTreeResource):
|
||||
"""Class for managing ManufacturerPart data import/export."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra admin options"""
|
||||
model = ManufacturerPart
|
||||
skip_unchanged = True
|
||||
report_skipped = True
|
||||
clean_model_instances = True
|
||||
|
||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||
|
||||
part_name = Field(attribute='part__full_name', readonly=True)
|
||||
@@ -95,13 +102,6 @@ class ManufacturerPartResource(InvenTreeResource):
|
||||
|
||||
manufacturer_name = Field(attribute='manufacturer__name', readonly=True)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra admin options"""
|
||||
model = ManufacturerPart
|
||||
skip_unchanged = True
|
||||
report_skipped = True
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class ManufacturerPartAdmin(ImportExportModelAdmin):
|
||||
"""Admin class for ManufacturerPart model."""
|
||||
@@ -157,6 +157,13 @@ class ManufacturerPartParameterAdmin(ImportExportModelAdmin):
|
||||
class SupplierPriceBreakResource(InvenTreeResource):
|
||||
"""Class for managing SupplierPriceBreak data import/export."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra admin options"""
|
||||
model = SupplierPriceBreak
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(SupplierPart))
|
||||
|
||||
supplier_id = Field(attribute='part__supplier__pk', readonly=True)
|
||||
@@ -169,13 +176,6 @@ class SupplierPriceBreakResource(InvenTreeResource):
|
||||
|
||||
MPN = Field(attribute='part__MPN', readonly=True)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra admin options"""
|
||||
model = SupplierPriceBreak
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class SupplierPriceBreakAdmin(ImportExportModelAdmin):
|
||||
"""Admin class for the SupplierPriceBreak model"""
|
||||
|
@@ -427,6 +427,15 @@ class SupplierPartDetail(RetrieveUpdateDestroyAPI):
|
||||
class SupplierPriceBreakFilter(rest_filters.FilterSet):
|
||||
"""Custom API filters for the SupplierPriceBreak list endpoint"""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options"""
|
||||
|
||||
model = SupplierPriceBreak
|
||||
fields = [
|
||||
'part',
|
||||
'quantity',
|
||||
]
|
||||
|
||||
base_part = rest_filters.ModelChoiceFilter(
|
||||
label='Base Part',
|
||||
queryset=part.models.Part.objects.all(),
|
||||
@@ -439,15 +448,6 @@ class SupplierPriceBreakFilter(rest_filters.FilterSet):
|
||||
field_name='part__supplier',
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options"""
|
||||
|
||||
model = SupplierPriceBreak
|
||||
fields = [
|
||||
'part',
|
||||
'quantity',
|
||||
]
|
||||
|
||||
|
||||
class SupplierPriceBreakList(ListCreateAPI):
|
||||
"""API endpoint for list view of SupplierPriceBreak object.
|
||||
|
@@ -81,11 +81,6 @@ class Company(MetadataMixin, models.Model):
|
||||
currency_code: Specifies the default currency for the company
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return the API URL associated with the Company model"""
|
||||
return reverse('api-company-list')
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
ordering = ['name', ]
|
||||
@@ -94,6 +89,11 @@ class Company(MetadataMixin, models.Model):
|
||||
]
|
||||
verbose_name_plural = "Companies"
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return the API URL associated with the Company model"""
|
||||
return reverse('api-company-list')
|
||||
|
||||
name = models.CharField(max_length=100, blank=False,
|
||||
help_text=_('Company name'),
|
||||
verbose_name=_('Company name'))
|
||||
@@ -258,15 +258,15 @@ class ManufacturerPart(models.Model):
|
||||
description: Descriptive notes field
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ('part', 'manufacturer', 'MPN')
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return the API URL associated with the ManufacturerPart instance"""
|
||||
return reverse('api-manufacturer-part-list')
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ('part', 'manufacturer', 'MPN')
|
||||
|
||||
part = models.ForeignKey('part.Part', on_delete=models.CASCADE,
|
||||
related_name='manufacturer_parts',
|
||||
verbose_name=_('Base Part'),
|
||||
@@ -360,15 +360,15 @@ class ManufacturerPartParameter(models.Model):
|
||||
Each parameter is a simple string (text) value.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ('manufacturer_part', 'name')
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return the API URL associated with the ManufacturerPartParameter model"""
|
||||
return reverse('api-manufacturer-part-parameter-list')
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ('manufacturer_part', 'name')
|
||||
|
||||
manufacturer_part = models.ForeignKey(
|
||||
ManufacturerPart,
|
||||
on_delete=models.CASCADE,
|
||||
@@ -434,6 +434,13 @@ class SupplierPart(InvenTreeBarcodeMixin, common.models.MetaMixin):
|
||||
updated: Date that the SupplierPart was last updated
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ('part', 'supplier', 'SKU')
|
||||
|
||||
# This model was moved from the 'Part' app
|
||||
db_table = 'part_supplierpart'
|
||||
|
||||
objects = SupplierPartManager()
|
||||
|
||||
@staticmethod
|
||||
@@ -453,13 +460,6 @@ class SupplierPart(InvenTreeBarcodeMixin, common.models.MetaMixin):
|
||||
}
|
||||
}
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ('part', 'supplier', 'SKU')
|
||||
|
||||
# This model was moved from the 'Part' app
|
||||
db_table = 'part_supplierpart'
|
||||
|
||||
def clean(self):
|
||||
"""Custom clean action for the SupplierPart model:
|
||||
|
||||
@@ -696,13 +696,6 @@ class SupplierPriceBreak(common.models.PriceBreak):
|
||||
currency: Reference to the currency of this pricebreak (leave empty for base currency)
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return the API URL associated with the SupplierPriceBreak model"""
|
||||
return reverse('api-part-supplier-price-list')
|
||||
|
||||
part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='pricebreaks', verbose_name=_('Part'),)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines extra model options"""
|
||||
unique_together = ("part", "quantity")
|
||||
@@ -714,6 +707,13 @@ class SupplierPriceBreak(common.models.PriceBreak):
|
||||
"""Format a string representation of a SupplierPriceBreak instance"""
|
||||
return f'{self.part.SKU} - {self.price} @ {self.quantity}'
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return the API URL associated with the SupplierPriceBreak model"""
|
||||
return reverse('api-part-supplier-price-list')
|
||||
|
||||
part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='pricebreaks', verbose_name=_('Part'),)
|
||||
|
||||
|
||||
@receiver(post_save, sender=SupplierPriceBreak, dispatch_uid='post_save_supplier_price_break')
|
||||
def after_save_supplier_price(sender, instance, created, **kwargs):
|
||||
|
@@ -25,10 +25,6 @@ from .models import (Company, CompanyAttachment, ManufacturerPart,
|
||||
class CompanyBriefSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for Company object (limited detail)"""
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
image = serializers.CharField(source='get_thumbnail_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
@@ -41,33 +37,14 @@ class CompanyBriefSerializer(InvenTreeModelSerializer):
|
||||
'image',
|
||||
]
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
image = serializers.CharField(source='get_thumbnail_url', read_only=True)
|
||||
|
||||
|
||||
class CompanySerializer(RemoteImageMixin, InvenTreeModelSerializer):
|
||||
"""Serializer for Company object (full detail)"""
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
"""Annoate the supplied queryset with aggregated information"""
|
||||
# Add count of parts manufactured
|
||||
queryset = queryset.annotate(
|
||||
parts_manufactured=SubqueryCount('manufactured_parts')
|
||||
)
|
||||
|
||||
queryset = queryset.annotate(
|
||||
parts_supplied=SubqueryCount('supplied_parts')
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
image = InvenTreeImageSerializerField(required=False, allow_null=True)
|
||||
|
||||
parts_supplied = serializers.IntegerField(read_only=True)
|
||||
parts_manufactured = serializers.IntegerField(read_only=True)
|
||||
|
||||
currency = InvenTreeCurrencySerializer(help_text=_('Default currency used for this supplier'), required=True)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
@@ -95,6 +72,29 @@ class CompanySerializer(RemoteImageMixin, InvenTreeModelSerializer):
|
||||
'remote_image',
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
"""Annoate the supplied queryset with aggregated information"""
|
||||
# Add count of parts manufactured
|
||||
queryset = queryset.annotate(
|
||||
parts_manufactured=SubqueryCount('manufactured_parts')
|
||||
)
|
||||
|
||||
queryset = queryset.annotate(
|
||||
parts_supplied=SubqueryCount('supplied_parts')
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
image = InvenTreeImageSerializerField(required=False, allow_null=True)
|
||||
|
||||
parts_supplied = serializers.IntegerField(read_only=True)
|
||||
parts_manufactured = serializers.IntegerField(read_only=True)
|
||||
|
||||
currency = InvenTreeCurrencySerializer(help_text=_('Default currency used for this supplier'), required=True)
|
||||
|
||||
def save(self):
|
||||
"""Save the Company instance"""
|
||||
super().save()
|
||||
@@ -135,11 +135,21 @@ class CompanyAttachmentSerializer(InvenTreeAttachmentSerializer):
|
||||
class ManufacturerPartSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for ManufacturerPart object."""
|
||||
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
manufacturer_detail = CompanyBriefSerializer(source='manufacturer', many=False, read_only=True)
|
||||
|
||||
pretty_name = serializers.CharField(read_only=True)
|
||||
model = ManufacturerPart
|
||||
fields = [
|
||||
'pk',
|
||||
'part',
|
||||
'part_detail',
|
||||
'pretty_name',
|
||||
'manufacturer',
|
||||
'manufacturer_detail',
|
||||
'description',
|
||||
'MPN',
|
||||
'link',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize this serializer with extra detail fields as required"""
|
||||
@@ -158,24 +168,14 @@ class ManufacturerPartSerializer(InvenTreeModelSerializer):
|
||||
if prettify is not True:
|
||||
self.fields.pop('pretty_name')
|
||||
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
|
||||
manufacturer_detail = CompanyBriefSerializer(source='manufacturer', many=False, read_only=True)
|
||||
|
||||
pretty_name = serializers.CharField(read_only=True)
|
||||
|
||||
manufacturer = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_manufacturer=True))
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
model = ManufacturerPart
|
||||
fields = [
|
||||
'pk',
|
||||
'part',
|
||||
'part_detail',
|
||||
'pretty_name',
|
||||
'manufacturer',
|
||||
'manufacturer_detail',
|
||||
'description',
|
||||
'MPN',
|
||||
'link',
|
||||
]
|
||||
|
||||
|
||||
class ManufacturerPartAttachmentSerializer(InvenTreeAttachmentSerializer):
|
||||
"""Serializer for the ManufacturerPartAttachment class."""
|
||||
@@ -193,17 +193,6 @@ class ManufacturerPartAttachmentSerializer(InvenTreeAttachmentSerializer):
|
||||
class ManufacturerPartParameterSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for the ManufacturerPartParameter model."""
|
||||
|
||||
manufacturer_part_detail = ManufacturerPartSerializer(source='manufacturer_part', many=False, read_only=True)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize this serializer with extra detail fields as required"""
|
||||
man_detail = kwargs.pop('manufacturer_part_detail', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if not man_detail:
|
||||
self.fields.pop('manufacturer_part_detail')
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
@@ -218,66 +207,20 @@ class ManufacturerPartParameterSerializer(InvenTreeModelSerializer):
|
||||
'units',
|
||||
]
|
||||
|
||||
|
||||
class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for SupplierPart object."""
|
||||
|
||||
# Annotated field showing total in-stock quantity
|
||||
in_stock = serializers.FloatField(read_only=True)
|
||||
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
|
||||
supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True)
|
||||
|
||||
manufacturer_detail = CompanyBriefSerializer(source='manufacturer_part.manufacturer', many=False, read_only=True)
|
||||
|
||||
pretty_name = serializers.CharField(read_only=True)
|
||||
|
||||
pack_size = serializers.FloatField(label=_('Pack Quantity'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize this serializer with extra detail fields as required"""
|
||||
|
||||
# Check if 'available' quantity was supplied
|
||||
self.has_available_quantity = 'available' in kwargs.get('data', {})
|
||||
|
||||
brief = kwargs.pop('brief', False)
|
||||
|
||||
detail_default = not brief
|
||||
|
||||
part_detail = kwargs.pop('part_detail', detail_default)
|
||||
supplier_detail = kwargs.pop('supplier_detail', detail_default)
|
||||
manufacturer_detail = kwargs.pop('manufacturer_detail', detail_default)
|
||||
|
||||
prettify = kwargs.pop('pretty', False)
|
||||
man_detail = kwargs.pop('manufacturer_part_detail', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if part_detail is not True:
|
||||
self.fields.pop('part_detail')
|
||||
|
||||
if supplier_detail is not True:
|
||||
self.fields.pop('supplier_detail')
|
||||
|
||||
if manufacturer_detail is not True:
|
||||
self.fields.pop('manufacturer_detail')
|
||||
if not man_detail:
|
||||
self.fields.pop('manufacturer_part_detail')
|
||||
|
||||
if prettify is not True:
|
||||
self.fields.pop('pretty_name')
|
||||
manufacturer_part_detail = ManufacturerPartSerializer(source='manufacturer_part', many=False, read_only=True)
|
||||
|
||||
supplier = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_supplier=True))
|
||||
|
||||
manufacturer = serializers.CharField(read_only=True)
|
||||
|
||||
MPN = serializers.CharField(read_only=True)
|
||||
|
||||
manufacturer_part_detail = ManufacturerPartSerializer(source='manufacturer_part', read_only=True)
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
# Date fields
|
||||
updated = serializers.DateTimeField(allow_null=True, read_only=True)
|
||||
class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for SupplierPart object."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
@@ -314,6 +257,63 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||
'barcode_hash',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize this serializer with extra detail fields as required"""
|
||||
|
||||
# Check if 'available' quantity was supplied
|
||||
self.has_available_quantity = 'available' in kwargs.get('data', {})
|
||||
|
||||
brief = kwargs.pop('brief', False)
|
||||
|
||||
detail_default = not brief
|
||||
|
||||
part_detail = kwargs.pop('part_detail', detail_default)
|
||||
supplier_detail = kwargs.pop('supplier_detail', detail_default)
|
||||
manufacturer_detail = kwargs.pop('manufacturer_detail', detail_default)
|
||||
|
||||
prettify = kwargs.pop('pretty', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if part_detail is not True:
|
||||
self.fields.pop('part_detail')
|
||||
|
||||
if supplier_detail is not True:
|
||||
self.fields.pop('supplier_detail')
|
||||
|
||||
if manufacturer_detail is not True:
|
||||
self.fields.pop('manufacturer_detail')
|
||||
self.fields.pop('manufacturer_part_detail')
|
||||
|
||||
if prettify is not True:
|
||||
self.fields.pop('pretty_name')
|
||||
|
||||
# Annotated field showing total in-stock quantity
|
||||
in_stock = serializers.FloatField(read_only=True)
|
||||
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
|
||||
supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True)
|
||||
|
||||
manufacturer_detail = CompanyBriefSerializer(source='manufacturer_part.manufacturer', many=False, read_only=True)
|
||||
|
||||
pretty_name = serializers.CharField(read_only=True)
|
||||
|
||||
pack_size = serializers.FloatField(label=_('Pack Quantity'))
|
||||
|
||||
supplier = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_supplier=True))
|
||||
|
||||
manufacturer = serializers.CharField(read_only=True)
|
||||
|
||||
MPN = serializers.CharField(read_only=True)
|
||||
|
||||
manufacturer_part_detail = ManufacturerPartSerializer(source='manufacturer_part', read_only=True)
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
# Date fields
|
||||
updated = serializers.DateTimeField(allow_null=True, read_only=True)
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
"""Annotate the SupplierPart queryset with extra fields:
|
||||
@@ -369,6 +369,22 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||
class SupplierPriceBreakSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for SupplierPriceBreak object."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
model = SupplierPriceBreak
|
||||
fields = [
|
||||
'pk',
|
||||
'part',
|
||||
'part_detail',
|
||||
'quantity',
|
||||
'price',
|
||||
'price_currency',
|
||||
'supplier',
|
||||
'supplier_detail',
|
||||
'updated',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize this serializer with extra fields as required"""
|
||||
|
||||
@@ -399,19 +415,3 @@ class SupplierPriceBreakSerializer(InvenTreeModelSerializer):
|
||||
|
||||
# Detail serializer for SupplierPart
|
||||
part_detail = SupplierPartSerializer(source='part', brief=True, many=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
model = SupplierPriceBreak
|
||||
fields = [
|
||||
'pk',
|
||||
'part',
|
||||
'part_detail',
|
||||
'quantity',
|
||||
'price',
|
||||
'price_currency',
|
||||
'supplier',
|
||||
'supplier_detail',
|
||||
'updated',
|
||||
]
|
||||
|
Reference in New Issue
Block a user