From de2b7e5daf176ecab2345e096f8870d1ac996ce0 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 3 Nov 2020 08:03:16 -0500 Subject: [PATCH 1/7] Re-added post_save method in AjaxCreateView --- InvenTree/InvenTree/views.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index dd7a782485..cfe07dcc68 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -333,6 +333,12 @@ class AjaxCreateView(AjaxMixin, CreateView): - Handles form validation via AJAX POST requests """ + def post_save(self, **kwargs): + """ + Hook for doing something with the created object after it is saved + """ + pass + def get(self, request, *args, **kwargs): """ Creates form with initial data, and renders JSON response """ @@ -386,6 +392,7 @@ class AjaxCreateView(AjaxMixin, CreateView): # Save the object to the database self.object = self.save(self.form) + self.post_save() # Return the PK of the newly-created object data['pk'] = self.object.pk From 32b46cdc2aff9b503d2ef14744b1f78985d8c7f2 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 3 Nov 2020 11:14:31 -0500 Subject: [PATCH 2/7] Added better PartRelated creation test --- InvenTree/part/test_views.py | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/InvenTree/part/test_views.py b/InvenTree/part/test_views.py index 1ad5c33e45..3391d4a0c2 100644 --- a/InvenTree/part/test_views.py +++ b/InvenTree/part/test_views.py @@ -5,7 +5,7 @@ from django.urls import reverse from django.contrib.auth import get_user_model from django.contrib.auth.models import Group -from .models import Part +from .models import Part, PartRelated class PartViewTestCase(TestCase): @@ -204,25 +204,18 @@ class PartTests(PartViewTestCase): class PartRelatedTests(PartViewTestCase): def test_valid_create(self): - """ test creation of an attachment for a valid part """ + """ test creation of a related part """ - response = self.client.get(reverse('part-related-create'), {'part': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + response = self.client.get(reverse('part-related-create'), {'part': 1}, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - # TODO - Create a new attachment using this view - - def test_invalid_create(self): - """ test creation of an attachment for an invalid part """ - - # TODO - pass - - def test_edit(self): - """ test editing an attachment """ - - # TODO - pass + response = self.client.post(reverse('part-related-create'), {'part_1': 1, 'part_2': 2}, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(response.status_code, 200) + n = PartRelated.objects.all().count() + self.assertEqual(n, 1) class PartAttachmentTests(PartViewTestCase): From 0882528b82b2ec233557cb5ed33d6be89093ab3d Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 3 Nov 2020 11:15:16 -0500 Subject: [PATCH 3/7] Missing class trailing space --- InvenTree/part/test_views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/InvenTree/part/test_views.py b/InvenTree/part/test_views.py index 3391d4a0c2..7c573fcd77 100644 --- a/InvenTree/part/test_views.py +++ b/InvenTree/part/test_views.py @@ -217,6 +217,7 @@ class PartRelatedTests(PartViewTestCase): n = PartRelated.objects.all().count() self.assertEqual(n, 1) + class PartAttachmentTests(PartViewTestCase): def test_valid_create(self): From 142cea0cbbbf04b529fd7ddf1f334c6ab38981a5 Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 4 Nov 2020 07:44:06 -0500 Subject: [PATCH 4/7] Removed custom form save method, remove unused model methods, restored InvenTree CreateAjaxView, improved part related testing --- InvenTree/InvenTree/views.py | 7 ------- InvenTree/part/forms.py | 5 ----- InvenTree/part/models.py | 21 --------------------- InvenTree/part/test_views.py | 15 ++++++++++++++- InvenTree/part/views.py | 11 ----------- 5 files changed, 14 insertions(+), 45 deletions(-) diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index cfe07dcc68..dd7a782485 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -333,12 +333,6 @@ class AjaxCreateView(AjaxMixin, CreateView): - Handles form validation via AJAX POST requests """ - def post_save(self, **kwargs): - """ - Hook for doing something with the created object after it is saved - """ - pass - def get(self, request, *args, **kwargs): """ Creates form with initial data, and renders JSON response """ @@ -392,7 +386,6 @@ class AjaxCreateView(AjaxMixin, CreateView): # Save the object to the database self.object = self.save(self.form) - self.post_save() # Return the PK of the newly-created object data['pk'] = self.object.pk diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index c4523113e5..0b24e5a462 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -154,11 +154,6 @@ class CreatePartRelatedForm(HelperForm): 'part_2': _('Related Part'), } - def save(self): - """ Disable model saving """ - - return super(CreatePartRelatedForm, self).save(commit=False) - class EditPartAttachmentForm(HelperForm): """ Form for editing a PartAttachment object """ diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 60e100b563..0c8aeb5665 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -1908,24 +1908,3 @@ class PartRelated(models.Model): 'and that the relationship is unique') raise ValidationError(error_message) - - def create_relationship(self, part_1, part_2): - ''' Create relationship between two parts ''' - - validate = self.validate(part_1, part_2) - - if validate: - # Add relationship - self.part_1 = part_1 - self.part_2 = part_2 - self.save() - - return validate - - @classmethod - def create(cls, part_1, part_2): - ''' Create PartRelated object and relationship between two parts ''' - - related_part = cls() - related_part.create_relationship(part_1, part_2) - return related_part diff --git a/InvenTree/part/test_views.py b/InvenTree/part/test_views.py index 7c573fcd77..2a36dd9012 100644 --- a/InvenTree/part/test_views.py +++ b/InvenTree/part/test_views.py @@ -206,14 +206,27 @@ class PartRelatedTests(PartViewTestCase): def test_valid_create(self): """ test creation of a related part """ + # Test GET view response = self.client.get(reverse('part-related-create'), {'part': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) + # Test POST view with valid form data response = self.client.post(reverse('part-related-create'), {'part_1': 1, 'part_2': 2}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - self.assertEqual(response.status_code, 200) + self.assertContains(response, '"form_valid": true', status_code=200) + # Try to create the same relationship with part_1 and part_2 pks reversed + response = self.client.post(reverse('part-related-create'), {'part_1': 2, 'part_2': 1}, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertContains(response, '"form_valid": false', status_code=200) + + # Try to create part related to itself + response = self.client.post(reverse('part-related-create'), {'part_1': 1, 'part_2': 1}, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertContains(response, '"form_valid": false', status_code=200) + + # Check final count n = PartRelated.objects.all().count() self.assertEqual(n, 1) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index bd602448db..2504b056c5 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -128,17 +128,6 @@ class PartRelatedCreate(AjaxCreateView): return form - def post_save(self): - """ Save PartRelated model (POST method does not) """ - - form = self.get_form() - - if form.is_valid(): - part_1 = form.cleaned_data['part_1'] - part_2 = form.cleaned_data['part_2'] - - PartRelated.create(part_1, part_2) - class PartRelatedDelete(AjaxDeleteView): """ View for deleting a PartRelated object """ From 8b7789cdb3b6c3f6ef7e7ec7adbbfce91ba3fcf2 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 5 Nov 2020 15:46:42 +1100 Subject: [PATCH 5/7] Set the specified location of a build output --- InvenTree/build/models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 6634b69cdf..2b2bdecbed 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -594,6 +594,9 @@ class Build(MPTTModel): - Mark the output as complete """ + # Select the location for the build output + location = kwargs.get('location', self.destination) + # List the allocated BuildItem objects for the given output allocated_items = output.items_to_install.all() @@ -613,6 +616,7 @@ class Build(MPTTModel): # Ensure that the output is updated correctly output.build = self output.is_building = False + output.location = location output.save() From d44092b209bd87fb138da3b01e57b1f657f6b808 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 5 Nov 2020 15:52:38 +1100 Subject: [PATCH 6/7] Fix issue with shadowed form field - Rename "quantity" to "output_quantity" to address this --- InvenTree/build/forms.py | 4 ++-- InvenTree/build/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/InvenTree/build/forms.py b/InvenTree/build/forms.py index 24f193865d..ba7787798d 100644 --- a/InvenTree/build/forms.py +++ b/InvenTree/build/forms.py @@ -66,7 +66,7 @@ class BuildOutputCreateForm(HelperForm): 'serial_numbers': 'fa-hashtag', } - quantity = forms.IntegerField( + output_quantity = forms.IntegerField( label=_('Quantity'), help_text=_('Enter quantity for build output'), ) @@ -86,7 +86,7 @@ class BuildOutputCreateForm(HelperForm): class Meta: model = Build fields = [ - 'quantity', + 'output_quantity', 'batch', 'serial_numbers', 'confirm', diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 5dd36a6871..1355738a9c 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -188,7 +188,7 @@ class BuildOutputCreate(AjaxUpdateView): Validation for the form: """ - quantity = form.cleaned_data.get('quantity', None) + quantity = form.cleaned_data.get('output_quantity', None) serials = form.cleaned_data.get('serial_numbers', None) # Check that the serial numbers are valid @@ -222,7 +222,7 @@ class BuildOutputCreate(AjaxUpdateView): data = form.cleaned_data - quantity = data.get('quantity', None) + quantity = data.get('output_quantity', None) batch = data.get('batch', None) serials = data.get('serial_numbers', None) From 2591d342607de22a1e19c9d375fc9aa8d23f223e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 5 Nov 2020 15:57:46 +1100 Subject: [PATCH 7/7] Fixed bug where "New output" button stopped working - Build status was changing from "PENDING" to "PRODUCTION" - Created new check for active builds --- InvenTree/build/models.py | 8 ++++++++ InvenTree/build/templates/build/allocate.html | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 2b2bdecbed..a18328be1a 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -182,6 +182,14 @@ class Build(MPTTModel): blank=True, help_text=_('Extra build notes') ) + @property + def active(self): + """ + Return True if this build is active + """ + + return self.status in BuildStatus.ACTIVE_CODES + @property def bom_items(self): """ diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html index e811c37ce8..aa45aa5054 100644 --- a/InvenTree/build/templates/build/allocate.html +++ b/InvenTree/build/templates/build/allocate.html @@ -21,6 +21,7 @@ InvenTree | Allocate Parts {% else %}
+ {% if build.active %} @@ -32,6 +33,7 @@ InvenTree | Allocate Parts + {% endif %}

@@ -74,7 +76,7 @@ InvenTree | Allocate Parts ); {% endfor %} - {% if build.status == BuildStatus.PENDING %} + {% if build.active %} $("#btn-allocate").on('click', function() { launchModalForm( "{% url 'build-auto-allocate' build.id %}",