From 4ffaad3f1acd12c031f232e17de5740f101ad9e8 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 4 May 2019 19:00:11 +1000 Subject: [PATCH 1/5] Add a default_location to the PartCategory model - If a part does not specify a default location, look at the default location of the category --- .../0015_partcategory_default_location.py | 20 +++++++++++++++++++ InvenTree/part/models.py | 7 +++++++ 2 files changed, 27 insertions(+) create mode 100644 InvenTree/part/migrations/0015_partcategory_default_location.py diff --git a/InvenTree/part/migrations/0015_partcategory_default_location.py b/InvenTree/part/migrations/0015_partcategory_default_location.py new file mode 100644 index 0000000000..33a47cc440 --- /dev/null +++ b/InvenTree/part/migrations/0015_partcategory_default_location.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2 on 2019-05-04 08:57 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0013_remove_stockitem_uuid'), + ('part', '0014_auto_20190502_2039'), + ] + + operations = [ + migrations.AddField( + model_name='partcategory', + name='default_location', + field=models.ForeignKey(blank=True, help_text='Default location for parts in this category', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_categories', to='stock.StockLocation'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index e2823ba93b..fb4dcd350d 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -30,6 +30,13 @@ class PartCategory(InvenTreeTree): """ PartCategory provides hierarchical organization of Part objects. """ + default_location = models.ForeignKey( + 'stock.StockLocation', related_name="default_categories", + null=True, blank=True, + on_delete = models.SET_NULL, + help_text='Default location for parts in this category' + ) + def get_absolute_url(self): return reverse('category-detail', kwargs={'pk': self.id}) From f27037584745044c77bf135202080c1e96819897 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 4 May 2019 19:03:32 +1000 Subject: [PATCH 2/5] Add ability to edit default_location for a PartCategory --- InvenTree/part/forms.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 0363b4ab37..e97386d229 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -90,7 +90,8 @@ class EditCategoryForm(HelperForm): fields = [ 'parent', 'name', - 'description' + 'description', + 'default_location' ] From 71972f4454c00df3249b3dfb55af184026dbcd95 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 4 May 2019 19:06:39 +1000 Subject: [PATCH 3/5] Add function to get the default location for a part - If field not specified, look at the part category --- InvenTree/part/models.py | 15 +++++++++++++++ InvenTree/stock/views.py | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index fb4dcd350d..f3caeeae6a 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -148,6 +148,21 @@ class Part(models.Model): help_text='Where is this item normally stored?', related_name='default_parts') + def get_default_location(self): + """ Get the default location for a Part (may be None). + + If the Part does not specify a default location, + look at the Category this part is in. + The PartCategory object may also specify a default stock location + """ + + if self.default_location: + return self.default_location + elif self.category: + return self.category.default_location + + return None + # Default supplier part default_supplier = models.ForeignKey('part.SupplierPart', on_delete=models.SET_NULL, diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index c0d1e0dc9d..fc174fa3f1 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -211,7 +211,7 @@ class StockItemCreate(AjaxCreateView): try: part = Part.objects.get(pk=part_id) initials['part'] = part - initials['location'] = part.default_location + initials['location'] = part.get_default_location() initials['supplier_part'] = part.default_supplier except Part.DoesNotExist: pass From 67eda51cd20142fe4ec005b0c7f3cd06ced500b0 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 4 May 2019 21:56:18 +1000 Subject: [PATCH 4/5] Add part category tree traversal - If a category doesn't have a default_location, look at the parent category - And so on and so on --- InvenTree/part/models.py | 10 +++++++++- InvenTree/part/templates/part/category.html | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index f3caeeae6a..cdd9247b13 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -159,8 +159,16 @@ class Part(models.Model): if self.default_location: return self.default_location elif self.category: - return self.category.default_location + # Traverse up the category tree until we find a default location + cat = self.category + while cat: + if cat.default_location: + return cat.default_location + else: + cat = cat.parent + + # Default case - no default category found return None # Default supplier part diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index d03d18be44..7dad872114 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -8,8 +8,11 @@ {% if category %}

{{ category.name }}

{{ category.description }}

+ {% if category.default_location %} +

Default Location: {{ category.default_location }}

+ {% endif %} {% else %} -

Parts

+

Part Categories

{% endif %}
From bc7f3f77dee4bfb5c921187a5943c5ff819fb809 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 4 May 2019 21:57:43 +1000 Subject: [PATCH 5/5] PEPEP --- InvenTree/part/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index cdd9247b13..8bc519d616 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -33,7 +33,7 @@ class PartCategory(InvenTreeTree): default_location = models.ForeignKey( 'stock.StockLocation', related_name="default_categories", null=True, blank=True, - on_delete = models.SET_NULL, + on_delete=models.SET_NULL, help_text='Default location for parts in this category' ) @@ -153,7 +153,7 @@ class Part(models.Model): If the Part does not specify a default location, look at the Category this part is in. - The PartCategory object may also specify a default stock location + The PartCategory object may also specify a default stock location """ if self.default_location: