From e30a089c7682a81bc23807df3f753618a026afe1 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 14 Apr 2018 14:19:03 +1000 Subject: [PATCH] Move BomItem into the Part app - Does not make sense to keep these separate - Removed bom app entirely --- InvenTree/InvenTree/settings.py | 2 -- InvenTree/InvenTree/urls.py | 4 ++-- InvenTree/bom/__init__.py | 0 InvenTree/bom/admin.py | 8 ------- InvenTree/bom/apps.py | 6 ------ InvenTree/bom/models.py | 37 --------------------------------- InvenTree/bom/serializers.py | 13 ------------ InvenTree/bom/tests.py | 6 ------ InvenTree/bom/urls.py | 12 ----------- InvenTree/bom/views.py | 35 ------------------------------- InvenTree/part/admin.py | 5 +++++ InvenTree/part/api.py | 28 ++++++++++++++++++++++++- InvenTree/part/models.py | 29 ++++++++++++++++++++++++++ InvenTree/part/serializers.py | 10 +++++++++ InvenTree/part/urls.py | 11 ++++++++++ 15 files changed, 84 insertions(+), 122 deletions(-) delete mode 100644 InvenTree/bom/__init__.py delete mode 100644 InvenTree/bom/admin.py delete mode 100644 InvenTree/bom/apps.py delete mode 100644 InvenTree/bom/models.py delete mode 100644 InvenTree/bom/serializers.py delete mode 100644 InvenTree/bom/tests.py delete mode 100644 InvenTree/bom/urls.py delete mode 100644 InvenTree/bom/views.py diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 211ab6058c..259d7c7a22 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -46,11 +46,9 @@ INSTALLED_APPS = [ # InvenTree apps 'part.apps.PartConfig', - 'bom.apps.BomConfig', 'supplier.apps.SupplierConfig', 'stock.apps.StockConfig', 'track.apps.TrackConfig', - #'project.apps.ProjectConfig', ] MIDDLEWARE = [ diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 33df33ed97..8ff3f19bac 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -4,8 +4,8 @@ from django.contrib import admin from rest_framework.documentation import include_docs_urls from part.urls import part_api_urls, part_cat_api_urls +from part.urls import bom_api_urls from part.urls import part_urls -from bom.urls import bom_urls from stock.urls import stock_urls, stock_loc_urls from supplier.urls import cust_urls, manu_urls, supplier_part_urls, price_break_urls, supplier_urls @@ -34,7 +34,7 @@ apipatterns = [ #url(r'^part-param-template/', include(part_param_template_urls)), # Part BOM URLs - url(r'^bom/', include(bom_urls)), + url(r'^bom/', include(bom_api_urls)), # Supplier URLs url(r'^supplier/', include(supplier_urls)), diff --git a/InvenTree/bom/__init__.py b/InvenTree/bom/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/InvenTree/bom/admin.py b/InvenTree/bom/admin.py deleted file mode 100644 index 4c31fcbf5a..0000000000 --- a/InvenTree/bom/admin.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.contrib import admin - -from .models import BomItem - -class BomItemAdmin(admin.ModelAdmin): - list_display=('part', 'sub_part', 'quantity') - -admin.site.register(BomItem, BomItemAdmin) \ No newline at end of file diff --git a/InvenTree/bom/apps.py b/InvenTree/bom/apps.py deleted file mode 100644 index e740d8d611..0000000000 --- a/InvenTree/bom/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals - -from django.apps import AppConfig - -class BomConfig(AppConfig): - name = 'bom' \ No newline at end of file diff --git a/InvenTree/bom/models.py b/InvenTree/bom/models.py deleted file mode 100644 index 67b5a932e0..0000000000 --- a/InvenTree/bom/models.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import unicode_literals -from django.utils.translation import ugettext as _ -from django.db import models -from django.db.models import Sum -from django.core.validators import MinValueValidator - -from part.models import Part - -class BomItem(models.Model): - """ A BomItem links a part to its component items. - A part can have a BOM (bill of materials) which defines - which parts are required (and in what quatity) to make it - """ - - # A link to the parent part - # Each part will get a reverse lookup field 'bom_items' - part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='bom_items') - - # A link to the child item (sub-part) - # Each part will get a reverse lookup field 'used_in' - sub_part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='used_in') - - # Quantity required - quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) - - - class Meta: - verbose_name = "BOM Item" - - # Prevent duplication of parent/child rows - unique_together = ('part', 'sub_part') - - def __str__(self): - return "{par} -> {child} ({n})".format( - par=self.part.name, - child=self.sub_part.name, - n=self.quantity) diff --git a/InvenTree/bom/serializers.py b/InvenTree/bom/serializers.py deleted file mode 100644 index adabb99fc6..0000000000 --- a/InvenTree/bom/serializers.py +++ /dev/null @@ -1,13 +0,0 @@ -from rest_framework import serializers - -from .models import BomItem - - -class BomItemSerializer(serializers.ModelSerializer): - - class Meta: - model = BomItem - fields = ('url', - 'part', - 'sub_part', - 'quantity') \ No newline at end of file diff --git a/InvenTree/bom/tests.py b/InvenTree/bom/tests.py deleted file mode 100644 index 5982e6bcd2..0000000000 --- a/InvenTree/bom/tests.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.test import TestCase - -# Create your tests here. diff --git a/InvenTree/bom/urls.py b/InvenTree/bom/urls.py deleted file mode 100644 index 495bbe553b..0000000000 --- a/InvenTree/bom/urls.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.conf.urls import url - -from . import views - -bom_urls = [ - # Bom Item detail - url(r'^(?P[0-9]+)/?$', views.BomItemDetail.as_view(), name='bomitem-detail'), - - # List of top-level categories - url(r'^\?*.*/?$', views.BomItemList.as_view()), - url(r'^$', views.BomItemList.as_view()) -] \ No newline at end of file diff --git a/InvenTree/bom/views.py b/InvenTree/bom/views.py deleted file mode 100644 index dd35ac3f2d..0000000000 --- a/InvenTree/bom/views.py +++ /dev/null @@ -1,35 +0,0 @@ -from django_filters.rest_framework import FilterSet, DjangoFilterBackend - -from rest_framework import generics, permissions - -from InvenTree.models import FilterChildren - -from .models import BomItem - -from .serializers import BomItemSerializer - - -class BomItemDetail(generics.RetrieveUpdateDestroyAPIView): - - queryset = BomItem.objects.all() - serializer_class = BomItemSerializer - permission_classes = (permissions.IsAuthenticatedOrReadOnly,) - - -class BomItemFilter(FilterSet): - - class Meta: - model = BomItem - fields = ['part', 'sub_part'] - - -class BomItemList(generics.ListCreateAPIView): - - #def get_queryset(self): - # params = self.request. - - queryset = BomItem.objects.all() - serializer_class = BomItemSerializer - permission_classes = (permissions.IsAuthenticatedOrReadOnly,) - filter_backends = (DjangoFilterBackend,) - filter_class = BomItemFilter \ No newline at end of file diff --git a/InvenTree/part/admin.py b/InvenTree/part/admin.py index 70a4728776..6f3a3e3e72 100644 --- a/InvenTree/part/admin.py +++ b/InvenTree/part/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from .models import PartCategory, Part +from .models import BomItem class PartAdmin(admin.ModelAdmin): @@ -11,6 +12,9 @@ class PartCategoryAdmin(admin.ModelAdmin): list_display = ('name', 'pathstring', 'description') +class BomItemAdmin(admin.ModelAdmin): + list_display=('part', 'sub_part', 'quantity') + """ class ParameterTemplateAdmin(admin.ModelAdmin): list_display = ('name', 'units', 'format') @@ -22,6 +26,7 @@ class ParameterAdmin(admin.ModelAdmin): admin.site.register(Part, PartAdmin) admin.site.register(PartCategory, PartCategoryAdmin) +admin.site.register(BomItem, BomItemAdmin) #admin.site.register(PartParameter, ParameterAdmin) #admin.site.register(PartParameterTemplate, ParameterTemplateAdmin) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 77f3b11357..417a151a72 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -1,11 +1,12 @@ from .serializers import PartSerializer from .serializers import PartCategorySerializer +from .serializers import BomItemSerializer from rest_framework import generics, permissions from django_filters.rest_framework import FilterSet, DjangoFilterBackend -from .models import PartCategory, Part +from .models import PartCategory, Part, BomItem class PartDetail(generics.RetrieveUpdateDestroyAPIView): """ @@ -172,3 +173,28 @@ class PartTemplateList(generics.ListCreateAPIView): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) """ + +class BomItemDetail(generics.RetrieveUpdateDestroyAPIView): + + queryset = BomItem.objects.all() + serializer_class = BomItemSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class BomItemFilter(FilterSet): + + class Meta: + model = BomItem + fields = ['part', 'sub_part'] + + +class BomItemList(generics.ListCreateAPIView): + + #def get_queryset(self): + # params = self.request. + + queryset = BomItem.objects.all() + serializer_class = BomItemSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + filter_backends = (DjangoFilterBackend,) + filter_class = BomItemFilter diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 3205b992db..4f7b2d8f4f 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -118,3 +118,32 @@ class Part(models.Model): """ +class BomItem(models.Model): + """ A BomItem links a part to its component items. + A part can have a BOM (bill of materials) which defines + which parts are required (and in what quatity) to make it + """ + + # A link to the parent part + # Each part will get a reverse lookup field 'bom_items' + part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='bom_items') + + # A link to the child item (sub-part) + # Each part will get a reverse lookup field 'used_in' + sub_part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='used_in') + + # Quantity required + quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) + + + class Meta: + verbose_name = "BOM Item" + + # Prevent duplication of parent/child rows + unique_together = ('part', 'sub_part') + + def __str__(self): + return "{par} -> {child} ({n})".format( + par=self.part.name, + child=self.sub_part.name, + n=self.quantity) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 34d8c98b8e..c4202b2bee 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -1,6 +1,16 @@ from rest_framework import serializers from .models import Part, PartCategory +from .models import BomItem + +class BomItemSerializer(serializers.ModelSerializer): + + class Meta: + model = BomItem + fields = ('url', + 'part', + 'sub_part', + 'quantity') """ class PartParameterSerializer(serializers.HyperlinkedModelSerializer): diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 79aad236b2..5abe293ffc 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -29,6 +29,15 @@ part_api_urls = [ url(r'^$', api.PartList.as_view()), ] +bom_api_urls = [ + # Bom Item detail + url(r'^(?P[0-9]+)/?$', api.BomItemDetail.as_view(), name='bomitem-detail'), + + # List of top-level categories + url(r'^\?*.*/?$', api.BomItemList.as_view()), + url(r'^$', api.BomItemList.as_view()) +] + part_detail_urls = [ url(r'^track/?', views.track, name='track'), url(r'^bom/?', views.bom, name='bom'), @@ -47,6 +56,8 @@ part_urls = [ url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='index'), ] + + """ part_param_urls = [ # Detail of a single part parameter