mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
b805cfabb0
@ -50,6 +50,16 @@
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.index-bg {
|
||||
width: 100%;
|
||||
object-fit: fill;
|
||||
opacity: 5%;
|
||||
}
|
||||
|
||||
.index-action-selected {
|
||||
background-color: #EEEEF5;
|
||||
}
|
||||
|
||||
.markdownx .row {
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
@ -487,6 +497,14 @@
|
||||
background-color: #f33;
|
||||
}
|
||||
|
||||
.badge-orange {
|
||||
background-color: #fcba03;
|
||||
}
|
||||
|
||||
.badge-green {
|
||||
background-color: #1A1;
|
||||
}
|
||||
|
||||
.part-thumb {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
|
@ -7,7 +7,7 @@ import django
|
||||
|
||||
import common.models
|
||||
|
||||
INVENTREE_SW_VERSION = "0.1.6 pre"
|
||||
INVENTREE_SW_VERSION = "0.1.7 pre"
|
||||
|
||||
|
||||
def inventreeInstanceName():
|
||||
|
@ -242,6 +242,13 @@ class InvenTreeSetting(models.Model):
|
||||
'validator': bool,
|
||||
},
|
||||
|
||||
'STOCK_GROUP_BY_PART': {
|
||||
'name': _('Group by Part'),
|
||||
'description': _('Group stock items by part reference in table views'),
|
||||
'default': True,
|
||||
'validator': bool,
|
||||
},
|
||||
|
||||
'BUILDORDER_REFERENCE_PREFIX': {
|
||||
'name': _('Build Order Reference Prefix'),
|
||||
'description': _('Prefix value for build order reference'),
|
||||
|
@ -184,6 +184,8 @@ class SupplierPartList(generics.ListCreateAPIView):
|
||||
'manufacturer__name',
|
||||
'description',
|
||||
'MPN',
|
||||
'part__name',
|
||||
'part__description',
|
||||
]
|
||||
|
||||
|
||||
|
@ -83,12 +83,21 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<td><span class='fas fa-industry'></span></td>
|
||||
<td>{% trans "Manufacturer" %}</td>
|
||||
<td><a href="{% url 'company-detail-parts' part.manufacturer.id %}">{{ part.manufacturer.name }}</a></td></tr>
|
||||
{% endif %}
|
||||
{% if part.MPN %}
|
||||
<tr>
|
||||
<td><span class='fas fa-hashtag'></span></td>
|
||||
<td>{% trans "MPN" %}</td>
|
||||
<td>{{ part.MPN }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if part.packaging %}
|
||||
<tr>
|
||||
<td><span class='fas fa-cube'></span></td>
|
||||
<td>{% trans "Packaging" %}</td>
|
||||
<td>{{ part.packaging }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if part.note %}
|
||||
<tr>
|
||||
<td><span class='fas fa-sticky-note'></span></td>
|
||||
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.0.7 on 2021-02-19 04:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('report', '0012_buildreport'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='testreport',
|
||||
name='include_installed',
|
||||
field=models.BooleanField(default=False, help_text='Include test results for stock items installed inside assembled item', verbose_name='Include Installed Tests'),
|
||||
),
|
||||
]
|
@ -281,6 +281,12 @@ class TestReport(ReportTemplateBase):
|
||||
]
|
||||
)
|
||||
|
||||
include_installed = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_('Include Installed Tests'),
|
||||
help_text=_('Include test results for stock items installed inside assembled item')
|
||||
)
|
||||
|
||||
def matches_stock_item(self, item):
|
||||
"""
|
||||
Test if this report template matches a given StockItem objects
|
||||
@ -304,8 +310,8 @@ class TestReport(ReportTemplateBase):
|
||||
return {
|
||||
'stock_item': stock_item,
|
||||
'part': stock_item.part,
|
||||
'results': stock_item.testResultMap(),
|
||||
'result_list': stock_item.testResultList()
|
||||
'results': stock_item.testResultMap(include_installed=self.include_installed),
|
||||
'result_list': stock_item.testResultList(include_installed=self.include_installed)
|
||||
}
|
||||
|
||||
|
||||
|
@ -684,11 +684,18 @@ class StockList(generics.ListCreateAPIView):
|
||||
try:
|
||||
part = Part.objects.get(pk=part_id)
|
||||
|
||||
# Do we wish to filter *just* for this part, or also for parts *under* this one?
|
||||
include_variants = str2bool(params.get('include_variants', True))
|
||||
|
||||
if include_variants:
|
||||
# Filter by any parts "under" the given part
|
||||
parts = part.get_descendants(include_self=True)
|
||||
|
||||
queryset = queryset.filter(part__in=parts)
|
||||
|
||||
else:
|
||||
queryset = queryset.filter(part=part)
|
||||
|
||||
except (ValueError, Part.DoesNotExist):
|
||||
raise ValidationError({"part": "Invalid Part ID specified"})
|
||||
|
||||
|
@ -134,6 +134,7 @@ class CreateStockItemForm(HelperForm):
|
||||
'quantity',
|
||||
'batch',
|
||||
'serial_numbers',
|
||||
'packaging',
|
||||
'purchase_price',
|
||||
'expiry_date',
|
||||
'link',
|
||||
@ -414,6 +415,7 @@ class EditStockItemForm(HelperForm):
|
||||
'status',
|
||||
'expiry_date',
|
||||
'purchase_price',
|
||||
'packaging',
|
||||
'link',
|
||||
'delete_on_deplete',
|
||||
'owner',
|
||||
|
18
InvenTree/stock/migrations/0058_stockitem_packaging.py
Normal file
18
InvenTree/stock/migrations/0058_stockitem_packaging.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.0.7 on 2021-02-19 00:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('stock', '0057_stock_location_item_owner'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='stockitem',
|
||||
name='packaging',
|
||||
field=models.CharField(blank=True, help_text='Packaging this stock item is stored in', max_length=50, null=True, verbose_name='Packaging'),
|
||||
),
|
||||
]
|
@ -155,6 +155,7 @@ class StockItem(MPTTModel):
|
||||
infinite: If True this StockItem can never be exhausted
|
||||
sales_order: Link to a SalesOrder object (if the StockItem has been assigned to a SalesOrder)
|
||||
purchase_price: The unit purchase price for this StockItem - this is the unit price at time of purchase (if this item was purchased from an external supplier)
|
||||
packaging: Description of how the StockItem is packaged (e.g. "reel", "loose", "tape" etc)
|
||||
"""
|
||||
|
||||
# A Query filter which will be re-used in multiple places to determine if a StockItem is actually "in stock"
|
||||
@ -387,6 +388,13 @@ class StockItem(MPTTModel):
|
||||
help_text=_('Where is this stock item located?')
|
||||
)
|
||||
|
||||
packaging = models.CharField(
|
||||
max_length=50,
|
||||
blank=True, null=True,
|
||||
verbose_name=_('Packaging'),
|
||||
help_text=_('Packaging this stock item is stored in')
|
||||
)
|
||||
|
||||
belongs_to = models.ForeignKey(
|
||||
'self',
|
||||
verbose_name=_('Installed In'),
|
||||
@ -699,6 +707,41 @@ class StockItem(MPTTModel):
|
||||
|
||||
return True
|
||||
|
||||
def get_installed_items(self, cascade=False):
|
||||
"""
|
||||
Return all stock items which are *installed* in this one!
|
||||
|
||||
Args:
|
||||
cascade - Include items which are installed in items which are installed in items
|
||||
|
||||
Note: This function is recursive, and may result in a number of database hits!
|
||||
"""
|
||||
|
||||
installed = set()
|
||||
|
||||
items = StockItem.objects.filter(belongs_to=self)
|
||||
|
||||
for item in items:
|
||||
|
||||
# Prevent duplication or recursion
|
||||
if item == self or item in installed:
|
||||
continue
|
||||
|
||||
installed.add(item)
|
||||
|
||||
if cascade:
|
||||
sub_items = item.get_installed_items(cascade=True)
|
||||
|
||||
for sub_item in sub_items:
|
||||
|
||||
# Prevent recursion
|
||||
if sub_item == self or sub_item in installed:
|
||||
continue
|
||||
|
||||
installed.add(sub_item)
|
||||
|
||||
return installed
|
||||
|
||||
def installedItemCount(self):
|
||||
"""
|
||||
Return the number of stock items installed inside this one.
|
||||
@ -824,6 +867,27 @@ class StockItem(MPTTModel):
|
||||
|
||||
return query.exists()
|
||||
|
||||
@property
|
||||
def can_adjust_location(self):
|
||||
"""
|
||||
Returns True if the stock location can be "adjusted" for this part
|
||||
|
||||
Cannot be adjusted if:
|
||||
- Has been delivered to a customer
|
||||
- Has been installed inside another StockItem
|
||||
"""
|
||||
|
||||
if self.customer is not None:
|
||||
return False
|
||||
|
||||
if self.belongs_to is not None:
|
||||
return False
|
||||
|
||||
if self.sales_order is not None:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@property
|
||||
def tracking_info_count(self):
|
||||
return self.tracking_info.count()
|
||||
@ -1276,6 +1340,9 @@ class StockItem(MPTTModel):
|
||||
as all named tests are accessible.
|
||||
"""
|
||||
|
||||
# Do we wish to include test results from installed items?
|
||||
include_installed = kwargs.pop('include_installed', False)
|
||||
|
||||
# Filter results by "date", so that newer results
|
||||
# will override older ones.
|
||||
results = self.getTestResults(**kwargs).order_by('date')
|
||||
@ -1286,6 +1353,20 @@ class StockItem(MPTTModel):
|
||||
key = helpers.generateTestKey(result.test)
|
||||
result_map[key] = result
|
||||
|
||||
# Do we wish to "cascade" and include test results from installed stock items?
|
||||
cascade = kwargs.get('cascade', False)
|
||||
|
||||
if include_installed:
|
||||
installed_items = self.get_installed_items(cascade=cascade)
|
||||
|
||||
for item in installed_items:
|
||||
item_results = item.testResultMap()
|
||||
|
||||
for key in item_results.keys():
|
||||
# Results from sub items should not override master ones
|
||||
if key not in result_map.keys():
|
||||
result_map[key] = item_results[key]
|
||||
|
||||
return result_map
|
||||
|
||||
def testResultList(self, **kwargs):
|
||||
|
@ -198,6 +198,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
|
||||
'location',
|
||||
'location_detail',
|
||||
'notes',
|
||||
'packaging',
|
||||
'part',
|
||||
'part_detail',
|
||||
'pk',
|
||||
|
@ -155,7 +155,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
|
||||
<div class='btn-group'>
|
||||
<button id='stock-actions' title='{% trans "Stock adjustment actions" %}' class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'><span class='fas fa-boxes'></span> <span class='caret'></span></button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
{% if item.in_stock %}
|
||||
{% if item.can_adjust_location %}
|
||||
{% if not item.serialized %}
|
||||
<li><a href='#' id='stock-count' title='{% trans "Count stock" %}'><span class='fas fa-clipboard-list'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a href='#' id='stock-add' title='{% trans "Add stock" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
|
||||
@ -283,6 +283,13 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
|
||||
<td>{{ item.batch }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if item.packaging %}
|
||||
<tr>
|
||||
<td><span class='fas fa-cube'></span></td>
|
||||
<td>{% trans "Packaging" %}</td>
|
||||
<td>{{ item.packaging }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if item.build %}
|
||||
<tr>
|
||||
<td><span class='fas fa-tools'></span></td>
|
||||
|
@ -622,3 +622,62 @@ class TestResultTest(StockTest):
|
||||
item3 = StockItem.objects.get(serial=100, part=item2.part)
|
||||
|
||||
self.assertEqual(item3.test_results.count(), 4)
|
||||
|
||||
def test_installed_tests(self):
|
||||
"""
|
||||
Test test results for stock in stock.
|
||||
|
||||
Or, test "test results" for "stock items" installed "inside" a "stock item"
|
||||
"""
|
||||
|
||||
# Get a "master" stock item
|
||||
item = StockItem.objects.get(pk=105)
|
||||
|
||||
tests = item.testResultMap(include_installed=False)
|
||||
self.assertEqual(len(tests), 3)
|
||||
|
||||
# There are no "sub items" intalled at this stage
|
||||
tests = item.testResultMap(include_installed=False)
|
||||
self.assertEqual(len(tests), 3)
|
||||
|
||||
# Create a stock item which is installed *inside* the master item
|
||||
sub_item = StockItem.objects.create(
|
||||
part=item.part,
|
||||
quantity=1,
|
||||
belongs_to=item,
|
||||
location=None
|
||||
)
|
||||
|
||||
# Now, create some test results against the sub item
|
||||
|
||||
# First test is overshadowed by the same test for the parent part
|
||||
StockItemTestResult.objects.create(
|
||||
stock_item=sub_item,
|
||||
test='firmware version',
|
||||
date=datetime.datetime.now().date(),
|
||||
result=True
|
||||
)
|
||||
|
||||
# Should return the same number of tests as before
|
||||
tests = item.testResultMap(include_installed=True)
|
||||
self.assertEqual(len(tests), 3)
|
||||
|
||||
# Now, add a *unique* test result for the sub item
|
||||
StockItemTestResult.objects.create(
|
||||
stock_item=sub_item,
|
||||
test='some new test',
|
||||
date=datetime.datetime.now().date(),
|
||||
result=False,
|
||||
value='abcde',
|
||||
)
|
||||
|
||||
tests = item.testResultMap(include_installed=True)
|
||||
self.assertEqual(len(tests), 4)
|
||||
|
||||
self.assertIn('somenewtest', tests)
|
||||
self.assertEqual(sub_item.test_results.count(), 2)
|
||||
|
||||
# Check that asking for test result map for *top item only* still works
|
||||
tests = item.testResultMap(include_installed=False)
|
||||
self.assertEqual(len(tests), 3)
|
||||
self.assertNotIn('somenewtest', tests)
|
||||
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-times-circle icon-header'></span>
|
||||
{% trans "BOM Waiting Validation" %}<span class='badge' id='bom-invalid-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='bom-invalid-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-calendar-times icon-header'></span>
|
||||
{% trans "Overdue Builds" %}<span class='badge' id='build-overdue-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='build-overdue-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-cogs icon-header'></span>
|
||||
{% trans "Pending Builds" %}<span class='badge' id='build-pending-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='build-pending-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-calendar-times icon-header'></span>
|
||||
{% trans "Expired Stock" %}<span class='badge' id='expired-stock-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='expired-stock-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,5 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
{% block page_title %}
|
||||
InvenTree | {% trans "Index" %}
|
||||
@ -9,50 +10,96 @@ InvenTree | {% trans "Index" %}
|
||||
<h3>InvenTree</h3>
|
||||
<hr>
|
||||
|
||||
<div class='col-sm-4'>
|
||||
{% if roles.part.view %}
|
||||
{% include "InvenTree/latest_parts.html" with collapse_id="latest_parts" %}
|
||||
{% include "InvenTree/bom_invalid.html" with collapse_id="bom_invalid" %}
|
||||
{% include "InvenTree/starred_parts.html" with collapse_id="starred" %}
|
||||
{% endif %}
|
||||
{% if roles.build.view %}
|
||||
{% include "InvenTree/build_pending.html" with collapse_id="build_pending" %}
|
||||
{% include "InvenTree/build_overdue.html" with collapse_id="build_overdue" %}
|
||||
{% endif %}
|
||||
<div class='col-sm-3' id='item-panel'>
|
||||
<ul class='list-group' id='action-item-list'>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='col-sm-4'>
|
||||
{% if roles.stock.view %}
|
||||
{% include "InvenTree/low_stock.html" with collapse_id="order" %}
|
||||
{% settings_value "STOCK_ENABLE_EXPIRY" as expiry %}
|
||||
{% if expiry %}
|
||||
{% include "InvenTree/expired_stock.html" with collapse_id="expired" %}
|
||||
{% include "InvenTree/stale_stock.html" with collapse_id="stale" %}
|
||||
{% endif %}
|
||||
{% include "InvenTree/required_stock_build.html" with collapse_id="stock_to_build" %}
|
||||
{% endif %}
|
||||
<div class='col-sm-9' id='details-panel'>
|
||||
<ul class='list-group' id='detail-item-list'>
|
||||
<li class='list-group-item'>
|
||||
<div class='container'>
|
||||
<img class='index-bg' src='{% static "img/inventree.png" %}'>
|
||||
</div>
|
||||
<div class='col-sm-4'>
|
||||
{% if roles.purchase_order.view %}
|
||||
{% include "InvenTree/po_outstanding.html" with collapse_id="po_outstanding" %}
|
||||
{% endif %}
|
||||
{% include "InvenTree/po_overdue.html" with collapse_id="po_overdue" %}
|
||||
{% if roles.sales_order.view %}
|
||||
{% include "InvenTree/so_outstanding.html" with collapse_id="so_outstanding" %}
|
||||
{% include "InvenTree/so_overdue.html" with collapse_id="so_overdue" %}
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_ready %}
|
||||
|
||||
{{ block.super }}
|
||||
|
||||
loadSimplePartTable("#latest-parts-table", "{% url 'api-part-list' %}", {
|
||||
function addHeaderTitle(title) {
|
||||
// Add a header block to the action list
|
||||
$("#action-item-list").append(
|
||||
`<li class='list-group-item'><b>${title}</b></li>`
|
||||
);
|
||||
}
|
||||
|
||||
function addHeaderAction(label, title, icon, options) {
|
||||
// Add an action block to the action list
|
||||
$("#action-item-list").append(
|
||||
`<li class='list-group-item' id='action-${label}'>
|
||||
<a href='#'>
|
||||
<span class='fas ${icon}'></span>
|
||||
${title}
|
||||
</a>
|
||||
<span class='badge' id='badge-${label}'>
|
||||
<span class='fas fa-spin fa-spinner'></span>
|
||||
</span>
|
||||
</li>`
|
||||
);
|
||||
|
||||
// Add a detail item to the detail item-panel
|
||||
$("#detail-item-list").append(
|
||||
`<li class='list-group-item' id='detail-${label}'>
|
||||
<h4>${title}</h4>
|
||||
<table class='table table-condensed table-striped' id='table-${label}'></table>
|
||||
</li>`
|
||||
);
|
||||
|
||||
$(`#detail-${label}`).hide();
|
||||
|
||||
$(`#action-${label}`).click(function() {
|
||||
|
||||
// Hide all child elements
|
||||
$('#detail-item-list').children('li').each(function() {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
// Show the one we want
|
||||
$(`#detail-${label}`).fadeIn();
|
||||
|
||||
// Remove css class from all action items
|
||||
$("#action-item-list").children('li').each(function() {
|
||||
$(this).removeClass('index-action-selected');
|
||||
});
|
||||
|
||||
// Add css class to the action we are interested in
|
||||
$(`#action-${label}`).addClass('index-action-selected');
|
||||
});
|
||||
|
||||
// Connect a callback to the table
|
||||
$(`#table-${label}`).on('load-success.bs.table', function() {
|
||||
var count = $(`#table-${label}`).bootstrapTable('getData').length;
|
||||
|
||||
$(`#badge-${label}`).html(count);
|
||||
|
||||
if (count > 0) {
|
||||
$(`#badge-${label}`).addClass('badge-orange');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{% if roles.part.view %}
|
||||
addHeaderTitle('{% trans "Parts" %}');
|
||||
addHeaderAction('starred-parts', '{% trans "Starred Parts" %}', 'fa-star');
|
||||
addHeaderAction('latest-parts', '{% trans "Latest Parts" %}', 'fa-newspaper');
|
||||
addHeaderAction('bom-validation', '{% trans "BOM Waiting Validation" %}', 'fa-times-circle');
|
||||
|
||||
|
||||
loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
ordering: "-creation_date",
|
||||
limit: 10,
|
||||
@ -60,21 +107,71 @@ loadSimplePartTable("#latest-parts-table", "{% url 'api-part-list' %}", {
|
||||
name: 'latest_parts',
|
||||
});
|
||||
|
||||
loadSimplePartTable("#starred-parts-table", "{% url 'api-part-list' %}", {
|
||||
loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
"starred": true,
|
||||
},
|
||||
name: 'starred_parts',
|
||||
});
|
||||
|
||||
loadSimplePartTable("#bom-invalid-table", "{% url 'api-part-list' %}", {
|
||||
loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
"bom_valid": false,
|
||||
},
|
||||
name: 'bom_invalid_parts',
|
||||
});
|
||||
|
||||
loadBuildTable("#build-pending-table", {
|
||||
{% endif %}
|
||||
|
||||
{% if roles.stock.view %}
|
||||
addHeaderTitle('{% trans "Stock" %}');
|
||||
addHeaderAction('low-stock', '{% trans "Low Stock" %}', 'fa-shopping-cart');
|
||||
addHeaderAction('stock-to-build', '{% trans "Required for Build Orders" %}', 'fa-bullhorn');
|
||||
{% settings_value "STOCK_ENABLE_EXPIRY" as expiry %}
|
||||
{% if expiry %}
|
||||
addHeaderAction('expired-stock', '{% trans "Expired Stock" %}', 'fa-calendar-times');
|
||||
addHeaderAction('stale-stock', '{% trans "Stale Stock" %}', 'fa-stopwatch');
|
||||
|
||||
loadStockTable($("#table-expired-stock"), {
|
||||
params: {
|
||||
expired: true,
|
||||
location_detail: true,
|
||||
part_detail: true,
|
||||
},
|
||||
});
|
||||
|
||||
loadStockTable($("#table-stale-stock"), {
|
||||
params: {
|
||||
stale: true,
|
||||
expired: false,
|
||||
location_detail: true,
|
||||
part_detail: true,
|
||||
},
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
low_stock: true,
|
||||
},
|
||||
name: "low_stock_parts",
|
||||
});
|
||||
|
||||
loadSimplePartTable("#table-stock-to-build", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
stock_to_build: true,
|
||||
},
|
||||
name: "to_build_parts",
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if roles.build.view %}
|
||||
addHeaderTitle('{% trans "Build Orders" %}');
|
||||
addHeaderAction('build-pending', '{% trans "Build Orders In Progress" %}', 'fa-cogs');
|
||||
addHeaderAction('build-overdue', '{% trans "Overdue Build Orders" %}', 'fa-calendar-times');
|
||||
|
||||
loadBuildTable("#table-build-pending", {
|
||||
url: "{% url 'api-build-list' %}",
|
||||
params: {
|
||||
part_detail: true,
|
||||
@ -83,7 +180,7 @@ loadBuildTable("#build-pending-table", {
|
||||
disableFilters: true,
|
||||
});
|
||||
|
||||
loadBuildTable("#build-overdue-table", {
|
||||
loadBuildTable("#table-build-overdue", {
|
||||
url: "{% url 'api-build-list' %}",
|
||||
params: {
|
||||
part_detail: true,
|
||||
@ -91,39 +188,14 @@ loadBuildTable("#build-overdue-table", {
|
||||
},
|
||||
disableFilters: true,
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
loadStockTable($("#expired-stock-table"), {
|
||||
params: {
|
||||
expired: true,
|
||||
location_detail: true,
|
||||
part_detail: true,
|
||||
},
|
||||
});
|
||||
{% if roles.purchase_order.view %}
|
||||
addHeaderTitle('{% trans "Purchase Orders" %}');
|
||||
addHeaderAction('po-outstanding', '{% trans "Outstanding Purchase Orders" %}', 'fa-sign-in-alt');
|
||||
addHeaderAction('po-overdue', '{% trans "Overdue Purchase Orders" %}', 'fa-calendar-times');
|
||||
|
||||
loadStockTable($("#stale-stock-table"), {
|
||||
params: {
|
||||
stale: true,
|
||||
expired: false,
|
||||
location_detail: true,
|
||||
part_detail: true,
|
||||
},
|
||||
});
|
||||
|
||||
loadSimplePartTable("#low-stock-table", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
low_stock: true,
|
||||
},
|
||||
name: "low_stock_parts",
|
||||
});
|
||||
|
||||
loadSimplePartTable("#stock-to-build-table", "{% url 'api-part-list' %}", {
|
||||
params: {
|
||||
stock_to_build: true,
|
||||
},
|
||||
name: "to_build_parts",
|
||||
});
|
||||
|
||||
loadPurchaseOrderTable("#po-outstanding-table", {
|
||||
loadPurchaseOrderTable("#table-po-outstanding", {
|
||||
url: "{% url 'api-po-list' %}",
|
||||
params: {
|
||||
supplier_detail: true,
|
||||
@ -131,7 +203,7 @@ loadPurchaseOrderTable("#po-outstanding-table", {
|
||||
}
|
||||
});
|
||||
|
||||
loadPurchaseOrderTable("#po-overdue-table", {
|
||||
loadPurchaseOrderTable("#table-po-overdue", {
|
||||
url: "{% url 'api-po-list' %}",
|
||||
params: {
|
||||
supplier_detail: true,
|
||||
@ -139,7 +211,14 @@ loadPurchaseOrderTable("#po-overdue-table", {
|
||||
}
|
||||
});
|
||||
|
||||
loadSalesOrderTable("#so-outstanding-table", {
|
||||
{% endif %}
|
||||
|
||||
{% if roles.sales_order.view %}
|
||||
addHeaderTitle('{% trans "Sales Orders" %}');
|
||||
addHeaderAction('so-outstanding', '{% trans "Outstanding Sales Orders" %}', 'fa-sign-out-alt');
|
||||
addHeaderAction('so-overdue', '{% trans "Overdue Sales Orders" %}', 'fa-calendar-times');
|
||||
|
||||
loadSalesOrderTable("#table-so-outstanding", {
|
||||
url: "{% url 'api-so-list' %}",
|
||||
params: {
|
||||
customer_detail: true,
|
||||
@ -147,7 +226,7 @@ loadSalesOrderTable("#so-outstanding-table", {
|
||||
},
|
||||
});
|
||||
|
||||
loadSalesOrderTable("#so-overdue-table", {
|
||||
loadSalesOrderTable("#table-so-overdue", {
|
||||
url: "{% url 'api-so-list' %}",
|
||||
params: {
|
||||
overdue: true,
|
||||
@ -155,20 +234,6 @@ loadSalesOrderTable("#so-overdue-table", {
|
||||
}
|
||||
});
|
||||
|
||||
{% include "InvenTree/index/on_load.html" with label="latest-parts" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="starred-parts" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="bom-invalid" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="build-pending" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="build-overdue" %}
|
||||
|
||||
{% include "InvenTree/index/on_load.html" with label="expired-stock" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="stale-stock" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="low-stock" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="stock-to-build" %}
|
||||
|
||||
{% include "InvenTree/index/on_load.html" with label="po-outstanding" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="po-overdue" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="so-outstanding" %}
|
||||
{% include "InvenTree/index/on_load.html" with label="so-overdue" %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@ -1,5 +0,0 @@
|
||||
$("#{{ label }}-table").on('load-success.bs.table', function() {
|
||||
var count = $("#{{ label }}-table").bootstrapTable('getData').length;
|
||||
|
||||
$("#{{ label }}-count").html(count);
|
||||
});
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-newspaper icon-header'></span>
|
||||
{% trans "Latest Parts" %}<span class='badge' id='latest-parts-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='latest-parts-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-shopping-cart icon-header'></span>
|
||||
{% trans "Low Stock" %}<span class='badge' id='low-stock-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='low-stock-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-sign-in-alt icon-header'></span>
|
||||
{% trans "Outstanding Purchase Orders" %}<span class='badge' id='po-outstanding-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='po-outstanding-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-calendar-times icon-header'></span>
|
||||
{% trans "Overdue Purchase Orders" %}<span class='badge' id='po-overdue-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='po-overdue-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-bullhorn icon-header'></span>
|
||||
{% trans "Require Stock To Complete Build" %}<span class='badge' id='stock-to-build-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='stock-to-build-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -9,98 +9,123 @@ InvenTree | {% trans "Search Results" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3>{% trans "Search Results" %}</h3>
|
||||
<h3>
|
||||
{% trans "Search Results" %}
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<div class="container" style='width: 100%'>
|
||||
{% include "search_form.html" with query_text=query %}
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
<hr>
|
||||
|
||||
{% if query %}
|
||||
|
||||
<div id='no-search-results'>
|
||||
<h4><i>{% trans "No results found for " %}'{{ query }}'</i></h4>
|
||||
</div>
|
||||
|
||||
{% include "InvenTree/search_part_category.html" with collapse_id="categories" %}
|
||||
|
||||
{% include "InvenTree/search_parts.html" with collapse_id='parts' %}
|
||||
|
||||
{% include "InvenTree/search_company.html" with collapse_id='companies' %}
|
||||
|
||||
{% include "InvenTree/search_supplier_parts.html" with collapse_id='supplier_parts' %}
|
||||
|
||||
{% include "InvenTree/search_stock_location.html" with collapse_id="locations" %}
|
||||
|
||||
{% include "InvenTree/search_stock_items.html" with collapse_id="stock" %}
|
||||
|
||||
{% else %}
|
||||
|
||||
<div id='empty-search-query'>
|
||||
<h4><i>{% trans "Enter a search query" %}</i></h4>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
<div class='col-sm-3' id='item-panel'>
|
||||
<ul class='list-group' id='search-item-list'>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='col-sm-9' id='details-panel'>
|
||||
<ul class='list-group' id='search-result-list'>
|
||||
<li class='list-group-item'>
|
||||
<div class='container'>
|
||||
<img class='index-bg' src='{% static "img/inventree.png" %}'>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% block js_load %}
|
||||
{{ block.super }}
|
||||
<script type='text/javascript' src="{% static 'script/inventree/part.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
function onSearchResults(table, output) {
|
||||
|
||||
$(table).on('load-success.bs.table', function() {
|
||||
|
||||
var panel = $(output).closest('.panel-group');
|
||||
|
||||
var n = $(table).bootstrapTable('getData').length;
|
||||
|
||||
var text = '';
|
||||
if (n == 0) {
|
||||
text = '<i>No results</i>'
|
||||
|
||||
$(panel).hide();
|
||||
|
||||
} else {
|
||||
text = n + ' result';
|
||||
|
||||
if (n > 1) {
|
||||
text += 's';
|
||||
function addItemTitle(title) {
|
||||
// Add header block to the results list
|
||||
$('#search-item-list').append(
|
||||
`<li class='list-group-item'><b>${title}</b></li>`
|
||||
);
|
||||
}
|
||||
|
||||
$(panel).show();
|
||||
function addItem(label, title, icon, options) {
|
||||
// Add a search itme to the action list
|
||||
$('#search-item-list').append(
|
||||
`<li class='list-group-item' id='search-item-${label}'>
|
||||
<a href='#'>
|
||||
<span class='fas ${icon}'></span>
|
||||
${title}
|
||||
</a>
|
||||
<span class='badge' id='badge-${label}'>
|
||||
<span class='fas fa-spin fa-spinner'></span>
|
||||
</span>
|
||||
</li>`
|
||||
);
|
||||
|
||||
var collapse = panel.find('.panel-collapse');
|
||||
// Add a results table
|
||||
$('#search-result-list').append(
|
||||
`<li class='list-group-item' id='search-result-${label}'>
|
||||
<h4>${title}</h4>
|
||||
<table class='table table-condensed table-striped' id='table-${label}'></table>
|
||||
</li>`
|
||||
);
|
||||
|
||||
collapse.collapse('show');
|
||||
// Hide the results table
|
||||
$(`#search-result-${label}`).hide();
|
||||
|
||||
$("#no-search-results").hide();
|
||||
// Add callback when the action is clicked
|
||||
$(`#search-item-${label}`).click(function() {
|
||||
|
||||
// Hide all childs
|
||||
$('#search-result-list').children('li').each(function() {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
// Show the one we want
|
||||
$(`#search-result-${label}`).fadeIn();
|
||||
|
||||
// Remove css class from all action items
|
||||
$("#search-item-list").children('li').each(function() {
|
||||
$(this).removeClass('index-action-selected');
|
||||
});
|
||||
|
||||
// Add css class to the action we are interested in
|
||||
$(`#search-item-${label}`).addClass('index-action-selected');
|
||||
});
|
||||
|
||||
// Connect a callback to the table
|
||||
$(`#table-${label}`).on('load-success.bs.table', function() {
|
||||
var count = $(`#table-${label}`).bootstrapTable('getData').length;
|
||||
|
||||
$(`#badge-${label}`).html(count);
|
||||
|
||||
if (count > 0) {
|
||||
$(`#badge-${label}`).addClass('badge-orange');
|
||||
}
|
||||
|
||||
$(output).html(`<i>${text}</i>`);
|
||||
});
|
||||
}
|
||||
|
||||
onSearchResults("#category-results-table", "#category-results-count");
|
||||
{% if roles.part.view %}
|
||||
addItemTitle('{% trans "Part" %}');
|
||||
|
||||
onSearchResults("#location-results-table", "#location-results-count");
|
||||
addItem('part', '{% trans "Parts" %}', 'fa-shapes');
|
||||
|
||||
onSearchResults("#stock-results-table", "#stock-results-count");
|
||||
loadPartTable("#table-part",
|
||||
"{% url 'api-part-list' %}",
|
||||
{
|
||||
params: {
|
||||
search: "{{ query }}",
|
||||
},
|
||||
checkbox: false,
|
||||
disableFilters: true,
|
||||
}
|
||||
);
|
||||
|
||||
onSearchResults('#part-results-table', '#part-result-count');
|
||||
addItem('category', '{% trans "Part Categories" %}', 'fa-sitemap');
|
||||
|
||||
onSearchResults('#company-results-table', '#company-result-count');
|
||||
|
||||
onSearchResults('#supplier-part-results-table', '#supplier-part-result-count');
|
||||
|
||||
$("#category-results-table").inventreeTable({
|
||||
$("#table-category").inventreeTable({
|
||||
url: "{% url 'api-part-category-list' %}",
|
||||
queryParams: {
|
||||
search: "{{ query }}",
|
||||
@ -120,7 +145,29 @@ InvenTree | {% trans "Search Results" %}
|
||||
],
|
||||
});
|
||||
|
||||
$('#stock-results-table').inventreeTable({
|
||||
addItem('supplier-part', '{% trans "Supplier Parts" %}', 'fa-pallet');
|
||||
|
||||
loadSupplierPartTable(
|
||||
"#table-supplier-part",
|
||||
"{% url 'api-supplier-part-list' %}",
|
||||
{
|
||||
params: {
|
||||
search: "{{ query }}",
|
||||
part_detail: true,
|
||||
supplier_detail: true,
|
||||
manufacturer_detail: true
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if roles.stock.view %}
|
||||
addItemTitle('{% trans "Stock" %}');
|
||||
|
||||
addItem('stock', '{% trans "Stock Items" %}', 'fa-boxes');
|
||||
|
||||
$('#table-stock').inventreeTable({
|
||||
url: "{% url 'api-stock-list' %}",
|
||||
queryParams: {
|
||||
search: "{{ query }}",
|
||||
@ -199,8 +246,9 @@ InvenTree | {% trans "Search Results" %}
|
||||
]
|
||||
});
|
||||
|
||||
addItem('location', '{% trans "Stock Locations" %}', 'fa-map-marker-alt');
|
||||
|
||||
$("#location-results-table").inventreeTable({
|
||||
$("#table-location").inventreeTable({
|
||||
url: "{% url 'api-location-list' %}",
|
||||
queryParams: {
|
||||
search: "{{ query }}",
|
||||
@ -220,36 +268,48 @@ InvenTree | {% trans "Search Results" %}
|
||||
],
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
|
||||
loadPartTable("#part-results-table",
|
||||
"{% url 'api-part-list' %}",
|
||||
{
|
||||
params: {
|
||||
search: "{{ query }}",
|
||||
},
|
||||
checkbox: false,
|
||||
disableFilters: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
loadCompanyTable('#company-results-table', "{% url 'api-company-list' %}", {
|
||||
{% if roles.purchase_order.view or roles.sales_order.view %}
|
||||
addItemTitle('{% trans "Company" %}');
|
||||
|
||||
{% if roles.purchase_order.view %}
|
||||
addItem('supplier', '{% trans "Suppliers" %}', 'fa-building');
|
||||
|
||||
loadCompanyTable('#table-supplier', "{% url 'api-company-list' %}", {
|
||||
params: {
|
||||
search: "{{ query }}",
|
||||
is_supplier: "true",
|
||||
}
|
||||
});
|
||||
|
||||
loadSupplierPartTable(
|
||||
"#supplier-part-results-table",
|
||||
"{% url 'api-supplier-part-list' %}",
|
||||
{
|
||||
addItem('manufacturer', '{% trans "Manufacturers" %}', 'fa-industry');
|
||||
|
||||
loadCompanyTable('#table-manufacturer', "{% url 'api-company-list' %}", {
|
||||
params: {
|
||||
search: "{{ query }}",
|
||||
part_detail: true,
|
||||
supplier_detail: true,
|
||||
manufacturer_detail: true
|
||||
},
|
||||
is_manufacturer: "true",
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if roles.sales_order.view %}
|
||||
addItem('customer', '{% trans "Customers" %}', 'fa-user-tie');
|
||||
|
||||
loadCompanyTable('#table-customer', "{% url 'api-company-list' %}", {
|
||||
params: {
|
||||
search: "{{ query }}",
|
||||
is_customer: "true",
|
||||
}
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
@ -1,14 +0,0 @@
|
||||
{% extends "collapse.html" %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<h4>Companies</h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_heading %}
|
||||
<h4><span id='company-result-count'>{% include "InvenTree/searching.html" %}</span></h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
<table class='table table-striped table-condensed' data-toolbar="#button-toolbar" id='company-results-table'>
|
||||
</table>
|
||||
{% endblock %}
|
@ -1,14 +0,0 @@
|
||||
{% extends "collapse.html" %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<h4>Part Categories</h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_heading %}
|
||||
<h4><span id='category-results-count'>{% include "InvenTree/searching.html" %}</span></h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
<table class='table table-striped table-condensed' data-toolbar="#button-toolbar" id='category-results-table'>
|
||||
</table>
|
||||
{% endblock %}
|
@ -1,21 +0,0 @@
|
||||
{% extends "collapse.html" %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<h4>Parts</h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_heading %}
|
||||
<h4><span id='part-result-count'>{% include "InvenTree/searching.html" %}</span></h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
<div id='button-toolbar'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<button class='btn btn-default'>Hello</button>
|
||||
<div class='filter-list' id='filter-list-parts'></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' data-toolbar="#button-toolbar" id='part-results-table'>
|
||||
</table>
|
||||
{% endblock %}
|
@ -1,16 +0,0 @@
|
||||
{% extends "collapse.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<h4>{% trans "Stock Items" %}</h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_heading %}
|
||||
<h4><span id='stock-results-count'>{% include "InvenTree/searching.html" %}</span></h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
<table class='table table-striped table-condensed' data-toolbar="#button-toolbar" id='stock-results-table'>
|
||||
</table>
|
||||
{% endblock %}
|
@ -1,16 +0,0 @@
|
||||
{% extends "collapse.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<h4>{% trans "Stock Locations" %}</h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_heading %}
|
||||
<h4><span id='location-results-count'>{% include "InvenTree/searching.html" %}</span></h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
<table class='table table-striped table-condensed' data-toolbar="#button-toolbar" id='location-results-table'>
|
||||
</table>
|
||||
{% endblock %}
|
@ -1,14 +0,0 @@
|
||||
{% extends "collapse.html" %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<h4>Supplier Parts</h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_heading %}
|
||||
<h4><span id='supplier-part-result-count'>{% include "InvenTree/searching.html" %}</span></h4>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
<table class='table table-striped table-condensed' data-toolbar="#button-toolbar" id='supplier-part-results-table'>
|
||||
</table>
|
||||
{% endblock %}
|
@ -1,3 +0,0 @@
|
||||
{% load i18n %}
|
||||
|
||||
<span class='fas fa-spin fa-spinner'></span> <i>{% trans "Searching" %}</i>
|
@ -15,11 +15,12 @@
|
||||
<table class='table table-striped table-condensed'>
|
||||
{% include "InvenTree/settings/header.html" %}
|
||||
<tbody>
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_BUILD" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_GROUP_BY_PART" icon="fa-layer-group" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" icon="fa-stopwatch" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" icon="fa-calendar" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" icon="fa-truck" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_BUILD" icon="fa-tools" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" icon="fa-users" %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-sign-out-alt icon-header'></span>
|
||||
{% trans "Outstanding Sales Orders" %}<span class='badge' id='so-outstanding-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='so-outstanding-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-calendar-times icon-header'></span>
|
||||
{% trans "Overdue Sales Orders" %}<span class='badge' id='so-overdue-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='so-overdue-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-stopwatch icon-header'></span>
|
||||
{% trans "Stale Stock" %}<span class='badge' id='stale-stock-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='stale-stock-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
{% extends "collapse_index.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block collapse_title %}
|
||||
<span class='fas fa-star icon-header'></span>
|
||||
{% trans "Starred Parts" %}<span class='badge' id='starred-parts-count'><span class='fas fa-spin fa-spinner'></span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block collapse_content %}
|
||||
|
||||
<table class='table table-striped table-condensed' id='starred-parts-table'>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -12,6 +12,7 @@
|
||||
<img src="{% static 'img/inventree.png' %}" height='60' style='float: left;' alt='Inventree Logo'>
|
||||
<h3>{% trans "InvenTree Version Information" %}</h3>
|
||||
</div>
|
||||
<div class='modal-form-content-wrapper'>
|
||||
<div class='modal-form-content'>
|
||||
<div>
|
||||
<table class='table table-striped table-condensed'>
|
||||
@ -39,7 +40,13 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fab fa-github'></span></td>
|
||||
<td>{% trans "View Code on GitHub" %}</td><td><a href="{% inventree_github_url %}">{% inventree_github_url %}</a></td>
|
||||
<td>{% trans "View Code on GitHub" %}</td>
|
||||
<td><a href="{% inventree_github_url %}">{% inventree_github_url %}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-mobile-alt'></span></td>
|
||||
<td>{% trans "Get the App" %}</td>
|
||||
<td><a href="https://inventree.readthedocs.io/en/latest/app/app">https://inventree.readthedocs.io/en/latest/app/app</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-bug'></span></td>
|
||||
@ -50,6 +57,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='modal-footer'>
|
||||
<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>
|
||||
</div>
|
||||
|
@ -327,11 +327,13 @@ function loadStockTable(table, options) {
|
||||
url: options.url || "{% url 'api-stock-list' %}",
|
||||
queryParams: filters,
|
||||
customSort: customGroupSorter,
|
||||
groupBy: true,
|
||||
name: 'stock',
|
||||
original: original,
|
||||
showColumns: true,
|
||||
{% settings_value 'STOCK_GROUP_BY_PART' as group_by_part %}
|
||||
{% if group_by_part %}
|
||||
groupByField: options.groupByField || 'part',
|
||||
groupBy: true,
|
||||
groupByFormatter: function(field, id, data) {
|
||||
|
||||
var row = data[0];
|
||||
@ -359,6 +361,29 @@ function loadStockTable(table, options) {
|
||||
else if (field == 'part_detail.description') {
|
||||
return row.part_detail.description;
|
||||
}
|
||||
else if (field == 'packaging') {
|
||||
var packaging = [];
|
||||
|
||||
data.forEach(function(item) {
|
||||
var pkg = item.packaging;
|
||||
|
||||
if (!pkg) {
|
||||
pkg = '-';
|
||||
}
|
||||
|
||||
if (!packaging.includes(pkg)) {
|
||||
packaging.push(pkg);
|
||||
}
|
||||
});
|
||||
|
||||
if (packaging.length > 1) {
|
||||
return "...";
|
||||
} else if (packaging.length == 1) {
|
||||
return packaging[0];
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
else if (field == 'quantity') {
|
||||
var stock = 0;
|
||||
var items = 0;
|
||||
@ -388,7 +413,7 @@ function loadStockTable(table, options) {
|
||||
|
||||
// Multiple status codes
|
||||
if (statii.length > 1) {
|
||||
return "-";
|
||||
return "...";
|
||||
} else if (statii.length == 1) {
|
||||
return stockStatusDisplay(statii[0]);
|
||||
} else {
|
||||
@ -468,6 +493,7 @@ function loadStockTable(table, options) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
columns: [
|
||||
{
|
||||
checkbox: true,
|
||||
@ -619,6 +645,12 @@ function loadStockTable(table, options) {
|
||||
title: '{% trans "Last Updated" %}',
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'packaging',
|
||||
title: '{% trans "Packaging" %}',
|
||||
sortable: true,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
field: 'notes',
|
||||
title: '{% trans "Notes" %}',
|
||||
|
@ -130,6 +130,11 @@ function getAvailableTableFilters(tableKey) {
|
||||
title: '{% trans "In Production" %}',
|
||||
description: '{% trans "Show items which are in production" %}',
|
||||
},
|
||||
include_variants: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Include Variants" %}',
|
||||
description: '{% trans "Include stock items for variant parts" %}',
|
||||
},
|
||||
installed: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Installed" %}',
|
||||
|
Loading…
Reference in New Issue
Block a user