Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2019-09-22 22:34:34 +10:00
commit d6749dfb24
32 changed files with 239 additions and 101 deletions

View File

@ -136,4 +136,53 @@ function imageHoverIcon(url) {
`;
return html;
}
function inventreeSave(name, value) {
/*
* Save a key:value pair to local storage
*/
var key = "inventree-" + name;
localStorage.setItem(key, value);
}
function inventreeLoad(name, defaultValue) {
/*
* Retrieve a key:value pair from local storage
*/
var key = "inventree-" + name;
var value = localStorage.getItem(key);
if (value == null) {
return defaultValue;
} else {
return value;
}
}
function inventreeLoadInt(name) {
/*
* Retrieve a value from local storage, and attempt to cast to integer
*/
var data = inventreeLoad(name);
return parseInt(data, 10);
}
function inventreeLoadFloat(name) {
var data = inventreeLoad(name);
return parseFloat(data);
}
function inventreeDel(name) {
var key = 'inventree-' + name;
localStorage.removeItem(key);
}

View File

@ -191,15 +191,10 @@ function loadPartTable(table, url, options={}) {
}
});
$(table).bootstrapTable({
$(table).inventreeTable({
url: url,
sortable: true,
search: true,
sortName: 'name',
method: 'get',
pagination: true,
pageSize: 25,
rememberOrder: true,
formatNoMatches: function() { return "No parts found"; },
queryParams: function(p) {
return query;

View File

@ -42,13 +42,10 @@ function loadStockTable(table, options) {
var params = options.params || {};
table.bootstrapTable({
sortable: true,
search: true,
console.log('load stock table');
table.inventreeTable({
method: 'get',
pagination: true,
pageSize: 25,
rememberOrder: true,
formatNoMatches: function() {
return 'No stock items matching query';
},
@ -386,15 +383,10 @@ function loadStockTrackingTable(table, options) {
}
});
table.bootstrapTable({
sortable: true,
search: true,
table.inventreeTable({
method: 'get',
rememberOrder: true,
queryParams: options.params,
columns: cols,
pagination: true,
pageSize: 50,
url: options.url,
});

View File

@ -44,6 +44,31 @@ function isNumeric(n) {
}
/* Wrapper function for bootstrapTable.
* Sets some useful defaults, and manage persistent settings.
*/
$.fn.inventreeTable = function(options) {
var tableName = options.name || 'table';
var varName = tableName + '-pagesize';
options.pagination = true;
options.pageSize = inventreeLoad(varName, 25);
options.pageList = [25, 50, 100, 250, 'all'];
options.rememberOrder = true;
options.sortable = true;
options.search = true;
// Callback to save pagination data
options.onPageChange = function(number, size) {
inventreeSave(varName, size);
};
// Standard options for all tables
this.bootstrapTable(options);
}
function customGroupSorter(sortName, sortOrder, sortData) {
console.log('got here');

View File

@ -62,9 +62,7 @@ InvenTree | Allocate Parts
{% else %}
$("#build-list").bootstrapTable({
search: true,
sortable: true,
$("#build-list").inventreeTable({
});
$("#btn-allocate").click(function() {

View File

@ -44,9 +44,7 @@ InvenTree | Build List
});
});
$(".build-table").bootstrapTable({
sortable: true,
search: true,
$(".build-table").inventreeTable({
formatNoMatches: function() { return 'No builds found'; },
columns: [
{

View File

@ -45,11 +45,7 @@
});
});
$("#part-table").bootstrapTable({
sortable: true,
search: true,
pagination: true,
pageSize: 50,
$("#part-table").inventreeTable({
formatNoMatches: function() { return "No supplier parts found for {{ company.name }}"; },
queryParams: function(p) {
return {

View File

@ -42,9 +42,7 @@
newOrder();
});
$("#po-table").bootstrapTable({
search: true,
sortable: true,
$(".po-table").inventreeTable({
});
{% endblock %}

View File

@ -32,11 +32,7 @@ InvenTree | Supplier List
});
});
$("#company-table").bootstrapTable({
sortable: true,
search: true,
pagination: true,
pageSize: 50,
$("#company-table").inventreeTable({
formatNoMatches: function() { return "No company information found"; },
columns: [
{

View File

@ -6,6 +6,7 @@ Django Forms for interacting with Order objects
from __future__ import unicode_literals
from django import forms
from django.utils.translation import ugettext as _
from InvenTree.forms import HelperForm
@ -14,7 +15,7 @@ from .models import PurchaseOrder, PurchaseOrderLineItem
class IssuePurchaseOrderForm(HelperForm):
confirm = forms.BooleanField(required=False, help_text='Place order')
confirm = forms.BooleanField(required=False, help_text=_('Place order'))
class Meta:
model = PurchaseOrder
@ -23,6 +24,17 @@ class IssuePurchaseOrderForm(HelperForm):
]
class CancelPurchaseOrderForm(HelperForm):
confirm = forms.BooleanField(required=False, help_text=_('Cancel order'))
class Meta:
model = PurchaseOrder
fields = [
'confirm',
]
class EditPurchaseOrderForm(HelperForm):
""" Form for editing a PurchaseOrder object """

View File

@ -98,6 +98,13 @@ class Order(models.Model):
self.complete_date = datetime.now().date()
self.save()
def cancel_order(self):
""" Marks the order as CANCELLED. """
if self.status in [OrderStatus.PLACED, OrderStatus.PENDING]:
self.status = OrderStatus.CANCELLED
self.save()
class PurchaseOrder(Order):
""" A PurchaseOrder represents goods shipped inwards from an external supplier.

View File

@ -0,0 +1,7 @@
{% extends "modal_form.html" %}
{% block pre_form_content %}
Cancelling this order means that the order will no longer be editable.
{% endblock %}

View File

@ -1,4 +1,4 @@
<table class='table table-striped table-condensed' id='po-table' {% if toolbar %}data-toolbar='{{ toolbar }}'{% endif %}>
<table class='table table-striped table-condensed po-table' id='po-table' {% if toolbar %}data-toolbar='{{ toolbar }}'{% endif %}>
<thead>
<tr>
<th data-field='company' data-sortable='true' data-searchable='true'>Company</th>

View File

@ -43,6 +43,11 @@ InvenTree | {{ order }}
<span class='glyphicon glyphicon-check'></span>
</button>
{% endif %}
{% if order.status == OrderStatus.PENDING or order.status == OrderStatus.PLACED %}
<button type='button' class='btn btn-default btn-glyph' id='cancel-order' title='Cancel order'>
<span class='glyphicon glyphicon-remove'></span>
</button>
{% endif %}
</div>
</div>
</p>
@ -176,6 +181,12 @@ $("#edit-order").click(function() {
);
});
$("#cancel-order").click(function() {
launchModalForm("{% url 'purchase-order-cancel' order.id %}", {
reload: true,
});
});
$("#receive-order").click(function() {
launchModalForm("{% url 'purchase-order-receive' order.id %}", {
reload: true,
@ -210,9 +221,7 @@ $('#new-po-line').click(function() {
});
{% endif %}
$("#po-lines-table").bootstrapTable({
search: true,
sortable: true,
$("#po-lines-table").inventreeTable({
});

View File

@ -32,8 +32,7 @@ $("#po-create").click(function() {
);
});
$("#po-table").bootstrapTable({
search: true,
$("#po-table").inventreeTable({
});
{% endblock %}

View File

@ -11,6 +11,7 @@ from . import views
purchase_order_detail_urls = [
url(r'^cancel/?', views.PurchaseOrderCancel.as_view(), name='purchase-order-cancel'),
url(r'^edit/?', views.PurchaseOrderEdit.as_view(), name='purchase-order-edit'),
url(r'^issue/?', views.PurchaseOrderIssue.as_view(), name='purchase-order-issue'),
url(r'^receive/?', views.PurchaseOrderReceive.as_view(), name='purchase-order-receive'),

View File

@ -112,6 +112,39 @@ class PurchaseOrderEdit(AjaxUpdateView):
return form
class PurchaseOrderCancel(AjaxUpdateView):
""" View for cancelling a purchase order """
model = PurchaseOrder
ajax_form_title = 'Cancel Order'
ajax_template_name = 'order/order_cancel.html'
form_class = order_forms.CancelPurchaseOrderForm
def post(self, request, *args, **kwargs):
""" Mark the PO as 'CANCELLED' """
order = self.get_object()
form = self.get_form()
confirm = str2bool(request.POST.get('confirm', False))
valid = False
if not confirm:
form.errors['confirm'] = [_('Confirm order cancellation')]
else:
valid = True
data = {
'form_valid': valid
}
if valid:
order.cancel_order()
return self.renderJsonResponse(request, form, data)
class PurchaseOrderIssue(AjaxUpdateView):
""" View for changing a purchase order from 'PENDING' to 'ISSUED' """

View File

@ -29,9 +29,7 @@
{% block js_ready %}
$("#build-table").bootstrapTable({
search: true,
sortable: true,
$("#build-table").inventreeTable({
columns: [
{
title: 'Build',

View File

@ -89,9 +89,7 @@
});
});
$("#attachment-table").bootstrapTable({
search: true,
sortable: true,
$("#attachment-table").inventreeTable({
});
{% endblock %}

View File

@ -31,11 +31,7 @@
});
});
$("#build-table").bootstrapTable({
sortable: true,
search: true,
pagination: true,
pageSize: 50,
$("#build-table").inventreeTable({
queryParams: function(p) {
return {
part: {{ part.id }},

View File

@ -8,9 +8,6 @@
{% if category %}
<h3>{{ category.name }}</h3>
<p>{{ category.description }}</p>
{% if category.default_location %}
<p>Default Location: <a href="{% url 'stock-location-detail' category.default-location.id }%">{{ category.default_location }}</a></p>
{% endif %}
{% else %}
<h3>Part Categories</h3>
<p>All parts</p>
@ -32,6 +29,39 @@
</p>
</div>
<div class='col-sm-6'>
{% if category %}
<h3>Category Details</h3>
<table class='table table-condensed table-striped'>
<tr>
<td>Category Path</td>
<td>{{ category.pathstring }}</td>
</tr>
<tr>
<td>Category Description</td>
<td>{{ category.description }}</td>
</tr>
{% if category.default_location %}
<tr>
<td>Default Location</td>
<td><a href="{% url 'stock-location-detail' category.default_location.pk %}">{{ category.default_location.pathstring }}</a></td>
</tr>
{% endif %}
{% if category.default_keywords %}
<tr>
<td>Keywords</td>
<td>{{ category.default_keywords }}</td>
</tr>
{% endif %}
<tr>
<td>Subcategories</td>
<td>{{ category.children.count }}</td>
</tr>
<tr>
<td>Parts (Including subcategories)</td>
<td>{{ category.partcount }}</td>
</tr>
</table>
{% endif %}
</div>
</div>
@ -67,16 +97,16 @@
{% block js_ready %}
{{ block.super }}
if (sessionStorage.getItem("inventree-show-part-categories")) {
if (inventreeLoadInt("show-part-cats") == 1) {
$("#collapse-item-categories").collapse('show');
}
$("#collapse-item-categories").on('shown.bs.collapse', function() {
sessionStorage.setItem('inventree-show-part-categories', 1);
inventreeSave('show-part-cats', 1);
});
$("#collapse-item-categories").on('hidden.bs.collapse', function() {
sessionStorage.removeItem('inventree-show-part-categories');
inventreeDel('show-part-cats');
});
$("#cat-create").click(function() {

View File

@ -26,9 +26,7 @@
{% block js_ready %}
{{ block.super }}
$("#po-table").bootstrapTable({
search: true,
sortable: true,
$("#po-table").inventreeTable({
});
$("#part-order2").click(function() {

View File

@ -44,9 +44,7 @@
{% block js_ready %}
{{ block.super }}
$('#param-table').bootstrapTable({
search: true,
sortable: true,
$('#param-table').inventreeTable({
});
$('#param-create').click(function() {

View File

@ -12,7 +12,9 @@
{% if child.description %}
<i> - {{ child.description }}</i>
{% endif %}
<span class='badge'>{{ child.partcount }}</span>
{% if child.partcount > 0 %}
<span class='badge'>{{ child.partcount }} Part{% if child.partcount > 1 %}s{% endif %}</span>
{% endif %}
</li>
{% endfor %}
</ul>

View File

@ -50,9 +50,7 @@
});
});
$("#supplier-table").bootstrapTable({
sortable: true,
search: true,
$("#supplier-table").inventreeTable({
formatNoMatches: function() { return "No supplier parts available for {{ part.full_name }}"; },
queryParams: function(p) {
return {

View File

@ -16,9 +16,7 @@
{% block js_ready %}
{{ block.super }}
$("#used-table").bootstrapTable({
sortable: true,
search: true,
$("#used-table").inventreeTable({
formatNoMatches: function() { return "{{ part.full_name }} is not used to make any other parts"; },
queryParams: function(p) {
return {

View File

@ -53,9 +53,7 @@
{{ block.super }}
$('#variant-table').bootstrapTable({
search: true,
sortable: true,
$('#variant-table').inventreeTable({
});
$('#new-variant').click(function() {

View File

@ -32,6 +32,27 @@
</p>
</div>
<div class='col-sm-6'>
{% if location %}
<h3>Location Details</h3>
<table class='table table-striped table-condensed'>
<tr>
<td>Location Path</td>
<td>{{ location.pathstring }}</td>
</tr>
<tr>
<td>Location Description</td>
<td>{{ location.description }}</td>
</tr>
<tr>
<td>Sublocations</td>
<td>{{ location.children.count }}</td>
</tr>
<tr>
<td>Stock Items</td>
<td>{{ location.item_count }}</td>
</tr>
</table>
{% endif %}
</div>
</h3>
</div>
@ -55,16 +76,16 @@
{% block js_ready %}
{{ block.super }}
if (sessionStorage.getItem("inventree-show-part-locations")) {
if (inventreeLoadInt("show-part-locs") == 1) {
$("#collapse-item-locations").collapse('show');
}
$("#collapse-item-locations").on('shown.bs.collapse', function() {
sessionStorage.setItem('inventree-show-part-locations', 1);
inventreeSave('show-part-locs', 1);
});
$("#collapse-item-locations").on('hidden.bs.collapse', function() {
sessionStorage.removeItem('inventree-show-part-locations');
inventreeDel('show-part-locs');
});
$("#stock-export").click(function() {

View File

@ -8,7 +8,9 @@ Sub-Locations<span class='badge'>{{ children|length }}</span>
<ul class="list-group">
{% for child in children %}
<li class="list-group-item"><a href="{% url 'stock-location-detail' child.id %}">{{ child.name }}</a> - <i>{{ child.description }}</i>
<span class='badge'>{{ child.item_count }}</span>
{% if child.item_count > 0 %}
<span class='badge'>{{ child.item_count }} Item{% if child.item_count > 1 %}s{% endif %}</span>
{% endif %}
</li>
{% endfor %}
</ul>

View File

@ -83,7 +83,7 @@ InvenTree | Search Results
onSearchResults('#supplier-part-results-table', '#supplier-part-result-count');
$("#category-results-table").bootstrapTable({
$("#category-results-table").inventreeTable({
url: "{% url 'api-part-category-list' %}",
queryParams: {
search: "{{ query }}",
@ -103,7 +103,7 @@ InvenTree | Search Results
],
});
$("#location-results-table").bootstrapTable({
$("#location-results-table").inventreeTable({
url: "{% url 'api-location-list' %}",
queryParams: {
search: "{{ query }}",
@ -134,14 +134,11 @@ InvenTree | Search Results
}
);
$("#company-results-table").bootstrapTable({
$("#company-results-table").inventreeTable({
url: "{% url 'api-company-list' %}",
queryParams: {
search: "{{ query }}",
},
pagination: true,
pageSize: 25,
search: true,
columns: [
{
field: 'name',
@ -157,14 +154,11 @@ InvenTree | Search Results
]
});
$("#supplier-part-results-table").bootstrapTable({
$("#supplier-part-results-table").inventreeTable({
url: "{% url 'api-part-supplier-list' %}",
queryParams: {
search: "{{ query }}",
},
pagination: true,
pageSize: 25,
search: true,
columns: [
{
field: 'supplier_name',

View File

@ -19,15 +19,11 @@
{% block js_ready %}
{{ block.super }}
$("#currency-table").bootstrapTable({
$("#currency-table").inventreeTable({
url: "{% url 'api-currency-list' %}",
queryParams: {
ordering: 'suffix'
},
sortable: true,
search: true,
pagination: true,
pageSize: 25,
formatNoMatches: function() { return "No currencies found"; },
rowStyle: function(row, index) {
if (row.base) {

View File

@ -19,15 +19,11 @@
{% block js_ready %}
{{ block.super }}
$("#param-table").bootstrapTable({
$("#param-table").inventreeTable({
url: "{% url 'api-part-param-template-list' %}",
queryParams: {
ordering: 'name',
},
sortable: true,
search: true,
pagination: true,
pageSize: 25,
formatNoMatches: function() { return "No part parameter templates found"; },
columns: [
{