2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 13:05:42 +00:00

Move Meta class to top of class definition (#4363)

This commit is contained in:
Oliver
2023-02-18 18:51:00 +11:00
committed by GitHub
parent 139274f356
commit cc2e7ee8a5
27 changed files with 1085 additions and 1084 deletions

View File

@ -16,6 +16,20 @@ from stock.models import StockLocation
class PartResource(InvenTreeResource):
"""Class for managing Part data import/export."""
class Meta:
"""Metaclass definition"""
model = models.Part
skip_unchanged = True
report_skipped = False
clean_model_instances = True
exclude = [
'bom_checksum', 'bom_checked_by', 'bom_checked_date',
'lft', 'rght', 'tree_id', 'level',
'image',
'metadata',
'barcode_data', 'barcode_hash',
]
id = Field(attribute='pk', column_name=_('Part ID'), widget=widgets.IntegerWidget())
name = Field(attribute='name', column_name=_('Part Name'), widget=widgets.CharWidget())
description = Field(attribute='description', column_name=_('Part Description'), widget=widgets.CharWidget())
@ -68,20 +82,6 @@ class PartResource(InvenTreeResource):
if max_cost is not None:
return float(max_cost.amount)
class Meta:
"""Metaclass definition"""
model = models.Part
skip_unchanged = True
report_skipped = False
clean_model_instances = True
exclude = [
'bom_checksum', 'bom_checked_by', 'bom_checked_date',
'lft', 'rght', 'tree_id', 'level',
'image',
'metadata',
'barcode_data', 'barcode_hash',
]
def get_queryset(self):
"""Prefetch related data for quicker access."""
query = super().get_queryset()
@ -175,18 +175,6 @@ class PartStocktakeReportAdmin(admin.ModelAdmin):
class PartCategoryResource(InvenTreeResource):
"""Class for managing PartCategory data import/export."""
id = Field(attribute='pk', column_name=_('Category ID'))
name = Field(attribute='name', column_name=_('Category Name'))
description = Field(attribute='description', column_name=_('Description'))
parent = Field(attribute='parent', column_name=_('Parent ID'), widget=widgets.ForeignKeyWidget(models.PartCategory))
parent_name = Field(attribute='parent__name', column_name=_('Parent Name'), readonly=True)
default_location = Field(attribute='default_location', column_name=_('Default Location ID'), widget=widgets.ForeignKeyWidget(StockLocation))
default_keywords = Field(attribute='default_keywords', column_name=_('Keywords'))
pathstring = Field(attribute='pathstring', column_name=_('Category Path'))
# Calculated fields
parts = Field(attribute='item_count', column_name=_('Parts'), widget=widgets.IntegerWidget(), readonly=True)
class Meta:
"""Metaclass definition"""
model = models.PartCategory
@ -201,6 +189,18 @@ class PartCategoryResource(InvenTreeResource):
'icon',
]
id = Field(attribute='pk', column_name=_('Category ID'))
name = Field(attribute='name', column_name=_('Category Name'))
description = Field(attribute='description', column_name=_('Description'))
parent = Field(attribute='parent', column_name=_('Parent ID'), widget=widgets.ForeignKeyWidget(models.PartCategory))
parent_name = Field(attribute='parent__name', column_name=_('Parent Name'), readonly=True)
default_location = Field(attribute='default_location', column_name=_('Default Location ID'), widget=widgets.ForeignKeyWidget(StockLocation))
default_keywords = Field(attribute='default_keywords', column_name=_('Keywords'))
pathstring = Field(attribute='pathstring', column_name=_('Category Path'))
# Calculated fields
parts = Field(attribute='item_count', column_name=_('Parts'), widget=widgets.IntegerWidget(), readonly=True)
def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
"""Rebuild MPTT tree structure after importing PartCategory data"""
@ -247,6 +247,20 @@ class PartTestTemplateAdmin(admin.ModelAdmin):
class BomItemResource(InvenTreeResource):
"""Class for managing BomItem data import/export."""
class Meta:
"""Metaclass definition"""
model = models.BomItem
skip_unchanged = True
report_skipped = False
clean_model_instances = True
exclude = [
'checksum',
'id',
'part',
'sub_part',
]
level = Field(attribute='level', column_name=_('BOM Level'), readonly=True)
bom_id = Field(attribute='pk', column_name=_('BOM Item ID'))
@ -335,20 +349,6 @@ class BomItemResource(InvenTreeResource):
return fields
class Meta:
"""Metaclass definition"""
model = models.BomItem
skip_unchanged = True
report_skipped = False
clean_model_instances = True
exclude = [
'checksum',
'id',
'part',
'sub_part',
]
class BomItemAdmin(ImportExportModelAdmin):
"""Admin class for the BomItem model"""
@ -373,6 +373,13 @@ class ParameterTemplateAdmin(ImportExportModelAdmin):
class ParameterResource(InvenTreeResource):
"""Class for managing PartParameter data import/export."""
class Meta:
"""Metaclass definition"""
model = models.PartParameter
skip_unchanged = True
report_skipped = False
clean_model_instance = True
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(models.Part))
part_name = Field(attribute='part__name', readonly=True)
@ -381,13 +388,6 @@ class ParameterResource(InvenTreeResource):
template_name = Field(attribute='template__name', readonly=True)
class Meta:
"""Metaclass definition"""
model = models.PartParameter
skip_unchanged = True
report_skipped = False
clean_model_instance = True
class ParameterAdmin(ImportExportModelAdmin):
"""Admin class for the PartParameter model"""

View File

@ -34,16 +34,16 @@ class BomMatchItemForm(MatchItemForm):
class PartPriceForm(forms.Form):
"""Simple form for viewing part pricing information."""
quantity = forms.IntegerField(
required=True,
initial=1,
label=_('Quantity'),
help_text=_('Input quantity for price calculation')
)
class Meta:
"""Metaclass defines fields for this form"""
model = Part
fields = [
'quantity',
]
quantity = forms.IntegerField(
required=True,
initial=1,
label=_('Quantity'),
help_text=_('Input quantity for price calculation')
)

View File

@ -3045,6 +3045,10 @@ class PartAttachment(InvenTreeAttachment):
class PartSellPriceBreak(common.models.PriceBreak):
"""Represents a price break for selling this part."""
class Meta:
"""Metaclass providing extra model definition"""
unique_together = ('part', 'quantity')
@staticmethod
def get_api_url():
"""Return the list API endpoint URL associated with the PartSellPriceBreak model"""
@ -3057,14 +3061,14 @@ class PartSellPriceBreak(common.models.PriceBreak):
verbose_name=_('Part')
)
class Meta:
"""Metaclass providing extra model definition"""
unique_together = ('part', 'quantity')
class PartInternalPriceBreak(common.models.PriceBreak):
"""Represents a price break for internally selling this part."""
class Meta:
"""Metaclass providing extra model definition"""
unique_together = ('part', 'quantity')
@staticmethod
def get_api_url():
"""Return the list API endpoint URL associated with the PartInternalPriceBreak model"""
@ -3076,10 +3080,6 @@ class PartInternalPriceBreak(common.models.PriceBreak):
verbose_name=_('Part')
)
class Meta:
"""Metaclass providing extra model definition"""
unique_together = ('part', 'quantity')
class PartStar(models.Model):
"""A PartStar object creates a subscription relationship between a User and a Part.
@ -3091,10 +3091,6 @@ class PartStar(models.Model):
user: Link to a User object
"""
part = models.ForeignKey(Part, on_delete=models.CASCADE, verbose_name=_('Part'), related_name='starred_users')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('User'), related_name='starred_parts')
class Meta:
"""Metaclass providing extra model definition"""
unique_together = [
@ -3102,6 +3098,10 @@ class PartStar(models.Model):
'user'
]
part = models.ForeignKey(Part, on_delete=models.CASCADE, verbose_name=_('Part'), related_name='starred_users')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('User'), related_name='starred_parts')
class PartCategoryStar(models.Model):
"""A PartCategoryStar creates a subscription relationship between a User and a PartCategory.
@ -3111,10 +3111,6 @@ class PartCategoryStar(models.Model):
user: Link to a User object
"""
category = models.ForeignKey(PartCategory, on_delete=models.CASCADE, verbose_name=_('Category'), related_name='starred_users')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('User'), related_name='starred_categories')
class Meta:
"""Metaclass providing extra model definition"""
unique_together = [
@ -3122,6 +3118,10 @@ class PartCategoryStar(models.Model):
'user',
]
category = models.ForeignKey(PartCategory, on_delete=models.CASCADE, verbose_name=_('Category'), related_name='starred_users')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('User'), related_name='starred_categories')
class PartTestTemplate(models.Model):
"""A PartTestTemplate defines a 'template' for a test which is required to be run against a StockItem (an instance of the Part).
@ -3292,6 +3292,11 @@ class PartParameter(models.Model):
data: The data (value) of the Parameter [string]
"""
class Meta:
"""Metaclass providing extra model definition"""
# Prevent multiple instances of a parameter for a single part
unique_together = ('part', 'template')
@staticmethod
def get_api_url():
"""Return the list API endpoint URL associated with the PartParameter model"""
@ -3306,11 +3311,6 @@ class PartParameter(models.Model):
units=str(self.template.units)
)
class Meta:
"""Metaclass providing extra model definition"""
# Prevent multiple instances of a parameter for a single part
unique_together = ('part', 'template')
part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='parameters', verbose_name=_('Part'), help_text=_('Parent Part'))
template = models.ForeignKey(PartParameterTemplate, on_delete=models.CASCADE, related_name='instances', verbose_name=_('Template'), help_text=_('Parameter Template'))
@ -3424,6 +3424,17 @@ class BomItem(DataImportMixin, models.Model):
}
}
class Meta:
"""Metaclass providing extra model definition"""
verbose_name = _("BOM Item")
def __str__(self):
"""Return a string representation of this BomItem instance"""
return "{n} x {child} to make {parent}".format(
parent=self.part.full_name,
child=self.sub_part.full_name,
n=decimal2string(self.quantity))
@staticmethod
def get_api_url():
"""Return the list API endpoint URL associated with the BomItem model"""
@ -3638,17 +3649,6 @@ class BomItem(DataImportMixin, models.Model):
except Part.DoesNotExist:
raise ValidationError({'sub_part': _('Sub part must be specified')})
class Meta:
"""Metaclass providing extra model definition"""
verbose_name = _("BOM Item")
def __str__(self):
"""Return a string representation of this BomItem instance"""
return "{n} x {child} to make {parent}".format(
parent=self.part.full_name,
child=self.sub_part.full_name,
n=decimal2string(self.quantity))
def get_overage_quantity(self, quantity):
"""Calculate overage quantity."""
# Most of the time overage string will be empty

View File

@ -46,6 +46,25 @@ from .models import (BomItem, BomItemSubstitute, Part, PartAttachment,
class CategorySerializer(InvenTreeModelSerializer):
"""Serializer for PartCategory."""
class Meta:
"""Metaclass defining serializer fields"""
model = PartCategory
fields = [
'pk',
'name',
'description',
'default_location',
'default_keywords',
'level',
'parent',
'part_count',
'pathstring',
'starred',
'url',
'structural',
'icon',
]
def get_starred(self, category):
"""Return True if the category is directly "starred" by the current user."""
return category in self.context.get('starred_categories', [])
@ -69,25 +88,6 @@ class CategorySerializer(InvenTreeModelSerializer):
starred = serializers.SerializerMethodField()
class Meta:
"""Metaclass defining serializer fields"""
model = PartCategory
fields = [
'pk',
'name',
'description',
'default_location',
'default_keywords',
'level',
'parent',
'part_count',
'pathstring',
'starred',
'url',
'structural',
'icon',
]
class CategoryTree(InvenTreeModelSerializer):
"""Serializer for PartCategory tree."""
@ -118,8 +118,6 @@ class PartAttachmentSerializer(InvenTreeAttachmentSerializer):
class PartTestTemplateSerializer(InvenTreeModelSerializer):
"""Serializer for the PartTestTemplate class."""
key = serializers.CharField(read_only=True)
class Meta:
"""Metaclass defining serializer fields"""
model = PartTestTemplate
@ -135,16 +133,12 @@ class PartTestTemplateSerializer(InvenTreeModelSerializer):
'requires_attachment',
]
key = serializers.CharField(read_only=True)
class PartSalePriceSerializer(InvenTreeModelSerializer):
"""Serializer for sale prices for Part model."""
quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer(allow_null=True)
price_currency = InvenTreeCurrencySerializer(help_text=_('Purchase currency of this stock item'))
class Meta:
"""Metaclass defining serializer fields"""
model = PartSellPriceBreak
@ -156,18 +150,16 @@ class PartSalePriceSerializer(InvenTreeModelSerializer):
'price_currency',
]
quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer(allow_null=True)
price_currency = InvenTreeCurrencySerializer(help_text=_('Purchase currency of this stock item'))
class PartInternalPriceSerializer(InvenTreeModelSerializer):
"""Serializer for internal prices for Part model."""
quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer(
allow_null=True
)
price_currency = InvenTreeCurrencySerializer(help_text=_('Purchase currency of this stock item'))
class Meta:
"""Metaclass defining serializer fields"""
model = PartInternalPriceBreak
@ -179,6 +171,14 @@ class PartInternalPriceSerializer(InvenTreeModelSerializer):
'price_currency',
]
quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer(
allow_null=True
)
price_currency = InvenTreeCurrencySerializer(help_text=_('Purchase currency of this stock item'))
class PartThumbSerializer(serializers.Serializer):
"""Serializer for the 'image' field of the Part model.
@ -193,6 +193,13 @@ class PartThumbSerializer(serializers.Serializer):
class PartThumbSerializerUpdate(InvenTreeModelSerializer):
"""Serializer for updating Part thumbnail."""
class Meta:
"""Metaclass defining serializer fields"""
model = Part
fields = [
'image',
]
def validate_image(self, value):
"""Check that file is an image."""
validate = imghdr.what(value)
@ -202,13 +209,6 @@ class PartThumbSerializerUpdate(InvenTreeModelSerializer):
image = InvenTreeAttachmentSerializerField(required=True)
class Meta:
"""Metaclass defining serializer fields"""
model = Part
fields = [
'image',
]
class PartParameterTemplateSerializer(InvenTreeModelSerializer):
"""JSON serializer for the PartParameterTemplate model."""
@ -227,6 +227,17 @@ class PartParameterTemplateSerializer(InvenTreeModelSerializer):
class PartParameterSerializer(InvenTreeModelSerializer):
"""JSON serializers for the PartParameter model."""
class Meta:
"""Metaclass defining serializer fields"""
model = PartParameter
fields = [
'pk',
'part',
'template',
'template_detail',
'data'
]
def __init__(self, *args, **kwargs):
"""Custom initialization method for the serializer.
@ -242,23 +253,10 @@ class PartParameterSerializer(InvenTreeModelSerializer):
template_detail = PartParameterTemplateSerializer(source='template', many=False, read_only=True)
class Meta:
"""Metaclass defining serializer fields"""
model = PartParameter
fields = [
'pk',
'part',
'template',
'template_detail',
'data'
]
class PartBriefSerializer(InvenTreeModelSerializer):
"""Serializer for Part (brief detail)"""
thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
class Meta:
"""Metaclass defining serializer fields"""
model = Part
@ -286,6 +284,8 @@ class PartBriefSerializer(InvenTreeModelSerializer):
'barcode_hash',
]
thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
class DuplicatePartSerializer(serializers.Serializer):
"""Serializer for specifying options when duplicating a Part.
@ -400,22 +400,65 @@ class PartSerializer(RemoteImageMixin, InvenTreeModelSerializer):
Used when displaying all details of a single component.
"""
def get_api_url(self):
"""Return the API url associated with this serializer"""
return reverse_lazy('api-part-list')
class Meta:
"""Metaclass defining serializer fields"""
model = Part
partial = True
fields = [
'active',
'allocated_to_build_orders',
'allocated_to_sales_orders',
'assembly',
'barcode_hash',
'category',
'category_detail',
'component',
'default_expiry',
'default_location',
'default_supplier',
'description',
'full_name',
'image',
'in_stock',
'variant_stock',
'ordering',
'building',
'IPN',
'is_template',
'keywords',
'last_stocktake',
'link',
'minimum_stock',
'name',
'notes',
'parameters',
'pk',
'purchaseable',
'remote_image',
'revision',
'salable',
'starred',
'stock_item_count',
'suppliers',
'thumbnail',
'trackable',
'unallocated_stock',
'units',
'variant_of',
'virtual',
'pricing_min',
'pricing_max',
'responsible',
def skip_create_fields(self):
"""Skip these fields when instantiating a new Part instance"""
fields = super().skip_create_fields()
fields += [
# Fields only used for Part creation
'duplicate',
'initial_stock',
'initial_supplier',
]
return fields
read_only_fields = [
'barcode_hash',
]
def __init__(self, *args, **kwargs):
"""Custom initialization method for PartSerializer:
@ -443,6 +486,23 @@ class PartSerializer(RemoteImageMixin, InvenTreeModelSerializer):
for f in self.skip_create_fields()[1:]:
self.fields.pop(f)
def get_api_url(self):
"""Return the API url associated with this serializer"""
return reverse_lazy('api-part-list')
def skip_create_fields(self):
"""Skip these fields when instantiating a new Part instance"""
fields = super().skip_create_fields()
fields += [
'duplicate',
'initial_stock',
'initial_supplier',
]
return fields
@staticmethod
def annotate_queryset(queryset):
"""Add some extra annotations to the queryset.
@ -553,66 +613,6 @@ class PartSerializer(RemoteImageMixin, InvenTreeModelSerializer):
write_only=True, required=False,
)
class Meta:
"""Metaclass defining serializer fields"""
model = Part
partial = True
fields = [
'active',
'allocated_to_build_orders',
'allocated_to_sales_orders',
'assembly',
'barcode_hash',
'category',
'category_detail',
'component',
'default_expiry',
'default_location',
'default_supplier',
'description',
'full_name',
'image',
'in_stock',
'variant_stock',
'ordering',
'building',
'IPN',
'is_template',
'keywords',
'last_stocktake',
'link',
'minimum_stock',
'name',
'notes',
'parameters',
'pk',
'purchaseable',
'remote_image',
'revision',
'salable',
'starred',
'stock_item_count',
'suppliers',
'thumbnail',
'trackable',
'unallocated_stock',
'units',
'variant_of',
'virtual',
'pricing_min',
'pricing_max',
'responsible',
# Fields only used for Part creation
'duplicate',
'initial_stock',
'initial_supplier',
]
read_only_fields = [
'barcode_hash',
]
@transaction.atomic
def create(self, validated_data):
"""Custom method for creating a new Part instance using this serializer"""
@ -708,16 +708,6 @@ class PartSerializer(RemoteImageMixin, InvenTreeModelSerializer):
class PartStocktakeSerializer(InvenTreeModelSerializer):
"""Serializer for the PartStocktake model"""
quantity = serializers.FloatField()
user_detail = UserSerializer(source='user', read_only=True, many=False)
cost_min = InvenTreeMoneySerializer(allow_null=True)
cost_min_currency = InvenTreeCurrencySerializer()
cost_max = InvenTreeMoneySerializer(allow_null=True)
cost_max_currency = InvenTreeCurrencySerializer()
class Meta:
"""Metaclass options"""
@ -742,6 +732,16 @@ class PartStocktakeSerializer(InvenTreeModelSerializer):
'user',
]
quantity = serializers.FloatField()
user_detail = UserSerializer(source='user', read_only=True, many=False)
cost_min = InvenTreeMoneySerializer(allow_null=True)
cost_min_currency = InvenTreeCurrencySerializer()
cost_max = InvenTreeMoneySerializer(allow_null=True)
cost_max_currency = InvenTreeCurrencySerializer()
def save(self):
"""Called when this serializer is saved"""
@ -757,10 +757,6 @@ class PartStocktakeSerializer(InvenTreeModelSerializer):
class PartStocktakeReportSerializer(InvenTreeModelSerializer):
"""Serializer for stocktake report class"""
user_detail = UserSerializer(source='user', read_only=True, many=False)
report = InvenTreeAttachmentSerializerField(read_only=True)
class Meta:
"""Metaclass defines serializer fields"""
@ -774,6 +770,10 @@ class PartStocktakeReportSerializer(InvenTreeModelSerializer):
'user_detail',
]
user_detail = UserSerializer(source='user', read_only=True, many=False)
report = InvenTreeAttachmentSerializerField(read_only=True)
class PartStocktakeReportGenerateSerializer(serializers.Serializer):
"""Serializer class for manually generating a new PartStocktakeReport via the API"""
@ -843,6 +843,32 @@ class PartStocktakeReportGenerateSerializer(serializers.Serializer):
class PartPricingSerializer(InvenTreeModelSerializer):
"""Serializer for Part pricing information"""
class Meta:
"""Metaclass defining serializer fields"""
model = PartPricing
fields = [
'currency',
'updated',
'scheduled_for_update',
'bom_cost_min',
'bom_cost_max',
'purchase_cost_min',
'purchase_cost_max',
'internal_cost_min',
'internal_cost_max',
'supplier_price_min',
'supplier_price_max',
'variant_cost_min',
'variant_cost_max',
'overall_min',
'overall_max',
'sale_price_min',
'sale_price_max',
'sale_history_min',
'sale_history_max',
'update',
]
currency = serializers.CharField(allow_null=True, read_only=True)
updated = serializers.DateTimeField(allow_null=True, read_only=True)
@ -882,32 +908,6 @@ class PartPricingSerializer(InvenTreeModelSerializer):
required=False,
)
class Meta:
"""Metaclass defining serializer fields"""
model = PartPricing
fields = [
'currency',
'updated',
'scheduled_for_update',
'bom_cost_min',
'bom_cost_max',
'purchase_cost_min',
'purchase_cost_max',
'internal_cost_min',
'internal_cost_max',
'supplier_price_min',
'supplier_price_max',
'variant_cost_min',
'variant_cost_max',
'overall_min',
'overall_max',
'sale_price_min',
'sale_price_max',
'sale_history_min',
'sale_history_max',
'update',
]
def save(self):
"""Called when the serializer is saved"""
data = self.validated_data
@ -921,9 +921,6 @@ class PartPricingSerializer(InvenTreeModelSerializer):
class PartRelationSerializer(InvenTreeModelSerializer):
"""Serializer for a PartRelated model."""
part_1_detail = PartSerializer(source='part_1', read_only=True, many=False)
part_2_detail = PartSerializer(source='part_2', read_only=True, many=False)
class Meta:
"""Metaclass defining serializer fields"""
model = PartRelated
@ -935,13 +932,13 @@ class PartRelationSerializer(InvenTreeModelSerializer):
'part_2_detail',
]
part_1_detail = PartSerializer(source='part_1', read_only=True, many=False)
part_2_detail = PartSerializer(source='part_2', read_only=True, many=False)
class PartStarSerializer(InvenTreeModelSerializer):
"""Serializer for a PartStar object."""
partname = serializers.CharField(source='part.full_name', read_only=True)
username = serializers.CharField(source='user.username', read_only=True)
class Meta:
"""Metaclass defining serializer fields"""
model = PartStar
@ -953,12 +950,13 @@ class PartStarSerializer(InvenTreeModelSerializer):
'username',
]
partname = serializers.CharField(source='part.full_name', read_only=True)
username = serializers.CharField(source='user.username', read_only=True)
class BomItemSubstituteSerializer(InvenTreeModelSerializer):
"""Serializer for the BomItemSubstitute class."""
part_detail = PartBriefSerializer(source='part', read_only=True, many=False)
class Meta:
"""Metaclass defining serializer fields"""
model = BomItemSubstitute
@ -969,10 +967,60 @@ class BomItemSubstituteSerializer(InvenTreeModelSerializer):
'part_detail',
]
part_detail = PartBriefSerializer(source='part', read_only=True, many=False)
class BomItemSerializer(InvenTreeModelSerializer):
"""Serializer for BomItem object."""
class Meta:
"""Metaclass defining serializer fields"""
model = BomItem
fields = [
'allow_variants',
'inherited',
'note',
'optional',
'consumable',
'overage',
'pk',
'part',
'part_detail',
'pricing_min',
'pricing_max',
'quantity',
'reference',
'sub_part',
'sub_part_detail',
'substitutes',
'validated',
# Annotated fields describing available quantity
'available_stock',
'available_substitute_stock',
'available_variant_stock',
# Annotated field describing quantity on order
'on_order',
]
def __init__(self, *args, **kwargs):
"""Determine if extra detail fields are to be annotated on this serializer
- part_detail and sub_part_detail serializers are only included if requested.
- This saves a bunch of database requests
"""
part_detail = kwargs.pop('part_detail', False)
sub_part_detail = kwargs.pop('sub_part_detail', False)
super(BomItemSerializer, self).__init__(*args, **kwargs)
if part_detail is not True:
self.fields.pop('part_detail')
if sub_part_detail is not True:
self.fields.pop('sub_part_detail')
quantity = InvenTreeDecimalField(required=True)
def validate_quantity(self, quantity):
@ -1005,23 +1053,6 @@ class BomItemSerializer(InvenTreeModelSerializer):
available_substitute_stock = serializers.FloatField(read_only=True)
available_variant_stock = serializers.FloatField(read_only=True)
def __init__(self, *args, **kwargs):
"""Determine if extra detail fields are to be annotated on this serializer
- part_detail and sub_part_detail serializers are only included if requested.
- This saves a bunch of database requests
"""
part_detail = kwargs.pop('part_detail', False)
sub_part_detail = kwargs.pop('sub_part_detail', False)
super(BomItemSerializer, self).__init__(*args, **kwargs)
if part_detail is not True:
self.fields.pop('part_detail')
if sub_part_detail is not True:
self.fields.pop('sub_part_detail')
@staticmethod
def setup_eager_loading(queryset):
"""Prefetch against the provided queryset to speed up database access"""
@ -1116,45 +1147,10 @@ class BomItemSerializer(InvenTreeModelSerializer):
return queryset
class Meta:
"""Metaclass defining serializer fields"""
model = BomItem
fields = [
'allow_variants',
'inherited',
'note',
'optional',
'consumable',
'overage',
'pk',
'part',
'part_detail',
'pricing_min',
'pricing_max',
'quantity',
'reference',
'sub_part',
'sub_part_detail',
'substitutes',
'validated',
# Annotated fields describing available quantity
'available_stock',
'available_substitute_stock',
'available_variant_stock',
# Annotated field describing quantity on order
'on_order',
]
class CategoryParameterTemplateSerializer(InvenTreeModelSerializer):
"""Serializer for the PartCategoryParameterTemplate model."""
parameter_template_detail = PartParameterTemplateSerializer(source='parameter_template', many=False, read_only=True)
category_detail = CategorySerializer(source='category', many=False, read_only=True)
class Meta:
"""Metaclass defining serializer fields"""
model = PartCategoryParameterTemplate
@ -1167,6 +1163,10 @@ class CategoryParameterTemplateSerializer(InvenTreeModelSerializer):
'default_value',
]
parameter_template_detail = PartParameterTemplateSerializer(source='parameter_template', many=False, read_only=True)
category_detail = CategorySerializer(source='category', many=False, read_only=True)
class PartCopyBOMSerializer(serializers.Serializer):
"""Serializer for copying a BOM from another part."""