Merge branch 'master' of git://github.com/inventree/InvenTree into empty_search_query

This commit is contained in:
eeintech 2020-09-30 11:50:12 -05:00
commit 87d836617e
19 changed files with 179 additions and 31 deletions

View File

@ -807,7 +807,19 @@ function launchModalForm(url, options = {}) {
}
},
error: function (xhr, ajaxOptions, thrownError) {
$(modal).modal('hide');
// Permission denied!
if (xhr.status == 403) {
showAlertDialog(
"Permission Denied",
"You do not have the required permissions to access this function"
);
return;
}
showAlertDialog('Error requesting form data', renderErrorMessage(xhr));
}
};

View File

@ -7,7 +7,7 @@ import django
import common.models
INVENTREE_SW_VERSION = "0.1.3 pre"
INVENTREE_SW_VERSION = "0.1.4 pre"
def inventreeInstanceName():

View File

@ -13,6 +13,8 @@ from django.template.loader import render_to_string
from django.http import JsonResponse, HttpResponseRedirect
from django.urls import reverse_lazy
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views import View
from django.views.generic import UpdateView, CreateView, FormView
from django.views.generic.base import TemplateView
@ -105,12 +107,32 @@ class TreeSerializer(views.APIView):
return JsonResponse(response, safe=False)
class AjaxMixin(object):
class AjaxMixin(PermissionRequiredMixin):
""" AjaxMixin provides basic functionality for rendering a Django form to JSON.
Handles jsonResponse rendering, and adds extra data for the modal forms to process
on the client side.
Any view which inherits the AjaxMixin will need
correct permissions set using the 'permission_required' attribute
"""
# By default, allow *any* permissions
permission_required = '*'
def has_permission(self):
"""
Override the default behaviour of has_permission from PermissionRequiredMixin.
Basically, if permission_required attribute = '*',
no permissions are actually required!
"""
if self.permission_required == '*':
return True
else:
return super().has_permission()
# By default, point to the modal_form template
# (this can be overridden by a child class)
ajax_template_name = 'modal_form.html'

View File

@ -20,6 +20,12 @@ class BuildAdmin(ImportExportModelAdmin):
'notes',
)
search_fields = [
'title',
'part__name',
'part__description',
]
class BuildItemAdmin(admin.ModelAdmin):

View File

@ -33,7 +33,12 @@ src="{% static 'img/blank_image.png' %}"
{% block page_data %}
<h3>{% trans "Build" %} {% build_status_label build.status large=True %}</h3>
<hr>
<h4>{{ build.quantity }} x {{ build.part.full_name }}</h4>
<h4>
{{ build.quantity }} x {{ build.part.full_name }}
{% if user.is_staff and perms.build.change_build %}
<a href="{% url 'admin:build_build_change' build.pk %}"><span title="{% trans 'Admin view' %}" class='fas fa-user-shield'></span></a>
{% endif %}
</h4>
<div class='btn-row'>
<div class='btn-group action-buttons'>
<button type='button' class='btn btn-default' id='build-edit' title='Edit Build'>

View File

@ -32,6 +32,11 @@ class CompanyAdmin(ImportExportModelAdmin):
list_display = ('name', 'website', 'contact')
search_fields = [
'name',
'description',
]
class SupplierPartResource(ModelResource):
""" Class for managing SupplierPart data import/export """
@ -57,6 +62,13 @@ class SupplierPartAdmin(ImportExportModelAdmin):
list_display = ('part', 'supplier', 'SKU')
search_fields = [
'company__name',
'part__name',
'MPN',
'SKU',
]
class SupplierPriceBreakResource(ModelResource):
""" Class for managing SupplierPriceBreak data import/export """

View File

@ -21,7 +21,12 @@ InvenTree | {% trans "Company" %} - {{ company.name }}
{% block page_data %}
<h3>{% trans "Company" %}</h3>
<hr>
<h4>{{ company.name }}</h4>
<h4>
{{ company.name }}
{% if user.is_staff and perms.company.change_company %}
<a href="{% url 'admin:company_company_change' company.pk %}"><span title="{% trans 'Admin view' %}" class='fas fa-user-shield'></span></a>
{% endif %}
</h4>
<p>{{ company.description }}</p>
<div class='btn-group action-buttons'>
{% if company.is_supplier %}

View File

@ -23,6 +23,12 @@ class PurchaseOrderAdmin(ImportExportModelAdmin):
'creation_date'
)
search_fields = [
'reference',
'supplier__name',
'description',
]
class SalesOrderAdmin(ImportExportModelAdmin):
@ -34,6 +40,12 @@ class SalesOrderAdmin(ImportExportModelAdmin):
'creation_date',
)
search_fields = [
'reference',
'customer__name',
'description',
]
class POLineItemResource(ModelResource):
""" Class for managing import / export of POLineItem data """

View File

@ -22,7 +22,12 @@ src="{% static 'img/blank_image.png' %}"
{% block page_data %}
<h3>{% trans "Purchase Order" %} {% purchase_order_status_label order.status large=True %}</h3>
<hr>
<h4>{{ order }}</h4>
<h4>
{{ order }}
{% if user.is_staff and perms.order.change_purchaseorder %}
<a href="{% url 'admin:order_purchaseorder_change' order.pk %}"><span title='{% trans "Admin view" %}' class='fas fa-user-shield'></span></a>
{% endif %}
</h4>
<p>{{ order.description }}</p>
<p>
<div class='btn-row'>

View File

@ -32,7 +32,12 @@ src="{% static 'img/blank_image.png' %}"
<h3>{% trans "Sales Order" %} {% sales_order_status_label order.status large=True %}</h3>
<hr>
<h4>{{ order }}</h4>
<h4>
{{ order }}
{% if user.is_staff and perms.order.change_salesorder %}
<a href="{% url 'admin:order_salesorder_change' order.pk %}"><span title='{% trans "Admin view" %}' class='fas fa-user-shield'></span></a>
{% endif %}
</h4>
<p>{{ order.description }}</p>
<div class='btn-row'>
<div class='btn-group action-buttons'>

View File

@ -430,6 +430,17 @@ class PartList(generics.ListCreateAPIView):
except (ValueError, Part.DoesNotExist):
pass
# Filter by whether the part has an IPN (internal part number) defined
has_ipn = params.get('has_ipn', None)
if has_ipn is not None:
has_ipn = str2bool(has_ipn)
if has_ipn:
queryset = queryset.exclude(IPN='')
else:
queryset = queryset.filter(IPN='')
# Filter by whether the BOM has been validated (or not)
bom_valid = params.get('bom_valid', None)

View File

@ -7,7 +7,12 @@
<div class='row'>
<div class='col-sm-6'>
{% if category %}
<h3>{{ category.name }}</h3>
<h3>
{{ category.name }}
{% if user.is_staff and perms.part.change_partcategory %}
<a href="{% url 'admin:part_partcategory_change' category.pk %}"><span title="{% trans 'Admin view' %}" class='fas fa-user-shield'></span></a>
{% endif %}
</h3>
<p>{{ category.description }}</p>
{% else %}
<h3>{% trans "Part Categories" %}</h3>
@ -109,9 +114,9 @@
</ul>
</div>
</div>
<div class='filter-list' id='filter-list-parts'>
<!-- Empty div -->
</div>
</div>
<div class='filter-list' id='filter-list-parts'>
<!-- Empty div -->
</div>
</div>

View File

@ -28,6 +28,9 @@
<div class="media-body">
<h3>
{{ part.full_name }}
{% if user.is_staff and perms.part.change_part %}
<a href="{% url 'admin:part_part_change' part.pk %}"><span title="{% trans 'Admin view' %}" class='fas fa-user-shield'></span></a>
{% endif %}
{% if not part.active %}
<div class='label label-large label-large-red'>
{% trans 'Inactive' %}

View File

@ -117,6 +117,14 @@ class StockItemAdmin(ImportExportModelAdmin):
list_display = ('part', 'quantity', 'location', 'status', 'updated')
# A list of search fields which can be used for lookup on matching 'autocomplete' fields
search_fields = [
'part__name',
'part__description',
'serial',
'batch',
]
class StockAttachmentAdmin(admin.ModelAdmin):

View File

@ -61,9 +61,12 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
<hr>
<h4>
{% if item.serialized %}
<a href='{% url "part-detail" item.part.pk %}'>{{ item.part.full_name}}</a> # {{ item.serial }}
<a href='{% url "part-detail" item.part.pk %}'>{{ item.part.full_name}}</a> # {{ item.serial }}
{% else %}
<a href='{% url "part-detail" item.part.pk %}'>{{ item.part.full_name }}</a> &times {% decimal item.quantity %}
<a href='{% url "part-detail" item.part.pk %}'>{{ item.part.full_name }}</a> &times {% decimal item.quantity %}
{% endif %}
{% if user.is_staff and perms.stock.change_stockitem %}
<a href="{% url 'admin:stock_stockitem_change' item.pk %}"><span title="{% trans 'Admin view' %}" class='fas fa-user-shield'></span></a>
{% endif %}
</h4>
@ -107,6 +110,11 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% if item.customer %}
<li><a href='#' id='stock-return-from-customer' title='{% trans "Return to stock" %}'><span class='fas fa-undo'></span> {% trans "Return to stock" %}</a></li>
{% endif %}
{% if item.belongs_to %}
<li>
<a href='#' id='stock-uninstall' title='{% trans "Uninstall stock item" %}'><span class='fas fa-unlink'></span> {% trans "Uninstall" %}</a>
</li>
{% endif %}
</ul>
</div>
<!-- Edit stock item -->
@ -165,8 +173,12 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% if item.belongs_to %}
<tr>
<td><span class='fas fa-box'></span></td>
<td>{% trans "Belongs To" %}</td>
<td><a href="{% url 'stock-item-detail' item.belongs_to.id %}">{{ item.belongs_to }}</a></td>
<td>
{% trans "Installed In" %}
</td>
<td>
<a href="{% url 'stock-item-detail' item.belongs_to.id %}">{{ item.belongs_to }}</a>
</td>
</tr>
{% elif item.sales_order %}
<tr>
@ -301,6 +313,19 @@ $("#stock-serialize").click(function() {
);
});
$('#stock-uninstall').click(function() {
launchModalForm(
"{% url 'stock-item-uninstall' %}",
{
data: {
'items[]': [{{ item.pk}}],
},
reload: true,
}
);
});
$("#stock-test-report").click(function() {
launchModalForm(
"{% url 'stock-item-test-report-select' item.id %}",

View File

@ -128,7 +128,7 @@ $('#installed-table').inventreeTable({
var html = `<div class='btn-group float-right' role='group'>`;
html += makeIconButton('fa-trash-alt icon-red', 'button-uninstall', pk, '{% trans "Uninstall item" %}');
html += makeIconButton('fa-unlink', 'button-uninstall', pk, '{% trans "Uninstall item" %}');
html += `</div>`;

View File

@ -6,7 +6,12 @@
<div class='row'>
<div class='col-sm-6'>
{% if location %}
<h3>{{ location.name }}</h3>
<h3>
{{ location.name }}
{% if user.is_staff and perms.stock.change_stocklocation %}
<a href="{% url 'admin:stock_stocklocation_change' location.pk %}"><span title="{% trans 'Admin view' %}" class='fas fa-user-shield'></span></a>
{% endif %}
</h3>
<p>{{ location.description }}</p>
{% else %}
<h3>{% trans "Stock" %}</h3>

View File

@ -173,6 +173,11 @@ function getAvailableTableFilters(tableKey) {
title: '{% trans "Include subcategories" %}',
description: '{% trans "Include parts in subcategories" %}',
},
has_ipn: {
type: 'bool',
title: '{% trans "Has IPN" %}',
description: '{% trans "Part has internal part number" %}',
},
active: {
type: 'bool',
title: '{% trans "Active" %}',

View File

@ -2,22 +2,24 @@
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-default' id='stock-export' title='{% trans "Export Stock Information" %}'>{% trans "Export" %}</button>
{% if read_only %}
{% else %}
<button class="btn btn-success" id='item-create'>{% trans "New Stock Item" %}</button>
<div class="btn-group">
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'>{% trans "Add stock" %}</a></li>
<li><a href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'>{% trans "Remove stock" %}</a></li>
<li><a href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'>{% trans "Count stock" %}</a></li>
<li><a href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'>{% trans "Move stock" %}</a></li>
<li><a href='#' id='multi-item-order' title='{% trans "Order selected items" %}'>{% trans "Order stock" %}</a></li>
<li><a href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'>{% trans "Delete Stock" %}</a></li>
</ul>
<div class='btn-group'>
<button class='btn btn-default' id='stock-export' title='{% trans "Export Stock Information" %}'>{% trans "Export" %}</button>
{% if read_only %}
{% else %}
<button class="btn btn-success" id='item-create'>{% trans "New Stock Item" %}</button>
<div class="btn-group">
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'>{% trans "Add stock" %}</a></li>
<li><a href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'>{% trans "Remove stock" %}</a></li>
<li><a href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'>{% trans "Count stock" %}</a></li>
<li><a href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'>{% trans "Move stock" %}</a></li>
<li><a href='#' id='multi-item-order' title='{% trans "Order selected items" %}'>{% trans "Order stock" %}</a></li>
<li><a href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'>{% trans "Delete Stock" %}</a></li>
</ul>
</div>
{% endif %}
</div>
{% endif %}
<div class='filter-list' id='filter-list-stock'>
<!-- An empty div in which the filter list will be constructed -->
</div>