mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	Documentation for Part app
This commit is contained in:
		| @@ -18,8 +18,6 @@ from .serializers import BuildSerializer | |||||||
| class BuildList(generics.ListCreateAPIView): | class BuildList(generics.ListCreateAPIView): | ||||||
|     """ API endpoint for accessing a list of Build objects. |     """ API endpoint for accessing a list of Build objects. | ||||||
|      |      | ||||||
|     Provides two methods: |  | ||||||
|      |  | ||||||
|     - GET: Return list of objects (with filters) |     - GET: Return list of objects (with filters) | ||||||
|     - POST: Create a new Build object |     - POST: Create a new Build object | ||||||
|     """ |     """ | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| """ | """ | ||||||
| Provides JSON serializers for Build API | JSON serializers for Build API | ||||||
| """ | """ | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| """ | """ | ||||||
| Provides Django views for interacting with Build objects | Django views for interacting with Build objects | ||||||
| """ | """ | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
|   | |||||||
| @@ -1,9 +1,14 @@ | |||||||
|  | """  | ||||||
|  | JSON serializers for Company app | ||||||
|  | """ | ||||||
|  |  | ||||||
| from rest_framework import serializers | from rest_framework import serializers | ||||||
|  |  | ||||||
| from .models import Company | from .models import Company | ||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyBriefSerializer(serializers.ModelSerializer): | class CompanyBriefSerializer(serializers.ModelSerializer): | ||||||
|  |     """ Serializer for Company object (limited detail) """ | ||||||
|  |  | ||||||
|     url = serializers.CharField(source='get_absolute_url', read_only=True) |     url = serializers.CharField(source='get_absolute_url', read_only=True) | ||||||
|  |  | ||||||
| @@ -17,6 +22,7 @@ class CompanyBriefSerializer(serializers.ModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanySerializer(serializers.ModelSerializer): | class CompanySerializer(serializers.ModelSerializer): | ||||||
|  |     """ Serializer for Company object (full detail) """ | ||||||
|  |  | ||||||
|     url = serializers.CharField(source='get_absolute_url', read_only=True) |     url = serializers.CharField(source='get_absolute_url', read_only=True) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | """ | ||||||
|  | Django views for interacting with Company app | ||||||
|  | """ | ||||||
|  |  | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| @@ -12,12 +17,20 @@ from .forms import CompanyImageForm | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyIndex(ListView): | class CompanyIndex(ListView): | ||||||
|  |     """ View for displaying list of companies  | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     model = Company |     model = Company | ||||||
|     template_name = 'company/index.html' |     template_name = 'company/index.html' | ||||||
|     context_object_name = 'companies' |     context_object_name = 'companies' | ||||||
|     paginate_by = 50 |     paginate_by = 50 | ||||||
|  |  | ||||||
|     def get_queryset(self): |     def get_queryset(self): | ||||||
|  |         """ Retrieve the Company queryset based on HTTP request parameters. | ||||||
|  |  | ||||||
|  |         - supplier: Filter by supplier | ||||||
|  |         - customer: Filter by customer | ||||||
|  |         """ | ||||||
|         queryset = Company.objects.all().order_by('name') |         queryset = Company.objects.all().order_by('name') | ||||||
|  |  | ||||||
|         if self.request.GET.get('supplier', None): |         if self.request.GET.get('supplier', None): | ||||||
| @@ -30,6 +43,7 @@ class CompanyIndex(ListView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyDetail(DetailView): | class CompanyDetail(DetailView): | ||||||
|  |     """ Detail view for Company object """ | ||||||
|     context_obect_name = 'company' |     context_obect_name = 'company' | ||||||
|     template_name = 'company/detail.html' |     template_name = 'company/detail.html' | ||||||
|     queryset = Company.objects.all() |     queryset = Company.objects.all() | ||||||
| @@ -37,6 +51,7 @@ class CompanyDetail(DetailView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyImage(AjaxUpdateView): | class CompanyImage(AjaxUpdateView): | ||||||
|  |     """ View for uploading an image for the Company """ | ||||||
|     model = Company |     model = Company | ||||||
|     ajax_template_name = 'modal_form.html' |     ajax_template_name = 'modal_form.html' | ||||||
|     ajax_form_title = 'Update Company Image' |     ajax_form_title = 'Update Company Image' | ||||||
| @@ -49,6 +64,7 @@ class CompanyImage(AjaxUpdateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyEdit(AjaxUpdateView): | class CompanyEdit(AjaxUpdateView): | ||||||
|  |     """ View for editing a Company object """ | ||||||
|     model = Company |     model = Company | ||||||
|     form_class = EditCompanyForm |     form_class = EditCompanyForm | ||||||
|     context_object_name = 'company' |     context_object_name = 'company' | ||||||
| @@ -62,6 +78,7 @@ class CompanyEdit(AjaxUpdateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyCreate(AjaxCreateView): | class CompanyCreate(AjaxCreateView): | ||||||
|  |     """ View for creating a new Company object """ | ||||||
|     model = Company |     model = Company | ||||||
|     context_object_name = 'company' |     context_object_name = 'company' | ||||||
|     form_class = EditCompanyForm |     form_class = EditCompanyForm | ||||||
| @@ -75,6 +92,7 @@ class CompanyCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyDelete(AjaxDeleteView): | class CompanyDelete(AjaxDeleteView): | ||||||
|  |     """ View for deleting a Company object """ | ||||||
|     model = Company |     model = Company | ||||||
|     success_url = '/company/' |     success_url = '/company/' | ||||||
|     ajax_template_name = 'company/delete.html' |     ajax_template_name = 'company/delete.html' | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | """ | ||||||
|  | Provides a JSON API for the Part app | ||||||
|  | """ | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| @@ -26,6 +30,12 @@ class PartCategoryTree(TreeSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategoryList(generics.ListCreateAPIView): | class CategoryList(generics.ListCreateAPIView): | ||||||
|  |     """ API endpoint for accessing a list of PartCategory objects. | ||||||
|  |  | ||||||
|  |     - GET: Return a list of PartCategory objects | ||||||
|  |     - POST: Create a new PartCategory object | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     queryset = PartCategory.objects.all() |     queryset = PartCategory.objects.all() | ||||||
|     serializer_class = CategorySerializer |     serializer_class = CategorySerializer | ||||||
|  |  | ||||||
| @@ -56,11 +66,13 @@ class CategoryList(generics.ListCreateAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategoryDetail(generics.RetrieveUpdateDestroyAPIView): | class CategoryDetail(generics.RetrieveUpdateDestroyAPIView): | ||||||
|  |     """ API endpoint for detail view of a single PartCategory object """ | ||||||
|     serializer_class = CategorySerializer |     serializer_class = CategorySerializer | ||||||
|     queryset = PartCategory.objects.all() |     queryset = PartCategory.objects.all() | ||||||
|  |  | ||||||
|  |  | ||||||
| class PartDetail(generics.RetrieveUpdateDestroyAPIView): | class PartDetail(generics.RetrieveUpdateDestroyAPIView): | ||||||
|  |     """ API endpoint for detail view of a single Part object """ | ||||||
|     queryset = Part.objects.all() |     queryset = Part.objects.all() | ||||||
|     serializer_class = PartSerializer |     serializer_class = PartSerializer | ||||||
|  |  | ||||||
| @@ -70,6 +82,11 @@ class PartDetail(generics.RetrieveUpdateDestroyAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartList(generics.ListCreateAPIView): | class PartList(generics.ListCreateAPIView): | ||||||
|  |     """ API endpoint for accessing a list of Part objects | ||||||
|  |  | ||||||
|  |     - GET: Return list of objects | ||||||
|  |     - POST: Create a new Part object | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     serializer_class = PartSerializer |     serializer_class = PartSerializer | ||||||
|  |  | ||||||
| @@ -130,6 +147,11 @@ class PartList(generics.ListCreateAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class BomList(generics.ListCreateAPIView): | class BomList(generics.ListCreateAPIView): | ||||||
|  |     """ API endpoing for accessing a list of BomItem objects | ||||||
|  |  | ||||||
|  |     - GET: Return list of BomItem objects | ||||||
|  |     - POST: Create a new BomItem object | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     queryset = BomItem.objects.all() |     queryset = BomItem.objects.all() | ||||||
|     serializer_class = BomItemSerializer |     serializer_class = BomItemSerializer | ||||||
| @@ -151,6 +173,7 @@ class BomList(generics.ListCreateAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class BomDetail(generics.RetrieveUpdateDestroyAPIView): | class BomDetail(generics.RetrieveUpdateDestroyAPIView): | ||||||
|  |     """ API endpoint for detail view of a single BomItem object """ | ||||||
|  |  | ||||||
|     queryset = BomItem.objects.all() |     queryset = BomItem.objects.all() | ||||||
|     serializer_class = BomItemSerializer |     serializer_class = BomItemSerializer | ||||||
| @@ -161,6 +184,11 @@ class BomDetail(generics.RetrieveUpdateDestroyAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartList(generics.ListCreateAPIView): | class SupplierPartList(generics.ListCreateAPIView): | ||||||
|  |     """ API endpoint for list view of SupplierPart object | ||||||
|  |  | ||||||
|  |     - GET: Return list of SupplierPart objects | ||||||
|  |     - POST: Create a new SupplierPart object | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     queryset = SupplierPart.objects.all() |     queryset = SupplierPart.objects.all() | ||||||
|     serializer_class = SupplierPartSerializer |     serializer_class = SupplierPartSerializer | ||||||
| @@ -182,6 +210,12 @@ class SupplierPartList(generics.ListCreateAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartDetail(generics.RetrieveUpdateDestroyAPIView): | class SupplierPartDetail(generics.RetrieveUpdateDestroyAPIView): | ||||||
|  |     """ API endpoint for detail view of SupplierPart object | ||||||
|  |  | ||||||
|  |     - GET: Retrieve detail view | ||||||
|  |     - PATCH: Update object | ||||||
|  |     - DELETE: Delete objec | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     queryset = SupplierPart.objects.all() |     queryset = SupplierPart.objects.all() | ||||||
|     serializer_class = SupplierPartSerializer |     serializer_class = SupplierPartSerializer | ||||||
| @@ -192,6 +226,11 @@ class SupplierPartDetail(generics.RetrieveUpdateDestroyAPIView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPriceBreakList(generics.ListCreateAPIView): | class SupplierPriceBreakList(generics.ListCreateAPIView): | ||||||
|  |     """ API endpoint for list view of SupplierPriceBreak object  | ||||||
|  |  | ||||||
|  |     - GET: Retrieve list of SupplierPriceBreak objects | ||||||
|  |     - POST: Create a new SupplierPriceBreak object | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     queryset = SupplierPriceBreak.objects.all() |     queryset = SupplierPriceBreak.objects.all() | ||||||
|     serializer_class = SupplierPriceBreakSerializer |     serializer_class = SupplierPriceBreakSerializer | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | """ | ||||||
|  | Django Forms for interacting with Part objects | ||||||
|  | """ | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| @@ -10,6 +14,7 @@ from .models import SupplierPart | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartImageForm(HelperForm): | class PartImageForm(HelperForm): | ||||||
|  |     """ Form for uploading a Part image """ | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Part |         model = Part | ||||||
| @@ -40,6 +45,7 @@ class BomExportForm(HelperForm): | |||||||
|  |  | ||||||
|  |  | ||||||
| class EditPartForm(HelperForm): | class EditPartForm(HelperForm): | ||||||
|  |     """ Form for editing a Part object """ | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Part |         model = Part | ||||||
| @@ -64,6 +70,7 @@ class EditPartForm(HelperForm): | |||||||
|  |  | ||||||
|  |  | ||||||
| class EditCategoryForm(HelperForm): | class EditCategoryForm(HelperForm): | ||||||
|  |     """ Form for editing a PartCategory object """ | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = PartCategory |         model = PartCategory | ||||||
| @@ -75,6 +82,7 @@ class EditCategoryForm(HelperForm): | |||||||
|  |  | ||||||
|  |  | ||||||
| class EditBomItemForm(HelperForm): | class EditBomItemForm(HelperForm): | ||||||
|  |     """ Form for editing a BomItem object """ | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = BomItem |         model = BomItem | ||||||
| @@ -88,6 +96,7 @@ class EditBomItemForm(HelperForm): | |||||||
|  |  | ||||||
|  |  | ||||||
| class EditSupplierPartForm(HelperForm): | class EditSupplierPartForm(HelperForm): | ||||||
|  |     """ Form for editing a SupplierPart object """ | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = SupplierPart |         model = SupplierPart | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | """ | ||||||
|  | Part database model definitions | ||||||
|  | """ | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| @@ -47,11 +51,19 @@ class PartCategory(InvenTreeTree): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def has_parts(self): |     def has_parts(self): | ||||||
|  |         """ True if there are any parts in this category """ | ||||||
|         return self.parts.count() > 0 |         return self.parts.count() > 0 | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(pre_delete, sender=PartCategory, dispatch_uid='partcategory_delete_log') | @receiver(pre_delete, sender=PartCategory, dispatch_uid='partcategory_delete_log') | ||||||
| def before_delete_part_category(sender, instance, using, **kwargs): | def before_delete_part_category(sender, instance, using, **kwargs): | ||||||
|  |     """ Receives before_delete signal for PartCategory object | ||||||
|  |  | ||||||
|  |     Before deleting, update child Part and PartCategory objects: | ||||||
|  |  | ||||||
|  |     - For each child category, set the parent to the parent of *this* category | ||||||
|  |     - For each part, set the 'category' to the parent of *this* category | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     # Update each part in this category to point to the parent category |     # Update each part in this category to point to the parent category | ||||||
|     for part in instance.parts.all(): |     for part in instance.parts.all(): | ||||||
| @@ -67,6 +79,16 @@ def before_delete_part_category(sender, instance, using, **kwargs): | |||||||
| # Function to automatically rename a part image on upload | # Function to automatically rename a part image on upload | ||||||
| # Format: part_pk.<img> | # Format: part_pk.<img> | ||||||
| def rename_part_image(instance, filename): | def rename_part_image(instance, filename): | ||||||
|  |     """ Function for renaming a part image file | ||||||
|  |  | ||||||
|  |     Args: | ||||||
|  |         instance: Instance of a Part object | ||||||
|  |         filename: Name of original uploaded file | ||||||
|  |  | ||||||
|  |     Returns: | ||||||
|  |         Cleaned filename in format part_<n>_img | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     base = 'part_images' |     base = 'part_images' | ||||||
|  |  | ||||||
|     if filename.count('.') > 0: |     if filename.count('.') > 0: | ||||||
| @@ -248,7 +270,8 @@ class Part(models.Model): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def allocation_count(self): |     def allocation_count(self): | ||||||
|         """ Return true if any of this part is allocated |         """ Return true if any of this part is allocated: | ||||||
|  |  | ||||||
|         - To another build |         - To another build | ||||||
|         - To a customer order |         - To a customer order | ||||||
|         """ |         """ | ||||||
| @@ -311,6 +334,15 @@ class Part(models.Model): | |||||||
|  |  | ||||||
|  |  | ||||||
| def attach_file(instance, filename): | def attach_file(instance, filename): | ||||||
|  |     """ Function for storing a file for a PartAttachment | ||||||
|  |  | ||||||
|  |     Args: | ||||||
|  |         instance: Instance of a PartAttachment object | ||||||
|  |         filename: name of uploaded file | ||||||
|  |  | ||||||
|  |     Returns: | ||||||
|  |         path to store file, format: 'part_file_<pk>_filename' | ||||||
|  |     """ | ||||||
|     # Construct a path to store a file attachment |     # Construct a path to store a file attachment | ||||||
|     return os.path.join('part_files', str(instance.part.id), filename) |     return os.path.join('part_files', str(instance.part.id), filename) | ||||||
|  |  | ||||||
| @@ -356,6 +388,13 @@ class BomItem(models.Model): | |||||||
|     note = models.CharField(max_length=100, blank=True, help_text='Item notes') |     note = models.CharField(max_length=100, blank=True, help_text='Item notes') | ||||||
|  |  | ||||||
|     def clean(self): |     def clean(self): | ||||||
|  |         """ Check validity of the BomItem model. | ||||||
|  |  | ||||||
|  |         Performs model checks beyond simple field validation. | ||||||
|  |  | ||||||
|  |         - A part cannot refer to itself in its BOM | ||||||
|  |         - A part cannot refer to a part which refers to it | ||||||
|  |         """ | ||||||
|  |  | ||||||
|         # A part cannot refer to itself in its BOM |         # A part cannot refer to itself in its BOM | ||||||
|         if self.part == self.sub_part: |         if self.part == self.sub_part: | ||||||
| @@ -382,8 +421,9 @@ class BomItem(models.Model): | |||||||
| class SupplierPart(models.Model): | class SupplierPart(models.Model): | ||||||
|     """ Represents a unique part as provided by a Supplier |     """ Represents a unique part as provided by a Supplier | ||||||
|     Each SupplierPart is identified by a MPN (Manufacturer Part Number) |     Each SupplierPart is identified by a MPN (Manufacturer Part Number) | ||||||
|     Each SupplierPart is also linked to a Part object |     Each SupplierPart is also linked to a Part object. | ||||||
|     - A Part may be available from multiple suppliers |  | ||||||
|  |     A Part may be available from multiple suppliers | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     def get_absolute_url(self): |     def get_absolute_url(self): | ||||||
| @@ -453,6 +493,7 @@ class SupplierPart(models.Model): | |||||||
|  |  | ||||||
|     def get_price(self, quantity, moq=True, multiples=True): |     def get_price(self, quantity, moq=True, multiples=True): | ||||||
|         """ Calculate the supplier price based on quantity price breaks. |         """ Calculate the supplier price based on quantity price breaks. | ||||||
|  |          | ||||||
|         - If no price breaks available, use the single_price field |         - If no price breaks available, use the single_price field | ||||||
|         - Don't forget to add in flat-fee cost (base_cost field) |         - Don't forget to add in flat-fee cost (base_cost field) | ||||||
|         - If MOQ (minimum order quantity) is required, bump quantity |         - If MOQ (minimum order quantity) is required, bump quantity | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | """ | ||||||
|  | JSON serializers for Part app | ||||||
|  | """ | ||||||
|  |  | ||||||
| from rest_framework import serializers | from rest_framework import serializers | ||||||
|  |  | ||||||
| from .models import Part, PartCategory, BomItem | from .models import Part, PartCategory, BomItem | ||||||
| @@ -7,6 +11,7 @@ from InvenTree.serializers import InvenTreeModelSerializer | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategorySerializer(serializers.ModelSerializer): | class CategorySerializer(serializers.ModelSerializer): | ||||||
|  |     """ Serializer for PartCategory """ | ||||||
|  |  | ||||||
|     url = serializers.CharField(source='get_absolute_url', read_only=True) |     url = serializers.CharField(source='get_absolute_url', read_only=True) | ||||||
|  |  | ||||||
| @@ -23,6 +28,7 @@ class CategorySerializer(serializers.ModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartBriefSerializer(serializers.ModelSerializer): | class PartBriefSerializer(serializers.ModelSerializer): | ||||||
|  |     """ Serializer for Part (brief detail) """ | ||||||
|  |  | ||||||
|     url = serializers.CharField(source='get_absolute_url', read_only=True) |     url = serializers.CharField(source='get_absolute_url', read_only=True) | ||||||
|  |  | ||||||
| @@ -68,6 +74,7 @@ class PartSerializer(serializers.ModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class BomItemSerializer(InvenTreeModelSerializer): | class BomItemSerializer(InvenTreeModelSerializer): | ||||||
|  |     """ Serializer for BomItem object """ | ||||||
|  |  | ||||||
|     # url = serializers.CharField(source='get_absolute_url', read_only=True) |     # url = serializers.CharField(source='get_absolute_url', read_only=True) | ||||||
|  |  | ||||||
| @@ -89,6 +96,7 @@ class BomItemSerializer(InvenTreeModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartSerializer(serializers.ModelSerializer): | class SupplierPartSerializer(serializers.ModelSerializer): | ||||||
|  |     """ Serializer for SupplierPart object """ | ||||||
|  |  | ||||||
|     url = serializers.CharField(source='get_absolute_url', read_only=True) |     url = serializers.CharField(source='get_absolute_url', read_only=True) | ||||||
|  |  | ||||||
| @@ -112,6 +120,7 @@ class SupplierPartSerializer(serializers.ModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPriceBreakSerializer(serializers.ModelSerializer): | class SupplierPriceBreakSerializer(serializers.ModelSerializer): | ||||||
|  |     """ Serializer for SupplierPriceBreak object """ | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = SupplierPriceBreak |         model = SupplierPriceBreak | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | """ | ||||||
|  | URL lookup for Part app | ||||||
|  | """ | ||||||
|  |  | ||||||
| from django.conf.urls import url, include | from django.conf.urls import url, include | ||||||
|  |  | ||||||
| from . import views | from . import views | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | """ | ||||||
|  | Django views for interacting with Part app | ||||||
|  | """ | ||||||
|  |  | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| @@ -21,10 +25,12 @@ from .forms import EditSupplierPartForm | |||||||
|  |  | ||||||
| from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView, AjaxDeleteView | from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView, AjaxDeleteView | ||||||
|  |  | ||||||
| from InvenTree.helpers import DownloadFile | from InvenTree.helpers import DownloadFile, str2bool | ||||||
|  |  | ||||||
|  |  | ||||||
| class PartIndex(ListView): | class PartIndex(ListView): | ||||||
|  |     """ View for displaying list of Part objects | ||||||
|  |     """ | ||||||
|     model = Part |     model = Part | ||||||
|     template_name = 'part/category.html' |     template_name = 'part/category.html' | ||||||
|     context_object_name = 'parts' |     context_object_name = 'parts' | ||||||
| @@ -45,8 +51,12 @@ class PartIndex(ListView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartCreate(AjaxCreateView): | class PartCreate(AjaxCreateView): | ||||||
|     """ Create a new part |     """ View for creating a new Part object. | ||||||
|     - Optionally provide a category object as initial data |  | ||||||
|  |     Options for providing initial conditions: | ||||||
|  |      | ||||||
|  |     - Provide a category object as initial data | ||||||
|  |     - Copy an existing Part | ||||||
|     """ |     """ | ||||||
|     model = Part |     model = Part | ||||||
|     form_class = EditPartForm |     form_class = EditPartForm | ||||||
| @@ -64,6 +74,10 @@ class PartCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|     # If a category is provided in the URL, pass that to the page context |     # If a category is provided in the URL, pass that to the page context | ||||||
|     def get_context_data(self, **kwargs): |     def get_context_data(self, **kwargs): | ||||||
|  |         """ Provide extra context information for the form to display: | ||||||
|  |  | ||||||
|  |         - Add category information (if provided) | ||||||
|  |         """ | ||||||
|         context = super(PartCreate, self).get_context_data(**kwargs) |         context = super(PartCreate, self).get_context_data(**kwargs) | ||||||
|  |  | ||||||
|         # Add category information to the page |         # Add category information to the page | ||||||
| @@ -76,6 +90,11 @@ class PartCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|     # Pre-fill the category field if a valid category is provided |     # Pre-fill the category field if a valid category is provided | ||||||
|     def get_initial(self): |     def get_initial(self): | ||||||
|  |         """ Get initial data for the new Part object: | ||||||
|  |  | ||||||
|  |         - If a category is provided, pre-fill the Category field | ||||||
|  |         - If 'copy' parameter is provided, copy from referenced Part | ||||||
|  |         """ | ||||||
|  |  | ||||||
|         # Is the client attempting to copy an existing part? |         # Is the client attempting to copy an existing part? | ||||||
|         part_to_copy = self.request.GET.get('copy', None) |         part_to_copy = self.request.GET.get('copy', None) | ||||||
| @@ -98,15 +117,22 @@ class PartCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartDetail(DetailView): | class PartDetail(DetailView): | ||||||
|  |     """ Detail view for Part object | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     context_object_name = 'part' |     context_object_name = 'part' | ||||||
|     queryset = Part.objects.all() |     queryset = Part.objects.all() | ||||||
|     template_name = 'part/detail.html' |     template_name = 'part/detail.html' | ||||||
|  |  | ||||||
|     # Add in some extra context information based on query params |     # Add in some extra context information based on query params | ||||||
|     def get_context_data(self, **kwargs): |     def get_context_data(self, **kwargs): | ||||||
|  |         """ Provide extra context data to template | ||||||
|  |  | ||||||
|  |         - If '?editing=True', set 'editing_enabled' context variable | ||||||
|  |         """ | ||||||
|         context = super(PartDetail, self).get_context_data(**kwargs) |         context = super(PartDetail, self).get_context_data(**kwargs) | ||||||
|  |  | ||||||
|         if self.request.GET.get('edit', '').lower() in ['true', 'yes', '1']: |         if str2bool(self.request.GET.get('edit', '')): | ||||||
|             context['editing_enabled'] = 1 |             context['editing_enabled'] = 1 | ||||||
|         else: |         else: | ||||||
|             context['editing_enabled'] = 0 |             context['editing_enabled'] = 0 | ||||||
| @@ -115,6 +141,7 @@ class PartDetail(DetailView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartImage(AjaxUpdateView): | class PartImage(AjaxUpdateView): | ||||||
|  |     """ View for uploading Part image """ | ||||||
|  |  | ||||||
|     model = Part |     model = Part | ||||||
|     ajax_template_name = 'modal_form.html' |     ajax_template_name = 'modal_form.html' | ||||||
| @@ -128,6 +155,8 @@ class PartImage(AjaxUpdateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartEdit(AjaxUpdateView): | class PartEdit(AjaxUpdateView): | ||||||
|  |     """ View for editing Part object """ | ||||||
|  |  | ||||||
|     model = Part |     model = Part | ||||||
|     template_name = 'part/edit.html' |     template_name = 'part/edit.html' | ||||||
|     form_class = EditPartForm |     form_class = EditPartForm | ||||||
| @@ -214,6 +243,8 @@ class BomDownload(AjaxView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PartDelete(AjaxDeleteView): | class PartDelete(AjaxDeleteView): | ||||||
|  |     """ View to delete a Part object """ | ||||||
|  |  | ||||||
|     model = Part |     model = Part | ||||||
|     template_name = 'part/delete.html' |     template_name = 'part/delete.html' | ||||||
|     ajax_template_name = 'part/partial_delete.html' |     ajax_template_name = 'part/partial_delete.html' | ||||||
| @@ -229,6 +260,7 @@ class PartDelete(AjaxDeleteView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategoryDetail(DetailView): | class CategoryDetail(DetailView): | ||||||
|  |     """ Detail view for PartCategory """ | ||||||
|     model = PartCategory |     model = PartCategory | ||||||
|     context_object_name = 'category' |     context_object_name = 'category' | ||||||
|     queryset = PartCategory.objects.all() |     queryset = PartCategory.objects.all() | ||||||
| @@ -236,6 +268,7 @@ class CategoryDetail(DetailView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategoryEdit(AjaxUpdateView): | class CategoryEdit(AjaxUpdateView): | ||||||
|  |     """ Update view to edit a PartCategory """ | ||||||
|     model = PartCategory |     model = PartCategory | ||||||
|     template_name = 'part/category_edit.html' |     template_name = 'part/category_edit.html' | ||||||
|     form_class = EditCategoryForm |     form_class = EditCategoryForm | ||||||
| @@ -251,6 +284,7 @@ class CategoryEdit(AjaxUpdateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategoryDelete(AjaxDeleteView): | class CategoryDelete(AjaxDeleteView): | ||||||
|  |     """ Delete view to delete a PartCategory """ | ||||||
|     model = PartCategory |     model = PartCategory | ||||||
|     template_name = 'part/category_delete.html' |     template_name = 'part/category_delete.html' | ||||||
|     context_object_name = 'category' |     context_object_name = 'category' | ||||||
| @@ -263,6 +297,7 @@ class CategoryDelete(AjaxDeleteView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class CategoryCreate(AjaxCreateView): | class CategoryCreate(AjaxCreateView): | ||||||
|  |     """ Create view to make a new PartCategory """ | ||||||
|     model = PartCategory |     model = PartCategory | ||||||
|     ajax_form_action = reverse_lazy('category-create') |     ajax_form_action = reverse_lazy('category-create') | ||||||
|     ajax_form_title = 'Create new part category' |     ajax_form_title = 'Create new part category' | ||||||
| @@ -271,6 +306,10 @@ class CategoryCreate(AjaxCreateView): | |||||||
|     form_class = EditCategoryForm |     form_class = EditCategoryForm | ||||||
|  |  | ||||||
|     def get_context_data(self, **kwargs): |     def get_context_data(self, **kwargs): | ||||||
|  |         """ Add extra context data to template. | ||||||
|  |  | ||||||
|  |         - If parent category provided, pass the category details to the template | ||||||
|  |         """ | ||||||
|         context = super(CategoryCreate, self).get_context_data(**kwargs).copy() |         context = super(CategoryCreate, self).get_context_data(**kwargs).copy() | ||||||
|  |  | ||||||
|         parent_id = self.request.GET.get('category', None) |         parent_id = self.request.GET.get('category', None) | ||||||
| @@ -281,6 +320,10 @@ class CategoryCreate(AjaxCreateView): | |||||||
|         return context |         return context | ||||||
|  |  | ||||||
|     def get_initial(self): |     def get_initial(self): | ||||||
|  |         """ Get initial data for new PartCategory | ||||||
|  |  | ||||||
|  |         - If parent provided, pre-fill the parent category | ||||||
|  |         """ | ||||||
|         initials = super(CategoryCreate, self).get_initial().copy() |         initials = super(CategoryCreate, self).get_initial().copy() | ||||||
|  |  | ||||||
|         parent_id = self.request.GET.get('category', None) |         parent_id = self.request.GET.get('category', None) | ||||||
| @@ -292,12 +335,14 @@ class CategoryCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class BomItemDetail(DetailView): | class BomItemDetail(DetailView): | ||||||
|  |     """ Detail view for BomItem """ | ||||||
|     context_object_name = 'item' |     context_object_name = 'item' | ||||||
|     queryset = BomItem.objects.all() |     queryset = BomItem.objects.all() | ||||||
|     template_name = 'part/bom-detail.html' |     template_name = 'part/bom-detail.html' | ||||||
|  |  | ||||||
|  |  | ||||||
| class BomItemCreate(AjaxCreateView): | class BomItemCreate(AjaxCreateView): | ||||||
|  |     """ Create view for making a new BomItem object """ | ||||||
|     model = BomItem |     model = BomItem | ||||||
|     form_class = EditBomItemForm |     form_class = EditBomItemForm | ||||||
|     template_name = 'part/bom-create.html' |     template_name = 'part/bom-create.html' | ||||||
| @@ -305,6 +350,11 @@ class BomItemCreate(AjaxCreateView): | |||||||
|     ajax_form_title = 'Create BOM item' |     ajax_form_title = 'Create BOM item' | ||||||
|  |  | ||||||
|     def get_initial(self): |     def get_initial(self): | ||||||
|  |         """ Provide initial data for the BomItem: | ||||||
|  |  | ||||||
|  |         - If 'parent' provided, set the parent part field | ||||||
|  |         """ | ||||||
|  |  | ||||||
|         # Look for initial values |         # Look for initial values | ||||||
|         initials = super(BomItemCreate, self).get_initial().copy() |         initials = super(BomItemCreate, self).get_initial().copy() | ||||||
|  |  | ||||||
| @@ -318,6 +368,8 @@ class BomItemCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class BomItemEdit(AjaxUpdateView): | class BomItemEdit(AjaxUpdateView): | ||||||
|  |     """ Update view for editing BomItem """ | ||||||
|  |  | ||||||
|     model = BomItem |     model = BomItem | ||||||
|     form_class = EditBomItemForm |     form_class = EditBomItemForm | ||||||
|     template_name = 'part/bom-edit.html' |     template_name = 'part/bom-edit.html' | ||||||
| @@ -326,6 +378,7 @@ class BomItemEdit(AjaxUpdateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class BomItemDelete(AjaxDeleteView): | class BomItemDelete(AjaxDeleteView): | ||||||
|  |     """ Delete view for removing BomItem """ | ||||||
|     model = BomItem |     model = BomItem | ||||||
|     template_name = 'part/bom-delete.html' |     template_name = 'part/bom-delete.html' | ||||||
|     context_object_name = 'item' |     context_object_name = 'item' | ||||||
| @@ -333,6 +386,7 @@ class BomItemDelete(AjaxDeleteView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartDetail(DetailView): | class SupplierPartDetail(DetailView): | ||||||
|  |     """ Detail view for SupplierPart """ | ||||||
|     model = SupplierPart |     model = SupplierPart | ||||||
|     template_name = 'company/partdetail.html' |     template_name = 'company/partdetail.html' | ||||||
|     context_object_name = 'part' |     context_object_name = 'part' | ||||||
| @@ -340,6 +394,8 @@ class SupplierPartDetail(DetailView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartEdit(AjaxUpdateView): | class SupplierPartEdit(AjaxUpdateView): | ||||||
|  |     """ Update view for editing SupplierPart """ | ||||||
|  |  | ||||||
|     model = SupplierPart |     model = SupplierPart | ||||||
|     template_name = 'company/partedit.html' |     template_name = 'company/partedit.html' | ||||||
|     context_object_name = 'part' |     context_object_name = 'part' | ||||||
| @@ -349,6 +405,8 @@ class SupplierPartEdit(AjaxUpdateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartCreate(AjaxCreateView): | class SupplierPartCreate(AjaxCreateView): | ||||||
|  |     """ Create view for making new SupplierPart """ | ||||||
|  |  | ||||||
|     model = SupplierPart |     model = SupplierPart | ||||||
|     form_class = EditSupplierPartForm |     form_class = EditSupplierPartForm | ||||||
|     ajax_template_name = 'modal_form.html' |     ajax_template_name = 'modal_form.html' | ||||||
| @@ -356,6 +414,11 @@ class SupplierPartCreate(AjaxCreateView): | |||||||
|     context_object_name = 'part' |     context_object_name = 'part' | ||||||
|  |  | ||||||
|     def get_initial(self): |     def get_initial(self): | ||||||
|  |         """ Provide initial data for new SupplierPart: | ||||||
|  |  | ||||||
|  |         - If 'supplier_id' provided, pre-fill supplier field | ||||||
|  |         - If 'part_id' provided, pre-fill part field | ||||||
|  |         """ | ||||||
|         initials = super(SupplierPartCreate, self).get_initial().copy() |         initials = super(SupplierPartCreate, self).get_initial().copy() | ||||||
|  |  | ||||||
|         supplier_id = self.request.GET.get('supplier', None) |         supplier_id = self.request.GET.get('supplier', None) | ||||||
| @@ -374,6 +437,7 @@ class SupplierPartCreate(AjaxCreateView): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartDelete(AjaxDeleteView): | class SupplierPartDelete(AjaxDeleteView): | ||||||
|  |     """ Delete view for removing a SupplierPart """ | ||||||
|     model = SupplierPart |     model = SupplierPart | ||||||
|     success_url = '/supplier/' |     success_url = '/supplier/' | ||||||
|     template_name = 'company/partdelete.html' |     template_name = 'company/partdelete.html' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user