mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
commit
a921b3fcee
@ -11,6 +11,8 @@ from django.core import validators
|
|||||||
from django import forms
|
from django import forms
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from InvenTree.helpers import normalize
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeURLFormField(FormURLField):
|
class InvenTreeURLFormField(FormURLField):
|
||||||
""" Custom URL form field with custom scheme validators """
|
""" Custom URL form field with custom scheme validators """
|
||||||
@ -53,7 +55,7 @@ class RoundingDecimalFormField(forms.DecimalField):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if type(value) == Decimal:
|
if type(value) == Decimal:
|
||||||
return value.normalize()
|
return normalize(value)
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ import json
|
|||||||
import os.path
|
import os.path
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from wsgiref.util import FileWrapper
|
from wsgiref.util import FileWrapper
|
||||||
from django.http import StreamingHttpResponse
|
from django.http import StreamingHttpResponse
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
@ -104,6 +106,20 @@ def isNull(text):
|
|||||||
return str(text).strip().lower() in ['top', 'null', 'none', 'empty', 'false', '-1', '']
|
return str(text).strip().lower() in ['top', 'null', 'none', 'empty', 'false', '-1', '']
|
||||||
|
|
||||||
|
|
||||||
|
def normalize(d):
|
||||||
|
"""
|
||||||
|
Normalize a decimal number, and remove exponential formatting.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if type(d) is not Decimal:
|
||||||
|
d = Decimal(d)
|
||||||
|
|
||||||
|
d = d.normalize()
|
||||||
|
|
||||||
|
# Ref: https://docs.python.org/3/library/decimal.html
|
||||||
|
return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
|
||||||
|
|
||||||
|
|
||||||
def decimal2string(d):
|
def decimal2string(d):
|
||||||
"""
|
"""
|
||||||
Format a Decimal number as a string,
|
Format a Decimal number as a string,
|
||||||
@ -117,6 +133,9 @@ def decimal2string(d):
|
|||||||
A string representation of the input number
|
A string representation of the input number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if type(d) is Decimal:
|
||||||
|
d = normalize(d)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Ensure that the provided string can actually be converted to a float
|
# Ensure that the provided string can actually be converted to a float
|
||||||
float(d)
|
float(d)
|
||||||
|
@ -125,6 +125,8 @@
|
|||||||
|
|
||||||
.label-right {
|
.label-right {
|
||||||
float: right;
|
float: right;
|
||||||
|
margin-left: 3px;
|
||||||
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bootstrap table overrides */
|
/* Bootstrap table overrides */
|
||||||
@ -157,6 +159,66 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
padding-left: 1px;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles for table buttons and filtering */
|
||||||
|
.button-toolbar .btn {
|
||||||
|
margin-left: 1px;
|
||||||
|
margin-right: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-list {
|
||||||
|
display: inline-block;
|
||||||
|
*display: inline;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
margin-top: 1px;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 1px;
|
||||||
|
padding: 2px;
|
||||||
|
background: #eee;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-list .close {
|
||||||
|
cursor: pointer;
|
||||||
|
right: 0%;
|
||||||
|
padding-right: 2px;
|
||||||
|
padding-left: 2px;
|
||||||
|
transform: translate(0%, -25%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-list .close:hover {background: #bbb;}
|
||||||
|
|
||||||
|
.filter-tag {
|
||||||
|
display: inline-block;
|
||||||
|
*display: inline;
|
||||||
|
zoom: 1;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #eee;
|
||||||
|
margin: 1px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
display: inline-block;
|
||||||
|
*display: inline;
|
||||||
|
zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-tag:hover {
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
/* Part image icons with full-display on mouse hover */
|
/* Part image icons with full-display on mouse hover */
|
||||||
|
|
||||||
.hover-img-thumb {
|
.hover-img-thumb {
|
||||||
|
@ -3272,10 +3272,7 @@
|
|||||||
}, {
|
}, {
|
||||||
key: 'getOptions',
|
key: 'getOptions',
|
||||||
value: function getOptions() {
|
value: function getOptions() {
|
||||||
// deep copy and remove data
|
return this.options;
|
||||||
var options = JSON.parse(JSON.stringify(this.options));
|
|
||||||
delete options.data;
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'getSelections',
|
key: 'getSelections',
|
||||||
|
@ -133,11 +133,11 @@ function loadBomTable(table, options) {
|
|||||||
title: 'Part',
|
title: 'Part',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
var html = imageHoverIcon(row.sub_part_detail.image_url) + renderLink(row.sub_part_detail.full_name, row.sub_part_detail.url);
|
var html = imageHoverIcon(row.sub_part_detail.thumbnail) + renderLink(row.sub_part_detail.full_name, row.sub_part_detail.url);
|
||||||
|
|
||||||
// Display an extra icon if this part is an assembly
|
// Display an extra icon if this part is an assembly
|
||||||
if (row.sub_part_detail.assembly) {
|
if (row.sub_part_detail.assembly) {
|
||||||
html += "<a href='" + row.sub_part_detail.url + "bom'><span class='glyphicon-right glyphicon glyphicon-th-list'></span></a>";
|
html += "<a href='" + row.sub_part_detail.url + "bom'><span title='Open subassembly' class='fas fa-stream label-right'></span></a>";
|
||||||
}
|
}
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
|
@ -1,3 +1,77 @@
|
|||||||
|
function loadBuildTable(table, options) {
|
||||||
|
|
||||||
|
var params = options.params || {};
|
||||||
|
|
||||||
|
var filters = loadTableFilters("build");
|
||||||
|
|
||||||
|
for (var key in params) {
|
||||||
|
filters[key] = params[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
setupFilterList("build", table);
|
||||||
|
|
||||||
|
table.inventreeTable({
|
||||||
|
method: 'get',
|
||||||
|
formatNoMatches: function() {
|
||||||
|
return "No builds matching query";
|
||||||
|
},
|
||||||
|
url: options.url,
|
||||||
|
queryParams: filters,
|
||||||
|
groupBy: false,
|
||||||
|
original: params,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'pk',
|
||||||
|
title: 'ID',
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'title',
|
||||||
|
title: 'Build',
|
||||||
|
sortable: true,
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
return renderLink(value, '/build/' + row.pk + '/');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'part',
|
||||||
|
title: 'Part',
|
||||||
|
sortable: true,
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
|
||||||
|
var name = row.part_detail.full_name;
|
||||||
|
|
||||||
|
return imageHoverIcon(row.part_detail.thumbnail) + renderLink(name, '/part/' + row.part + '/');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'quantity',
|
||||||
|
title: 'Quantity',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: 'Status',
|
||||||
|
sortable: true,
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
return buildStatusDisplay(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'creation_date',
|
||||||
|
title: 'Created',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'completion_date',
|
||||||
|
title: 'Completed',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateAllocationTotal(id, count, required) {
|
function updateAllocationTotal(id, count, required) {
|
||||||
|
|
||||||
count = parseFloat(count);
|
count = parseFloat(count);
|
||||||
|
410
InvenTree/InvenTree/static/script/inventree/filters.js
Normal file
410
InvenTree/InvenTree/static/script/inventree/filters.js
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
/**
|
||||||
|
* Code for managing query filters / table options.
|
||||||
|
*
|
||||||
|
* Optional query filters are available to the user for various
|
||||||
|
* tables display in the web interface.
|
||||||
|
* These filters are saved to the web session, and should be
|
||||||
|
* persistent for a given table type.
|
||||||
|
*
|
||||||
|
* This makes use of the 'inventreeSave' and 'inventreeLoad' functions
|
||||||
|
* for writing to and reading from session storage.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function defaultFilters() {
|
||||||
|
return {
|
||||||
|
stock: "cascade=1",
|
||||||
|
build: "",
|
||||||
|
parts: "cascade=1",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load table filters for the given table from session storage
|
||||||
|
*
|
||||||
|
* @param tableKey - String key for the particular table
|
||||||
|
* @param defaults - Default filters for this table e.g. 'cascade=1&location=5'
|
||||||
|
*/
|
||||||
|
function loadTableFilters(tableKey) {
|
||||||
|
|
||||||
|
var lookup = "table-filters-" + tableKey.toLowerCase();
|
||||||
|
|
||||||
|
var defaults = defaultFilters()[tableKey] || '';
|
||||||
|
|
||||||
|
var filterstring = inventreeLoad(lookup, defaults);
|
||||||
|
|
||||||
|
var filters = {};
|
||||||
|
|
||||||
|
filterstring.split("&").forEach(function(item, index) {
|
||||||
|
item = item.trim();
|
||||||
|
|
||||||
|
if (item.length > 0) {
|
||||||
|
var f = item.split('=');
|
||||||
|
|
||||||
|
if (f.length == 2) {
|
||||||
|
filters[f[0]] = f[1];
|
||||||
|
} else {
|
||||||
|
console.log(`Improperly formatted filter: ${item}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save table filters to session storage
|
||||||
|
*
|
||||||
|
* @param {*} tableKey - string key for the given table
|
||||||
|
* @param {*} filters - object of string:string pairs
|
||||||
|
*/
|
||||||
|
function saveTableFilters(tableKey, filters) {
|
||||||
|
var lookup = "table-filters-" + tableKey.toLowerCase();
|
||||||
|
|
||||||
|
var strings = [];
|
||||||
|
|
||||||
|
for (var key in filters) {
|
||||||
|
strings.push(`${key.trim()}=${String(filters[key]).trim()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterstring = strings.join('&');
|
||||||
|
|
||||||
|
console.log(`Saving filters for table '${tableKey}' - ${filterstring}`);
|
||||||
|
|
||||||
|
inventreeSave(lookup, filterstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a named filter parameter
|
||||||
|
*/
|
||||||
|
function removeTableFilter(tableKey, filterKey) {
|
||||||
|
|
||||||
|
var filters = loadTableFilters(tableKey);
|
||||||
|
|
||||||
|
delete filters[filterKey];
|
||||||
|
|
||||||
|
saveTableFilters(tableKey, filters);
|
||||||
|
|
||||||
|
// Return a copy of the updated filters
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function addTableFilter(tableKey, filterKey, filterValue) {
|
||||||
|
|
||||||
|
var filters = loadTableFilters(tableKey);
|
||||||
|
|
||||||
|
filters[filterKey] = filterValue;
|
||||||
|
|
||||||
|
saveTableFilters(tableKey, filters);
|
||||||
|
|
||||||
|
// Return a copy of the updated filters
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear all the custom filters for a given table
|
||||||
|
*/
|
||||||
|
function clearTableFilters(tableKey) {
|
||||||
|
saveTableFilters(tableKey, {});
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a list of the "available" filters for a given table key.
|
||||||
|
* A filter is "available" if it is not already being used to filter the table.
|
||||||
|
* Once a filter is selected, it will not be returned here.
|
||||||
|
*/
|
||||||
|
function getRemainingTableFilters(tableKey) {
|
||||||
|
|
||||||
|
var filters = loadTableFilters(tableKey);
|
||||||
|
|
||||||
|
var remaining = getAvailableTableFilters(tableKey);
|
||||||
|
|
||||||
|
for (var key in filters) {
|
||||||
|
// Delete the filter if it is already in use
|
||||||
|
delete remaining[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the filter settings for a given table and key combination.
|
||||||
|
* Return empty object if the combination does not exist.
|
||||||
|
*/
|
||||||
|
function getFilterSettings(tableKey, filterKey) {
|
||||||
|
|
||||||
|
return getAvailableTableFilters(tableKey)[filterKey] || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a set of key:value options for the given filter.
|
||||||
|
* If no options are specified (e.g. for a number field),
|
||||||
|
* then a null object is returned.
|
||||||
|
*/
|
||||||
|
function getFilterOptionList(tableKey, filterKey) {
|
||||||
|
|
||||||
|
var settings = getFilterSettings(tableKey, filterKey);
|
||||||
|
|
||||||
|
if (settings.type == 'bool') {
|
||||||
|
return {
|
||||||
|
'1': {
|
||||||
|
key: '1',
|
||||||
|
value: 'true',
|
||||||
|
},
|
||||||
|
'0': {
|
||||||
|
key: '0',
|
||||||
|
value: 'false',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else if ('options' in settings) {
|
||||||
|
return settings.options;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a list of <option> tags for the given table.
|
||||||
|
*/
|
||||||
|
function generateAvailableFilterList(tableKey) {
|
||||||
|
|
||||||
|
var remaining = getRemainingTableFilters(tableKey);
|
||||||
|
|
||||||
|
var id = 'filter-tag-' + tableKey.toLowerCase();
|
||||||
|
|
||||||
|
var html = `<select class='form-control filter-input' id='${id}' name='tag'>`;
|
||||||
|
|
||||||
|
html += `<option value=''>Select filter</option>`;
|
||||||
|
|
||||||
|
for (var opt in remaining) {
|
||||||
|
var title = getFilterTitle(tableKey, opt);
|
||||||
|
html += `<option value='${opt}'>${title}</option>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `</select>`;
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate an input for setting the value of a given filter.
|
||||||
|
*/
|
||||||
|
function generateFilterInput(tableKey, filterKey) {
|
||||||
|
|
||||||
|
var id = 'filter-value-' + tableKey.toLowerCase();
|
||||||
|
|
||||||
|
if (filterKey == null || filterKey.length == 0) {
|
||||||
|
// Return an 'empty' element
|
||||||
|
return `<div class='filter-input' id='${id}'></div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = getFilterOptionList(tableKey, filterKey);
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
// A 'null' options list means that a simple text-input dialog should be used
|
||||||
|
if (options == null) {
|
||||||
|
html = `<input class='form-control filter-input' id='${id}' name='value'></input>`;
|
||||||
|
} else {
|
||||||
|
// Return a 'select' input with the available values
|
||||||
|
html = `<select class='form-control filter-input' id='${id}' name='value'>`;
|
||||||
|
|
||||||
|
for (var key in options) {
|
||||||
|
option = options[key];
|
||||||
|
html += `<option value='${key}'>${option.value}</option>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `</select>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a filter list for a given table
|
||||||
|
*
|
||||||
|
* @param {*} tableKey - string lookup key for filter settings
|
||||||
|
* @param {*} table - bootstrapTable element to update
|
||||||
|
* @param {*} target - name of target element on page
|
||||||
|
*/
|
||||||
|
function setupFilterList(tableKey, table, target) {
|
||||||
|
|
||||||
|
var addClicked = false;
|
||||||
|
|
||||||
|
if (target == null || target.length == 0) {
|
||||||
|
target = `#filter-list-${tableKey}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tag = `filter-tag-${tableKey}`;
|
||||||
|
var add = `filter-add-${tableKey}`;
|
||||||
|
var clear = `filter-clear-${tableKey}`;
|
||||||
|
var make = `filter-make-${tableKey}`;
|
||||||
|
|
||||||
|
console.log(`Generating filter list: ${tableKey}`);
|
||||||
|
|
||||||
|
var filters = loadTableFilters(tableKey);
|
||||||
|
|
||||||
|
console.log("Filters: " + filters.count);
|
||||||
|
|
||||||
|
var element = $(target);
|
||||||
|
|
||||||
|
// One blank slate, please
|
||||||
|
element.empty();
|
||||||
|
|
||||||
|
element.append(`<button id='${add}' title='Add new filter' class='btn btn-default filter-tag'><span class='fas fa-filter'></span></button>`);
|
||||||
|
|
||||||
|
if (Object.keys(filters).length > 0) {
|
||||||
|
element.append(`<button id='${clear}' title='Clear all filters' class='btn btn-default filter-tag'><span class='fas fa-trash-alt'></span></button>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in filters) {
|
||||||
|
var value = getFilterOptionValue(tableKey, key, filters[key]);
|
||||||
|
var title = getFilterTitle(tableKey, key);
|
||||||
|
|
||||||
|
element.append(`<div class='filter-tag'>${title} = ${value}<span ${tag}='${key}' class='close'>x</span></div>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a callback for adding a new filter
|
||||||
|
element.find(`#${add}`).click(function clicked() {
|
||||||
|
|
||||||
|
if (!addClicked) {
|
||||||
|
|
||||||
|
addClicked = true;
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
//`<div class='filter-input'>`;
|
||||||
|
|
||||||
|
html += generateAvailableFilterList(tableKey);
|
||||||
|
html += generateFilterInput(tableKey);
|
||||||
|
|
||||||
|
html += `<button title='Create filter' class='btn btn-default filter-tag' id='${make}'><span class='fas fa-plus'></span></button>`;
|
||||||
|
|
||||||
|
//html += '</div>';
|
||||||
|
|
||||||
|
element.append(html);
|
||||||
|
|
||||||
|
// Add a callback for when the filter tag selection is changed
|
||||||
|
element.find(`#filter-tag-${tableKey}`).on('change', function() {
|
||||||
|
var list = element.find(`#filter-value-${tableKey}`);
|
||||||
|
|
||||||
|
list.replaceWith(generateFilterInput(tableKey, this.value));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback for when the new filter is created
|
||||||
|
element.find(`#filter-make-${tableKey}`).click(function() {
|
||||||
|
var tag = element.find(`#filter-tag-${tableKey}`).val();
|
||||||
|
var val = element.find(`#filter-value-${tableKey}`).val();
|
||||||
|
|
||||||
|
// Only add the new filter if it is not empty!
|
||||||
|
if (tag && tag.length > 0) {
|
||||||
|
var filters = addTableFilter(tableKey, tag, val);
|
||||||
|
reloadTable(table, filters);
|
||||||
|
|
||||||
|
// Run this function again
|
||||||
|
setupFilterList(tableKey, table, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addClicked = false;
|
||||||
|
|
||||||
|
setupFilterList(tableKey, table, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback for clearing all the filters
|
||||||
|
element.find(`#${clear}`).click(function() {
|
||||||
|
var filters = clearTableFilters(tableKey);
|
||||||
|
|
||||||
|
reloadTable(table, filters);
|
||||||
|
|
||||||
|
setupFilterList(tableKey, table, target);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add callback for deleting each filter
|
||||||
|
element.find(".close").click(function(event) {
|
||||||
|
var me = $(this);
|
||||||
|
|
||||||
|
var filter = me.attr(`filter-tag-${tableKey}`);
|
||||||
|
|
||||||
|
var filters = removeTableFilter(tableKey, filter);
|
||||||
|
|
||||||
|
reloadTable(table, filters);
|
||||||
|
|
||||||
|
// Run this function again!
|
||||||
|
setupFilterList(tableKey, table, target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pretty title for the given table and filter selection.
|
||||||
|
* If no title is provided, default to the key value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function getFilterTitle(tableKey, filterKey) {
|
||||||
|
var settings = getFilterSettings(tableKey, filterKey);
|
||||||
|
return settings.title || filterKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a description for the given table and filter selection.
|
||||||
|
*/
|
||||||
|
function getFilterDescription(tableKey, filterKey) {
|
||||||
|
var settings = getFilterSettings(tableKey, filterKey);
|
||||||
|
return settings.description || filterKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the display value for a particular option
|
||||||
|
*/
|
||||||
|
function getFilterOptionValue(tableKey, filterKey, valueKey) {
|
||||||
|
|
||||||
|
var filter = getFilterSettings(tableKey, filterKey);
|
||||||
|
|
||||||
|
var value = String(valueKey);
|
||||||
|
|
||||||
|
// Lookup for boolean options
|
||||||
|
if (filter.type == 'bool') {
|
||||||
|
if (value == '1') return 'true';
|
||||||
|
if (value == '0') return 'false';
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through a list of options
|
||||||
|
if ('options' in filter) {
|
||||||
|
for (var key in filter.options) {
|
||||||
|
|
||||||
|
if (key == valueKey) {
|
||||||
|
return filter.options[key].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could not find a match
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot map to a display string - return the original text
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
@ -104,8 +104,21 @@ function removePurchaseOrderLineItem(e) {
|
|||||||
function loadPurchaseOrderTable(table, options) {
|
function loadPurchaseOrderTable(table, options) {
|
||||||
/* Create a purchase-order table */
|
/* Create a purchase-order table */
|
||||||
|
|
||||||
|
var params = options.params || {};
|
||||||
|
|
||||||
|
var filters = loadTableFilters("order");
|
||||||
|
|
||||||
|
for (var key in params) {
|
||||||
|
filters[key] = params[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
setupFilterList("order", table);
|
||||||
|
|
||||||
table.inventreeTable({
|
table.inventreeTable({
|
||||||
url: options.url,
|
url: options.url,
|
||||||
|
queryParams: filters,
|
||||||
|
groupBy: false,
|
||||||
|
original: params,
|
||||||
formatNoMatches: function() { return "No purchase orders found"; },
|
formatNoMatches: function() { return "No purchase orders found"; },
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
@ -144,7 +157,7 @@ function loadPurchaseOrderTable(table, options) {
|
|||||||
field: 'status',
|
field: 'status',
|
||||||
title: 'Status',
|
title: 'Status',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
return orderStatusLabel(row.status, row.status_text);
|
return orderStatusDisplay(row.status, row.status_text);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -155,39 +168,3 @@ function loadPurchaseOrderTable(table, options) {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function orderStatusLabel(code, label) {
|
|
||||||
/* Render a purchase-order status label. */
|
|
||||||
|
|
||||||
var html = "<span class='label";
|
|
||||||
|
|
||||||
switch (code) {
|
|
||||||
case 10: // pending
|
|
||||||
html += " label-info";
|
|
||||||
break;
|
|
||||||
case 20: // placed
|
|
||||||
html += " label-primary";
|
|
||||||
break;
|
|
||||||
case 30: // complete
|
|
||||||
html += " label-success";
|
|
||||||
break;
|
|
||||||
case 40: // cancelled
|
|
||||||
case 50: // lost
|
|
||||||
html += " label-warning";
|
|
||||||
break;
|
|
||||||
case 60: // returned
|
|
||||||
html += " label-danger";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
html += "'>";
|
|
||||||
html += label;
|
|
||||||
html += "</span>";
|
|
||||||
|
|
||||||
console.log(html);
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
@ -87,17 +87,15 @@ function loadPartTable(table, url, options={}) {
|
|||||||
* buttons: If provided, link buttons to selection status of this table
|
* buttons: If provided, link buttons to selection status of this table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Default query params
|
var params = options.parms || {};
|
||||||
query = options.query;
|
|
||||||
|
var filters = loadTableFilters("parts");
|
||||||
if (!options.allowInactive) {
|
|
||||||
// Only display active parts
|
for (var key in params) {
|
||||||
query.active = true;
|
filters[key] = params[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include sub-category search
|
setupFilterList("parts", $(table));
|
||||||
// TODO - Make this user-configurable!
|
|
||||||
query.cascade = true;
|
|
||||||
|
|
||||||
var columns = [
|
var columns = [
|
||||||
{
|
{
|
||||||
@ -142,11 +140,21 @@ function loadPartTable(table, url, options={}) {
|
|||||||
var display = imageHoverIcon(row.thumbnail) + renderLink(name, '/part/' + row.pk + '/');
|
var display = imageHoverIcon(row.thumbnail) + renderLink(name, '/part/' + row.pk + '/');
|
||||||
|
|
||||||
if (row.is_template) {
|
if (row.is_template) {
|
||||||
display = display + "<span class='label label-info' style='float: right;'>TEMPLATE</span>";
|
display += `<span class='fas fa-clone label-right' title='Template part'></span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.assembly) {
|
||||||
|
display += `<span class='fas fa-tools label-right' title='Assembled part'></span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (row.component) {
|
||||||
|
display = display + `<span class='fas fa-cogs label-right' title='Component part'></span>`;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (!row.active) {
|
if (!row.active) {
|
||||||
display = display + "<span class='label label-warning' style='float: right;'>INACTIVE</span>";
|
display += `<span class='label label-warning label-right'>INACTIVE</span>`;
|
||||||
}
|
}
|
||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
@ -175,7 +183,7 @@ function loadPartTable(table, url, options={}) {
|
|||||||
return renderLink(row.category__name, "/part/category/" + row.category + "/");
|
return renderLink(row.category__name, "/part/category/" + row.category + "/");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return '';
|
return 'No category';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -217,10 +225,10 @@ function loadPartTable(table, url, options={}) {
|
|||||||
url: url,
|
url: url,
|
||||||
sortName: 'name',
|
sortName: 'name',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
queryParams: filters,
|
||||||
|
groupBy: false,
|
||||||
|
original: params,
|
||||||
formatNoMatches: function() { return "No parts found"; },
|
formatNoMatches: function() { return "No parts found"; },
|
||||||
queryParams: function(p) {
|
|
||||||
return query;
|
|
||||||
},
|
|
||||||
columns: columns,
|
columns: columns,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ function getStockLocations(filters={}, options={}) {
|
|||||||
return inventreeGet('/api/stock/location/', filters, options)
|
return inventreeGet('/api/stock/location/', filters, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Functions for interacting with stock management forms
|
/* Functions for interacting with stock management forms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ function removeStockRow(e) {
|
|||||||
$('#' + row).remove();
|
$('#' + row).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function loadStockTable(table, options) {
|
function loadStockTable(table, options) {
|
||||||
/* Load data into a stock table with adjustable options.
|
/* Load data into a stock table with adjustable options.
|
||||||
* Fetches data (via AJAX) and loads into a bootstrap table.
|
* Fetches data (via AJAX) and loads into a bootstrap table.
|
||||||
@ -38,23 +40,39 @@ function loadStockTable(table, options) {
|
|||||||
* params - query params for augmenting stock data request
|
* params - query params for augmenting stock data request
|
||||||
* groupByField - Column for grouping stock items
|
* groupByField - Column for grouping stock items
|
||||||
* buttons - Which buttons to link to stock selection callbacks
|
* buttons - Which buttons to link to stock selection callbacks
|
||||||
|
* filterList - <ul> element where filters are displayed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// List of user-params which override the default filters
|
||||||
var params = options.params || {};
|
var params = options.params || {};
|
||||||
|
|
||||||
// Enforce 'cascade' option
|
var filterListElement = options.filterList || "#filter-list-stock";
|
||||||
// TODO - Make this user-configurable?
|
|
||||||
params.cascade = true;
|
|
||||||
|
|
||||||
console.log('load stock table');
|
var filters = loadTableFilters("stock");
|
||||||
|
|
||||||
|
var original = {};
|
||||||
|
|
||||||
|
for (var key in params) {
|
||||||
|
original[key] = params[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
setupFilterList("stock", table, filterListElement);
|
||||||
|
|
||||||
|
// Override the default values, or add new ones
|
||||||
|
for (var key in params) {
|
||||||
|
filters[key] = params[key];
|
||||||
|
}
|
||||||
|
|
||||||
table.inventreeTable({
|
table.inventreeTable({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
formatNoMatches: function() {
|
formatNoMatches: function() {
|
||||||
return 'No stock items matching query';
|
return 'No stock items matching query';
|
||||||
},
|
},
|
||||||
|
url: options.url,
|
||||||
|
queryParams: filters,
|
||||||
customSort: customGroupSorter,
|
customSort: customGroupSorter,
|
||||||
groupBy: true,
|
groupBy: true,
|
||||||
|
original: original,
|
||||||
groupByField: options.groupByField || 'part',
|
groupByField: options.groupByField || 'part',
|
||||||
groupByFormatter: function(field, id, data) {
|
groupByFormatter: function(field, id, data) {
|
||||||
|
|
||||||
@ -87,6 +105,29 @@ function loadStockTable(table, options) {
|
|||||||
stock = +stock.toFixed(5);
|
stock = +stock.toFixed(5);
|
||||||
|
|
||||||
return stock + " (" + items + " items)";
|
return stock + " (" + items + " items)";
|
||||||
|
} else if (field == 'status') {
|
||||||
|
var statii = [];
|
||||||
|
|
||||||
|
data.forEach(function(item) {
|
||||||
|
var status = String(item.status);
|
||||||
|
|
||||||
|
if (!status || status == '') {
|
||||||
|
status = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!statii.includes(status)) {
|
||||||
|
statii.push(status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Multiple status codes
|
||||||
|
if (statii.length > 1) {
|
||||||
|
return "-";
|
||||||
|
} else if (statii.length == 1) {
|
||||||
|
return stockStatusDisplay(statii[0]);
|
||||||
|
} else {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
} else if (field == 'batch') {
|
} else if (field == 'batch') {
|
||||||
var batches = [];
|
var batches = [];
|
||||||
|
|
||||||
@ -211,13 +252,17 @@ function loadStockTable(table, options) {
|
|||||||
|
|
||||||
var text = renderLink(val, '/stock/item/' + row.pk + '/');
|
var text = renderLink(val, '/stock/item/' + row.pk + '/');
|
||||||
|
|
||||||
if (row.status_text != 'OK') {
|
|
||||||
text = text + "<span class='badge'>" + row.status_text + "</span>";
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: 'Status',
|
||||||
|
sortable: 'true',
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
return stockStatusDisplay(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'batch',
|
field: 'batch',
|
||||||
title: 'Batch',
|
title: 'Batch',
|
||||||
@ -241,8 +286,6 @@ function loadStockTable(table, options) {
|
|||||||
title: 'Notes',
|
title: 'Notes',
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
url: options.url,
|
|
||||||
queryParams: params,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (options.buttons) {
|
if (options.buttons) {
|
||||||
|
@ -44,6 +44,42 @@ function isNumeric(n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reload a table which has already been made into a bootstrap table.
|
||||||
|
* New filters can be optionally provided, to change the query params.
|
||||||
|
*/
|
||||||
|
function reloadTable(table, filters) {
|
||||||
|
|
||||||
|
// Simply perform a refresh
|
||||||
|
if (filters == null) {
|
||||||
|
table.bootstrapTable('refresh');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// More complex refresh with new filters supplied
|
||||||
|
var options = table.bootstrapTable('getOptions');
|
||||||
|
|
||||||
|
// Construct a new list of filters to use for the query
|
||||||
|
var params = {};
|
||||||
|
|
||||||
|
for (var key in filters) {
|
||||||
|
params[key] = filters[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original query params will override
|
||||||
|
if (options.original != null) {
|
||||||
|
for (var key in options.original) {
|
||||||
|
params[key] = options.original[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options.queryParams = params;
|
||||||
|
|
||||||
|
table.bootstrapTable('refreshOptions', options);
|
||||||
|
table.bootstrapTable('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Wrapper function for bootstrapTable.
|
/* Wrapper function for bootstrapTable.
|
||||||
* Sets some useful defaults, and manage persistent settings.
|
* Sets some useful defaults, and manage persistent settings.
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,56 @@ from django.utils.translation import ugettext as _
|
|||||||
|
|
||||||
|
|
||||||
class StatusCode:
|
class StatusCode:
|
||||||
|
"""
|
||||||
|
Base class for representing a set of StatusCodes.
|
||||||
|
This is used to map a set of integer values to text.
|
||||||
|
"""
|
||||||
|
|
||||||
|
labels = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def render(cls, key):
|
||||||
|
"""
|
||||||
|
Render the value as a label.
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("Rendering:", key, cls.options)
|
||||||
|
|
||||||
|
# If the key cannot be found, pass it back
|
||||||
|
if key not in cls.options.keys():
|
||||||
|
return key
|
||||||
|
|
||||||
|
value = cls.options.get(key, key)
|
||||||
|
label = cls.labels.get(key, None)
|
||||||
|
|
||||||
|
if label:
|
||||||
|
return "<span class='label label-{label}'>{value}</span>".format(label=label, value=value)
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list(cls):
|
||||||
|
"""
|
||||||
|
Return the StatusCode options as a list of mapped key / value items
|
||||||
|
"""
|
||||||
|
|
||||||
|
codes = []
|
||||||
|
|
||||||
|
for key in cls.options.keys():
|
||||||
|
|
||||||
|
opt = {
|
||||||
|
'key': key,
|
||||||
|
'value': cls.options[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
label = cls.labels.get(key)
|
||||||
|
|
||||||
|
if label:
|
||||||
|
opt['label'] = label
|
||||||
|
|
||||||
|
codes.append(opt)
|
||||||
|
|
||||||
|
return codes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def items(cls):
|
def items(cls):
|
||||||
@ -41,6 +91,15 @@ class OrderStatus(StatusCode):
|
|||||||
RETURNED: _("Returned"),
|
RETURNED: _("Returned"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
PENDING: "primary",
|
||||||
|
PLACED: "primary",
|
||||||
|
COMPLETE: "success",
|
||||||
|
CANCELLED: "danger",
|
||||||
|
LOST: "warning",
|
||||||
|
RETURNED: "warning",
|
||||||
|
}
|
||||||
|
|
||||||
# Open orders
|
# Open orders
|
||||||
OPEN = [
|
OPEN = [
|
||||||
PENDING,
|
PENDING,
|
||||||
@ -71,6 +130,12 @@ class StockStatus(StatusCode):
|
|||||||
LOST: _("Lost"),
|
LOST: _("Lost"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
OK: 'success',
|
||||||
|
ATTENTION: 'warning',
|
||||||
|
DAMAGED: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
# The following codes correspond to parts that are 'available' or 'in stock'
|
# The following codes correspond to parts that are 'available' or 'in stock'
|
||||||
AVAILABLE_CODES = [
|
AVAILABLE_CODES = [
|
||||||
OK,
|
OK,
|
||||||
@ -100,6 +165,13 @@ class BuildStatus(StatusCode):
|
|||||||
COMPLETE: _("Complete"),
|
COMPLETE: _("Complete"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
PENDING: 'primary',
|
||||||
|
ALLOCATED: 'info',
|
||||||
|
COMPLETE: 'success',
|
||||||
|
CANCELLED: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
ACTIVE_CODES = [
|
ACTIVE_CODES = [
|
||||||
PENDING,
|
PENDING,
|
||||||
ALLOCATED
|
ALLOCATED
|
||||||
|
@ -11,6 +11,8 @@ from rest_framework import generics, permissions
|
|||||||
|
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
|
|
||||||
|
from InvenTree.helpers import str2bool
|
||||||
|
|
||||||
from .models import Build, BuildItem
|
from .models import Build, BuildItem
|
||||||
from .serializers import BuildSerializer, BuildItemSerializer
|
from .serializers import BuildSerializer, BuildItemSerializer
|
||||||
|
|
||||||
@ -36,9 +38,41 @@ class BuildList(generics.ListCreateAPIView):
|
|||||||
]
|
]
|
||||||
|
|
||||||
filter_fields = [
|
filter_fields = [
|
||||||
'part',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""
|
||||||
|
Override the queryset filtering,
|
||||||
|
as some of the fields don't natively play nicely with DRF
|
||||||
|
"""
|
||||||
|
|
||||||
|
build_list = super().get_queryset()
|
||||||
|
|
||||||
|
# Filter by part
|
||||||
|
part = self.request.query_params.get('part', None)
|
||||||
|
|
||||||
|
if part is not None:
|
||||||
|
build_list = build_list.filter(part=part)
|
||||||
|
|
||||||
|
# Filter by build status?
|
||||||
|
status = self.request.query_params.get('status', None)
|
||||||
|
|
||||||
|
if status is not None:
|
||||||
|
build_list = build_list.filter(status=status)
|
||||||
|
|
||||||
|
return build_list
|
||||||
|
|
||||||
|
def get_serializer(self, *args, **kwargs):
|
||||||
|
|
||||||
|
try:
|
||||||
|
part_detail = str2bool(self.request.GET.get('part_detail', None))
|
||||||
|
except AttributeError:
|
||||||
|
part_detail = None
|
||||||
|
|
||||||
|
kwargs['part_detail'] = part_detail
|
||||||
|
|
||||||
|
return self.serializer_class(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BuildDetail(generics.RetrieveUpdateAPIView):
|
class BuildDetail(generics.RetrieveUpdateAPIView):
|
||||||
""" API endpoint for detail view of a Build object """
|
""" API endpoint for detail view of a Build object """
|
||||||
|
@ -10,6 +10,7 @@ from InvenTree.serializers import InvenTreeModelSerializer
|
|||||||
from stock.serializers import StockItemSerializerBrief
|
from stock.serializers import StockItemSerializerBrief
|
||||||
|
|
||||||
from .models import Build, BuildItem
|
from .models import Build, BuildItem
|
||||||
|
from part.serializers import PartBriefSerializer
|
||||||
|
|
||||||
|
|
||||||
class BuildSerializer(InvenTreeModelSerializer):
|
class BuildSerializer(InvenTreeModelSerializer):
|
||||||
@ -18,6 +19,16 @@ class BuildSerializer(InvenTreeModelSerializer):
|
|||||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||||
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
||||||
|
|
||||||
|
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
part_detail = kwargs.pop('part_detail', False)
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
if part_detail is not True:
|
||||||
|
self.fields.pop('part_detail')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Build
|
model = Build
|
||||||
fields = [
|
fields = [
|
||||||
@ -27,6 +38,7 @@ class BuildSerializer(InvenTreeModelSerializer):
|
|||||||
'creation_date',
|
'creation_date',
|
||||||
'completion_date',
|
'completion_date',
|
||||||
'part',
|
'part',
|
||||||
|
'part_detail',
|
||||||
'quantity',
|
'quantity',
|
||||||
'status',
|
'status',
|
||||||
'status_text',
|
'status_text',
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load status_codes %}
|
||||||
|
|
||||||
{% block page_title %}
|
{% block page_title %}
|
||||||
InvenTree | Build - {{ build }}
|
InvenTree | Build - {{ build }}
|
||||||
@ -22,61 +24,70 @@ InvenTree | Build - {{ build }}
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='media-body'>
|
<div class='media-body'>
|
||||||
<h4>Build Details</h4>
|
<h4>{% trans "Build" %}</h4>
|
||||||
|
<div class='btn-row'>
|
||||||
<p>
|
<div class='btn-group'>
|
||||||
<div class='btn-row'>
|
<button type='button' class='btn btn-default btn-glyph' id='build-edit' title='Edit Build'>
|
||||||
<div class='btn-group'>
|
<span class='glyphicon glyphicon-edit'/>
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='build-edit' title='Edit Build'>
|
</button>
|
||||||
<span class='glyphicon glyphicon-edit'/>
|
{% if build.is_active %}
|
||||||
</button>
|
<button type='button' class='btn btn-default btn-glyph' id='build-complete' title="Complete Build">
|
||||||
{% if build.is_active %}
|
<span class='glyphicon glyphicon-send'/>
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='build-complete' title="Complete Build">
|
</button>
|
||||||
<span class='glyphicon glyphicon-send'/>
|
<button type='button' class='btn btn-default btn-glyph' id='build-cancel' title='Cancel Build'>
|
||||||
</button>
|
<span class='glyphicon glyphicon-remove'/>
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='build-cancel' title='Cancel Build'>
|
</button>
|
||||||
<span class='glyphicon glyphicon-remove'/>
|
{% endif %}
|
||||||
</button>
|
{% if build.status == BuildStatus.CANCELLED %}
|
||||||
{% endif %}
|
<button type='button' class='btn btn-default btn-glyph' id='build-delete' title='Delete Build'>
|
||||||
{% if build.status == BuildStatus.CANCELLED %}
|
<span class='glyphicon glyphicon-trash'/>
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='build-delete' title='Delete Build'>
|
</button>
|
||||||
<span class='glyphicon glyphicon-trash'/>
|
{% endif %}
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</div>
|
||||||
|
|
||||||
<table class='table table-striped table-condensed'>
|
|
||||||
<tr>
|
|
||||||
<td>{{ build.title }}</td>
|
|
||||||
<td>{% include "build_status.html" with build=build %}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Part</td>
|
|
||||||
<td><a href="{% url 'part-detail' build.part.id %}">{{ build.part.full_name }}</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Quantity</td>
|
|
||||||
<td>{{ build.quantity }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>BOM Price</td>
|
|
||||||
<td>
|
|
||||||
{% if bom_price %}
|
|
||||||
{{ bom_price }}
|
|
||||||
{% if build.part.has_complete_bom_pricing == False %}
|
|
||||||
<br><span class='warning-msg'><i>BOM pricing is incomplete</i></span>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
<span class='warning-msg'><i>No pricing information</i></span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='col-sm-6'>
|
||||||
|
<h4>{% trans "Build Details" %}</h4>
|
||||||
|
<table class='table table-striped table-condensed'>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>{% trans "Build Title" %}</td>
|
||||||
|
<td>{{ build.title }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><span class='fas fa-shapes'></span></td>
|
||||||
|
<td>Part</td>
|
||||||
|
<td><a href="{% url 'part-detail' build.part.id %}">{{ build.part.full_name }}</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>{% trans "Quantity" %}</td>
|
||||||
|
<td>{{ build.quantity }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><span class='fas fa-info'></span></td>
|
||||||
|
<td>{% trans "Status" %}</td>
|
||||||
|
<td>{% build_status build.status %}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><span class='fas fa-dollar-sign'></span></td>
|
||||||
|
<td>{% trans "BOM Price" %}</td>
|
||||||
|
<td>
|
||||||
|
{% if bom_price %}
|
||||||
|
{{ bom_price }}
|
||||||
|
{% if build.part.has_complete_bom_pricing == False %}
|
||||||
|
<br><span class='warning-msg'><i>{% trans "BOM pricing is incomplete" %}</i></span>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<span class='warning-msg'><i>{% trans "No pricing information" %}</i></span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
{% extends "collapse.html" %}
|
|
||||||
|
|
||||||
{% block collapse_title %}
|
|
||||||
<b>{{ title }}</b> - {{ builds | length }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block collapse_content %}
|
|
||||||
<table class='table table-striped table-condensed build-table' id='build-table-{{collapse_id}}' data-toolbar='#button-toolbar'>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Build</th>
|
|
||||||
<th>Part</th>
|
|
||||||
<th>Quantity</th>
|
|
||||||
<th>Status</th>
|
|
||||||
{% if completed %}
|
|
||||||
<th>Completed</th>
|
|
||||||
{% else %}
|
|
||||||
<th>Created</th>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for build in builds %}
|
|
||||||
<tr>
|
|
||||||
<td><a href="{% url 'build-detail' build.id %}">{{ build.title }}</a></td>
|
|
||||||
<td><a href="{% url 'part-build' build.part.id %}">{{ build.part.full_name }}</a></td>
|
|
||||||
<td>{{ build.quantity }}</td>
|
|
||||||
<td>{% include "build_status.html" with build=build %}
|
|
||||||
{% if completed %}
|
|
||||||
<td>{{ build.completion_date }}<span class='badge'>{{ build.completed_by.username }}</span></td>
|
|
||||||
{% else %}
|
|
||||||
<td>{{ build.creation_date }}</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% endblock %}
|
|
@ -2,6 +2,7 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block details %}
|
{% block details %}
|
||||||
|
{% load status_codes %}
|
||||||
|
|
||||||
{% include "build/tabs.html" with tab='details' %}
|
{% include "build/tabs.html" with tab='details' %}
|
||||||
|
|
||||||
@ -39,7 +40,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-info'></span></td>
|
<td><span class='fas fa-info'></span></td>
|
||||||
<td>{% trans "Status" %}</td>
|
<td>{% trans "Status" %}</td>
|
||||||
<td>{% include "build_status.html" with build=build %}</td>
|
<td>{% build_status build.status %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if build.batch %}
|
{% if build.batch %}
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -13,21 +13,23 @@ InvenTree | Build List
|
|||||||
<h3>Part Builds</h3>
|
<h3>Part Builds</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class='col-sm-6'>
|
<div class='col-sm-6'>
|
||||||
<div class='container' id='active-build-toolbar' style='float: right;'>
|
|
||||||
<div class='btn-group' style='float: right;'>
|
</div>
|
||||||
<button type='button' class="btn btn-success" id='new-build'>Start New Build</button>
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div id='button-toolbar'>
|
||||||
|
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||||
|
<button type='button' class="btn btn-success" id='new-build'>Start New Build</button>
|
||||||
|
<div class='filter-list' id='filter-list-build'>
|
||||||
|
<!-- An empty div in which the filter list will be constructed -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<table class='table table-striped table-condensed' id='build-table' data-toolbar='#button-toolbar'>
|
||||||
|
</table>
|
||||||
{% include "build/build_list.html" with builds=active title="Active Builds" completed=False collapse_id='active' %}
|
|
||||||
|
|
||||||
{% include "build/build_list.html" with builds=completed completed=True title="Completed Builds" collapse_id="complete" %}
|
|
||||||
|
|
||||||
{% include "build/build_list.html" with builds=cancelled title="Cancelled Builds" completed=False collapse_id="cancelled" %}
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -38,38 +40,18 @@ InvenTree | Build List
|
|||||||
|
|
||||||
$("#new-build").click(function() {
|
$("#new-build").click(function() {
|
||||||
launchModalForm(
|
launchModalForm(
|
||||||
"{% url 'build-create' %}",
|
"{% url 'build-create' %}",
|
||||||
{
|
{
|
||||||
follow: true
|
follow: true
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".build-table").inventreeTable({
|
loadBuildTable($("#build-table"), {
|
||||||
formatNoMatches: function() { return 'No builds found'; },
|
url: "{% url 'api-build-list' %}",
|
||||||
columns: [
|
params: {
|
||||||
{
|
part_detail: "true",
|
||||||
field: 'name',
|
},
|
||||||
title: 'Build',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'part',
|
|
||||||
title: 'Part',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Quantity',
|
|
||||||
sortable: true,
|
|
||||||
searchable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Status',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -143,9 +143,7 @@ class TestBuildViews(TestCase):
|
|||||||
|
|
||||||
content = str(response.content)
|
content = str(response.content)
|
||||||
|
|
||||||
# Content should contain build titles
|
self.assertIn("Part Builds", content)
|
||||||
for build in Build.objects.all():
|
|
||||||
self.assertIn(build.title, content)
|
|
||||||
|
|
||||||
def test_build_detail(self):
|
def test_build_detail(self):
|
||||||
""" Test the detail view for a Build object """
|
""" Test the detail view for a Build object """
|
||||||
|
@ -30,21 +30,21 @@
|
|||||||
|
|
||||||
$("#part-create").click(function () {
|
$("#part-create").click(function () {
|
||||||
launchModalForm(
|
launchModalForm(
|
||||||
"{% url 'supplier-part-create' %}",
|
"{% url 'supplier-part-create' %}",
|
||||||
{
|
{
|
||||||
data: {
|
data: {
|
||||||
supplier: {{ company.id }}
|
supplier: {{ company.id }}
|
||||||
},
|
},
|
||||||
reload: true,
|
reload: true,
|
||||||
secondary: [
|
secondary: [
|
||||||
{
|
{
|
||||||
field: 'part',
|
field: 'part',
|
||||||
label: 'New Part',
|
label: 'New Part',
|
||||||
title: 'Create New Part',
|
title: 'Create New Part',
|
||||||
url: "{% url 'part-create' %}"
|
url: "{% url 'part-create' %}"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#part-table").inventreeTable({
|
$("#part-table").inventreeTable({
|
||||||
@ -64,7 +64,22 @@
|
|||||||
field: 'part_detail.full_name',
|
field: 'part_detail.full_name',
|
||||||
title: '{% trans "Part" %}',
|
title: '{% trans "Part" %}',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
return imageHoverIcon(row.part_detail.image_url) + renderLink(value, '/part/' + row.part + '/suppliers/');
|
|
||||||
|
var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, '/part/' + row.part + '/suppliers/');
|
||||||
|
|
||||||
|
if (row.part_detail.is_template) {
|
||||||
|
html += `<span class='fas fa-clone label-right' title='Template part'></span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.part_detail.assembly) {
|
||||||
|
html += `<span class='fas fa-tools label-right' title='Assembled part'></span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!row.part_detail.active) {
|
||||||
|
html += `<span class='label label-warning label-right'>INACTIVE</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -9,8 +9,11 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id='button-bar'>
|
<div id='button-bar'>
|
||||||
<div class='btn-group'>
|
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||||
<button class='btn btn-primary' type='button' id='company-order2' title='Create new purchase order'>{% trans "New Purchase Order" %}</button>
|
<button class='btn btn-primary' type='button' id='company-order2' title='Create new purchase order'>{% trans "New Purchase Order" %}</button>
|
||||||
|
<div class='filter-list' id='filter-list-order'>
|
||||||
|
<!-- Empty div -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
{% for order in orders %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ order }}</td>
|
|
||||||
<td>{{ order.description }}</td>
|
|
||||||
<td>{% include "order/order_status.html" with order=order %}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
@ -96,8 +96,8 @@ class CompanySimpleTest(TestCase):
|
|||||||
def test_part_pricing(self):
|
def test_part_pricing(self):
|
||||||
m2x4 = Part.objects.get(name='M2x4 LPHS')
|
m2x4 = Part.objects.get(name='M2x4 LPHS')
|
||||||
|
|
||||||
self.assertEqual(m2x4.get_price_info(10), "70.00000 - 75.00000")
|
self.assertEqual(m2x4.get_price_info(10), "70 - 75")
|
||||||
self.assertEqual(m2x4.get_price_info(100), "125.00000 - 350.00000")
|
self.assertEqual(m2x4.get_price_info(100), "125 - 350")
|
||||||
|
|
||||||
pmin, pmax = m2x4.get_price_range(5)
|
pmin, pmax = m2x4.get_price_range(5)
|
||||||
self.assertEqual(pmin, 35)
|
self.assertEqual(pmin, 35)
|
||||||
|
@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-04-09 15:04+0000\n"
|
"POT-Creation-Date: 2020-04-11 15:00+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-02 08:07+0100\n"
|
"PO-Revision-Date: 2020-02-02 08:07+0100\n"
|
||||||
"Last-Translator: Christian Schlüter <chschlue@gmail.com>\n"
|
"Last-Translator: Christian Schlüter <chschlue@gmail.com>\n"
|
||||||
"Language-Team: C <kde-i18n-doc@kde.org>\n"
|
"Language-Team: C <kde-i18n-doc@kde.org>\n"
|
||||||
@ -17,30 +17,30 @@ msgstr ""
|
|||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Generator: Lokalize 19.12.0\n"
|
"X-Generator: Lokalize 19.12.0\n"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:240 order/models.py:164 order/models.py:215
|
#: InvenTree/helpers.py:259 order/models.py:164 order/models.py:215
|
||||||
msgid "Invalid quantity provided"
|
msgid "Invalid quantity provided"
|
||||||
msgstr "Keine gültige Menge"
|
msgstr "Keine gültige Menge"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:243
|
#: InvenTree/helpers.py:262
|
||||||
msgid "Empty serial number string"
|
msgid "Empty serial number string"
|
||||||
msgstr "Keine Seriennummer angegeben"
|
msgstr "Keine Seriennummer angegeben"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:264 InvenTree/helpers.py:281
|
#: InvenTree/helpers.py:283 InvenTree/helpers.py:300
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Duplicate serial: {n}"
|
msgid "Duplicate serial: {n}"
|
||||||
msgstr "Doppelte Seriennummer: {n}"
|
msgstr "Doppelte Seriennummer: {n}"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:268 InvenTree/helpers.py:271 InvenTree/helpers.py:274
|
#: InvenTree/helpers.py:287 InvenTree/helpers.py:290 InvenTree/helpers.py:293
|
||||||
#: InvenTree/helpers.py:285
|
#: InvenTree/helpers.py:304
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Invalid group: {g}"
|
msgid "Invalid group: {g}"
|
||||||
msgstr "Ungültige Gruppe: {g}"
|
msgstr "Ungültige Gruppe: {g}"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:291
|
#: InvenTree/helpers.py:310
|
||||||
msgid "No serial numbers found"
|
msgid "No serial numbers found"
|
||||||
msgstr "Keine Seriennummern gefunden"
|
msgstr "Keine Seriennummern gefunden"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:295
|
#: InvenTree/helpers.py:314
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Number of unique serial number ({s}) must match quantity ({q})"
|
msgid "Number of unique serial number ({s}) must match quantity ({q})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -71,49 +71,49 @@ msgstr "Französisch"
|
|||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr "Polnisch"
|
msgstr "Polnisch"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:36 InvenTree/status_codes.py:97
|
#: InvenTree/status_codes.py:86 InvenTree/status_codes.py:162
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr "Ausstehend"
|
msgstr "Ausstehend"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:37
|
#: InvenTree/status_codes.py:87
|
||||||
msgid "Placed"
|
msgid "Placed"
|
||||||
msgstr "Platziert"
|
msgstr "Platziert"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:38 InvenTree/status_codes.py:100
|
#: InvenTree/status_codes.py:88 InvenTree/status_codes.py:165
|
||||||
msgid "Complete"
|
msgid "Complete"
|
||||||
msgstr "Fertig"
|
msgstr "Fertig"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:39 InvenTree/status_codes.py:99
|
#: InvenTree/status_codes.py:89 InvenTree/status_codes.py:164
|
||||||
msgid "Cancelled"
|
msgid "Cancelled"
|
||||||
msgstr "Storniert"
|
msgstr "Storniert"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71
|
#: InvenTree/status_codes.py:90 InvenTree/status_codes.py:130
|
||||||
msgid "Lost"
|
msgid "Lost"
|
||||||
msgstr "Verloren"
|
msgstr "Verloren"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:41
|
#: InvenTree/status_codes.py:91
|
||||||
msgid "Returned"
|
msgid "Returned"
|
||||||
msgstr "Zurückgegeben"
|
msgstr "Zurückgegeben"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:67
|
#: InvenTree/status_codes.py:126
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:68
|
#: InvenTree/status_codes.py:127
|
||||||
msgid "Attention needed"
|
msgid "Attention needed"
|
||||||
msgstr "erfordert Eingriff"
|
msgstr "erfordert Eingriff"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:69
|
#: InvenTree/status_codes.py:128
|
||||||
msgid "Damaged"
|
msgid "Damaged"
|
||||||
msgstr "Beschädigt"
|
msgstr "Beschädigt"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:70
|
#: InvenTree/status_codes.py:129
|
||||||
msgid "Destroyed"
|
msgid "Destroyed"
|
||||||
msgstr "Zerstört"
|
msgstr "Zerstört"
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:98 build/templates/build/allocate_edit.html:28
|
#: InvenTree/status_codes.py:163 build/templates/build/allocate_edit.html:28
|
||||||
#: build/templates/build/allocate_view.html:21
|
#: build/templates/build/allocate_view.html:21
|
||||||
#: part/templates/part/part_base.html:109 part/templates/part/tabs.html:21
|
#: part/templates/part/part_base.html:114 part/templates/part/tabs.html:21
|
||||||
msgid "Allocated"
|
msgid "Allocated"
|
||||||
msgstr "Zugeordnet"
|
msgstr "Zugeordnet"
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ msgstr ""
|
|||||||
msgid "Number of parts to build"
|
msgid "Number of parts to build"
|
||||||
msgstr "Anzahl der zu bauenden Teile"
|
msgstr "Anzahl der zu bauenden Teile"
|
||||||
|
|
||||||
#: build/models.py:82
|
#: build/models.py:82 templates/table_filters.html:42
|
||||||
msgid "Build status"
|
msgid "Build status"
|
||||||
msgstr "Bau-Status"
|
msgstr "Bau-Status"
|
||||||
|
|
||||||
@ -231,10 +231,10 @@ msgstr "Zuweisung aufheben"
|
|||||||
|
|
||||||
#: build/templates/build/allocate_edit.html:19
|
#: build/templates/build/allocate_edit.html:19
|
||||||
#: build/templates/build/allocate_view.html:17
|
#: build/templates/build/allocate_view.html:17
|
||||||
#: build/templates/build/detail.html:21
|
#: build/templates/build/detail.html:22
|
||||||
#: company/templates/company/detail_part.html:65
|
#: company/templates/company/detail_part.html:65
|
||||||
#: order/templates/order/order_wizard/select_parts.html:30
|
#: order/templates/order/order_wizard/select_parts.html:30
|
||||||
#: order/templates/order/purchase_order_detail.html:25
|
#: order/templates/order/purchase_order_detail.html:26
|
||||||
#: part/templates/part/part_app_base.html:7
|
#: part/templates/part/part_app_base.html:7
|
||||||
msgid "Part"
|
msgid "Part"
|
||||||
msgstr "Teil"
|
msgstr "Teil"
|
||||||
@ -266,16 +266,62 @@ msgstr "Teile bestellen"
|
|||||||
#: company/templates/company/index.html:54
|
#: company/templates/company/index.html:54
|
||||||
#: company/templates/company/supplier_part_base.html:50
|
#: company/templates/company/supplier_part_base.html:50
|
||||||
#: company/templates/company/supplier_part_detail.html:27
|
#: company/templates/company/supplier_part_detail.html:27
|
||||||
#: order/templates/order/purchase_order_detail.html:26
|
#: order/templates/order/purchase_order_detail.html:27
|
||||||
#: part/templates/part/detail.html:38
|
#: part/templates/part/detail.html:38
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Beschreibung"
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
#: build/templates/build/allocate_view.html:22
|
#: build/templates/build/allocate_view.html:22
|
||||||
#: part/templates/part/part_base.html:115
|
#: part/templates/part/part_base.html:121
|
||||||
msgid "On Order"
|
msgid "On Order"
|
||||||
msgstr "bestellt"
|
msgstr "bestellt"
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:27 part/templates/part/tabs.html:28
|
||||||
|
#: stock/templates/stock/item_base.html:122 templates/navbar.html:12
|
||||||
|
msgid "Build"
|
||||||
|
msgstr "Bau"
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:52 build/templates/build/detail.html:9
|
||||||
|
msgid "Build Details"
|
||||||
|
msgstr "Bau-Status"
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:56
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Build Notes"
|
||||||
|
msgid "Build Title"
|
||||||
|
msgstr "Bau-Bemerkungen"
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:66
|
||||||
|
#: build/templates/build/detail.html:27
|
||||||
|
#: company/templates/company/supplier_part_pricing.html:27
|
||||||
|
#: order/templates/order/order_wizard/select_parts.html:32
|
||||||
|
#: order/templates/order/purchase_order_detail.html:30
|
||||||
|
#: stock/templates/stock/item_base.html:108
|
||||||
|
#: stock/templates/stock/stock_adjust.html:18
|
||||||
|
msgid "Quantity"
|
||||||
|
msgstr "Anzahl"
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:71
|
||||||
|
#: build/templates/build/detail.html:42
|
||||||
|
#: order/templates/order/order_base.html:72
|
||||||
|
#: stock/templates/stock/item_base.html:175
|
||||||
|
msgid "Status"
|
||||||
|
msgstr "Status"
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:76
|
||||||
|
msgid "BOM Price"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:81
|
||||||
|
msgid "BOM pricing is incomplete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:84
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Show pricing information"
|
||||||
|
msgid "No pricing information"
|
||||||
|
msgstr "Kosteninformationen ansehen"
|
||||||
|
|
||||||
#: build/templates/build/build_output.html:9
|
#: build/templates/build/build_output.html:9
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Build status"
|
#| msgid "Build status"
|
||||||
@ -289,68 +335,49 @@ msgid "Are you sure you want to unallocate these parts?"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Sind Sie sicher, dass sie die folgenden Zulieferer-Teile löschen möchten?"
|
"Sind Sie sicher, dass sie die folgenden Zulieferer-Teile löschen möchten?"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:8
|
#: build/templates/build/detail.html:17
|
||||||
msgid "Build Details"
|
|
||||||
msgstr "Bau-Status"
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:16
|
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:26
|
#: build/templates/build/detail.html:31
|
||||||
#: company/templates/company/supplier_part_pricing.html:27
|
|
||||||
#: order/templates/order/order_wizard/select_parts.html:32
|
|
||||||
#: order/templates/order/purchase_order_detail.html:29
|
|
||||||
#: stock/templates/stock/item_base.html:107
|
|
||||||
#: stock/templates/stock/stock_adjust.html:18
|
|
||||||
msgid "Quantity"
|
|
||||||
msgstr "Anzahl"
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:30
|
|
||||||
msgid "Stock Source"
|
msgid "Stock Source"
|
||||||
msgstr "Lagerobjekt"
|
msgstr "Lagerobjekt"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:35
|
#: build/templates/build/detail.html:36
|
||||||
msgid "Stock can be taken from any available location."
|
msgid "Stock can be taken from any available location."
|
||||||
msgstr "Bestand kann jedem verfügbaren Lagerort entnommen werden."
|
msgstr "Bestand kann jedem verfügbaren Lagerort entnommen werden."
|
||||||
|
|
||||||
#: build/templates/build/detail.html:41
|
#: build/templates/build/detail.html:48
|
||||||
#: order/templates/order/order_base.html:71
|
#: stock/templates/stock/item_base.html:115
|
||||||
#: stock/templates/stock/item_base.html:174
|
|
||||||
msgid "Status"
|
|
||||||
msgstr "Status"
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:47
|
|
||||||
#: stock/templates/stock/item_base.html:114
|
|
||||||
msgid "Batch"
|
msgid "Batch"
|
||||||
msgstr "Los"
|
msgstr "Los"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:54
|
#: build/templates/build/detail.html:55
|
||||||
#: company/templates/company/supplier_part_base.html:47
|
#: company/templates/company/supplier_part_base.html:47
|
||||||
#: company/templates/company/supplier_part_detail.html:24
|
#: company/templates/company/supplier_part_detail.html:24
|
||||||
#: part/templates/part/detail.html:67 part/templates/part/part_base.html:84
|
#: part/templates/part/detail.html:67 part/templates/part/part_base.html:85
|
||||||
#: stock/templates/stock/item_base.html:142
|
#: stock/templates/stock/item_base.html:143
|
||||||
msgid "External Link"
|
msgid "External Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:60
|
#: build/templates/build/detail.html:61
|
||||||
#: order/templates/order/order_base.html:83
|
#: order/templates/order/order_base.html:84
|
||||||
msgid "Created"
|
msgid "Created"
|
||||||
msgstr "Erstellt"
|
msgstr "Erstellt"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:66
|
#: build/templates/build/detail.html:67
|
||||||
msgid "Enough Parts?"
|
msgid "Enough Parts?"
|
||||||
msgstr "Genügend Teile?"
|
msgstr "Genügend Teile?"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:69
|
#: build/templates/build/detail.html:70
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Ja"
|
msgstr "Ja"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:71
|
#: build/templates/build/detail.html:72
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Nein"
|
msgstr "Nein"
|
||||||
|
|
||||||
#: build/templates/build/detail.html:79
|
#: build/templates/build/detail.html:80
|
||||||
msgid "Completed"
|
msgid "Completed"
|
||||||
msgstr "Fertig"
|
msgstr "Fertig"
|
||||||
|
|
||||||
@ -622,7 +649,7 @@ msgstr "Zulieferer auswählen"
|
|||||||
msgid "Supplier stock keeping unit"
|
msgid "Supplier stock keeping unit"
|
||||||
msgstr "Stock Keeping Units (SKU) des Zulieferers"
|
msgstr "Stock Keeping Units (SKU) des Zulieferers"
|
||||||
|
|
||||||
#: company/models.py:256 company/templates/company/detail_part.html:81
|
#: company/models.py:256 company/templates/company/detail_part.html:96
|
||||||
#: company/templates/company/supplier_part_base.html:53
|
#: company/templates/company/supplier_part_base.html:53
|
||||||
#: company/templates/company/supplier_part_detail.html:30
|
#: company/templates/company/supplier_part_detail.html:30
|
||||||
msgid "Manufacturer"
|
msgid "Manufacturer"
|
||||||
@ -680,7 +707,7 @@ msgid "Company Details"
|
|||||||
msgstr "Firmenbemerkungen"
|
msgstr "Firmenbemerkungen"
|
||||||
|
|
||||||
#: company/templates/company/detail.html:16
|
#: company/templates/company/detail.html:16
|
||||||
#: stock/templates/stock/item_base.html:135
|
#: stock/templates/stock/item_base.html:136
|
||||||
msgid "Customer"
|
msgid "Customer"
|
||||||
msgstr "Kunde"
|
msgstr "Kunde"
|
||||||
|
|
||||||
@ -688,9 +715,9 @@ msgstr "Kunde"
|
|||||||
#: company/templates/company/index.html:46
|
#: company/templates/company/index.html:46
|
||||||
#: company/templates/company/supplier_part_base.html:44
|
#: company/templates/company/supplier_part_base.html:44
|
||||||
#: company/templates/company/supplier_part_detail.html:21
|
#: company/templates/company/supplier_part_detail.html:21
|
||||||
#: order/templates/order/order_base.html:66
|
#: order/templates/order/order_base.html:67
|
||||||
#: order/templates/order/order_wizard/select_pos.html:30
|
#: order/templates/order/order_wizard/select_pos.html:30
|
||||||
#: stock/templates/stock/item_base.html:149
|
#: stock/templates/stock/item_base.html:150
|
||||||
msgid "Supplier"
|
msgid "Supplier"
|
||||||
msgstr "Zulieferer"
|
msgstr "Zulieferer"
|
||||||
|
|
||||||
@ -716,13 +743,13 @@ msgstr ""
|
|||||||
msgid "Delete Parts"
|
msgid "Delete Parts"
|
||||||
msgstr "Anhang löschen"
|
msgstr "Anhang löschen"
|
||||||
|
|
||||||
#: company/templates/company/detail_part.html:73
|
#: company/templates/company/detail_part.html:88
|
||||||
#: company/templates/company/supplier_part_base.html:45
|
#: company/templates/company/supplier_part_base.html:45
|
||||||
#: company/templates/company/supplier_part_detail.html:22
|
#: company/templates/company/supplier_part_detail.html:22
|
||||||
msgid "SKU"
|
msgid "SKU"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail_part.html:90
|
#: company/templates/company/detail_part.html:105
|
||||||
msgid "Link"
|
msgid "Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -783,7 +810,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: company/templates/company/supplier_part_base.html:6
|
#: company/templates/company/supplier_part_base.html:6
|
||||||
#: company/templates/company/supplier_part_base.html:13
|
#: company/templates/company/supplier_part_base.html:13
|
||||||
#: stock/templates/stock/item_base.html:154
|
#: stock/templates/stock/item_base.html:155
|
||||||
msgid "Supplier Part"
|
msgid "Supplier Part"
|
||||||
msgstr "Zulieferer-Teil"
|
msgstr "Zulieferer-Teil"
|
||||||
|
|
||||||
@ -810,7 +837,7 @@ msgstr "IPN (Interne Produktnummer)"
|
|||||||
|
|
||||||
#: company/templates/company/supplier_part_base.html:57
|
#: company/templates/company/supplier_part_base.html:57
|
||||||
#: company/templates/company/supplier_part_detail.html:34
|
#: company/templates/company/supplier_part_detail.html:34
|
||||||
#: order/templates/order/purchase_order_detail.html:33
|
#: order/templates/order/purchase_order_detail.html:34
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr "Notiz"
|
msgstr "Notiz"
|
||||||
|
|
||||||
@ -1030,7 +1057,7 @@ msgstr "Position - Referenz"
|
|||||||
msgid "Line item notes"
|
msgid "Line item notes"
|
||||||
msgstr "Position - Notizen"
|
msgstr "Position - Notizen"
|
||||||
|
|
||||||
#: order/models.py:298 stock/templates/stock/item_base.html:128
|
#: order/models.py:298 stock/templates/stock/item_base.html:129
|
||||||
msgid "Purchase Order"
|
msgid "Purchase Order"
|
||||||
msgstr "Kaufvertrag"
|
msgstr "Kaufvertrag"
|
||||||
|
|
||||||
@ -1042,16 +1069,16 @@ msgstr "Zulieferer-Teil"
|
|||||||
msgid "Number of items received"
|
msgid "Number of items received"
|
||||||
msgstr "Empfangene Objekt-Anzahl"
|
msgstr "Empfangene Objekt-Anzahl"
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:61
|
#: order/templates/order/order_base.html:62
|
||||||
msgid "Purchase Order Details"
|
msgid "Purchase Order Details"
|
||||||
msgstr "Bestelldetails"
|
msgstr "Bestelldetails"
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:89
|
#: order/templates/order/order_base.html:90
|
||||||
msgid "Issued"
|
msgid "Issued"
|
||||||
msgstr "Aufgegeben"
|
msgstr "Aufgegeben"
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:96
|
#: order/templates/order/order_base.html:97
|
||||||
#: order/templates/order/purchase_order_detail.html:31
|
#: order/templates/order/purchase_order_detail.html:32
|
||||||
msgid "Received"
|
msgid "Received"
|
||||||
msgstr "Empfangen"
|
msgstr "Empfangen"
|
||||||
|
|
||||||
@ -1152,23 +1179,23 @@ msgid "Are you sure you want to delete this attachment?"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Sind Sie sicher, dass sie die folgenden Zulieferer-Teile löschen möchten?"
|
"Sind Sie sicher, dass sie die folgenden Zulieferer-Teile löschen möchten?"
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:15 order/views.py:825
|
#: order/templates/order/purchase_order_detail.html:16 order/views.py:825
|
||||||
msgid "Add Line Item"
|
msgid "Add Line Item"
|
||||||
msgstr "Position hinzufügen"
|
msgstr "Position hinzufügen"
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:19
|
#: order/templates/order/purchase_order_detail.html:20
|
||||||
msgid "Order Items"
|
msgid "Order Items"
|
||||||
msgstr "Bestellungspositionen"
|
msgstr "Bestellungspositionen"
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:24
|
#: order/templates/order/purchase_order_detail.html:25
|
||||||
msgid "Line"
|
msgid "Line"
|
||||||
msgstr "Position"
|
msgstr "Position"
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:27
|
#: order/templates/order/purchase_order_detail.html:28
|
||||||
msgid "Order Code"
|
msgid "Order Code"
|
||||||
msgstr "Bestellnummer"
|
msgstr "Bestellnummer"
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:28
|
#: order/templates/order/purchase_order_detail.html:29
|
||||||
msgid "Reference"
|
msgid "Reference"
|
||||||
msgstr "Referenz"
|
msgstr "Referenz"
|
||||||
|
|
||||||
@ -1475,63 +1502,63 @@ msgstr "Bemerkungen - unterstüzt Markdown-Formatierung"
|
|||||||
msgid "Stored BOM checksum"
|
msgid "Stored BOM checksum"
|
||||||
msgstr "Prüfsumme der Stückliste gespeichert"
|
msgstr "Prüfsumme der Stückliste gespeichert"
|
||||||
|
|
||||||
#: part/models.py:1040
|
#: part/models.py:1049
|
||||||
msgid "Parameter template name must be unique"
|
msgid "Parameter template name must be unique"
|
||||||
msgstr "Vorlagen-Name des Parameters muss eindeutig sein"
|
msgstr "Vorlagen-Name des Parameters muss eindeutig sein"
|
||||||
|
|
||||||
#: part/models.py:1045
|
#: part/models.py:1054
|
||||||
msgid "Parameter Name"
|
msgid "Parameter Name"
|
||||||
msgstr "Name des Parameters"
|
msgstr "Name des Parameters"
|
||||||
|
|
||||||
#: part/models.py:1047
|
#: part/models.py:1056
|
||||||
msgid "Parameter Units"
|
msgid "Parameter Units"
|
||||||
msgstr "Parameter Einheit"
|
msgstr "Parameter Einheit"
|
||||||
|
|
||||||
#: part/models.py:1073
|
#: part/models.py:1082
|
||||||
msgid "Parent Part"
|
msgid "Parent Part"
|
||||||
msgstr "Ausgangsteil"
|
msgstr "Ausgangsteil"
|
||||||
|
|
||||||
#: part/models.py:1075
|
#: part/models.py:1084
|
||||||
msgid "Parameter Template"
|
msgid "Parameter Template"
|
||||||
msgstr "Parameter Vorlage"
|
msgstr "Parameter Vorlage"
|
||||||
|
|
||||||
#: part/models.py:1077
|
#: part/models.py:1086
|
||||||
msgid "Parameter Value"
|
msgid "Parameter Value"
|
||||||
msgstr "Parameter Wert"
|
msgstr "Parameter Wert"
|
||||||
|
|
||||||
#: part/models.py:1101
|
#: part/models.py:1110
|
||||||
msgid "Select parent part"
|
msgid "Select parent part"
|
||||||
msgstr "Ausgangsteil auswählen"
|
msgstr "Ausgangsteil auswählen"
|
||||||
|
|
||||||
#: part/models.py:1110
|
#: part/models.py:1119
|
||||||
msgid "Select part to be used in BOM"
|
msgid "Select part to be used in BOM"
|
||||||
msgstr "Teil für die Nutzung in der Stückliste auswählen"
|
msgstr "Teil für die Nutzung in der Stückliste auswählen"
|
||||||
|
|
||||||
#: part/models.py:1117
|
#: part/models.py:1126
|
||||||
msgid "BOM quantity for this BOM item"
|
msgid "BOM quantity for this BOM item"
|
||||||
msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil"
|
msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil"
|
||||||
|
|
||||||
#: part/models.py:1120
|
#: part/models.py:1129
|
||||||
msgid "Estimated build wastage quantity (absolute or percentage)"
|
msgid "Estimated build wastage quantity (absolute or percentage)"
|
||||||
msgstr "Geschätzter Ausschuss (absolut oder prozentual)"
|
msgstr "Geschätzter Ausschuss (absolut oder prozentual)"
|
||||||
|
|
||||||
#: part/models.py:1123
|
#: part/models.py:1132
|
||||||
msgid "BOM item reference"
|
msgid "BOM item reference"
|
||||||
msgstr "Referenz des Objekts auf der Stückliste"
|
msgstr "Referenz des Objekts auf der Stückliste"
|
||||||
|
|
||||||
#: part/models.py:1126
|
#: part/models.py:1135
|
||||||
msgid "BOM item notes"
|
msgid "BOM item notes"
|
||||||
msgstr "Notizen zum Stücklisten-Objekt"
|
msgstr "Notizen zum Stücklisten-Objekt"
|
||||||
|
|
||||||
#: part/models.py:1128
|
#: part/models.py:1137
|
||||||
msgid "BOM line checksum"
|
msgid "BOM line checksum"
|
||||||
msgstr "Prüfsumme der Stückliste"
|
msgstr "Prüfsumme der Stückliste"
|
||||||
|
|
||||||
#: part/models.py:1191
|
#: part/models.py:1200
|
||||||
msgid "Part cannot be added to its own Bill of Materials"
|
msgid "Part cannot be added to its own Bill of Materials"
|
||||||
msgstr "Teil kann nicht zu seiner eigenen Stückliste hinzugefügt werden"
|
msgstr "Teil kann nicht zu seiner eigenen Stückliste hinzugefügt werden"
|
||||||
|
|
||||||
#: part/models.py:1198
|
#: part/models.py:1207
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
|
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
|
||||||
msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)"
|
msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)"
|
||||||
@ -1581,7 +1608,7 @@ msgstr "Teile (inklusive Unter-Kategorien)"
|
|||||||
msgid "Part Details"
|
msgid "Part Details"
|
||||||
msgstr "Teile-Details"
|
msgstr "Teile-Details"
|
||||||
|
|
||||||
#: part/templates/part/detail.html:25 part/templates/part/part_base.html:77
|
#: part/templates/part/detail.html:25 part/templates/part/part_base.html:78
|
||||||
msgid "IPN"
|
msgid "IPN"
|
||||||
msgstr "IPN (Interne Produktnummer)"
|
msgstr "IPN (Interne Produktnummer)"
|
||||||
|
|
||||||
@ -1637,7 +1664,7 @@ msgstr "Teil ist virtuell (kein physisches Teil)"
|
|||||||
msgid "Part is not a virtual part"
|
msgid "Part is not a virtual part"
|
||||||
msgstr "Teil ist nicht virtuell"
|
msgstr "Teil ist nicht virtuell"
|
||||||
|
|
||||||
#: part/templates/part/detail.html:132
|
#: part/templates/part/detail.html:132 templates/table_filters.html:86
|
||||||
msgid "Assembly"
|
msgid "Assembly"
|
||||||
msgstr "Baugruppe"
|
msgstr "Baugruppe"
|
||||||
|
|
||||||
@ -1649,7 +1676,7 @@ msgstr "Teil kann aus anderen Teilen angefertigt werden"
|
|||||||
msgid "Part cannot be assembled from other parts"
|
msgid "Part cannot be assembled from other parts"
|
||||||
msgstr "Teil kann nicht aus anderen Teilen angefertigt werden"
|
msgstr "Teil kann nicht aus anderen Teilen angefertigt werden"
|
||||||
|
|
||||||
#: part/templates/part/detail.html:141
|
#: part/templates/part/detail.html:141 templates/table_filters.html:90
|
||||||
msgid "Component"
|
msgid "Component"
|
||||||
msgstr "Komponente"
|
msgstr "Komponente"
|
||||||
|
|
||||||
@ -1713,31 +1740,47 @@ msgstr "Teile"
|
|||||||
msgid "This part is not active"
|
msgid "This part is not active"
|
||||||
msgstr "Dieses Teil ist nicht aktiv"
|
msgstr "Dieses Teil ist nicht aktiv"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:37
|
#: part/templates/part/part_base.html:16
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Is this part a template part?"
|
||||||
|
msgid "This part is a template part."
|
||||||
|
msgstr "Ist dieses Teil eine Vorlage?"
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:18
|
||||||
|
msgid "It is not a real part, but real parts can be based on this template."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:23
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "This part is not active"
|
||||||
|
msgid "This part is a variant of"
|
||||||
|
msgstr "Dieses Teil ist nicht aktiv"
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:38
|
||||||
msgid "Star this part"
|
msgid "Star this part"
|
||||||
msgstr "Teil favorisieren"
|
msgstr "Teil favorisieren"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:43
|
#: part/templates/part/part_base.html:44
|
||||||
msgid "Show pricing information"
|
msgid "Show pricing information"
|
||||||
msgstr "Kosteninformationen ansehen"
|
msgstr "Kosteninformationen ansehen"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:98
|
#: part/templates/part/part_base.html:101
|
||||||
msgid "Available Stock"
|
msgid "Available Stock"
|
||||||
msgstr "Verfügbarer Lagerbestand"
|
msgstr "Verfügbarer Lagerbestand"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:103
|
#: part/templates/part/part_base.html:107
|
||||||
msgid "In Stock"
|
msgid "In Stock"
|
||||||
msgstr "Auf Lager"
|
msgstr "Auf Lager"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:124
|
#: part/templates/part/part_base.html:131
|
||||||
msgid "Build Status"
|
msgid "Build Status"
|
||||||
msgstr "Bau-Status"
|
msgstr "Bau-Status"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:128
|
#: part/templates/part/part_base.html:136
|
||||||
msgid "Can Build"
|
msgid "Can Build"
|
||||||
msgstr "Herstellbar?"
|
msgstr "Herstellbar?"
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:133
|
#: part/templates/part/part_base.html:142
|
||||||
msgid "Underway"
|
msgid "Underway"
|
||||||
msgstr "unterwegs"
|
msgstr "unterwegs"
|
||||||
|
|
||||||
@ -1787,11 +1830,6 @@ msgstr "Varianten"
|
|||||||
msgid "BOM"
|
msgid "BOM"
|
||||||
msgstr "Stückliste"
|
msgstr "Stückliste"
|
||||||
|
|
||||||
#: part/templates/part/tabs.html:28 stock/templates/stock/item_base.html:121
|
|
||||||
#: templates/navbar.html:12
|
|
||||||
msgid "Build"
|
|
||||||
msgstr "Bau"
|
|
||||||
|
|
||||||
#: part/templates/part/tabs.html:32
|
#: part/templates/part/tabs.html:32
|
||||||
msgid "Used In"
|
msgid "Used In"
|
||||||
msgstr "Benutzt in"
|
msgstr "Benutzt in"
|
||||||
@ -2164,11 +2202,11 @@ msgstr "Link auf externe Seite für weitere Informationen"
|
|||||||
msgid "Stock Tracking Information"
|
msgid "Stock Tracking Information"
|
||||||
msgstr "Informationen zum Lagerbestands-Tracking"
|
msgstr "Informationen zum Lagerbestands-Tracking"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:10
|
#: stock/templates/stock/item_base.html:11
|
||||||
msgid "Stock Item Details"
|
msgid "Stock Item Details"
|
||||||
msgstr "Lagerbestands-Details"
|
msgstr "Lagerbestands-Details"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:55
|
#: stock/templates/stock/item_base.html:56
|
||||||
msgid ""
|
msgid ""
|
||||||
"This stock item is serialized - it has a unique serial number and the "
|
"This stock item is serialized - it has a unique serial number and the "
|
||||||
"quantity cannot be adjusted."
|
"quantity cannot be adjusted."
|
||||||
@ -2176,45 +2214,45 @@ msgstr ""
|
|||||||
"Dieses Lagerobjekt ist serialisiert. Es hat eine eindeutige Seriennummer und "
|
"Dieses Lagerobjekt ist serialisiert. Es hat eine eindeutige Seriennummer und "
|
||||||
"die Anzahl kann nicht angepasst werden."
|
"die Anzahl kann nicht angepasst werden."
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:59
|
#: stock/templates/stock/item_base.html:60
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Stock item cannot be created for a template Part"
|
#| msgid "Stock item cannot be created for a template Part"
|
||||||
msgid "This stock item cannot be deleted as it has child items"
|
msgid "This stock item cannot be deleted as it has child items"
|
||||||
msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden"
|
msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:63
|
#: stock/templates/stock/item_base.html:64
|
||||||
msgid ""
|
msgid ""
|
||||||
"This stock item will be automatically deleted when all stock is depleted."
|
"This stock item will be automatically deleted when all stock is depleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Dieses Lagerobjekt wird automatisch gelöscht wenn der Lagerbestand "
|
"Dieses Lagerobjekt wird automatisch gelöscht wenn der Lagerbestand "
|
||||||
"aufgebraucht ist."
|
"aufgebraucht ist."
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:68
|
#: stock/templates/stock/item_base.html:69
|
||||||
msgid "This stock item was split from "
|
msgid "This stock item was split from "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:88
|
#: stock/templates/stock/item_base.html:89
|
||||||
msgid "Belongs To"
|
msgid "Belongs To"
|
||||||
msgstr "Gehört zu"
|
msgstr "Gehört zu"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:94
|
#: stock/templates/stock/item_base.html:95
|
||||||
#: stock/templates/stock/stock_adjust.html:17
|
#: stock/templates/stock/stock_adjust.html:17
|
||||||
msgid "Location"
|
msgid "Location"
|
||||||
msgstr "Standort"
|
msgstr "Standort"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:101
|
#: stock/templates/stock/item_base.html:102
|
||||||
msgid "Serial Number"
|
msgid "Serial Number"
|
||||||
msgstr "Seriennummer"
|
msgstr "Seriennummer"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:160
|
#: stock/templates/stock/item_base.html:161
|
||||||
msgid "Last Updated"
|
msgid "Last Updated"
|
||||||
msgstr "Zuletzt aktualisiert"
|
msgstr "Zuletzt aktualisiert"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:165
|
#: stock/templates/stock/item_base.html:166
|
||||||
msgid "Last Stocktake"
|
msgid "Last Stocktake"
|
||||||
msgstr "Letzte Inventur"
|
msgstr "Letzte Inventur"
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:169
|
#: stock/templates/stock/item_base.html:170
|
||||||
msgid "No stocktake performed"
|
msgid "No stocktake performed"
|
||||||
msgstr "Keine Inventur ausgeführt"
|
msgstr "Keine Inventur ausgeführt"
|
||||||
|
|
||||||
@ -2540,6 +2578,80 @@ msgstr "bestellt"
|
|||||||
msgid "Delete Stock"
|
msgid "Delete Stock"
|
||||||
msgstr "Lagerobjekt löschen"
|
msgstr "Lagerobjekt löschen"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:22
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Include stock items in sub locations"
|
||||||
|
msgid "Include sublocations"
|
||||||
|
msgstr "Lagerobjekte in untergeordneten Lagerorten einschließen"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:23
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Include stock items in sub locations"
|
||||||
|
msgid "Include stock in sublocations"
|
||||||
|
msgstr "Lagerobjekte in untergeordneten Lagerorten einschließen"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:27
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Required Parts"
|
||||||
|
msgid "Active parts"
|
||||||
|
msgstr "benötigte Teile"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:28
|
||||||
|
msgid "Show stock for active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:32 templates/table_filters.html:33
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Stock Details"
|
||||||
|
msgid "Stock status"
|
||||||
|
msgstr "Objekt-Details"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:53
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Order Parts"
|
||||||
|
msgid "Order status"
|
||||||
|
msgstr "Teile bestellen"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:64
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Parts (Including subcategories)"
|
||||||
|
msgid "Include subcategories"
|
||||||
|
msgstr "Teile (inklusive Unter-Kategorien)"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:65
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Parts (Including subcategories)"
|
||||||
|
msgid "Include parts in subcategories"
|
||||||
|
msgstr "Teile (inklusive Unter-Kategorien)"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:69
|
||||||
|
msgid "Active"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:70
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Build to allocate parts"
|
||||||
|
msgid "Show active parts"
|
||||||
|
msgstr "Bau starten um Teile zuzuweisen"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:74
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Parameter Template"
|
||||||
|
msgid "Template"
|
||||||
|
msgstr "Parameter Vorlage"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:78
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Available"
|
||||||
|
msgid "Stock available"
|
||||||
|
msgstr "verfügbar"
|
||||||
|
|
||||||
|
#: templates/table_filters.html:82
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Stock"
|
||||||
|
msgid "Low stock"
|
||||||
|
msgstr "Lagerbestand"
|
||||||
|
|
||||||
#~ msgid "URL"
|
#~ msgid "URL"
|
||||||
#~ msgstr "URL"
|
#~ msgstr "URL"
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-04-09 15:04+0000\n"
|
"POT-Creation-Date: 2020-04-11 15:00+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,30 +18,30 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:240 order/models.py:164 order/models.py:215
|
#: InvenTree/helpers.py:259 order/models.py:164 order/models.py:215
|
||||||
msgid "Invalid quantity provided"
|
msgid "Invalid quantity provided"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:243
|
#: InvenTree/helpers.py:262
|
||||||
msgid "Empty serial number string"
|
msgid "Empty serial number string"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:264 InvenTree/helpers.py:281
|
#: InvenTree/helpers.py:283 InvenTree/helpers.py:300
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Duplicate serial: {n}"
|
msgid "Duplicate serial: {n}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:268 InvenTree/helpers.py:271 InvenTree/helpers.py:274
|
#: InvenTree/helpers.py:287 InvenTree/helpers.py:290 InvenTree/helpers.py:293
|
||||||
#: InvenTree/helpers.py:285
|
#: InvenTree/helpers.py:304
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Invalid group: {g}"
|
msgid "Invalid group: {g}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:291
|
#: InvenTree/helpers.py:310
|
||||||
msgid "No serial numbers found"
|
msgid "No serial numbers found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:295
|
#: InvenTree/helpers.py:314
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Number of unique serial number ({s}) must match quantity ({q})"
|
msgid "Number of unique serial number ({s}) must match quantity ({q})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -70,49 +70,49 @@ msgstr ""
|
|||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:36 InvenTree/status_codes.py:97
|
#: InvenTree/status_codes.py:86 InvenTree/status_codes.py:162
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:37
|
#: InvenTree/status_codes.py:87
|
||||||
msgid "Placed"
|
msgid "Placed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:38 InvenTree/status_codes.py:100
|
#: InvenTree/status_codes.py:88 InvenTree/status_codes.py:165
|
||||||
msgid "Complete"
|
msgid "Complete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:39 InvenTree/status_codes.py:99
|
#: InvenTree/status_codes.py:89 InvenTree/status_codes.py:164
|
||||||
msgid "Cancelled"
|
msgid "Cancelled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71
|
#: InvenTree/status_codes.py:90 InvenTree/status_codes.py:130
|
||||||
msgid "Lost"
|
msgid "Lost"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:41
|
#: InvenTree/status_codes.py:91
|
||||||
msgid "Returned"
|
msgid "Returned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:67
|
#: InvenTree/status_codes.py:126
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:68
|
#: InvenTree/status_codes.py:127
|
||||||
msgid "Attention needed"
|
msgid "Attention needed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:69
|
#: InvenTree/status_codes.py:128
|
||||||
msgid "Damaged"
|
msgid "Damaged"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:70
|
#: InvenTree/status_codes.py:129
|
||||||
msgid "Destroyed"
|
msgid "Destroyed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:98 build/templates/build/allocate_edit.html:28
|
#: InvenTree/status_codes.py:163 build/templates/build/allocate_edit.html:28
|
||||||
#: build/templates/build/allocate_view.html:21
|
#: build/templates/build/allocate_view.html:21
|
||||||
#: part/templates/part/part_base.html:109 part/templates/part/tabs.html:21
|
#: part/templates/part/part_base.html:114 part/templates/part/tabs.html:21
|
||||||
msgid "Allocated"
|
msgid "Allocated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ msgstr ""
|
|||||||
msgid "Number of parts to build"
|
msgid "Number of parts to build"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/models.py:82
|
#: build/models.py:82 templates/table_filters.html:42
|
||||||
msgid "Build status"
|
msgid "Build status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -227,10 +227,10 @@ msgstr ""
|
|||||||
|
|
||||||
#: build/templates/build/allocate_edit.html:19
|
#: build/templates/build/allocate_edit.html:19
|
||||||
#: build/templates/build/allocate_view.html:17
|
#: build/templates/build/allocate_view.html:17
|
||||||
#: build/templates/build/detail.html:21
|
#: build/templates/build/detail.html:22
|
||||||
#: company/templates/company/detail_part.html:65
|
#: company/templates/company/detail_part.html:65
|
||||||
#: order/templates/order/order_wizard/select_parts.html:30
|
#: order/templates/order/order_wizard/select_parts.html:30
|
||||||
#: order/templates/order/purchase_order_detail.html:25
|
#: order/templates/order/purchase_order_detail.html:26
|
||||||
#: part/templates/part/part_app_base.html:7
|
#: part/templates/part/part_app_base.html:7
|
||||||
msgid "Part"
|
msgid "Part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -262,16 +262,58 @@ msgstr ""
|
|||||||
#: company/templates/company/index.html:54
|
#: company/templates/company/index.html:54
|
||||||
#: company/templates/company/supplier_part_base.html:50
|
#: company/templates/company/supplier_part_base.html:50
|
||||||
#: company/templates/company/supplier_part_detail.html:27
|
#: company/templates/company/supplier_part_detail.html:27
|
||||||
#: order/templates/order/purchase_order_detail.html:26
|
#: order/templates/order/purchase_order_detail.html:27
|
||||||
#: part/templates/part/detail.html:38
|
#: part/templates/part/detail.html:38
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/allocate_view.html:22
|
#: build/templates/build/allocate_view.html:22
|
||||||
#: part/templates/part/part_base.html:115
|
#: part/templates/part/part_base.html:121
|
||||||
msgid "On Order"
|
msgid "On Order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:27 part/templates/part/tabs.html:28
|
||||||
|
#: stock/templates/stock/item_base.html:122 templates/navbar.html:12
|
||||||
|
msgid "Build"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:52 build/templates/build/detail.html:9
|
||||||
|
msgid "Build Details"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:56
|
||||||
|
msgid "Build Title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:66
|
||||||
|
#: build/templates/build/detail.html:27
|
||||||
|
#: company/templates/company/supplier_part_pricing.html:27
|
||||||
|
#: order/templates/order/order_wizard/select_parts.html:32
|
||||||
|
#: order/templates/order/purchase_order_detail.html:30
|
||||||
|
#: stock/templates/stock/item_base.html:108
|
||||||
|
#: stock/templates/stock/stock_adjust.html:18
|
||||||
|
msgid "Quantity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:71
|
||||||
|
#: build/templates/build/detail.html:42
|
||||||
|
#: order/templates/order/order_base.html:72
|
||||||
|
#: stock/templates/stock/item_base.html:175
|
||||||
|
msgid "Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:76
|
||||||
|
msgid "BOM Price"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:81
|
||||||
|
msgid "BOM pricing is incomplete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:84
|
||||||
|
msgid "No pricing information"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/build_output.html:9
|
#: build/templates/build/build_output.html:9
|
||||||
msgid "Build Outputs"
|
msgid "Build Outputs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -280,68 +322,49 @@ msgstr ""
|
|||||||
msgid "Are you sure you want to unallocate these parts?"
|
msgid "Are you sure you want to unallocate these parts?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:8
|
#: build/templates/build/detail.html:17
|
||||||
msgid "Build Details"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:16
|
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:26
|
#: build/templates/build/detail.html:31
|
||||||
#: company/templates/company/supplier_part_pricing.html:27
|
|
||||||
#: order/templates/order/order_wizard/select_parts.html:32
|
|
||||||
#: order/templates/order/purchase_order_detail.html:29
|
|
||||||
#: stock/templates/stock/item_base.html:107
|
|
||||||
#: stock/templates/stock/stock_adjust.html:18
|
|
||||||
msgid "Quantity"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:30
|
|
||||||
msgid "Stock Source"
|
msgid "Stock Source"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:35
|
#: build/templates/build/detail.html:36
|
||||||
msgid "Stock can be taken from any available location."
|
msgid "Stock can be taken from any available location."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:41
|
#: build/templates/build/detail.html:48
|
||||||
#: order/templates/order/order_base.html:71
|
#: stock/templates/stock/item_base.html:115
|
||||||
#: stock/templates/stock/item_base.html:174
|
|
||||||
msgid "Status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:47
|
|
||||||
#: stock/templates/stock/item_base.html:114
|
|
||||||
msgid "Batch"
|
msgid "Batch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:54
|
#: build/templates/build/detail.html:55
|
||||||
#: company/templates/company/supplier_part_base.html:47
|
#: company/templates/company/supplier_part_base.html:47
|
||||||
#: company/templates/company/supplier_part_detail.html:24
|
#: company/templates/company/supplier_part_detail.html:24
|
||||||
#: part/templates/part/detail.html:67 part/templates/part/part_base.html:84
|
#: part/templates/part/detail.html:67 part/templates/part/part_base.html:85
|
||||||
#: stock/templates/stock/item_base.html:142
|
#: stock/templates/stock/item_base.html:143
|
||||||
msgid "External Link"
|
msgid "External Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:60
|
#: build/templates/build/detail.html:61
|
||||||
#: order/templates/order/order_base.html:83
|
#: order/templates/order/order_base.html:84
|
||||||
msgid "Created"
|
msgid "Created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:66
|
#: build/templates/build/detail.html:67
|
||||||
msgid "Enough Parts?"
|
msgid "Enough Parts?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:69
|
#: build/templates/build/detail.html:70
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:71
|
#: build/templates/build/detail.html:72
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:79
|
#: build/templates/build/detail.html:80
|
||||||
msgid "Completed"
|
msgid "Completed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -581,7 +604,7 @@ msgstr ""
|
|||||||
msgid "Supplier stock keeping unit"
|
msgid "Supplier stock keeping unit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/models.py:256 company/templates/company/detail_part.html:81
|
#: company/models.py:256 company/templates/company/detail_part.html:96
|
||||||
#: company/templates/company/supplier_part_base.html:53
|
#: company/templates/company/supplier_part_base.html:53
|
||||||
#: company/templates/company/supplier_part_detail.html:30
|
#: company/templates/company/supplier_part_detail.html:30
|
||||||
msgid "Manufacturer"
|
msgid "Manufacturer"
|
||||||
@ -637,7 +660,7 @@ msgid "Company Details"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail.html:16
|
#: company/templates/company/detail.html:16
|
||||||
#: stock/templates/stock/item_base.html:135
|
#: stock/templates/stock/item_base.html:136
|
||||||
msgid "Customer"
|
msgid "Customer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -645,9 +668,9 @@ msgstr ""
|
|||||||
#: company/templates/company/index.html:46
|
#: company/templates/company/index.html:46
|
||||||
#: company/templates/company/supplier_part_base.html:44
|
#: company/templates/company/supplier_part_base.html:44
|
||||||
#: company/templates/company/supplier_part_detail.html:21
|
#: company/templates/company/supplier_part_detail.html:21
|
||||||
#: order/templates/order/order_base.html:66
|
#: order/templates/order/order_base.html:67
|
||||||
#: order/templates/order/order_wizard/select_pos.html:30
|
#: order/templates/order/order_wizard/select_pos.html:30
|
||||||
#: stock/templates/stock/item_base.html:149
|
#: stock/templates/stock/item_base.html:150
|
||||||
msgid "Supplier"
|
msgid "Supplier"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -669,13 +692,13 @@ msgstr ""
|
|||||||
msgid "Delete Parts"
|
msgid "Delete Parts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail_part.html:73
|
#: company/templates/company/detail_part.html:88
|
||||||
#: company/templates/company/supplier_part_base.html:45
|
#: company/templates/company/supplier_part_base.html:45
|
||||||
#: company/templates/company/supplier_part_detail.html:22
|
#: company/templates/company/supplier_part_detail.html:22
|
||||||
msgid "SKU"
|
msgid "SKU"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail_part.html:90
|
#: company/templates/company/detail_part.html:105
|
||||||
msgid "Link"
|
msgid "Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -727,7 +750,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: company/templates/company/supplier_part_base.html:6
|
#: company/templates/company/supplier_part_base.html:6
|
||||||
#: company/templates/company/supplier_part_base.html:13
|
#: company/templates/company/supplier_part_base.html:13
|
||||||
#: stock/templates/stock/item_base.html:154
|
#: stock/templates/stock/item_base.html:155
|
||||||
msgid "Supplier Part"
|
msgid "Supplier Part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -748,7 +771,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: company/templates/company/supplier_part_base.html:57
|
#: company/templates/company/supplier_part_base.html:57
|
||||||
#: company/templates/company/supplier_part_detail.html:34
|
#: company/templates/company/supplier_part_detail.html:34
|
||||||
#: order/templates/order/purchase_order_detail.html:33
|
#: order/templates/order/purchase_order_detail.html:34
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -930,7 +953,7 @@ msgstr ""
|
|||||||
msgid "Line item notes"
|
msgid "Line item notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/models.py:298 stock/templates/stock/item_base.html:128
|
#: order/models.py:298 stock/templates/stock/item_base.html:129
|
||||||
msgid "Purchase Order"
|
msgid "Purchase Order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -942,16 +965,16 @@ msgstr ""
|
|||||||
msgid "Number of items received"
|
msgid "Number of items received"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:61
|
#: order/templates/order/order_base.html:62
|
||||||
msgid "Purchase Order Details"
|
msgid "Purchase Order Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:89
|
#: order/templates/order/order_base.html:90
|
||||||
msgid "Issued"
|
msgid "Issued"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:96
|
#: order/templates/order/order_base.html:97
|
||||||
#: order/templates/order/purchase_order_detail.html:31
|
#: order/templates/order/purchase_order_detail.html:32
|
||||||
msgid "Received"
|
msgid "Received"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1035,23 +1058,23 @@ msgstr ""
|
|||||||
msgid "Are you sure you want to delete this attachment?"
|
msgid "Are you sure you want to delete this attachment?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:15 order/views.py:825
|
#: order/templates/order/purchase_order_detail.html:16 order/views.py:825
|
||||||
msgid "Add Line Item"
|
msgid "Add Line Item"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:19
|
#: order/templates/order/purchase_order_detail.html:20
|
||||||
msgid "Order Items"
|
msgid "Order Items"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:24
|
#: order/templates/order/purchase_order_detail.html:25
|
||||||
msgid "Line"
|
msgid "Line"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:27
|
#: order/templates/order/purchase_order_detail.html:28
|
||||||
msgid "Order Code"
|
msgid "Order Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:28
|
#: order/templates/order/purchase_order_detail.html:29
|
||||||
msgid "Reference"
|
msgid "Reference"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1324,63 +1347,63 @@ msgstr ""
|
|||||||
msgid "Stored BOM checksum"
|
msgid "Stored BOM checksum"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1040
|
#: part/models.py:1049
|
||||||
msgid "Parameter template name must be unique"
|
msgid "Parameter template name must be unique"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1045
|
#: part/models.py:1054
|
||||||
msgid "Parameter Name"
|
msgid "Parameter Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1047
|
#: part/models.py:1056
|
||||||
msgid "Parameter Units"
|
msgid "Parameter Units"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1073
|
#: part/models.py:1082
|
||||||
msgid "Parent Part"
|
msgid "Parent Part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1075
|
#: part/models.py:1084
|
||||||
msgid "Parameter Template"
|
msgid "Parameter Template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1077
|
#: part/models.py:1086
|
||||||
msgid "Parameter Value"
|
msgid "Parameter Value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1101
|
#: part/models.py:1110
|
||||||
msgid "Select parent part"
|
msgid "Select parent part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1110
|
#: part/models.py:1119
|
||||||
msgid "Select part to be used in BOM"
|
msgid "Select part to be used in BOM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1117
|
#: part/models.py:1126
|
||||||
msgid "BOM quantity for this BOM item"
|
msgid "BOM quantity for this BOM item"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1120
|
#: part/models.py:1129
|
||||||
msgid "Estimated build wastage quantity (absolute or percentage)"
|
msgid "Estimated build wastage quantity (absolute or percentage)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1123
|
#: part/models.py:1132
|
||||||
msgid "BOM item reference"
|
msgid "BOM item reference"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1126
|
#: part/models.py:1135
|
||||||
msgid "BOM item notes"
|
msgid "BOM item notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1128
|
#: part/models.py:1137
|
||||||
msgid "BOM line checksum"
|
msgid "BOM line checksum"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1191
|
#: part/models.py:1200
|
||||||
msgid "Part cannot be added to its own Bill of Materials"
|
msgid "Part cannot be added to its own Bill of Materials"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1198
|
#: part/models.py:1207
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
|
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1430,7 +1453,7 @@ msgstr ""
|
|||||||
msgid "Part Details"
|
msgid "Part Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/detail.html:25 part/templates/part/part_base.html:77
|
#: part/templates/part/detail.html:25 part/templates/part/part_base.html:78
|
||||||
msgid "IPN"
|
msgid "IPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1482,7 +1505,7 @@ msgstr ""
|
|||||||
msgid "Part is not a virtual part"
|
msgid "Part is not a virtual part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/detail.html:132
|
#: part/templates/part/detail.html:132 templates/table_filters.html:86
|
||||||
msgid "Assembly"
|
msgid "Assembly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1494,7 +1517,7 @@ msgstr ""
|
|||||||
msgid "Part cannot be assembled from other parts"
|
msgid "Part cannot be assembled from other parts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/detail.html:141
|
#: part/templates/part/detail.html:141 templates/table_filters.html:90
|
||||||
msgid "Component"
|
msgid "Component"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1554,31 +1577,43 @@ msgstr ""
|
|||||||
msgid "This part is not active"
|
msgid "This part is not active"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:37
|
#: part/templates/part/part_base.html:16
|
||||||
|
msgid "This part is a template part."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:18
|
||||||
|
msgid "It is not a real part, but real parts can be based on this template."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:23
|
||||||
|
msgid "This part is a variant of"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:38
|
||||||
msgid "Star this part"
|
msgid "Star this part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:43
|
#: part/templates/part/part_base.html:44
|
||||||
msgid "Show pricing information"
|
msgid "Show pricing information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:98
|
#: part/templates/part/part_base.html:101
|
||||||
msgid "Available Stock"
|
msgid "Available Stock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:103
|
#: part/templates/part/part_base.html:107
|
||||||
msgid "In Stock"
|
msgid "In Stock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:124
|
#: part/templates/part/part_base.html:131
|
||||||
msgid "Build Status"
|
msgid "Build Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:128
|
#: part/templates/part/part_base.html:136
|
||||||
msgid "Can Build"
|
msgid "Can Build"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:133
|
#: part/templates/part/part_base.html:142
|
||||||
msgid "Underway"
|
msgid "Underway"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1618,11 +1653,6 @@ msgstr ""
|
|||||||
msgid "BOM"
|
msgid "BOM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/tabs.html:28 stock/templates/stock/item_base.html:121
|
|
||||||
#: templates/navbar.html:12
|
|
||||||
msgid "Build"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: part/templates/part/tabs.html:32
|
#: part/templates/part/tabs.html:32
|
||||||
msgid "Used In"
|
msgid "Used In"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1938,51 +1968,51 @@ msgstr ""
|
|||||||
msgid "Stock Tracking Information"
|
msgid "Stock Tracking Information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:10
|
#: stock/templates/stock/item_base.html:11
|
||||||
msgid "Stock Item Details"
|
msgid "Stock Item Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:55
|
#: stock/templates/stock/item_base.html:56
|
||||||
msgid ""
|
msgid ""
|
||||||
"This stock item is serialized - it has a unique serial number and the "
|
"This stock item is serialized - it has a unique serial number and the "
|
||||||
"quantity cannot be adjusted."
|
"quantity cannot be adjusted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:59
|
#: stock/templates/stock/item_base.html:60
|
||||||
msgid "This stock item cannot be deleted as it has child items"
|
msgid "This stock item cannot be deleted as it has child items"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:63
|
#: stock/templates/stock/item_base.html:64
|
||||||
msgid ""
|
msgid ""
|
||||||
"This stock item will be automatically deleted when all stock is depleted."
|
"This stock item will be automatically deleted when all stock is depleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:68
|
#: stock/templates/stock/item_base.html:69
|
||||||
msgid "This stock item was split from "
|
msgid "This stock item was split from "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:88
|
#: stock/templates/stock/item_base.html:89
|
||||||
msgid "Belongs To"
|
msgid "Belongs To"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:94
|
#: stock/templates/stock/item_base.html:95
|
||||||
#: stock/templates/stock/stock_adjust.html:17
|
#: stock/templates/stock/stock_adjust.html:17
|
||||||
msgid "Location"
|
msgid "Location"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:101
|
#: stock/templates/stock/item_base.html:102
|
||||||
msgid "Serial Number"
|
msgid "Serial Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:160
|
#: stock/templates/stock/item_base.html:161
|
||||||
msgid "Last Updated"
|
msgid "Last Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:165
|
#: stock/templates/stock/item_base.html:166
|
||||||
msgid "Last Stocktake"
|
msgid "Last Stocktake"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:169
|
#: stock/templates/stock/item_base.html:170
|
||||||
msgid "No stocktake performed"
|
msgid "No stocktake performed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2280,3 +2310,55 @@ msgstr ""
|
|||||||
#: templates/stock_table.html:17
|
#: templates/stock_table.html:17
|
||||||
msgid "Delete Stock"
|
msgid "Delete Stock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:22
|
||||||
|
msgid "Include sublocations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:23
|
||||||
|
msgid "Include stock in sublocations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:27
|
||||||
|
msgid "Active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:28
|
||||||
|
msgid "Show stock for active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:32 templates/table_filters.html:33
|
||||||
|
msgid "Stock status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:53
|
||||||
|
msgid "Order status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:64
|
||||||
|
msgid "Include subcategories"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:65
|
||||||
|
msgid "Include parts in subcategories"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:69
|
||||||
|
msgid "Active"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:70
|
||||||
|
msgid "Show active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:74
|
||||||
|
msgid "Template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:78
|
||||||
|
msgid "Stock available"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:82
|
||||||
|
msgid "Low stock"
|
||||||
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-04-09 15:04+0000\n"
|
"POT-Creation-Date: 2020-04-11 15:00+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,30 +18,30 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: InvenTree/helpers.py:240 order/models.py:164 order/models.py:215
|
#: InvenTree/helpers.py:259 order/models.py:164 order/models.py:215
|
||||||
msgid "Invalid quantity provided"
|
msgid "Invalid quantity provided"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:243
|
#: InvenTree/helpers.py:262
|
||||||
msgid "Empty serial number string"
|
msgid "Empty serial number string"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:264 InvenTree/helpers.py:281
|
#: InvenTree/helpers.py:283 InvenTree/helpers.py:300
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Duplicate serial: {n}"
|
msgid "Duplicate serial: {n}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:268 InvenTree/helpers.py:271 InvenTree/helpers.py:274
|
#: InvenTree/helpers.py:287 InvenTree/helpers.py:290 InvenTree/helpers.py:293
|
||||||
#: InvenTree/helpers.py:285
|
#: InvenTree/helpers.py:304
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Invalid group: {g}"
|
msgid "Invalid group: {g}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:291
|
#: InvenTree/helpers.py:310
|
||||||
msgid "No serial numbers found"
|
msgid "No serial numbers found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/helpers.py:295
|
#: InvenTree/helpers.py:314
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Number of unique serial number ({s}) must match quantity ({q})"
|
msgid "Number of unique serial number ({s}) must match quantity ({q})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -70,49 +70,49 @@ msgstr ""
|
|||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:36 InvenTree/status_codes.py:97
|
#: InvenTree/status_codes.py:86 InvenTree/status_codes.py:162
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:37
|
#: InvenTree/status_codes.py:87
|
||||||
msgid "Placed"
|
msgid "Placed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:38 InvenTree/status_codes.py:100
|
#: InvenTree/status_codes.py:88 InvenTree/status_codes.py:165
|
||||||
msgid "Complete"
|
msgid "Complete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:39 InvenTree/status_codes.py:99
|
#: InvenTree/status_codes.py:89 InvenTree/status_codes.py:164
|
||||||
msgid "Cancelled"
|
msgid "Cancelled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71
|
#: InvenTree/status_codes.py:90 InvenTree/status_codes.py:130
|
||||||
msgid "Lost"
|
msgid "Lost"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:41
|
#: InvenTree/status_codes.py:91
|
||||||
msgid "Returned"
|
msgid "Returned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:67
|
#: InvenTree/status_codes.py:126
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:68
|
#: InvenTree/status_codes.py:127
|
||||||
msgid "Attention needed"
|
msgid "Attention needed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:69
|
#: InvenTree/status_codes.py:128
|
||||||
msgid "Damaged"
|
msgid "Damaged"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:70
|
#: InvenTree/status_codes.py:129
|
||||||
msgid "Destroyed"
|
msgid "Destroyed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: InvenTree/status_codes.py:98 build/templates/build/allocate_edit.html:28
|
#: InvenTree/status_codes.py:163 build/templates/build/allocate_edit.html:28
|
||||||
#: build/templates/build/allocate_view.html:21
|
#: build/templates/build/allocate_view.html:21
|
||||||
#: part/templates/part/part_base.html:109 part/templates/part/tabs.html:21
|
#: part/templates/part/part_base.html:114 part/templates/part/tabs.html:21
|
||||||
msgid "Allocated"
|
msgid "Allocated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ msgstr ""
|
|||||||
msgid "Number of parts to build"
|
msgid "Number of parts to build"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/models.py:82
|
#: build/models.py:82 templates/table_filters.html:42
|
||||||
msgid "Build status"
|
msgid "Build status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -227,10 +227,10 @@ msgstr ""
|
|||||||
|
|
||||||
#: build/templates/build/allocate_edit.html:19
|
#: build/templates/build/allocate_edit.html:19
|
||||||
#: build/templates/build/allocate_view.html:17
|
#: build/templates/build/allocate_view.html:17
|
||||||
#: build/templates/build/detail.html:21
|
#: build/templates/build/detail.html:22
|
||||||
#: company/templates/company/detail_part.html:65
|
#: company/templates/company/detail_part.html:65
|
||||||
#: order/templates/order/order_wizard/select_parts.html:30
|
#: order/templates/order/order_wizard/select_parts.html:30
|
||||||
#: order/templates/order/purchase_order_detail.html:25
|
#: order/templates/order/purchase_order_detail.html:26
|
||||||
#: part/templates/part/part_app_base.html:7
|
#: part/templates/part/part_app_base.html:7
|
||||||
msgid "Part"
|
msgid "Part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -262,16 +262,58 @@ msgstr ""
|
|||||||
#: company/templates/company/index.html:54
|
#: company/templates/company/index.html:54
|
||||||
#: company/templates/company/supplier_part_base.html:50
|
#: company/templates/company/supplier_part_base.html:50
|
||||||
#: company/templates/company/supplier_part_detail.html:27
|
#: company/templates/company/supplier_part_detail.html:27
|
||||||
#: order/templates/order/purchase_order_detail.html:26
|
#: order/templates/order/purchase_order_detail.html:27
|
||||||
#: part/templates/part/detail.html:38
|
#: part/templates/part/detail.html:38
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/allocate_view.html:22
|
#: build/templates/build/allocate_view.html:22
|
||||||
#: part/templates/part/part_base.html:115
|
#: part/templates/part/part_base.html:121
|
||||||
msgid "On Order"
|
msgid "On Order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:27 part/templates/part/tabs.html:28
|
||||||
|
#: stock/templates/stock/item_base.html:122 templates/navbar.html:12
|
||||||
|
msgid "Build"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:52 build/templates/build/detail.html:9
|
||||||
|
msgid "Build Details"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:56
|
||||||
|
msgid "Build Title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:66
|
||||||
|
#: build/templates/build/detail.html:27
|
||||||
|
#: company/templates/company/supplier_part_pricing.html:27
|
||||||
|
#: order/templates/order/order_wizard/select_parts.html:32
|
||||||
|
#: order/templates/order/purchase_order_detail.html:30
|
||||||
|
#: stock/templates/stock/item_base.html:108
|
||||||
|
#: stock/templates/stock/stock_adjust.html:18
|
||||||
|
msgid "Quantity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:71
|
||||||
|
#: build/templates/build/detail.html:42
|
||||||
|
#: order/templates/order/order_base.html:72
|
||||||
|
#: stock/templates/stock/item_base.html:175
|
||||||
|
msgid "Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:76
|
||||||
|
msgid "BOM Price"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:81
|
||||||
|
msgid "BOM pricing is incomplete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: build/templates/build/build_base.html:84
|
||||||
|
msgid "No pricing information"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/build_output.html:9
|
#: build/templates/build/build_output.html:9
|
||||||
msgid "Build Outputs"
|
msgid "Build Outputs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -280,68 +322,49 @@ msgstr ""
|
|||||||
msgid "Are you sure you want to unallocate these parts?"
|
msgid "Are you sure you want to unallocate these parts?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:8
|
#: build/templates/build/detail.html:17
|
||||||
msgid "Build Details"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:16
|
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:26
|
#: build/templates/build/detail.html:31
|
||||||
#: company/templates/company/supplier_part_pricing.html:27
|
|
||||||
#: order/templates/order/order_wizard/select_parts.html:32
|
|
||||||
#: order/templates/order/purchase_order_detail.html:29
|
|
||||||
#: stock/templates/stock/item_base.html:107
|
|
||||||
#: stock/templates/stock/stock_adjust.html:18
|
|
||||||
msgid "Quantity"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:30
|
|
||||||
msgid "Stock Source"
|
msgid "Stock Source"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:35
|
#: build/templates/build/detail.html:36
|
||||||
msgid "Stock can be taken from any available location."
|
msgid "Stock can be taken from any available location."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:41
|
#: build/templates/build/detail.html:48
|
||||||
#: order/templates/order/order_base.html:71
|
#: stock/templates/stock/item_base.html:115
|
||||||
#: stock/templates/stock/item_base.html:174
|
|
||||||
msgid "Status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: build/templates/build/detail.html:47
|
|
||||||
#: stock/templates/stock/item_base.html:114
|
|
||||||
msgid "Batch"
|
msgid "Batch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:54
|
#: build/templates/build/detail.html:55
|
||||||
#: company/templates/company/supplier_part_base.html:47
|
#: company/templates/company/supplier_part_base.html:47
|
||||||
#: company/templates/company/supplier_part_detail.html:24
|
#: company/templates/company/supplier_part_detail.html:24
|
||||||
#: part/templates/part/detail.html:67 part/templates/part/part_base.html:84
|
#: part/templates/part/detail.html:67 part/templates/part/part_base.html:85
|
||||||
#: stock/templates/stock/item_base.html:142
|
#: stock/templates/stock/item_base.html:143
|
||||||
msgid "External Link"
|
msgid "External Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:60
|
#: build/templates/build/detail.html:61
|
||||||
#: order/templates/order/order_base.html:83
|
#: order/templates/order/order_base.html:84
|
||||||
msgid "Created"
|
msgid "Created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:66
|
#: build/templates/build/detail.html:67
|
||||||
msgid "Enough Parts?"
|
msgid "Enough Parts?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:69
|
#: build/templates/build/detail.html:70
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:71
|
#: build/templates/build/detail.html:72
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build/templates/build/detail.html:79
|
#: build/templates/build/detail.html:80
|
||||||
msgid "Completed"
|
msgid "Completed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -581,7 +604,7 @@ msgstr ""
|
|||||||
msgid "Supplier stock keeping unit"
|
msgid "Supplier stock keeping unit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/models.py:256 company/templates/company/detail_part.html:81
|
#: company/models.py:256 company/templates/company/detail_part.html:96
|
||||||
#: company/templates/company/supplier_part_base.html:53
|
#: company/templates/company/supplier_part_base.html:53
|
||||||
#: company/templates/company/supplier_part_detail.html:30
|
#: company/templates/company/supplier_part_detail.html:30
|
||||||
msgid "Manufacturer"
|
msgid "Manufacturer"
|
||||||
@ -637,7 +660,7 @@ msgid "Company Details"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail.html:16
|
#: company/templates/company/detail.html:16
|
||||||
#: stock/templates/stock/item_base.html:135
|
#: stock/templates/stock/item_base.html:136
|
||||||
msgid "Customer"
|
msgid "Customer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -645,9 +668,9 @@ msgstr ""
|
|||||||
#: company/templates/company/index.html:46
|
#: company/templates/company/index.html:46
|
||||||
#: company/templates/company/supplier_part_base.html:44
|
#: company/templates/company/supplier_part_base.html:44
|
||||||
#: company/templates/company/supplier_part_detail.html:21
|
#: company/templates/company/supplier_part_detail.html:21
|
||||||
#: order/templates/order/order_base.html:66
|
#: order/templates/order/order_base.html:67
|
||||||
#: order/templates/order/order_wizard/select_pos.html:30
|
#: order/templates/order/order_wizard/select_pos.html:30
|
||||||
#: stock/templates/stock/item_base.html:149
|
#: stock/templates/stock/item_base.html:150
|
||||||
msgid "Supplier"
|
msgid "Supplier"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -669,13 +692,13 @@ msgstr ""
|
|||||||
msgid "Delete Parts"
|
msgid "Delete Parts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail_part.html:73
|
#: company/templates/company/detail_part.html:88
|
||||||
#: company/templates/company/supplier_part_base.html:45
|
#: company/templates/company/supplier_part_base.html:45
|
||||||
#: company/templates/company/supplier_part_detail.html:22
|
#: company/templates/company/supplier_part_detail.html:22
|
||||||
msgid "SKU"
|
msgid "SKU"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: company/templates/company/detail_part.html:90
|
#: company/templates/company/detail_part.html:105
|
||||||
msgid "Link"
|
msgid "Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -727,7 +750,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: company/templates/company/supplier_part_base.html:6
|
#: company/templates/company/supplier_part_base.html:6
|
||||||
#: company/templates/company/supplier_part_base.html:13
|
#: company/templates/company/supplier_part_base.html:13
|
||||||
#: stock/templates/stock/item_base.html:154
|
#: stock/templates/stock/item_base.html:155
|
||||||
msgid "Supplier Part"
|
msgid "Supplier Part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -748,7 +771,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: company/templates/company/supplier_part_base.html:57
|
#: company/templates/company/supplier_part_base.html:57
|
||||||
#: company/templates/company/supplier_part_detail.html:34
|
#: company/templates/company/supplier_part_detail.html:34
|
||||||
#: order/templates/order/purchase_order_detail.html:33
|
#: order/templates/order/purchase_order_detail.html:34
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -930,7 +953,7 @@ msgstr ""
|
|||||||
msgid "Line item notes"
|
msgid "Line item notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/models.py:298 stock/templates/stock/item_base.html:128
|
#: order/models.py:298 stock/templates/stock/item_base.html:129
|
||||||
msgid "Purchase Order"
|
msgid "Purchase Order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -942,16 +965,16 @@ msgstr ""
|
|||||||
msgid "Number of items received"
|
msgid "Number of items received"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:61
|
#: order/templates/order/order_base.html:62
|
||||||
msgid "Purchase Order Details"
|
msgid "Purchase Order Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:89
|
#: order/templates/order/order_base.html:90
|
||||||
msgid "Issued"
|
msgid "Issued"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/order_base.html:96
|
#: order/templates/order/order_base.html:97
|
||||||
#: order/templates/order/purchase_order_detail.html:31
|
#: order/templates/order/purchase_order_detail.html:32
|
||||||
msgid "Received"
|
msgid "Received"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1035,23 +1058,23 @@ msgstr ""
|
|||||||
msgid "Are you sure you want to delete this attachment?"
|
msgid "Are you sure you want to delete this attachment?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:15 order/views.py:825
|
#: order/templates/order/purchase_order_detail.html:16 order/views.py:825
|
||||||
msgid "Add Line Item"
|
msgid "Add Line Item"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:19
|
#: order/templates/order/purchase_order_detail.html:20
|
||||||
msgid "Order Items"
|
msgid "Order Items"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:24
|
#: order/templates/order/purchase_order_detail.html:25
|
||||||
msgid "Line"
|
msgid "Line"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:27
|
#: order/templates/order/purchase_order_detail.html:28
|
||||||
msgid "Order Code"
|
msgid "Order Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: order/templates/order/purchase_order_detail.html:28
|
#: order/templates/order/purchase_order_detail.html:29
|
||||||
msgid "Reference"
|
msgid "Reference"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1324,63 +1347,63 @@ msgstr ""
|
|||||||
msgid "Stored BOM checksum"
|
msgid "Stored BOM checksum"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1040
|
#: part/models.py:1049
|
||||||
msgid "Parameter template name must be unique"
|
msgid "Parameter template name must be unique"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1045
|
#: part/models.py:1054
|
||||||
msgid "Parameter Name"
|
msgid "Parameter Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1047
|
#: part/models.py:1056
|
||||||
msgid "Parameter Units"
|
msgid "Parameter Units"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1073
|
#: part/models.py:1082
|
||||||
msgid "Parent Part"
|
msgid "Parent Part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1075
|
#: part/models.py:1084
|
||||||
msgid "Parameter Template"
|
msgid "Parameter Template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1077
|
#: part/models.py:1086
|
||||||
msgid "Parameter Value"
|
msgid "Parameter Value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1101
|
#: part/models.py:1110
|
||||||
msgid "Select parent part"
|
msgid "Select parent part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1110
|
#: part/models.py:1119
|
||||||
msgid "Select part to be used in BOM"
|
msgid "Select part to be used in BOM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1117
|
#: part/models.py:1126
|
||||||
msgid "BOM quantity for this BOM item"
|
msgid "BOM quantity for this BOM item"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1120
|
#: part/models.py:1129
|
||||||
msgid "Estimated build wastage quantity (absolute or percentage)"
|
msgid "Estimated build wastage quantity (absolute or percentage)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1123
|
#: part/models.py:1132
|
||||||
msgid "BOM item reference"
|
msgid "BOM item reference"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1126
|
#: part/models.py:1135
|
||||||
msgid "BOM item notes"
|
msgid "BOM item notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1128
|
#: part/models.py:1137
|
||||||
msgid "BOM line checksum"
|
msgid "BOM line checksum"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1191
|
#: part/models.py:1200
|
||||||
msgid "Part cannot be added to its own Bill of Materials"
|
msgid "Part cannot be added to its own Bill of Materials"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/models.py:1198
|
#: part/models.py:1207
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
|
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1430,7 +1453,7 @@ msgstr ""
|
|||||||
msgid "Part Details"
|
msgid "Part Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/detail.html:25 part/templates/part/part_base.html:77
|
#: part/templates/part/detail.html:25 part/templates/part/part_base.html:78
|
||||||
msgid "IPN"
|
msgid "IPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1482,7 +1505,7 @@ msgstr ""
|
|||||||
msgid "Part is not a virtual part"
|
msgid "Part is not a virtual part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/detail.html:132
|
#: part/templates/part/detail.html:132 templates/table_filters.html:86
|
||||||
msgid "Assembly"
|
msgid "Assembly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1494,7 +1517,7 @@ msgstr ""
|
|||||||
msgid "Part cannot be assembled from other parts"
|
msgid "Part cannot be assembled from other parts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/detail.html:141
|
#: part/templates/part/detail.html:141 templates/table_filters.html:90
|
||||||
msgid "Component"
|
msgid "Component"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1554,31 +1577,43 @@ msgstr ""
|
|||||||
msgid "This part is not active"
|
msgid "This part is not active"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:37
|
#: part/templates/part/part_base.html:16
|
||||||
|
msgid "This part is a template part."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:18
|
||||||
|
msgid "It is not a real part, but real parts can be based on this template."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:23
|
||||||
|
msgid "This part is a variant of"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: part/templates/part/part_base.html:38
|
||||||
msgid "Star this part"
|
msgid "Star this part"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:43
|
#: part/templates/part/part_base.html:44
|
||||||
msgid "Show pricing information"
|
msgid "Show pricing information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:98
|
#: part/templates/part/part_base.html:101
|
||||||
msgid "Available Stock"
|
msgid "Available Stock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:103
|
#: part/templates/part/part_base.html:107
|
||||||
msgid "In Stock"
|
msgid "In Stock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:124
|
#: part/templates/part/part_base.html:131
|
||||||
msgid "Build Status"
|
msgid "Build Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:128
|
#: part/templates/part/part_base.html:136
|
||||||
msgid "Can Build"
|
msgid "Can Build"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/part_base.html:133
|
#: part/templates/part/part_base.html:142
|
||||||
msgid "Underway"
|
msgid "Underway"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1618,11 +1653,6 @@ msgstr ""
|
|||||||
msgid "BOM"
|
msgid "BOM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: part/templates/part/tabs.html:28 stock/templates/stock/item_base.html:121
|
|
||||||
#: templates/navbar.html:12
|
|
||||||
msgid "Build"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: part/templates/part/tabs.html:32
|
#: part/templates/part/tabs.html:32
|
||||||
msgid "Used In"
|
msgid "Used In"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1938,51 +1968,51 @@ msgstr ""
|
|||||||
msgid "Stock Tracking Information"
|
msgid "Stock Tracking Information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:10
|
#: stock/templates/stock/item_base.html:11
|
||||||
msgid "Stock Item Details"
|
msgid "Stock Item Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:55
|
#: stock/templates/stock/item_base.html:56
|
||||||
msgid ""
|
msgid ""
|
||||||
"This stock item is serialized - it has a unique serial number and the "
|
"This stock item is serialized - it has a unique serial number and the "
|
||||||
"quantity cannot be adjusted."
|
"quantity cannot be adjusted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:59
|
#: stock/templates/stock/item_base.html:60
|
||||||
msgid "This stock item cannot be deleted as it has child items"
|
msgid "This stock item cannot be deleted as it has child items"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:63
|
#: stock/templates/stock/item_base.html:64
|
||||||
msgid ""
|
msgid ""
|
||||||
"This stock item will be automatically deleted when all stock is depleted."
|
"This stock item will be automatically deleted when all stock is depleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:68
|
#: stock/templates/stock/item_base.html:69
|
||||||
msgid "This stock item was split from "
|
msgid "This stock item was split from "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:88
|
#: stock/templates/stock/item_base.html:89
|
||||||
msgid "Belongs To"
|
msgid "Belongs To"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:94
|
#: stock/templates/stock/item_base.html:95
|
||||||
#: stock/templates/stock/stock_adjust.html:17
|
#: stock/templates/stock/stock_adjust.html:17
|
||||||
msgid "Location"
|
msgid "Location"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:101
|
#: stock/templates/stock/item_base.html:102
|
||||||
msgid "Serial Number"
|
msgid "Serial Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:160
|
#: stock/templates/stock/item_base.html:161
|
||||||
msgid "Last Updated"
|
msgid "Last Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:165
|
#: stock/templates/stock/item_base.html:166
|
||||||
msgid "Last Stocktake"
|
msgid "Last Stocktake"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stock/templates/stock/item_base.html:169
|
#: stock/templates/stock/item_base.html:170
|
||||||
msgid "No stocktake performed"
|
msgid "No stocktake performed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2280,3 +2310,55 @@ msgstr ""
|
|||||||
#: templates/stock_table.html:17
|
#: templates/stock_table.html:17
|
||||||
msgid "Delete Stock"
|
msgid "Delete Stock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:22
|
||||||
|
msgid "Include sublocations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:23
|
||||||
|
msgid "Include stock in sublocations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:27
|
||||||
|
msgid "Active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:28
|
||||||
|
msgid "Show stock for active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:32 templates/table_filters.html:33
|
||||||
|
msgid "Stock status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:53
|
||||||
|
msgid "Order status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:64
|
||||||
|
msgid "Include subcategories"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:65
|
||||||
|
msgid "Include parts in subcategories"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:69
|
||||||
|
msgid "Active"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:70
|
||||||
|
msgid "Show active parts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:74
|
||||||
|
msgid "Template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:78
|
||||||
|
msgid "Stock available"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/table_filters.html:82
|
||||||
|
msgid "Low stock"
|
||||||
|
msgstr ""
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load inventree_extras %}
|
{% load inventree_extras %}
|
||||||
|
{% load status_codes %}
|
||||||
|
|
||||||
{% block page_title %}
|
{% block page_title %}
|
||||||
InvenTree | {{ order }}
|
InvenTree | {{ order }}
|
||||||
@ -69,7 +70,7 @@ InvenTree | {{ order }}
|
|||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-info'></span></td>
|
<td><span class='fas fa-info'></span></td>
|
||||||
<td>{% trans "Status" %}</td>
|
<td>{% trans "Status" %}</td>
|
||||||
<td>{% include "order/order_status.html" %}</td>
|
<td>{% order_status order.status %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if order.link %}
|
{% if order.link %}
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
{% if order.status == OrderStatus.PENDING %}
|
|
||||||
<span class='label label-large label-info'>
|
|
||||||
{% elif order.status == OrderStatus.PLACED %}
|
|
||||||
<span class='label label-large label-primary'>
|
|
||||||
{% elif order.status == OrderStatus.COMPLETE %}
|
|
||||||
<span class='label label-large label-success'>
|
|
||||||
{% elif order.status == OrderStatus.CANCELLED or order.status == OrderStatus.RETURNED %}
|
|
||||||
<span class='label label-large label-warning'>
|
|
||||||
{% else %}
|
|
||||||
<span class='label label-large label-danger'>
|
|
||||||
{% endif %}
|
|
||||||
{{ order.get_status_display }}
|
|
||||||
</span>
|
|
@ -1,22 +0,0 @@
|
|||||||
<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>
|
|
||||||
<th data-field='reference' data-sortable='true' data-searchable='true'>Order Reference</th>
|
|
||||||
<th data-field='description' data-sortable='true' data-searchable='true'>Description</th>
|
|
||||||
<th data-field='status' data-sortable='true'>Status</th>
|
|
||||||
<th data-field='items' data-sortable='true'>Items</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for order in orders %}
|
|
||||||
<tr>
|
|
||||||
<td>{% include "hover_image.html" with image=order.supplier.image hover=True %}<a href="{{ order.supplier.get_absolute_url }}purchase-orders/">{{ order.supplier.name }}</a></td>
|
|
||||||
<td><a href="{% url 'po-detail' order.id %}">{{ order }}</a></td>
|
|
||||||
<td>{{ order.description }}</td>
|
|
||||||
<td>{% include "order/order_status.html" %}</td>
|
|
||||||
<td>{{ order.lines.count }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
@ -1,6 +1,7 @@
|
|||||||
{% extends "order/order_base.html" %}
|
{% extends "order/order_base.html" %}
|
||||||
|
|
||||||
{% load inventree_extras %}
|
{% load inventree_extras %}
|
||||||
|
{% load status_codes %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
|
@ -13,8 +13,11 @@ InvenTree | Purchase Orders
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id='table-buttons'>
|
<div id='table-buttons'>
|
||||||
<div class='btn-group' style='float: right;'>
|
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||||
<button class='btn btn-primary' type='button' id='po-create' title='Create new purchase order'>New Purchase Order</button>
|
<button class='btn btn-primary' type='button' id='po-create' title='Create new purchase order'>New Purchase Order</button>
|
||||||
|
<div class='filter-list' id='filter-list-order'>
|
||||||
|
<!-- An empty div in which the filter list will be constructed -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
44
InvenTree/order/test_api.py
Normal file
44
InvenTree/order/test_api.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
"""
|
||||||
|
Tests for the Order API
|
||||||
|
"""
|
||||||
|
|
||||||
|
from rest_framework.test import APITestCase
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
|
||||||
|
class OrderTest(APITestCase):
|
||||||
|
|
||||||
|
fixtures = [
|
||||||
|
'category',
|
||||||
|
'part',
|
||||||
|
'company',
|
||||||
|
'location',
|
||||||
|
'supplier_part',
|
||||||
|
'stock',
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
# Create a user for auth
|
||||||
|
User = get_user_model()
|
||||||
|
User.objects.create_user('testuser', 'test@testing.com', 'password')
|
||||||
|
self.client.login(username='testuser', password='password')
|
||||||
|
|
||||||
|
def doGet(self, url, options=''):
|
||||||
|
|
||||||
|
return self.client.get(url + "?" + options, format='json')
|
||||||
|
|
||||||
|
def test_po_list(self,):
|
||||||
|
|
||||||
|
url = reverse('api-po-list')
|
||||||
|
|
||||||
|
# List all order items
|
||||||
|
response = self.doGet(url)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
# Filter by stuff
|
||||||
|
response = self.doGet(url, 'status=10&part=1&supplier_part=1')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
@ -8,7 +8,8 @@ from __future__ import unicode_literals
|
|||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from django.db.models import Q, Sum, Count
|
from django.db.models import Q, F, Sum, Count
|
||||||
|
from django.db.models.functions import Coalesce
|
||||||
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
@ -19,6 +20,7 @@ from django.conf.urls import url, include
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from .models import Part, PartCategory, BomItem, PartStar
|
from .models import Part, PartCategory, BomItem, PartStar
|
||||||
from .models import PartParameter, PartParameterTemplate
|
from .models import PartParameter, PartParameterTemplate
|
||||||
@ -147,6 +149,18 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
- GET: Return list of objects
|
- GET: Return list of objects
|
||||||
- POST: Create a new Part object
|
- POST: Create a new Part object
|
||||||
|
|
||||||
|
The Part object list can be filtered by:
|
||||||
|
- category: Filter by PartCategory reference
|
||||||
|
- cascade: If true, include parts from sub-categories
|
||||||
|
- is_template: Is the part a template part?
|
||||||
|
- variant_of: Filter by variant_of Part reference
|
||||||
|
- assembly: Filter by assembly field
|
||||||
|
- component: Filter by component field
|
||||||
|
- trackable: Filter by trackable field
|
||||||
|
- purchaseable: Filter by purcahseable field
|
||||||
|
- salable: Filter by salable field
|
||||||
|
- active: Filter by active field
|
||||||
"""
|
"""
|
||||||
|
|
||||||
serializer_class = part_serializers.PartSerializer
|
serializer_class = part_serializers.PartSerializer
|
||||||
@ -210,11 +224,39 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
'active',
|
'active',
|
||||||
).annotate(
|
).annotate(
|
||||||
# Quantity of items which are "in stock"
|
# Quantity of items which are "in stock"
|
||||||
in_stock=Sum('stock_items__quantity', filter=stock_filter),
|
in_stock=Coalesce(Sum('stock_items__quantity', filter=stock_filter), Decimal(0)),
|
||||||
on_order=Sum('supplier_parts__purchase_order_line_items__quantity', filter=order_filter),
|
on_order=Coalesce(Sum('supplier_parts__purchase_order_line_items__quantity', filter=order_filter), Decimal(0)),
|
||||||
building=Sum('builds__quantity', filter=build_filter),
|
building=Coalesce(Sum('builds__quantity', filter=build_filter), Decimal(0)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# If we are filtering by 'has_stock' status
|
||||||
|
has_stock = self.request.query_params.get('has_stock', None)
|
||||||
|
|
||||||
|
if has_stock is not None:
|
||||||
|
has_stock = str2bool(has_stock)
|
||||||
|
|
||||||
|
if has_stock:
|
||||||
|
# Filter items which have a non-null 'in_stock' quantity above zero
|
||||||
|
data = data.filter(in_stock__gt=0)
|
||||||
|
else:
|
||||||
|
# Filter items which a null or zero 'in_stock' quantity
|
||||||
|
data = data.filter(Q(in_stock__lte=0))
|
||||||
|
|
||||||
|
# If we are filtering by 'low_stock' status
|
||||||
|
low_stock = self.request.query_params.get('low_stock', None)
|
||||||
|
|
||||||
|
if low_stock is not None:
|
||||||
|
low_stock = str2bool(low_stock)
|
||||||
|
|
||||||
|
if low_stock:
|
||||||
|
# Ignore any parts which do not have a specified 'minimum_stock' level
|
||||||
|
data = data.exclude(minimum_stock=0)
|
||||||
|
# Filter items which have an 'in_stock' level lower than 'minimum_stock'
|
||||||
|
data = data.filter(Q(in_stock__lt=F('minimum_stock')))
|
||||||
|
else:
|
||||||
|
# Filter items which have an 'in_stock' level higher than 'minimum_stock'
|
||||||
|
data = data.filter(Q(in_stock__gte=F('minimum_stock')))
|
||||||
|
|
||||||
# Reduce the number of lookups we need to do for the part categories
|
# Reduce the number of lookups we need to do for the part categories
|
||||||
categories = {}
|
categories = {}
|
||||||
|
|
||||||
@ -261,23 +303,23 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
cascade = str2bool(self.request.query_params.get('cascade', False))
|
cascade = str2bool(self.request.query_params.get('cascade', False))
|
||||||
|
|
||||||
if cat_id is not None:
|
if cat_id is None:
|
||||||
|
# Top-level parts
|
||||||
if isNull(cat_id):
|
if not cascade:
|
||||||
parts_list = parts_list.filter(category=None)
|
parts_list = parts_list.filter(category=None)
|
||||||
else:
|
|
||||||
try:
|
|
||||||
cat_id = int(cat_id)
|
|
||||||
category = PartCategory.objects.get(pk=cat_id)
|
|
||||||
|
|
||||||
# If '?cascade=true' then include parts which exist in sub-categories
|
else:
|
||||||
if cascade:
|
try:
|
||||||
parts_list = parts_list.filter(category__in=category.getUniqueChildren())
|
category = PartCategory.objects.get(pk=cat_id)
|
||||||
# Just return parts directly in the requested category
|
|
||||||
else:
|
# If '?cascade=true' then include parts which exist in sub-categories
|
||||||
parts_list = parts_list.filter(category=cat_id)
|
if cascade:
|
||||||
except (ValueError, PartCategory.DoesNotExist):
|
parts_list = parts_list.filter(category__in=category.getUniqueChildren())
|
||||||
pass
|
# Just return parts directly in the requested category
|
||||||
|
else:
|
||||||
|
parts_list = parts_list.filter(category=cat_id)
|
||||||
|
except (ValueError, PartCategory.DoesNotExist):
|
||||||
|
pass
|
||||||
|
|
||||||
# Ensure that related models are pre-loaded to reduce DB trips
|
# Ensure that related models are pre-loaded to reduce DB trips
|
||||||
parts_list = self.get_serializer_class().setup_eager_loading(parts_list)
|
parts_list = self.get_serializer_class().setup_eager_loading(parts_list)
|
||||||
@ -443,6 +485,19 @@ class BomList(generics.ListCreateAPIView):
|
|||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = BomItem.objects.all()
|
queryset = BomItem.objects.all()
|
||||||
queryset = self.get_serializer_class().setup_eager_loading(queryset)
|
queryset = self.get_serializer_class().setup_eager_loading(queryset)
|
||||||
|
|
||||||
|
# Filter by part?
|
||||||
|
part = self.request.query_params.get('part', None)
|
||||||
|
|
||||||
|
if part is not None:
|
||||||
|
queryset = queryset.filter(part=part)
|
||||||
|
|
||||||
|
# Filter by sub-part?
|
||||||
|
sub_part = self.request.query_params.get('sub_part', None)
|
||||||
|
|
||||||
|
if sub_part is not None:
|
||||||
|
queryset = queryset.filter(sub_part=sub_part)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
@ -456,8 +511,6 @@ class BomList(generics.ListCreateAPIView):
|
|||||||
]
|
]
|
||||||
|
|
||||||
filter_fields = [
|
filter_fields = [
|
||||||
'part',
|
|
||||||
'sub_part',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ from InvenTree import helpers
|
|||||||
from InvenTree import validators
|
from InvenTree import validators
|
||||||
from InvenTree.models import InvenTreeTree, InvenTreeAttachment
|
from InvenTree.models import InvenTreeTree, InvenTreeAttachment
|
||||||
from InvenTree.fields import InvenTreeURLField
|
from InvenTree.fields import InvenTreeURLField
|
||||||
from InvenTree.helpers import decimal2string
|
from InvenTree.helpers import decimal2string, normalize
|
||||||
|
|
||||||
from InvenTree.status_codes import BuildStatus, StockStatus, OrderStatus
|
from InvenTree.status_codes import BuildStatus, StockStatus, OrderStatus
|
||||||
|
|
||||||
@ -659,7 +659,7 @@ class Part(models.Model):
|
|||||||
if total:
|
if total:
|
||||||
return total
|
return total
|
||||||
else:
|
else:
|
||||||
return 0
|
return Decimal(0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_bom(self):
|
def has_bom(self):
|
||||||
@ -781,6 +781,9 @@ class Part(models.Model):
|
|||||||
if min_price == max_price:
|
if min_price == max_price:
|
||||||
return min_price
|
return min_price
|
||||||
|
|
||||||
|
min_price = normalize(min_price)
|
||||||
|
max_price = normalize(max_price)
|
||||||
|
|
||||||
return "{a} - {b}".format(a=min_price, b=max_price)
|
return "{a} - {b}".format(a=min_price, b=max_price)
|
||||||
|
|
||||||
def get_supplier_price_range(self, quantity=1):
|
def get_supplier_price_range(self, quantity=1):
|
||||||
@ -804,6 +807,9 @@ class Part(models.Model):
|
|||||||
if min_price is None or max_price is None:
|
if min_price is None or max_price is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
min_price = normalize(min_price)
|
||||||
|
max_price = normalize(max_price)
|
||||||
|
|
||||||
return (min_price, max_price)
|
return (min_price, max_price)
|
||||||
|
|
||||||
def get_bom_price_range(self, quantity=1):
|
def get_bom_price_range(self, quantity=1):
|
||||||
@ -837,6 +843,9 @@ class Part(models.Model):
|
|||||||
if min_price is None or max_price is None:
|
if min_price is None or max_price is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
min_price = normalize(min_price)
|
||||||
|
max_price = normalize(max_price)
|
||||||
|
|
||||||
return (min_price, max_price)
|
return (min_price, max_price)
|
||||||
|
|
||||||
def get_price_range(self, quantity=1, buy=True, bom=True):
|
def get_price_range(self, quantity=1, buy=True, bom=True):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{% extends "part/part_base.html" %}
|
{% extends "part/part_base.html" %}
|
||||||
{% block details %}
|
{% block details %}
|
||||||
|
{% load status_codes %}
|
||||||
|
|
||||||
{% include "part/tabs.html" with tab="allocation" %}
|
{% include "part/tabs.html" with tab="allocation" %}
|
||||||
|
|
||||||
@ -17,7 +18,7 @@
|
|||||||
<td><a href="{% url 'build-detail' allocation.build.id %}">{{ allocation.build.title }}</a></td>
|
<td><a href="{% url 'build-detail' allocation.build.id %}">{{ allocation.build.title }}</a></td>
|
||||||
<td>{{ allocation.build.quantity }} × <a href="{% url 'part-detail' allocation.build.part.id %}">{{ allocation.build.part.full_name }}</a></td>
|
<td>{{ allocation.build.quantity }} × <a href="{% url 'part-detail' allocation.build.part.id %}">{{ allocation.build.part.full_name }}</a></td>
|
||||||
<td>{{ allocation.quantity }}</td>
|
<td>{{ allocation.quantity }}</td>
|
||||||
<td>{% include "build_status.html" with build=allocation.build %}</td>
|
<td>{% build_status allocation.build.status %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
@ -7,9 +7,14 @@
|
|||||||
<h3>Part Builds</h3>
|
<h3>Part Builds</h3>
|
||||||
|
|
||||||
<div id='button-toolbar'>
|
<div id='button-toolbar'>
|
||||||
{% if part.active %}
|
<div class='button-toolbar container-flui' style='float: right';>
|
||||||
<button class="btn btn-success" id='start-build'>Start New Build</button>
|
{% if part.active %}
|
||||||
{% endif %}
|
<button class="btn btn-success" id='start-build'>Start New Build</button>
|
||||||
|
{% endif %}
|
||||||
|
<div class='filter-list' id='filter-list-build'>
|
||||||
|
<!-- Empty div for filters -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='build-table'>
|
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='build-table'>
|
||||||
@ -31,64 +36,12 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#build-table").inventreeTable({
|
loadBuildTable($("#build-table"), {
|
||||||
queryParams: function(p) {
|
url: "{% url 'api-build-list' %}",
|
||||||
return {
|
params: {
|
||||||
part: {{ part.id }},
|
part_detail: "true",
|
||||||
}
|
part: {{ part.id }},
|
||||||
},
|
}
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
field: 'pk',
|
|
||||||
title: 'ID',
|
|
||||||
visible: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'title',
|
|
||||||
title: 'Title',
|
|
||||||
formatter: function(value, row, index, field) {
|
|
||||||
return renderLink(value, row.url);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'quantity',
|
|
||||||
title: 'Quantity',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'status',
|
|
||||||
title: 'Status',
|
|
||||||
formatter: function(value, row, index, field) {
|
|
||||||
|
|
||||||
var color = '';
|
|
||||||
|
|
||||||
switch (value) {
|
|
||||||
case 10: // Pending
|
|
||||||
color = 'label-info';
|
|
||||||
break;
|
|
||||||
case 20: // Allocated
|
|
||||||
color = 'label-primary';
|
|
||||||
break;
|
|
||||||
case 30: // Cancelled
|
|
||||||
color = 'label-danger';
|
|
||||||
break;
|
|
||||||
case 40: // Complete
|
|
||||||
color = 'label-success';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var html = "<span class='label " + color + " label-large'>" + row.status_text + "</span>";
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'completion_date',
|
|
||||||
title: 'Completed'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
url: "{% url 'api-build-list' %}",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,10 +0,0 @@
|
|||||||
{% for build in builds %}
|
|
||||||
<tr>
|
|
||||||
<td><a href="{% url 'build-detail' build.id %}">{{ build.title }}</a></td>
|
|
||||||
<td>{{ build.quantity }}</td>
|
|
||||||
<td>
|
|
||||||
{% include "build_status.html" with build=build %}
|
|
||||||
</td>
|
|
||||||
<td>{% if build.completion_date %}{{ build.completion_date }}{% endif %}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
@ -99,7 +99,7 @@
|
|||||||
<div class='button-toolbar container-fluid' style="float: right;">
|
<div class='button-toolbar container-fluid' style="float: right;">
|
||||||
<button class='btn btn-default' id='part-export' title='Export Part Data'>Export</button>
|
<button class='btn btn-default' id='part-export' title='Export Part Data'>Export</button>
|
||||||
<button class='btn btn-success' id='part-create'>New Part</button>
|
<button class='btn btn-success' id='part-create'>New Part</button>
|
||||||
<div class='dropdown' style='float: right;'>
|
<div class='btn dropdown'>
|
||||||
<button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown">Options<span class='caret'></span></button>
|
<button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown">Options<span class='caret'></span></button>
|
||||||
<ul class='dropdown-menu'>
|
<ul class='dropdown-menu'>
|
||||||
<li><a href='#' id='multi-part-category' title='Set category'>Set Category</a></li>
|
<li><a href='#' id='multi-part-category' title='Set category'>Set Category</a></li>
|
||||||
@ -107,6 +107,9 @@
|
|||||||
<li><a href='#' id='multi-part-export' title='Export'>Export Data</a></li>
|
<li><a href='#' id='multi-part-export' title='Export'>Export Data</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='filter-list' id='filter-list-parts'>
|
||||||
|
<!-- Empty div -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -8,18 +8,19 @@
|
|||||||
|
|
||||||
{% if part.active == False %}
|
{% if part.active == False %}
|
||||||
<div class='alert alert-danger alert-block'>
|
<div class='alert alert-danger alert-block'>
|
||||||
{% trans "This part is not active" %}"
|
{% trans "This part is not active" %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.is_template %}
|
{% if part.is_template %}
|
||||||
<div class='alert alert-info alert-block'>
|
<div class='alert alert-info alert-block'>
|
||||||
This part is a <i>template part</i>.<br>
|
{% trans "This part is a template part." %}
|
||||||
It is not a <i>real</i> part, but real parts can be based on this template.
|
<br>
|
||||||
|
{% trans "It is not a real part, but real parts can be based on this template." %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.variant_of %}
|
{% if part.variant_of %}
|
||||||
<div class='alert alert-info alert-block'>
|
<div class='alert alert-info alert-block'>
|
||||||
This part is a variant of <b><a href="{% url 'part-detail' part.variant_of.id %}">{{ part.variant_of.full_name }}</a></b>
|
{% trans "This part is a variant of" %} <b><a href="{% url 'part-detail' part.variant_of.id %}">{{ part.variant_of.full_name }}</a></b>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@ -93,25 +94,30 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
|
<col width='25'>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td><span class='fas fa-boxes'></span></td>
|
||||||
<td>
|
<td>
|
||||||
<h4>{% trans "Available Stock" %}</h4>
|
<h4>{% trans "Available Stock" %}</h4>
|
||||||
</td>
|
</td>
|
||||||
<td><h4>{% decimal part.available_stock %} {{ part.units }}</h4></td>
|
<td><h4>{% decimal part.available_stock %} {{ part.units }}</h4></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td><span class='fas fa-map-marker-alt'></span></td>
|
||||||
<td>{% trans "In Stock" %}</td>
|
<td>{% trans "In Stock" %}</td>
|
||||||
<td>{% include "part/stock_count.html" %}</td>
|
<td>{% include "part/stock_count.html" %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if not part.is_template %}
|
{% if not part.is_template %}
|
||||||
{% if part.allocation_count > 0 %}
|
{% if part.allocation_count > 0 %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td><span class='fas fa-dolly'></span></td>
|
||||||
<td>{% trans "Allocated" %}</td>
|
<td>{% trans "Allocated" %}</td>
|
||||||
<td>{% decimal part.allocation_count %}</td>
|
<td>{% decimal part.allocation_count %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.on_order > 0 %}
|
{% if part.on_order > 0 %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td><span class='fas fa-shopping-cart'></span></td>
|
||||||
<td>{% trans "On Order" %}</td>
|
<td>{% trans "On Order" %}</td>
|
||||||
<td>{% decimal part.on_order %}</td>
|
<td>{% decimal part.on_order %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -120,16 +126,19 @@
|
|||||||
{% if not part.is_template %}
|
{% if not part.is_template %}
|
||||||
{% if part.assembly %}
|
{% if part.assembly %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td><span class='fas fa-tools'></span></td>
|
||||||
<td colspan='2'>
|
<td colspan='2'>
|
||||||
<b>{% trans "Build Status" %}</b>
|
<b>{% trans "Build Status" %}</b>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td></td>
|
||||||
<td>{% trans "Can Build" %}</td>
|
<td>{% trans "Can Build" %}</td>
|
||||||
<td>{% decimal part.can_build %}</td>
|
<td>{% decimal part.can_build %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if part.quantity_being_built > 0 %}
|
{% if part.quantity_being_built > 0 %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td></td>
|
||||||
<td>{% trans "Underway" %}</td>
|
<td>{% trans "Underway" %}</td>
|
||||||
<td>{% decimal part.quantity_being_built %}</td>
|
<td>{% decimal part.quantity_being_built %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{% decimal part.total_stock %}
|
{% decimal part.total_stock %}
|
||||||
|
|
||||||
{% if part.total_stock == 0 %}
|
{% if part.total_stock == 0 %}
|
||||||
<span class='label label-danger'>{% trans "No Stock" %}</span>
|
<span class='label label-danger label-right'>{% trans "No Stock" %}</span>
|
||||||
{% elif part.total_stock < part.minimum_stock %}
|
{% elif part.total_stock < part.minimum_stock %}
|
||||||
<span class='label label-warning'>{% trans "Low Stock" %}</span>
|
<span class='label label-warning label-right'>{% trans "Low Stock" %}</span>
|
||||||
{% endif %}
|
{% endif %}
|
@ -25,7 +25,7 @@
|
|||||||
<li{% ifequal tab 'bom' %} class="active"{% endifequal %}>
|
<li{% ifequal tab 'bom' %} class="active"{% endifequal %}>
|
||||||
<a href="{% url 'part-bom' part.id %}">{% trans "BOM" %}<span class="badge{% if part.is_bom_valid == False %} badge-alert{% endif %}">{{ part.bom_count }}</span></a></li>
|
<a href="{% url 'part-bom' part.id %}">{% trans "BOM" %}<span class="badge{% if part.is_bom_valid == False %} badge-alert{% endif %}">{{ part.bom_count }}</span></a></li>
|
||||||
<li{% ifequal tab 'build' %} class="active"{% endifequal %}>
|
<li{% ifequal tab 'build' %} class="active"{% endifequal %}>
|
||||||
<a href="{% url 'part-build' part.id %}">{% trans "Build" %}<span class='badge'>{{ part.active_builds|length }}</span></a></li>
|
<a href="{% url 'part-build' part.id %}">{% trans "Build" %}<span class='badge'>{{ part.builds|length }}</span></a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.component or part.used_in_count > 0 %}
|
{% if part.component or part.used_in_count > 0 %}
|
||||||
<li{% ifequal tab 'used' %} class="active"{% endifequal %}>
|
<li{% ifequal tab 'used' %} class="active"{% endifequal %}>
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
title: 'Part',
|
title: 'Part',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
var html = imageHoverIcon(row.part_detail.image_url) + renderLink(value.full_name, value.url + 'bom/');
|
var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value.full_name, value.url + 'bom/');
|
||||||
|
|
||||||
if (!row.part_detail.active) {
|
if (!row.part_detail.active) {
|
||||||
html += "<span class='label label-warning' style='float: right;'>INACTIVE</span>";
|
html += "<span class='label label-warning' style='float: right;'>INACTIVE</span>";
|
||||||
|
38
InvenTree/part/templatetags/status_codes.py
Normal file
38
InvenTree/part/templatetags/status_codes.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"""
|
||||||
|
Provide templates for the various model status codes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
from InvenTree.status_codes import OrderStatus, StockStatus, BuildStatus
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def order_status(key, *args, **kwargs):
|
||||||
|
return mark_safe(OrderStatus.render(key))
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def stock_status(key, *args, **kwargs):
|
||||||
|
return mark_safe(StockStatus.render(key))
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def build_status(key, *args, **kwargs):
|
||||||
|
return mark_safe(BuildStatus.render(key))
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=True)
|
||||||
|
def load_status_codes(context):
|
||||||
|
"""
|
||||||
|
Make the various StatusCodes available to the page context
|
||||||
|
"""
|
||||||
|
|
||||||
|
context['order_status_codes'] = OrderStatus.list()
|
||||||
|
context['stock_status_codes'] = StockStatus.list()
|
||||||
|
context['build_status_codes'] = BuildStatus.list()
|
||||||
|
|
||||||
|
# Need to return something as the result is rendered to the page
|
||||||
|
return ''
|
@ -82,7 +82,8 @@ class PartAPITest(APITestCase):
|
|||||||
|
|
||||||
def test_get_all_parts(self):
|
def test_get_all_parts(self):
|
||||||
url = reverse('api-part-list')
|
url = reverse('api-part-list')
|
||||||
response = self.client.get(url, format='json')
|
data = {'cascade': True}
|
||||||
|
response = self.client.get(url, data, format='json')
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(len(response.data), 8)
|
self.assertEqual(len(response.data), 8)
|
||||||
|
|
||||||
|
@ -410,8 +410,16 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
# Start with all objects
|
# Start with all objects
|
||||||
stock_list = super(StockList, self).get_queryset()
|
stock_list = super(StockList, self).get_queryset()
|
||||||
|
|
||||||
|
# Filter out parts which are not actually "in stock"
|
||||||
stock_list = stock_list.filter(customer=None, belongs_to=None)
|
stock_list = stock_list.filter(customer=None, belongs_to=None)
|
||||||
|
|
||||||
|
# Do we wish to filter by "active parts"
|
||||||
|
active = self.request.query_params.get('active', None)
|
||||||
|
|
||||||
|
if active is not None:
|
||||||
|
active = str2bool(active)
|
||||||
|
stock_list = stock_list.filter(part__active=active)
|
||||||
|
|
||||||
# Does the client wish to filter by the Part ID?
|
# Does the client wish to filter by the Part ID?
|
||||||
part_id = self.request.query_params.get('part', None)
|
part_id = self.request.query_params.get('part', None)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{% extends "stock/stock_app_base.html" %}
|
{% extends "stock/stock_app_base.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load inventree_extras %}
|
{% load inventree_extras %}
|
||||||
|
{% load status_codes %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
@ -172,7 +173,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-info'></span></td>
|
<td><span class='fas fa-info'></span></td>
|
||||||
<td>{% trans "Status" %}</td>
|
<td>{% trans "Status" %}</td>
|
||||||
<td>{{ item.get_status_display }}</td>
|
<td>{% stock_status item.status %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@ -102,7 +103,9 @@ InvenTree
|
|||||||
<script type='text/javascript' src="{% static 'script/inventree/inventree.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/inventree.js' %}"></script>
|
||||||
<script type='text/javascript' src="{% static 'script/inventree/api.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/api.js' %}"></script>
|
||||||
<script type='text/javascript' src="{% static 'script/inventree/bom.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/bom.js' %}"></script>
|
||||||
|
<script type='text/javascript' src="{% static 'script/inventree/filters.js' %}"></script>
|
||||||
<script type='text/javascript' src="{% static 'script/inventree/tables.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/tables.js' %}"></script>
|
||||||
|
<script type='text/javascript' src="{% static 'script/inventree/build.js' %}"></script>
|
||||||
<script type='text/javascript' src="{% static 'script/inventree/modals.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/modals.js' %}"></script>
|
||||||
<script type='text/javascript' src="{% static 'script/inventree/order.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/order.js' %}"></script>
|
||||||
<script type='text/javascript' src="{% static 'script/inventree/notification.js' %}"></script>
|
<script type='text/javascript' src="{% static 'script/inventree/notification.js' %}"></script>
|
||||||
@ -115,7 +118,10 @@ InvenTree
|
|||||||
{% block js_load %}
|
{% block js_load %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% include "table_filters.html" %}
|
||||||
|
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
{% block js_ready %}
|
{% block js_ready %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -124,6 +130,7 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
showCachedAlerts();
|
showCachedAlerts();
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
{% if build.status == BuildStatus.PENDING %}
|
|
||||||
<span class='label label-large label-info'>
|
|
||||||
{% elif build.status == BuildStatus.ALLOCATED %}
|
|
||||||
<span class='label label-large label-primary'>
|
|
||||||
{% elif build.status == BuildStatus.CANCELLED %}
|
|
||||||
<span class='label label-large label-danger'>
|
|
||||||
{% elif build.status == BuildStatus.COMPLETE %}
|
|
||||||
<span class='label label-large label-success'>
|
|
||||||
{% endif %}
|
|
||||||
{{ build.get_status_display }}
|
|
||||||
</span>
|
|
35
InvenTree/templates/status_codes.html
Normal file
35
InvenTree/templates/status_codes.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Status codes for the {{ label }} model.
|
||||||
|
*/
|
||||||
|
var {{ label }}Codes = {
|
||||||
|
{% for opt in options %}'{{ opt.key }}': {
|
||||||
|
key: '{{ opt.key }}',
|
||||||
|
value: '{{ opt.value }}',{% if opt.label %}
|
||||||
|
label: '{{ opt.label }}',{% endif %}
|
||||||
|
},{% endfor %}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Render the status for a {{ label }} object.
|
||||||
|
* Uses the values specified in "status_codes.py"
|
||||||
|
* This function is generated by the "status_codes.html" template
|
||||||
|
*/
|
||||||
|
function {{ label }}StatusDisplay(key) {
|
||||||
|
|
||||||
|
key = String(key);
|
||||||
|
|
||||||
|
var label = {{ label }}Codes[key].label;
|
||||||
|
|
||||||
|
var value = {{ label }}Codes[key].value;
|
||||||
|
|
||||||
|
if (value == null || value.length == 0) {
|
||||||
|
value = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label not found, return the original string
|
||||||
|
if (label == null || label.length == 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<span class='label label-${label}'>${value}</span>`;
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
{% if read_only %}
|
{% if read_only %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<button class="btn btn-success" id='item-create'>{% trans "New Stock Item" %}</button>
|
<button class="btn btn-success" id='item-create'>{% trans "New Stock Item" %}</button>
|
||||||
<div class="dropdown" style='float: right;'>
|
<div class="btn dropdown">
|
||||||
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
|
<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">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#" id='multi-item-add' title='Add to selected stock items'>{% trans "Add stock" %}</a></li>
|
<li><a href="#" id='multi-item-add' title='Add to selected stock items'>{% trans "Add stock" %}</a></li>
|
||||||
@ -18,6 +18,9 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class='filter-list' id='filter-list-stock'>
|
||||||
|
<!-- An empty div in which the filter list will be constructed -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
98
InvenTree/templates/table_filters.html
Normal file
98
InvenTree/templates/table_filters.html
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% load status_codes %}
|
||||||
|
|
||||||
|
{% load_status_codes %}
|
||||||
|
|
||||||
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
{% include "status_codes.html" with label='stock' options=stock_status_codes %}
|
||||||
|
{% include "status_codes.html" with label='build' options=build_status_codes %}
|
||||||
|
{% include "status_codes.html" with label='order' options=order_status_codes %}
|
||||||
|
|
||||||
|
|
||||||
|
function getAvailableTableFilters(tableKey) {
|
||||||
|
|
||||||
|
tableKey = tableKey.toLowerCase();
|
||||||
|
|
||||||
|
// Filters for the "Stock" table
|
||||||
|
if (tableKey == 'stock') {
|
||||||
|
return {
|
||||||
|
cascade: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Include sublocations" %}',
|
||||||
|
description: '{% trans "Include stock in sublocations" %}',
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Active parts" %}',
|
||||||
|
description: '{% trans "Show stock for active parts" %}',
|
||||||
|
},
|
||||||
|
'status': {
|
||||||
|
options: stockCodes,
|
||||||
|
title: '{% trans "Stock status" %}',
|
||||||
|
description: '{% trans "Stock status" %}',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters for the "Build" table
|
||||||
|
if (tableKey == 'build') {
|
||||||
|
return {
|
||||||
|
status: {
|
||||||
|
title: '{% trans "Build status" %}',
|
||||||
|
options: buildCodes,
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters for the "Order" table
|
||||||
|
if (tableKey == "order") {
|
||||||
|
return {
|
||||||
|
status: {
|
||||||
|
title: '{% trans "Order status" %}',
|
||||||
|
options: orderCodes,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters for the "Parts" table
|
||||||
|
if (tableKey == "parts") {
|
||||||
|
return {
|
||||||
|
cascade: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Include subcategories" %}',
|
||||||
|
description: '{% trans "Include parts in subcategories" %}',
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Active" %}',
|
||||||
|
description: '{% trans "Show active parts" %}',
|
||||||
|
},
|
||||||
|
is_template: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Template" %}',
|
||||||
|
},
|
||||||
|
has_stock: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Stock available" %}'
|
||||||
|
},
|
||||||
|
low_stock: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Low stock" %}',
|
||||||
|
},
|
||||||
|
assembly: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Assembly" %}',
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
type: 'bool',
|
||||||
|
title: '{% trans "Component" %}',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, no matching key
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user