Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2020-11-05 18:29:53 +11:00
commit bf1490c68a
8 changed files with 40 additions and 56 deletions

View File

@ -66,7 +66,7 @@ class BuildOutputCreateForm(HelperForm):
'serial_numbers': 'fa-hashtag', 'serial_numbers': 'fa-hashtag',
} }
quantity = forms.IntegerField( output_quantity = forms.IntegerField(
label=_('Quantity'), label=_('Quantity'),
help_text=_('Enter quantity for build output'), help_text=_('Enter quantity for build output'),
) )
@ -86,7 +86,7 @@ class BuildOutputCreateForm(HelperForm):
class Meta: class Meta:
model = Build model = Build
fields = [ fields = [
'quantity', 'output_quantity',
'batch', 'batch',
'serial_numbers', 'serial_numbers',
'confirm', 'confirm',

View File

@ -182,6 +182,14 @@ class Build(MPTTModel):
blank=True, help_text=_('Extra build notes') 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 @property
def bom_items(self): def bom_items(self):
""" """
@ -594,6 +602,9 @@ class Build(MPTTModel):
- Mark the output as complete - 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 # List the allocated BuildItem objects for the given output
allocated_items = output.items_to_install.all() allocated_items = output.items_to_install.all()
@ -613,6 +624,7 @@ class Build(MPTTModel):
# Ensure that the output is updated correctly # Ensure that the output is updated correctly
output.build = self output.build = self
output.is_building = False output.is_building = False
output.location = location
output.save() output.save()

View File

@ -21,6 +21,7 @@ InvenTree | Allocate Parts
</div> </div>
{% else %} {% else %}
<div class='btn-group' role='group'> <div class='btn-group' role='group'>
{% if build.active %}
<button class='btn btn-primary' type='button' id='btn-create-output' title='{% trans "Create new build output" %}'> <button class='btn btn-primary' type='button' id='btn-create-output' title='{% trans "Create new build output" %}'>
<span class='fas fa-plus-circle'></span> {% trans "Create New Output" %} <span class='fas fa-plus-circle'></span> {% trans "Create New Output" %}
</button> </button>
@ -32,6 +33,7 @@ InvenTree | Allocate Parts
<button class='btn btn-danger' type='button' id='btn-unallocate' title='{% trans "Unallocate stock" %}'> <button class='btn btn-danger' type='button' id='btn-unallocate' title='{% trans "Unallocate stock" %}'>
<span class='fas fa-minus-circle'></span> {% trans "Unallocate Stock" %} <span class='fas fa-minus-circle'></span> {% trans "Unallocate Stock" %}
</button> </button>
{% endif %}
</div> </div>
<hr> <hr>
@ -74,7 +76,7 @@ InvenTree | Allocate Parts
); );
{% endfor %} {% endfor %}
{% if build.status == BuildStatus.PENDING %} {% if build.active %}
$("#btn-allocate").on('click', function() { $("#btn-allocate").on('click', function() {
launchModalForm( launchModalForm(
"{% url 'build-auto-allocate' build.id %}", "{% url 'build-auto-allocate' build.id %}",

View File

@ -188,7 +188,7 @@ class BuildOutputCreate(AjaxUpdateView):
Validation for the form: 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) serials = form.cleaned_data.get('serial_numbers', None)
# Check that the serial numbers are valid # Check that the serial numbers are valid
@ -222,7 +222,7 @@ class BuildOutputCreate(AjaxUpdateView):
data = form.cleaned_data data = form.cleaned_data
quantity = data.get('quantity', None) quantity = data.get('output_quantity', None)
batch = data.get('batch', None) batch = data.get('batch', None)
serials = data.get('serial_numbers', None) serials = data.get('serial_numbers', None)

View File

@ -154,11 +154,6 @@ class CreatePartRelatedForm(HelperForm):
'part_2': _('Related Part'), 'part_2': _('Related Part'),
} }
def save(self):
""" Disable model saving """
return super(CreatePartRelatedForm, self).save(commit=False)
class EditPartAttachmentForm(HelperForm): class EditPartAttachmentForm(HelperForm):
""" Form for editing a PartAttachment object """ """ Form for editing a PartAttachment object """

View File

@ -1908,24 +1908,3 @@ class PartRelated(models.Model):
'and that the relationship is unique') 'and that the relationship is unique')
raise ValidationError(error_message) 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

View File

@ -5,7 +5,7 @@ from django.urls import reverse
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from .models import Part from .models import Part, PartRelated
class PartViewTestCase(TestCase): class PartViewTestCase(TestCase):
@ -204,24 +204,31 @@ class PartTests(PartViewTestCase):
class PartRelatedTests(PartViewTestCase): class PartRelatedTests(PartViewTestCase):
def test_valid_create(self): 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') # Test GET view
response = self.client.get(reverse('part-related-create'), {'part': 1},
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# TODO - Create a new attachment using this view # 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.assertContains(response, '"form_valid": true', status_code=200)
def test_invalid_create(self): # Try to create the same relationship with part_1 and part_2 pks reversed
""" test creation of an attachment for an invalid part """ 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)
# TODO # Try to create part related to itself
pass 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)
def test_edit(self): # Check final count
""" test editing an attachment """ n = PartRelated.objects.all().count()
self.assertEqual(n, 1)
# TODO
pass
class PartAttachmentTests(PartViewTestCase): class PartAttachmentTests(PartViewTestCase):

View File

@ -128,17 +128,6 @@ class PartRelatedCreate(AjaxCreateView):
return form 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): class PartRelatedDelete(AjaxDeleteView):
""" View for deleting a PartRelated object """ """ View for deleting a PartRelated object """