mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
f7a1fb0a9d
@ -164,6 +164,8 @@ class AjaxMixin(object):
|
||||
|
||||
if form:
|
||||
context['form'] = form
|
||||
else:
|
||||
context['form'] = None
|
||||
|
||||
data['title'] = self.ajax_form_title
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
<span class="caret"></span></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href='#' id='multi-part-order' title='Order parts'>Order Parts</a></li>
|
||||
<li><a href='#' id='multi-part-delete' title='Delete parts'>Delete Parts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -98,6 +99,23 @@
|
||||
url: "{% url 'api-part-supplier-list' %}"
|
||||
});
|
||||
|
||||
$("#multi-part-delete").click(function() {
|
||||
var selections = $("#part-table").bootstrapTable("getSelections");
|
||||
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
parts.push(item.pk);
|
||||
});
|
||||
|
||||
launchModalForm("{% url 'supplier-part-delete' %}", {
|
||||
data: {
|
||||
parts: parts,
|
||||
},
|
||||
reload: true,
|
||||
});
|
||||
});
|
||||
|
||||
$("#multi-part-order").click(function() {
|
||||
var selections = $("#part-table").bootstrapTable("getSelections");
|
||||
|
||||
|
@ -1,5 +1,28 @@
|
||||
{% extends "modal_delete_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block pre_form_content %}
|
||||
Are you sure you want to delete this supplier part?
|
||||
{% trans "Are you sure you want to delete the following Supplier Parts?" %}
|
||||
|
||||
<hr>
|
||||
{% endblock %}
|
||||
|
||||
{% block form_data %}
|
||||
<table class='table table-striped table-condensed'>
|
||||
{% for part in parts %}
|
||||
<tr>
|
||||
<input type='hidden' name='supplier-part-{{ part.id}}' value='supplier-part-{{ part.id }}'/>
|
||||
|
||||
<td>
|
||||
{% include "hover_image.html" with image=part.supplier.image %}
|
||||
{{ part.supplier.name }}
|
||||
</td>
|
||||
<td>
|
||||
{% include "hover_image.html" with image=part.part.image %}
|
||||
{{ part.part.full_name }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -130,10 +130,10 @@ InvenTree | {{ company.name }} - Parts
|
||||
|
||||
$('#delete-part').click(function() {
|
||||
launchModalForm(
|
||||
"{% url 'supplier-part-delete' part.id %}",
|
||||
{
|
||||
redirect: "{% url 'company-index' %}"
|
||||
}
|
||||
"{% url 'supplier-part-delete' %}?part={{ part.id }}",
|
||||
{
|
||||
redirect: "{% url 'company-detail-parts' part.supplier.id %}"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
64
InvenTree/company/test_views.py
Normal file
64
InvenTree/company/test_views.py
Normal file
@ -0,0 +1,64 @@
|
||||
""" Unit tests for Company views (see views.py) """
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from .models import SupplierPart
|
||||
|
||||
|
||||
class CompanyViewTest(TestCase):
|
||||
|
||||
fixtures = [
|
||||
'category',
|
||||
'part',
|
||||
'location',
|
||||
'company',
|
||||
'supplier_part',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
# Create a user
|
||||
User = get_user_model()
|
||||
User.objects.create_user('username', 'user@email.com', 'password')
|
||||
|
||||
self.client.login(username='username', password='password')
|
||||
|
||||
def test_company_index(self):
|
||||
""" Test the company index """
|
||||
|
||||
response = self.client.get(reverse('company-index'))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_supplier_part_delete(self):
|
||||
""" Test the SupplierPartDelete view """
|
||||
|
||||
url = reverse('supplier-part-delete')
|
||||
|
||||
# Get form using 'part' argument
|
||||
response = self.client.get(url, {'part': '1'}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Get form using 'parts' argument
|
||||
response = self.client.get(url + '?parts[]=1&parts[]=2', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to delete two parts
|
||||
n = SupplierPart.objects.count()
|
||||
response = self.client.post(
|
||||
url,
|
||||
{
|
||||
'supplier-part-2': 'supplier-part-2',
|
||||
'supplier-part-3': 'supplier-part-3',
|
||||
'confirm_delete': True
|
||||
},
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertEqual(n - 2, SupplierPart.objects.count())
|
@ -47,7 +47,6 @@ price_break_urls = [
|
||||
|
||||
supplier_part_detail_urls = [
|
||||
url(r'edit/?', views.SupplierPartEdit.as_view(), name='supplier-part-edit'),
|
||||
url(r'delete/?', views.SupplierPartDelete.as_view(), name='supplier-part-delete'),
|
||||
|
||||
url('^.*$', views.SupplierPartDetail.as_view(), name='supplier-part-detail'),
|
||||
]
|
||||
@ -55,5 +54,7 @@ supplier_part_detail_urls = [
|
||||
supplier_part_urls = [
|
||||
url(r'^new/?', views.SupplierPartCreate.as_view(), name='supplier-part-create'),
|
||||
|
||||
url(r'delete/', views.SupplierPartDelete.as_view(), name='supplier-part-delete'),
|
||||
|
||||
url(r'^(?P<pk>\d+)/', include(supplier_part_detail_urls)),
|
||||
]
|
||||
|
@ -12,6 +12,7 @@ from django.forms import HiddenInput
|
||||
|
||||
from InvenTree.views import AjaxCreateView, AjaxUpdateView, AjaxDeleteView
|
||||
from InvenTree.status_codes import OrderStatus
|
||||
from InvenTree.helpers import str2bool
|
||||
|
||||
from .models import Company
|
||||
from .models import SupplierPart
|
||||
@ -197,12 +198,80 @@ class SupplierPartCreate(AjaxCreateView):
|
||||
|
||||
|
||||
class SupplierPartDelete(AjaxDeleteView):
|
||||
""" Delete view for removing a SupplierPart """
|
||||
model = SupplierPart
|
||||
""" Delete view for removing a SupplierPart.
|
||||
|
||||
SupplierParts can be deleted using a variety of 'selectors'.
|
||||
|
||||
- ?part=<pk> -> Delete a single SupplierPart object
|
||||
- ?parts=[] -> Delete a list of SupplierPart objects
|
||||
|
||||
"""
|
||||
|
||||
success_url = '/supplier/'
|
||||
ajax_template_name = 'company/partdelete.html'
|
||||
ajax_form_title = 'Delete Supplier Part'
|
||||
context_object_name = 'supplier_part'
|
||||
|
||||
parts = []
|
||||
|
||||
def get_context_data(self):
|
||||
ctx = {}
|
||||
|
||||
ctx['parts'] = self.parts
|
||||
|
||||
return ctx
|
||||
|
||||
def get_parts(self):
|
||||
""" Determine which SupplierPart object(s) the user wishes to delete.
|
||||
"""
|
||||
|
||||
self.parts = []
|
||||
|
||||
# User passes a single SupplierPart ID
|
||||
if 'part' in self.request.GET:
|
||||
try:
|
||||
self.parts.append(SupplierPart.objects.get(pk=self.request.GET.get('part')))
|
||||
except (ValueError, SupplierPart.DoesNotExist):
|
||||
pass
|
||||
|
||||
elif 'parts[]' in self.request.GET:
|
||||
|
||||
part_id_list = self.request.GET.getlist('parts[]')
|
||||
|
||||
self.parts = SupplierPart.objects.filter(id__in=part_id_list)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.get_parts()
|
||||
|
||||
return self.renderJsonResponse(request, form=self.get_form())
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
""" Handle the POST action for deleting supplier parts.
|
||||
"""
|
||||
|
||||
self.request = request
|
||||
self.parts = []
|
||||
|
||||
for item in self.request.POST:
|
||||
if item.startswith('supplier-part-'):
|
||||
pk = item.replace('supplier-part-', '')
|
||||
|
||||
try:
|
||||
self.parts.append(SupplierPart.objects.get(pk=pk))
|
||||
except (ValueError, SupplierPart.DoesNotExist):
|
||||
pass
|
||||
|
||||
confirm = str2bool(self.request.POST.get('confirm_delete', False))
|
||||
|
||||
data = {
|
||||
'form_valid': confirm,
|
||||
}
|
||||
|
||||
if confirm:
|
||||
for part in self.parts:
|
||||
part.delete()
|
||||
|
||||
return self.renderJsonResponse(self.request, data=data, form=self.get_form())
|
||||
|
||||
|
||||
class PriceBreakCreate(AjaxCreateView):
|
||||
|
@ -1,5 +1,8 @@
|
||||
""" Unit tests for Order views (see views.py) """
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth import get_user_model
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
<div id='button-toolbar'>
|
||||
<button class="btn btn-success" id='supplier-create'>New Supplier Part</button>
|
||||
{% if 0 %}
|
||||
<div id='opt-dropdown' class="dropdown" style='float: right;'>
|
||||
<button id='supplier-part-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Options
|
||||
<span class="caret"></span></button>
|
||||
@ -17,7 +16,6 @@
|
||||
<li><a href='#' id='supplier-part-delete' title='Delete supplier parts'>Delete</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-condensed" id='supplier-table' data-toolbar='#button-toolbar'>
|
||||
@ -50,6 +48,24 @@
|
||||
});
|
||||
});
|
||||
|
||||
$("#supplier-part-delete").click(function() {
|
||||
|
||||
var selections = $("#supplier-table").bootstrapTable("getSelections");
|
||||
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
parts.push(item.pk);
|
||||
});
|
||||
|
||||
launchModalForm("{% url 'supplier-part-delete' %}", {
|
||||
data: {
|
||||
parts: parts,
|
||||
},
|
||||
reload: true,
|
||||
});
|
||||
});
|
||||
|
||||
$("#supplier-table").inventreeTable({
|
||||
formatNoMatches: function() { return "No supplier parts available for {{ part.full_name }}"; },
|
||||
queryParams: function(p) {
|
||||
@ -58,12 +74,9 @@
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
/*
|
||||
// TODO - Re-enable the checkbox column for performing actions on multiple supplier parts
|
||||
{
|
||||
checkbox: true,
|
||||
},
|
||||
*/
|
||||
{
|
||||
sortable: true,
|
||||
field: 'supplier_name',
|
||||
|
@ -27,11 +27,11 @@
|
||||
{% csrf_token %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block form_data %}
|
||||
{% endblock %}
|
||||
|
||||
{% crispy form %}
|
||||
|
||||
{% block form_data %}
|
||||
{% endblock %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
Loading…
Reference in New Issue
Block a user