mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
bf1490c68a
@ -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',
|
||||
|
@ -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):
|
||||
"""
|
||||
@ -594,6 +602,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 +624,7 @@ class Build(MPTTModel):
|
||||
# Ensure that the output is updated correctly
|
||||
output.build = self
|
||||
output.is_building = False
|
||||
output.location = location
|
||||
|
||||
output.save()
|
||||
|
||||
|
@ -21,6 +21,7 @@ InvenTree | Allocate Parts
|
||||
</div>
|
||||
{% else %}
|
||||
<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" %}'>
|
||||
<span class='fas fa-plus-circle'></span> {% trans "Create New Output" %}
|
||||
</button>
|
||||
@ -32,6 +33,7 @@ InvenTree | Allocate Parts
|
||||
<button class='btn btn-danger' type='button' id='btn-unallocate' title='{% trans "Unallocate stock" %}'>
|
||||
<span class='fas fa-minus-circle'></span> {% trans "Unallocate Stock" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
@ -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 %}",
|
||||
|
@ -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)
|
||||
|
@ -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 """
|
||||
|
@ -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
|
||||
|
@ -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,24 +204,31 @@ 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')
|
||||
# Test GET view
|
||||
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
|
||||
# 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):
|
||||
""" test creation of an attachment for an invalid part """
|
||||
# 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)
|
||||
|
||||
# TODO
|
||||
pass
|
||||
|
||||
def test_edit(self):
|
||||
""" test editing an attachment """
|
||||
|
||||
# TODO
|
||||
pass
|
||||
# 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)
|
||||
|
||||
|
||||
class PartAttachmentTests(PartViewTestCase):
|
||||
|
@ -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 """
|
||||
|
Loading…
Reference in New Issue
Block a user