mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Return all part parameters to the main part edit form
- refactor purchaseorder view - refactor salesorder view
This commit is contained in:
parent
352a58b373
commit
984e16d5af
@ -781,7 +781,7 @@ input[type="submit"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidenav .list-group-item.active {
|
.sidenav .list-group-item.active {
|
||||||
background-color: #bbab8b;
|
background-color: #b3a997;
|
||||||
border-color: #ccc;
|
border-color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,7 +1104,7 @@ part_api_urls = [
|
|||||||
url(r'^(?P<pk>\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'),
|
url(r'^(?P<pk>\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'),
|
||||||
])),
|
])),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/?', PartDetail.as_view(), name='api-part-detail'),
|
url(r'^(?P<pk>\d+)/', PartDetail.as_view(), name='api-part-detail'),
|
||||||
|
|
||||||
url(r'^.*$', PartList.as_view(), name='api-part-list'),
|
url(r'^.*$', PartList.as_view(), name='api-part-list'),
|
||||||
]
|
]
|
||||||
|
@ -44,6 +44,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class='panel panel-default panel-inventree panel-hidden' id='panel-purchase-orders'>
|
||||||
|
<div class='panel-heading'>
|
||||||
|
<h4>{% trans "Purchase Orders" %}</h4>
|
||||||
|
</div>
|
||||||
|
<div class='panel-content'>
|
||||||
|
<div id='po-button-bar'>
|
||||||
|
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||||
|
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "Order part" %}'>
|
||||||
|
<span class='fas fa-shopping-cart'></span> {% trans "Order Part" %}
|
||||||
|
</button>
|
||||||
|
<div class='filter-list' id='filter-list-purchaseorder'>
|
||||||
|
<!-- An empty div in which the filter list will be constructed -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#po-button-bar'>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='panel panel-default panel-inventree panel-hidden' id='panel-sales-orders'>
|
||||||
|
<div class='panel-heading'>
|
||||||
|
<h4>{% trans "Sales Orders" %}</h4>
|
||||||
|
</div>
|
||||||
|
<div class='panel-content'>
|
||||||
|
<div id='so-button-bar'>
|
||||||
|
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||||
|
{% if 0 %}
|
||||||
|
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "New sales order" %}'>{% trans "New Order" %}</button>
|
||||||
|
{% endif %}
|
||||||
|
<div class='filter-list' id='filter-list-salesorder'>
|
||||||
|
<!-- An empty div in which the filter list will be constructed -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class='table table-striped table-condensed po-table' id='sales-order-table' data-toolbar='#so-button-bar'>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class='panel panel-default panel-inventree panel-hidden' id='panel-part-notes'>
|
<div class='panel panel-default panel-inventree panel-hidden' id='panel-part-notes'>
|
||||||
<div class='panel-heading'>
|
<div class='panel-heading'>
|
||||||
<div class='row'>
|
<div class='row'>
|
||||||
@ -101,6 +143,29 @@
|
|||||||
{% block js_ready %}
|
{% block js_ready %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
||||||
|
loadPurchaseOrderTable($("#purchase-order-table"), {
|
||||||
|
url: "{% url 'api-po-list' %}",
|
||||||
|
params: {
|
||||||
|
part: {{ part.id }},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#part-order2").click(function() {
|
||||||
|
launchModalForm("{% url 'order-parts' %}", {
|
||||||
|
data: {
|
||||||
|
part: {{ part.id }},
|
||||||
|
},
|
||||||
|
reload: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
loadSalesOrderTable($("#sales-order-table"), {
|
||||||
|
url: "{% url 'api-so-list' %}",
|
||||||
|
params: {
|
||||||
|
part: {{ part.id }},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
loadPartTestTemplateTable(
|
loadPartTestTemplateTable(
|
||||||
$("#test-template-table"),
|
$("#test-template-table"),
|
||||||
{
|
{
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
{% extends "part/part_base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block menubar %}
|
|
||||||
{% include 'part/navbar.html' with tab='orders' %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block heading %}
|
|
||||||
{% trans "Purchase Orders" %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block details %}
|
|
||||||
|
|
||||||
<div id='button-bar'>
|
|
||||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
|
||||||
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "Order part" %}'>
|
|
||||||
<span class='fas fa-shopping-cart'></span> {% trans "Order Part" %}
|
|
||||||
</button>
|
|
||||||
<div class='filter-list' id='filter-list-purchaseorder'>
|
|
||||||
<!-- An empty div in which the filter list will be constructed -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block js_ready %}
|
|
||||||
{{ block.super }}
|
|
||||||
|
|
||||||
loadPurchaseOrderTable($("#purchase-order-table"), {
|
|
||||||
url: "{% url 'api-po-list' %}",
|
|
||||||
params: {
|
|
||||||
part: {{ part.id }},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#part-order2").click(function() {
|
|
||||||
launchModalForm("{% url 'order-parts' %}", {
|
|
||||||
data: {
|
|
||||||
part: {{ part.id }},
|
|
||||||
},
|
|
||||||
reload: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -421,80 +421,7 @@
|
|||||||
|
|
||||||
$("#part-edit").click(function() {
|
$("#part-edit").click(function() {
|
||||||
|
|
||||||
constructForm('{% url "api-part-detail" part.id %}', {
|
editPart({{ part.pk }});
|
||||||
focus: 'name',
|
|
||||||
fields: {
|
|
||||||
category: {
|
|
||||||
secondary: {
|
|
||||||
label: '{% trans "New Category" %}',
|
|
||||||
title: '{% trans "Create New Part Category" %}',
|
|
||||||
api_url: '{% url "api-part-category-list" %}',
|
|
||||||
method: 'POST',
|
|
||||||
fields: {
|
|
||||||
name: {},
|
|
||||||
description: {},
|
|
||||||
parent: {
|
|
||||||
secondary: {
|
|
||||||
title: '{% trans "New Parent" %}',
|
|
||||||
api_url: '{% url "api-part-category-list" %}',
|
|
||||||
method: 'POST',
|
|
||||||
fields: {
|
|
||||||
name: {},
|
|
||||||
description: {},
|
|
||||||
parent: {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
placeholder: 'part name',
|
|
||||||
},
|
|
||||||
IPN: {},
|
|
||||||
description: {},
|
|
||||||
revision: {},
|
|
||||||
keywords: {
|
|
||||||
icon: 'fa-key',
|
|
||||||
},
|
|
||||||
variant_of: {},
|
|
||||||
link: {
|
|
||||||
icon: 'fa-link',
|
|
||||||
},
|
|
||||||
default_location: {
|
|
||||||
secondary: {
|
|
||||||
label: '{% trans "New Location" %}',
|
|
||||||
title: '{% trans "Create new stock location" %}',
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default_supplier: {
|
|
||||||
filters: {
|
|
||||||
part: {{ part.pk }},
|
|
||||||
part_detail: true,
|
|
||||||
manufacturer_detail: true,
|
|
||||||
supplier_detail: true,
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
label: '{% trans "New Supplier Part" %}',
|
|
||||||
title: '{% trans "Create new supplier part" %}',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
units: {},
|
|
||||||
minimum_stock: {},
|
|
||||||
},
|
|
||||||
title: '{% trans "Edit Part" %}',
|
|
||||||
reload: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
launchModalForm(
|
|
||||||
"{% url 'part-edit' part.id %}",
|
|
||||||
{
|
|
||||||
reload: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
{% extends "part/part_base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block menubar %}
|
|
||||||
{% include 'part/navbar.html' with tab='sales-orders' %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block heading %}
|
|
||||||
{% trans "Sales Orders" %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block details %}
|
|
||||||
|
|
||||||
<div id='button-bar'>
|
|
||||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
|
||||||
{% if 0 %}
|
|
||||||
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "New sales order" %}'>{% trans "New Order" %}</button>
|
|
||||||
{% endif %}
|
|
||||||
<div class='filter-list' id='filter-list-salesorder'>
|
|
||||||
<!-- An empty div in which the filter list will be constructed -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class='table table-striped table-condensed po-table' id='sales-order-table' data-toolbar='#button-bar'>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block js_ready %}
|
|
||||||
{{ block.super }}
|
|
||||||
|
|
||||||
loadSalesOrderTable($("#sales-order-table"), {
|
|
||||||
url: "{% url 'api-so-list' %}",
|
|
||||||
params: {
|
|
||||||
part: {{ part.id }},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -158,21 +158,6 @@ class PartDetailTest(PartViewTestCase):
|
|||||||
class PartTests(PartViewTestCase):
|
class PartTests(PartViewTestCase):
|
||||||
""" Tests for Part forms """
|
""" Tests for Part forms """
|
||||||
|
|
||||||
def test_part_edit(self):
|
|
||||||
|
|
||||||
response = self.client.get(reverse('part-edit', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
|
|
||||||
keys = response.context.keys()
|
|
||||||
data = str(response.content)
|
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
self.assertIn('part', keys)
|
|
||||||
self.assertIn('csrf_token', keys)
|
|
||||||
|
|
||||||
self.assertIn('html_form', data)
|
|
||||||
self.assertIn('"title":', data)
|
|
||||||
|
|
||||||
def test_part_create(self):
|
def test_part_create(self):
|
||||||
""" Launch form to create a new part """
|
""" Launch form to create a new part """
|
||||||
response = self.client.get(reverse('part-create'), {'category': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
response = self.client.get(reverse('part-create'), {'category': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||||
|
@ -36,7 +36,6 @@ part_parameter_urls = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
part_detail_urls = [
|
part_detail_urls = [
|
||||||
url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'),
|
|
||||||
url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
|
url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
|
||||||
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
|
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
|
||||||
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
||||||
@ -55,8 +54,6 @@ part_detail_urls = [
|
|||||||
url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'),
|
url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'),
|
||||||
url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'),
|
url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'),
|
||||||
url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'),
|
url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'),
|
||||||
url(r'^orders/?', views.PartDetail.as_view(template_name='part/orders.html'), name='part-orders'),
|
|
||||||
url(r'^sales-orders/', views.PartDetail.as_view(template_name='part/sales_orders.html'), name='part-sales-orders'),
|
|
||||||
url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'),
|
url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'),
|
||||||
url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'),
|
url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'),
|
||||||
|
|
||||||
|
@ -1084,40 +1084,6 @@ class PartImageSelect(AjaxUpdateView):
|
|||||||
return self.renderJsonResponse(request, form, data)
|
return self.renderJsonResponse(request, form, data)
|
||||||
|
|
||||||
|
|
||||||
class PartEdit(AjaxUpdateView):
|
|
||||||
""" View for editing Part object """
|
|
||||||
|
|
||||||
model = Part
|
|
||||||
form_class = part_forms.EditPartForm
|
|
||||||
ajax_template_name = 'modal_form.html'
|
|
||||||
ajax_form_title = _('Edit Part Properties')
|
|
||||||
context_object_name = 'part'
|
|
||||||
|
|
||||||
def get_form(self):
|
|
||||||
""" Create form for Part editing.
|
|
||||||
Overrides default get_form() method to limit the choices
|
|
||||||
for the 'default_supplier' field to SupplierParts that reference this part
|
|
||||||
"""
|
|
||||||
|
|
||||||
form = super(AjaxUpdateView, self).get_form()
|
|
||||||
|
|
||||||
# Hide the "default expiry" field if the feature is not enabled
|
|
||||||
if not inventree_settings.stock_expiry_enabled():
|
|
||||||
form.fields['default_expiry'].widget = HiddenInput()
|
|
||||||
|
|
||||||
part = self.get_object()
|
|
||||||
|
|
||||||
form.fields['default_supplier'].queryset = SupplierPart.objects.filter(part=part)
|
|
||||||
|
|
||||||
# Check if IPN can be edited
|
|
||||||
ipn_edit_enable = InvenTreeSetting.get_setting('PART_ALLOW_EDIT_IPN')
|
|
||||||
if not ipn_edit_enable and not self.request.user.is_superuser:
|
|
||||||
# Admin can still change IPN
|
|
||||||
form.fields['IPN'].disabled = True
|
|
||||||
|
|
||||||
return form
|
|
||||||
|
|
||||||
|
|
||||||
class BomDuplicate(AjaxUpdateView):
|
class BomDuplicate(AjaxUpdateView):
|
||||||
"""
|
"""
|
||||||
View for duplicating BOM from a parent item.
|
View for duplicating BOM from a parent item.
|
||||||
|
@ -56,15 +56,10 @@ function activatePanel(panelName, options={}) {
|
|||||||
// Iterate through the available 'select' elements until one matches
|
// Iterate through the available 'select' elements until one matches
|
||||||
panelName = null;
|
panelName = null;
|
||||||
|
|
||||||
console.log("no match for panel:", panelName);
|
|
||||||
|
|
||||||
$('.nav-toggle').each(function(item) {
|
$('.nav-toggle').each(function(item) {
|
||||||
var panel_name = $(this).attr('id').replace('select-', '');
|
var panel_name = $(this).attr('id').replace('select-', '');
|
||||||
|
|
||||||
console.log("checking:", panel_name);
|
|
||||||
|
|
||||||
if ($(`#panel-${panel_name}`).length && (panelName == null)) {
|
if ($(`#panel-${panel_name}`).length && (panelName == null)) {
|
||||||
console.log("found match -", panel_name);
|
|
||||||
panelName = panel_name;
|
panelName = panel_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,94 @@ function yesNoLabel(value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function editPart(pk, options={}) {
|
||||||
|
|
||||||
|
var url = `/api/part/${pk}/`;
|
||||||
|
|
||||||
|
var fields = {
|
||||||
|
category: {
|
||||||
|
/*
|
||||||
|
secondary: {
|
||||||
|
label: '{% trans "New Category" %}',
|
||||||
|
title: '{% trans "Create New Part Category" %}',
|
||||||
|
api_url: '{% url "api-part-category-list" %}',
|
||||||
|
method: 'POST',
|
||||||
|
fields: {
|
||||||
|
name: {},
|
||||||
|
description: {},
|
||||||
|
parent: {
|
||||||
|
secondary: {
|
||||||
|
title: '{% trans "New Parent" %}',
|
||||||
|
api_url: '{% url "api-part-category-list" %}',
|
||||||
|
method: 'POST',
|
||||||
|
fields: {
|
||||||
|
name: {},
|
||||||
|
description: {},
|
||||||
|
parent: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
placeholder: 'part name',
|
||||||
|
},
|
||||||
|
IPN: {},
|
||||||
|
description: {},
|
||||||
|
revision: {},
|
||||||
|
keywords: {
|
||||||
|
icon: 'fa-key',
|
||||||
|
},
|
||||||
|
variant_of: {},
|
||||||
|
link: {
|
||||||
|
icon: 'fa-link',
|
||||||
|
},
|
||||||
|
default_location: {
|
||||||
|
/*
|
||||||
|
secondary: {
|
||||||
|
label: '{% trans "New Location" %}',
|
||||||
|
title: '{% trans "Create new stock location" %}',
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
},
|
||||||
|
default_supplier: {
|
||||||
|
filters: {
|
||||||
|
part: pk,
|
||||||
|
part_detail: true,
|
||||||
|
manufacturer_detail: true,
|
||||||
|
supplier_detail: true,
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
secondary: {
|
||||||
|
label: '{% trans "New Supplier Part" %}',
|
||||||
|
title: '{% trans "Create new supplier part" %}',
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
},
|
||||||
|
units: {},
|
||||||
|
minimum_stock: {},
|
||||||
|
virtual: {},
|
||||||
|
is_template: {},
|
||||||
|
assembly: {},
|
||||||
|
component: {},
|
||||||
|
trackable: {},
|
||||||
|
purchaseable: {},
|
||||||
|
salable: {},
|
||||||
|
active: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
constructForm(url, {
|
||||||
|
fields: fields,
|
||||||
|
title: '{% trans "Edit Part" %}',
|
||||||
|
reload: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function toggleStar(options) {
|
function toggleStar(options) {
|
||||||
/* Toggle the 'starred' status of a part.
|
/* Toggle the 'starred' status of a part.
|
||||||
* Performs AJAX queries and updates the display on the button.
|
* Performs AJAX queries and updates the display on the button.
|
||||||
|
Loading…
Reference in New Issue
Block a user