Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2019-11-16 20:45:34 +11:00
commit 6e54c49142
10 changed files with 481 additions and 79 deletions

View File

@ -125,6 +125,28 @@ function loadStockTable(table, options) {
// A single location! // A single location!
return renderLink(row.location__path, '/stock/location/' + row.location + '/') return renderLink(row.location__path, '/stock/location/' + row.location + '/')
} }
} else if (field == 'notes') {
var notes = [];
data.forEach(function(item) {
var note = item.notes;
if (!note || note == '') {
note = '-';
}
if (!notes.includes(note)) {
notes.push(note);
}
});
if (notes.length > 1) {
return '...';
} else if (notes.length == 1) {
return notes[0] || '-';
} else {
return '-';
}
} }
else { else {
return ''; return '';
@ -288,6 +310,18 @@ function loadStockTable(table, options) {
}, },
}); });
}); });
$("#multi-item-delete").click(function() {
var selections = $("#stock-table").bootstrapTable("getSelections");
var stock = [];
selections.forEach(function(item) {
stock.push(item.pk);
});
stockAdjustment('delete');
});
} }

View File

@ -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: 2019-09-27 00:12+0000\n" "POT-Creation-Date: 2019-11-16 09:28+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"
@ -149,7 +149,7 @@ msgstr ""
msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgid "Allocated quantity ({n}) must not exceed available quantity ({q})"
msgstr "" msgstr ""
#: build/views.py:289 stock/views.py:834 #: build/views.py:289 stock/views.py:859
#, python-brace-format #, python-brace-format
msgid "The following serial numbers already exist: ({sn})" msgid "The following serial numbers already exist: ({sn})"
msgstr "" msgstr ""
@ -190,6 +190,10 @@ msgstr ""
msgid "Use this currency as the base currency" msgid "Use this currency as the base currency"
msgstr "" msgstr ""
#: company/templates/company/partdelete.html:5
msgid "Are you sure you want to delete the following Supplier Parts?"
msgstr ""
#: order/forms.py:21 #: order/forms.py:21
msgid "Place order" msgid "Place order"
msgstr "" msgstr ""
@ -247,7 +251,7 @@ msgstr ""
msgid "Line item notes" msgid "Line item notes"
msgstr "" msgstr ""
#: order/models.py:275 #: order/models.py:275 stock/templates/stock/item.html:106
msgid "Purchase Order" msgid "Purchase Order"
msgstr "" msgstr ""
@ -409,7 +413,7 @@ msgstr ""
msgid "Variant Of" msgid "Variant Of"
msgstr "" msgstr ""
#: part/templates/part/detail.html:49 #: part/templates/part/detail.html:49 stock/templates/stock/item.html:118
msgid "URL" msgid "URL"
msgstr "" msgstr ""
@ -497,7 +501,7 @@ msgstr ""
msgid "Part cannot be sold to customers" msgid "Part cannot be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:151 #: part/templates/part/detail.html:151 stock/templates/stock/item.html:150
msgid "Notes" msgid "Notes"
msgstr "" msgstr ""
@ -585,6 +589,10 @@ msgstr ""
msgid "Item cannot belong to itself" msgid "Item cannot belong to itself"
msgstr "" msgstr ""
#: stock/models.py:360
msgid "Stock Item Notes"
msgstr ""
#: stock/models.py:434 #: stock/models.py:434
msgid "Quantity must be integer" msgid "Quantity must be integer"
msgstr "" msgstr ""
@ -615,6 +623,79 @@ msgstr ""
msgid "Serialized {n} items" msgid "Serialized {n} items"
msgstr "" msgstr ""
#: stock/templates/stock/item.html:8
msgid "Stock Item Details"
msgstr ""
#: stock/templates/stock/item.html:51
msgid ""
"This stock item is serialized - it has a unique serial number and the "
"quantity cannot be adjusted."
msgstr ""
#: stock/templates/stock/item.html:55
msgid ""
"This stock item will be automatically deleted when all stock is depleted."
msgstr ""
#: stock/templates/stock/item.html:72
msgid "Belongs To"
msgstr ""
#: stock/templates/stock/item.html:77
#: stock/templates/stock/stock_adjust.html:16
msgid "Location"
msgstr ""
#: stock/templates/stock/item.html:83
msgid "Serial Number"
msgstr ""
#: stock/templates/stock/item.html:88
#: stock/templates/stock/stock_adjust.html:20
msgid "Quantity"
msgstr ""
#: stock/templates/stock/item.html:94
msgid "Batch"
msgstr ""
#: stock/templates/stock/item.html:100
msgid "Build"
msgstr ""
#: stock/templates/stock/item.html:112
msgid "Customer"
msgstr ""
#: stock/templates/stock/item.html:124
msgid "Supplier"
msgstr ""
#: stock/templates/stock/item.html:128
msgid "Supplier Part"
msgstr ""
#: stock/templates/stock/item.html:133
msgid "Last Updated"
msgstr ""
#: stock/templates/stock/item.html:137
msgid "Last Stocktake"
msgstr ""
#: stock/templates/stock/item.html:141
msgid "No stocktake performed"
msgstr ""
#: stock/templates/stock/item.html:145
msgid "Status"
msgstr ""
#: stock/templates/stock/item.html:159
msgid "Stock Tracking Information"
msgstr ""
#: stock/templates/stock/location.html:37 #: stock/templates/stock/location.html:37
msgid "Location Details" msgid "Location Details"
msgstr "" msgstr ""
@ -644,51 +725,80 @@ msgstr ""
msgid "Stock Locations" msgid "Stock Locations"
msgstr "" msgstr ""
#: stock/views.py:399 #: stock/templates/stock/stock_adjust.html:15
msgid "Must enter integer value" msgid "Stock Item"
msgstr ""
#: stock/views.py:373
msgid "Move Stock Items"
msgstr ""
#: stock/views.py:374
msgid "Count Stock Items"
msgstr ""
#: stock/views.py:375
msgid "Remove From Stock"
msgstr ""
#: stock/views.py:376
msgid "Add Stock Items"
msgstr ""
#: stock/views.py:377
msgid "Delete Stock Items"
msgstr "" msgstr ""
#: stock/views.py:404 #: stock/views.py:404
msgid "Must enter integer value"
msgstr ""
#: stock/views.py:409
msgid "Quantity must be positive" msgid "Quantity must be positive"
msgstr "" msgstr ""
#: stock/views.py:411 #: stock/views.py:416
#, python-brace-format #, python-brace-format
msgid "Quantity must not exceed {x}" msgid "Quantity must not exceed {x}"
msgstr "" msgstr ""
#: stock/views.py:419 #: stock/views.py:424
msgid "Confirm stock adjustment" msgid "Confirm stock adjustment"
msgstr "" msgstr ""
#: stock/views.py:487 #: stock/views.py:495
#, python-brace-format #, python-brace-format
msgid "Added stock to {n} items" msgid "Added stock to {n} items"
msgstr "" msgstr ""
#: stock/views.py:502 #: stock/views.py:510
#, python-brace-format #, python-brace-format
msgid "Removed stock from {n} items" msgid "Removed stock from {n} items"
msgstr "" msgstr ""
#: stock/views.py:515 #: stock/views.py:523
#, python-brace-format #, python-brace-format
msgid "Counted stock for {n} items" msgid "Counted stock for {n} items"
msgstr "" msgstr ""
#: stock/views.py:543 #: stock/views.py:551
msgid "No items were moved" msgid "No items were moved"
msgstr "" msgstr ""
#: stock/views.py:546 #: stock/views.py:554
#, python-brace-format #, python-brace-format
msgid "Moved {n} items to {dest}" msgid "Moved {n} items to {dest}"
msgstr "" msgstr ""
#: stock/views.py:813 #: stock/views.py:573
#, python-brace-format
msgid "Deleted {n} stock items"
msgstr ""
#: stock/views.py:838
msgid "Invalid part selection" msgid "Invalid part selection"
msgstr "" msgstr ""
#: stock/views.py:875 #: stock/views.py:900
msgid "Created new stock item" msgid "Created new stock item"
msgstr "" msgstr ""

View File

@ -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: 2019-09-27 00:12+0000\n" "POT-Creation-Date: 2019-11-16 09:28+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"
@ -149,7 +149,7 @@ msgstr ""
msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgid "Allocated quantity ({n}) must not exceed available quantity ({q})"
msgstr "" msgstr ""
#: build/views.py:289 stock/views.py:834 #: build/views.py:289 stock/views.py:859
#, python-brace-format #, python-brace-format
msgid "The following serial numbers already exist: ({sn})" msgid "The following serial numbers already exist: ({sn})"
msgstr "" msgstr ""
@ -190,6 +190,10 @@ msgstr ""
msgid "Use this currency as the base currency" msgid "Use this currency as the base currency"
msgstr "" msgstr ""
#: company/templates/company/partdelete.html:5
msgid "Are you sure you want to delete the following Supplier Parts?"
msgstr ""
#: order/forms.py:21 #: order/forms.py:21
msgid "Place order" msgid "Place order"
msgstr "" msgstr ""
@ -247,7 +251,7 @@ msgstr ""
msgid "Line item notes" msgid "Line item notes"
msgstr "" msgstr ""
#: order/models.py:275 #: order/models.py:275 stock/templates/stock/item.html:106
msgid "Purchase Order" msgid "Purchase Order"
msgstr "" msgstr ""
@ -409,7 +413,7 @@ msgstr ""
msgid "Variant Of" msgid "Variant Of"
msgstr "" msgstr ""
#: part/templates/part/detail.html:49 #: part/templates/part/detail.html:49 stock/templates/stock/item.html:118
msgid "URL" msgid "URL"
msgstr "" msgstr ""
@ -497,7 +501,7 @@ msgstr ""
msgid "Part cannot be sold to customers" msgid "Part cannot be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:151 #: part/templates/part/detail.html:151 stock/templates/stock/item.html:150
msgid "Notes" msgid "Notes"
msgstr "" msgstr ""
@ -585,6 +589,10 @@ msgstr ""
msgid "Item cannot belong to itself" msgid "Item cannot belong to itself"
msgstr "" msgstr ""
#: stock/models.py:360
msgid "Stock Item Notes"
msgstr ""
#: stock/models.py:434 #: stock/models.py:434
msgid "Quantity must be integer" msgid "Quantity must be integer"
msgstr "" msgstr ""
@ -615,6 +623,79 @@ msgstr ""
msgid "Serialized {n} items" msgid "Serialized {n} items"
msgstr "" msgstr ""
#: stock/templates/stock/item.html:8
msgid "Stock Item Details"
msgstr ""
#: stock/templates/stock/item.html:51
msgid ""
"This stock item is serialized - it has a unique serial number and the "
"quantity cannot be adjusted."
msgstr ""
#: stock/templates/stock/item.html:55
msgid ""
"This stock item will be automatically deleted when all stock is depleted."
msgstr ""
#: stock/templates/stock/item.html:72
msgid "Belongs To"
msgstr ""
#: stock/templates/stock/item.html:77
#: stock/templates/stock/stock_adjust.html:16
msgid "Location"
msgstr ""
#: stock/templates/stock/item.html:83
msgid "Serial Number"
msgstr ""
#: stock/templates/stock/item.html:88
#: stock/templates/stock/stock_adjust.html:20
msgid "Quantity"
msgstr ""
#: stock/templates/stock/item.html:94
msgid "Batch"
msgstr ""
#: stock/templates/stock/item.html:100
msgid "Build"
msgstr ""
#: stock/templates/stock/item.html:112
msgid "Customer"
msgstr ""
#: stock/templates/stock/item.html:124
msgid "Supplier"
msgstr ""
#: stock/templates/stock/item.html:128
msgid "Supplier Part"
msgstr ""
#: stock/templates/stock/item.html:133
msgid "Last Updated"
msgstr ""
#: stock/templates/stock/item.html:137
msgid "Last Stocktake"
msgstr ""
#: stock/templates/stock/item.html:141
msgid "No stocktake performed"
msgstr ""
#: stock/templates/stock/item.html:145
msgid "Status"
msgstr ""
#: stock/templates/stock/item.html:159
msgid "Stock Tracking Information"
msgstr ""
#: stock/templates/stock/location.html:37 #: stock/templates/stock/location.html:37
msgid "Location Details" msgid "Location Details"
msgstr "" msgstr ""
@ -644,51 +725,80 @@ msgstr ""
msgid "Stock Locations" msgid "Stock Locations"
msgstr "" msgstr ""
#: stock/views.py:399 #: stock/templates/stock/stock_adjust.html:15
msgid "Must enter integer value" msgid "Stock Item"
msgstr ""
#: stock/views.py:373
msgid "Move Stock Items"
msgstr ""
#: stock/views.py:374
msgid "Count Stock Items"
msgstr ""
#: stock/views.py:375
msgid "Remove From Stock"
msgstr ""
#: stock/views.py:376
msgid "Add Stock Items"
msgstr ""
#: stock/views.py:377
msgid "Delete Stock Items"
msgstr "" msgstr ""
#: stock/views.py:404 #: stock/views.py:404
msgid "Must enter integer value"
msgstr ""
#: stock/views.py:409
msgid "Quantity must be positive" msgid "Quantity must be positive"
msgstr "" msgstr ""
#: stock/views.py:411 #: stock/views.py:416
#, python-brace-format #, python-brace-format
msgid "Quantity must not exceed {x}" msgid "Quantity must not exceed {x}"
msgstr "" msgstr ""
#: stock/views.py:419 #: stock/views.py:424
msgid "Confirm stock adjustment" msgid "Confirm stock adjustment"
msgstr "" msgstr ""
#: stock/views.py:487 #: stock/views.py:495
#, python-brace-format #, python-brace-format
msgid "Added stock to {n} items" msgid "Added stock to {n} items"
msgstr "" msgstr ""
#: stock/views.py:502 #: stock/views.py:510
#, python-brace-format #, python-brace-format
msgid "Removed stock from {n} items" msgid "Removed stock from {n} items"
msgstr "" msgstr ""
#: stock/views.py:515 #: stock/views.py:523
#, python-brace-format #, python-brace-format
msgid "Counted stock for {n} items" msgid "Counted stock for {n} items"
msgstr "" msgstr ""
#: stock/views.py:543 #: stock/views.py:551
msgid "No items were moved" msgid "No items were moved"
msgstr "" msgstr ""
#: stock/views.py:546 #: stock/views.py:554
#, python-brace-format #, python-brace-format
msgid "Moved {n} items to {dest}" msgid "Moved {n} items to {dest}"
msgstr "" msgstr ""
#: stock/views.py:813 #: stock/views.py:573
#, python-brace-format
msgid "Deleted {n} stock items"
msgstr ""
#: stock/views.py:838
msgid "Invalid part selection" msgid "Invalid part selection"
msgstr "" msgstr ""
#: stock/views.py:875 #: stock/views.py:900
msgid "Created new stock item" msgid "Created new stock item"
msgstr "" msgstr ""

View File

@ -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: 2019-09-27 00:12+0000\n" "POT-Creation-Date: 2019-11-16 09:28+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"
@ -149,7 +149,7 @@ msgstr ""
msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgid "Allocated quantity ({n}) must not exceed available quantity ({q})"
msgstr "" msgstr ""
#: build/views.py:289 stock/views.py:834 #: build/views.py:289 stock/views.py:859
#, python-brace-format #, python-brace-format
msgid "The following serial numbers already exist: ({sn})" msgid "The following serial numbers already exist: ({sn})"
msgstr "" msgstr ""
@ -190,6 +190,10 @@ msgstr ""
msgid "Use this currency as the base currency" msgid "Use this currency as the base currency"
msgstr "" msgstr ""
#: company/templates/company/partdelete.html:5
msgid "Are you sure you want to delete the following Supplier Parts?"
msgstr ""
#: order/forms.py:21 #: order/forms.py:21
msgid "Place order" msgid "Place order"
msgstr "" msgstr ""
@ -247,7 +251,7 @@ msgstr ""
msgid "Line item notes" msgid "Line item notes"
msgstr "" msgstr ""
#: order/models.py:275 #: order/models.py:275 stock/templates/stock/item.html:106
msgid "Purchase Order" msgid "Purchase Order"
msgstr "" msgstr ""
@ -409,7 +413,7 @@ msgstr ""
msgid "Variant Of" msgid "Variant Of"
msgstr "" msgstr ""
#: part/templates/part/detail.html:49 #: part/templates/part/detail.html:49 stock/templates/stock/item.html:118
msgid "URL" msgid "URL"
msgstr "" msgstr ""
@ -497,7 +501,7 @@ msgstr ""
msgid "Part cannot be sold to customers" msgid "Part cannot be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:151 #: part/templates/part/detail.html:151 stock/templates/stock/item.html:150
msgid "Notes" msgid "Notes"
msgstr "" msgstr ""
@ -585,6 +589,10 @@ msgstr ""
msgid "Item cannot belong to itself" msgid "Item cannot belong to itself"
msgstr "" msgstr ""
#: stock/models.py:360
msgid "Stock Item Notes"
msgstr ""
#: stock/models.py:434 #: stock/models.py:434
msgid "Quantity must be integer" msgid "Quantity must be integer"
msgstr "" msgstr ""
@ -615,6 +623,79 @@ msgstr ""
msgid "Serialized {n} items" msgid "Serialized {n} items"
msgstr "" msgstr ""
#: stock/templates/stock/item.html:8
msgid "Stock Item Details"
msgstr ""
#: stock/templates/stock/item.html:51
msgid ""
"This stock item is serialized - it has a unique serial number and the "
"quantity cannot be adjusted."
msgstr ""
#: stock/templates/stock/item.html:55
msgid ""
"This stock item will be automatically deleted when all stock is depleted."
msgstr ""
#: stock/templates/stock/item.html:72
msgid "Belongs To"
msgstr ""
#: stock/templates/stock/item.html:77
#: stock/templates/stock/stock_adjust.html:16
msgid "Location"
msgstr ""
#: stock/templates/stock/item.html:83
msgid "Serial Number"
msgstr ""
#: stock/templates/stock/item.html:88
#: stock/templates/stock/stock_adjust.html:20
msgid "Quantity"
msgstr ""
#: stock/templates/stock/item.html:94
msgid "Batch"
msgstr ""
#: stock/templates/stock/item.html:100
msgid "Build"
msgstr ""
#: stock/templates/stock/item.html:112
msgid "Customer"
msgstr ""
#: stock/templates/stock/item.html:124
msgid "Supplier"
msgstr ""
#: stock/templates/stock/item.html:128
msgid "Supplier Part"
msgstr ""
#: stock/templates/stock/item.html:133
msgid "Last Updated"
msgstr ""
#: stock/templates/stock/item.html:137
msgid "Last Stocktake"
msgstr ""
#: stock/templates/stock/item.html:141
msgid "No stocktake performed"
msgstr ""
#: stock/templates/stock/item.html:145
msgid "Status"
msgstr ""
#: stock/templates/stock/item.html:159
msgid "Stock Tracking Information"
msgstr ""
#: stock/templates/stock/location.html:37 #: stock/templates/stock/location.html:37
msgid "Location Details" msgid "Location Details"
msgstr "" msgstr ""
@ -644,51 +725,80 @@ msgstr ""
msgid "Stock Locations" msgid "Stock Locations"
msgstr "" msgstr ""
#: stock/views.py:399 #: stock/templates/stock/stock_adjust.html:15
msgid "Must enter integer value" msgid "Stock Item"
msgstr ""
#: stock/views.py:373
msgid "Move Stock Items"
msgstr ""
#: stock/views.py:374
msgid "Count Stock Items"
msgstr ""
#: stock/views.py:375
msgid "Remove From Stock"
msgstr ""
#: stock/views.py:376
msgid "Add Stock Items"
msgstr ""
#: stock/views.py:377
msgid "Delete Stock Items"
msgstr "" msgstr ""
#: stock/views.py:404 #: stock/views.py:404
msgid "Must enter integer value"
msgstr ""
#: stock/views.py:409
msgid "Quantity must be positive" msgid "Quantity must be positive"
msgstr "" msgstr ""
#: stock/views.py:411 #: stock/views.py:416
#, python-brace-format #, python-brace-format
msgid "Quantity must not exceed {x}" msgid "Quantity must not exceed {x}"
msgstr "" msgstr ""
#: stock/views.py:419 #: stock/views.py:424
msgid "Confirm stock adjustment" msgid "Confirm stock adjustment"
msgstr "" msgstr ""
#: stock/views.py:487 #: stock/views.py:495
#, python-brace-format #, python-brace-format
msgid "Added stock to {n} items" msgid "Added stock to {n} items"
msgstr "" msgstr ""
#: stock/views.py:502 #: stock/views.py:510
#, python-brace-format #, python-brace-format
msgid "Removed stock from {n} items" msgid "Removed stock from {n} items"
msgstr "" msgstr ""
#: stock/views.py:515 #: stock/views.py:523
#, python-brace-format #, python-brace-format
msgid "Counted stock for {n} items" msgid "Counted stock for {n} items"
msgstr "" msgstr ""
#: stock/views.py:543 #: stock/views.py:551
msgid "No items were moved" msgid "No items were moved"
msgstr "" msgstr ""
#: stock/views.py:546 #: stock/views.py:554
#, python-brace-format #, python-brace-format
msgid "Moved {n} items to {dest}" msgid "Moved {n} items to {dest}"
msgstr "" msgstr ""
#: stock/views.py:813 #: stock/views.py:573
#, python-brace-format
msgid "Deleted {n} stock items"
msgstr ""
#: stock/views.py:838
msgid "Invalid part selection" msgid "Invalid part selection"
msgstr "" msgstr ""
#: stock/views.py:875 #: stock/views.py:900
msgid "Created new stock item" msgid "Created new stock item"
msgstr "" msgstr ""

View File

@ -357,7 +357,7 @@ class StockItem(models.Model):
choices=StockStatus.items(), choices=StockStatus.items(),
validators=[MinValueValidator(0)]) validators=[MinValueValidator(0)])
notes = models.CharField(max_length=250, blank=True, help_text='Stock Item Notes') notes = models.CharField(max_length=250, blank=True, help_text=_('Stock Item Notes'))
# If stock item is incoming, an (optional) ETA field # If stock item is incoming, an (optional) ETA field
# expected_arrival = models.DateField(null=True, blank=True) # expected_arrival = models.DateField(null=True, blank=True)

View File

@ -1,10 +1,11 @@
{% extends "stock/stock_app_base.html" %} {% extends "stock/stock_app_base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block content %} {% block content %}
<div class='row'> <div class='row'>
<div class='col-sm-6'> <div class='col-sm-6'>
<h3>Stock Item Details</h3> <h3>{% trans "Stock Item Details" %}</h3>
{% if item.serialized %} {% if item.serialized %}
<p><i>{{ item.part.full_name}} # {{ item.serial }}</i></p> <p><i>{{ item.part.full_name}} # {{ item.serial }}</i></p>
{% else %} {% else %}
@ -47,11 +48,11 @@
</p> </p>
{% if item.serialized %} {% if item.serialized %}
<div class='alert alert-block alert-info'> <div class='alert alert-block alert-info'>
This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted. {% trans "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." %}
</div> </div>
{% elif item.delete_on_deplete %} {% elif item.delete_on_deplete %}
<div class='alert alert-block alert-warning'> <div class='alert alert-block alert-warning'>
This stock item will be automatically deleted when all stock is depleted. {% trans "This stock item will be automatically deleted when all stock is depleted." %}
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -68,85 +69,85 @@
</tr> </tr>
{% if item.belongs_to %} {% if item.belongs_to %}
<tr> <tr>
<td>Belongs To</td> <td>{% trans "Belongs To" %}</td>
<td><a href="{% url 'stock-item-detail' item.belongs_to.id %}">{{ item.belongs_to }}</a></td> <td><a href="{% url 'stock-item-detail' item.belongs_to.id %}">{{ item.belongs_to }}</a></td>
</tr> </tr>
{% elif item.location %} {% elif item.location %}
<tr> <tr>
<td>Location</td> <td>{% trans "Location" %}</td>
<td><a href="{% url 'stock-location-detail' item.location.id %}">{{ item.location.name }}</a></td> <td><a href="{% url 'stock-location-detail' item.location.id %}">{{ item.location.name }}</a></td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.serialized %} {% if item.serialized %}
<tr> <tr>
<td>Serial Number</td> <td>{% trans "Serial Number" %}</td>
<td>{{ item.serial }}</td> <td>{{ item.serial }}</td>
</tr> </tr>
{% else %} {% else %}
<tr> <tr>
<td>Quantity</td> <td>{% trans "Quantity" %}</td>
<td>{{ item.quantity }}</td> <td>{{ item.quantity }}</td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.batch %} {% if item.batch %}
<tr> <tr>
<td>Batch</td> <td>{% trans "Batch" %}</td>
<td>{{ item.batch }}</td> <td>{{ item.batch }}</td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.build %} {% if item.build %}
<tr> <tr>
<td>Build</td> <td>{% trans "Build" %}</td>
<td><a href="{% url 'build-detail' item.build.id %}">{{ item.build }}</a></td> <td><a href="{% url 'build-detail' item.build.id %}">{{ item.build }}</a></td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.purchase_order %} {% if item.purchase_order %}
<tr> <tr>
<td>Purchase Order</td> <td>{% trans "Purchase Order" %}</td>
<td><a href="{% url 'purchase-order-detail' item.purchase_order.id %}">{{ item.purchase_order }}</a></td> <td><a href="{% url 'purchase-order-detail' item.purchase_order.id %}">{{ item.purchase_order }}</a></td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.customer %} {% if item.customer %}
<tr> <tr>
<td>Customer</td> <td>{% trans "Customer" %}</td>
<td>{{ item.customer.name }}</td> <td>{{ item.customer.name }}</td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.URL %} {% if item.URL %}
<tr> <tr>
<td>URL</td> <td>{% trans "URL" %}</td>
<td><a href="{{ item.URL }}">{{ item.URL }}</a></td> <td><a href="{{ item.URL }}">{{ item.URL }}</a></td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.supplier_part %} {% if item.supplier_part %}
<tr> <tr>
<td>Supplier</td> <td>{% trans "Supplier" %}</td>
<td><a href="{% url 'company-detail' item.supplier_part.supplier.id %}">{{ item.supplier_part.supplier.name }}</a></td> <td><a href="{% url 'company-detail' item.supplier_part.supplier.id %}">{{ item.supplier_part.supplier.name }}</a></td>
</tr> </tr>
<tr> <tr>
<td>Supplier Part</td> <td>{% trans "Supplier Part" %}</td>
<td><a href="{% url 'supplier-part-detail' item.supplier_part.id %}">{{ item.supplier_part.SKU }}</a></td> <td><a href="{% url 'supplier-part-detail' item.supplier_part.id %}">{{ item.supplier_part.SKU }}</a></td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<td>Last Updated</td> <td>{% trans "Last Updated" %}</td>
<td>{{ item.updated }}</td> <td>{{ item.updated }}</td>
</tr> </tr>
<tr> <tr>
<td>Last Stocktake</td> <td>{% trans "Last Stocktake" %}</td>
{% if item.stocktake_date %} {% if item.stocktake_date %}
<td>{{ item.stocktake_date }} <span class='badge'>{{ item.stocktake_user }}</span></td> <td>{{ item.stocktake_date }} <span class='badge'>{{ item.stocktake_user }}</span></td>
{% else %} {% else %}
<td>No stocktake performed</td> <td>{% trans "No stocktake performed" %}</td>
{% endif %} {% endif %}
</tr> </tr>
<tr> <tr>
<td>Status</td> <td>{% trans "Status" %}</td>
<td>{{ item.get_status_display }}</td> <td>{{ item.get_status_display }}</td>
</tr> </tr>
{% if item.notes %} {% if item.notes %}
<tr> <tr>
<td>Notes</td> <td>{% trans "Notes" %}</td>
<td>{{ item.notes }}</td> <td>{{ item.notes }}</td>
</tr> </tr>
{% endif %} {% endif %}
@ -155,7 +156,7 @@
</div> </div>
<hr> <hr>
<h4>Stock Tracking Information</h4> <h4>{% trans "Stock Tracking Information" %}</h4>
<div id='table-toolbar'> <div id='table-toolbar'>
<div class='btn-group'> <div class='btn-group'>
<button class='btn btn-success' type='button' title='New tracking entry' id='new-entry'>New Entry</button> <button class='btn btn-success' type='button' title='New tracking entry' id='new-entry'>New Entry</button>

View File

@ -1,3 +1,5 @@
{% load i18n %}
{% block pre_form_content %} {% block pre_form_content %}
{% endblock %} {% endblock %}
@ -10,9 +12,13 @@
<table class='table table-condensed table-striped' id='stock-table'> <table class='table table-condensed table-striped' id='stock-table'>
<tr> <tr>
<th>Stock Item</th> <th>{% trans "Stock Item" %}</th>
<th>Location</th> <th>{% trans "Location" %}</th>
{% if edit_quantity %}
<th>{{ stock_action_title }}</th> <th>{{ stock_action_title }}</th>
{% else %}
<th>{% trans "Quantity" %}</th>
{% endif %}
<th></th> <th></th>
</tr> </tr>
{% for item in stock_items %} {% for item in stock_items %}
@ -21,6 +27,7 @@
{{ item.part.full_name }} <small><i>{{ item.part.description }}</i></small></td> {{ item.part.full_name }} <small><i>{{ item.part.description }}</i></small></td>
<td>{{ item.location.pathstring }}</td> <td>{{ item.location.pathstring }}</td>
<td> <td>
{% if edit_quantity %}
<input class='numberinput' <input class='numberinput'
min='0' min='0'
{% if stock_action == 'take' or stock_action == 'move' %} max='{{ item.quantity }}' {% endif %} {% if stock_action == 'take' or stock_action == 'move' %} max='{{ item.quantity }}' {% endif %}
@ -28,6 +35,10 @@
{% if item.error %} {% if item.error %}
<br><span class='help-inline'>{{ item.error }}</span> <br><span class='help-inline'>{{ item.error }}</span>
{% endif %} {% endif %}
{% else %}
{{ item.new_quantity }}
<input type='hidden' name='stock-id-{{ item.id }}' value='{{ item.new_quantity }}'/>
{% endif %}
</td> </td>
<td><button class='btn btn-default btn-remove' onclick='removeStockRow()' id='del-{{ item.id }}' title='Remove item' type='button'><span row='stock-row-{{ item.id }}' class='glyphicon glyphicon-small glyphicon-remove'></span></button></td> <td><button class='btn btn-default btn-remove' onclick='removeStockRow()' id='del-{{ item.id }}' title='Remove item' type='button'><span row='stock-row-{{ item.id }}' class='glyphicon glyphicon-small glyphicon-remove'></span></button></td>
</tr> </tr>

View File

@ -256,6 +256,7 @@ class StockAdjust(AjaxView, FormMixin):
- Add items to stock - Add items to stock
- Count items - Count items
- Move stock - Move stock
- Delete stock items
""" """
@ -337,10 +338,13 @@ class StockAdjust(AjaxView, FormMixin):
context['stock_items'] = self.stock_items context['stock_items'] = self.stock_items
context['stock_action'] = self.stock_action context['stock_action'] = self.stock_action.strip().lower()
context['stock_action_title'] = self.stock_action.capitalize() context['stock_action_title'] = self.stock_action.capitalize()
# Quantity column will be read-only in some circumstances
context['edit_quantity'] = not self.stock_action == 'delete'
return context return context
def get_form(self): def get_form(self):
@ -361,15 +365,16 @@ class StockAdjust(AjaxView, FormMixin):
self.stock_action = request.GET.get('action', '').lower() self.stock_action = request.GET.get('action', '').lower()
# Pick a default action... # Pick a default action...
if self.stock_action not in ['move', 'count', 'take', 'add']: if self.stock_action not in ['move', 'count', 'take', 'add', 'delete']:
self.stock_action = 'count' self.stock_action = 'count'
# Choose the form title based on the action # Choose the form title based on the action
titles = { titles = {
'move': 'Move Stock', 'move': _('Move Stock Items'),
'count': 'Count Stock', 'count': _('Count Stock Items'),
'take': 'Remove Stock', 'take': _('Remove From Stock'),
'add': 'Add Stock' 'add': _('Add Stock Items'),
'delete': _('Delete Stock Items')
} }
self.ajax_form_title = titles[self.stock_action] self.ajax_form_title = titles[self.stock_action]
@ -383,7 +388,7 @@ class StockAdjust(AjaxView, FormMixin):
self.request = request self.request = request
self.stock_action = request.POST.get('stock_action', 'invalid').lower() self.stock_action = request.POST.get('stock_action', 'invalid').strip().lower()
# Update list of stock items # Update list of stock items
self.stock_items = self.get_POST_items() self.stock_items = self.get_POST_items()
@ -468,6 +473,9 @@ class StockAdjust(AjaxView, FormMixin):
elif self.stock_action == 'count': elif self.stock_action == 'count':
return self.do_count() return self.do_count()
elif self.stock_action == 'delete':
return self.do_delete()
else: else:
return 'No action performed' return 'No action performed'
@ -547,6 +555,23 @@ class StockAdjust(AjaxView, FormMixin):
n=count, n=count,
dest=destination.pathstring)) dest=destination.pathstring))
def do_delete(self):
""" Delete multiple stock items """
count = 0
# note = self.request.POST['note']
for item in self.stock_items:
# TODO - In the future, StockItems should not be 'deleted'
# TODO - Instead, they should be marked as "inactive"
item.delete()
count += 1
return _("Deleted {n} stock items".format(n=count))
class StockItemEdit(AjaxUpdateView): class StockItemEdit(AjaxUpdateView):
""" """

View File

@ -12,6 +12,7 @@
<li><a href="#" id='multi-item-stocktake' title='Stocktake selected stock items'>Count stock</a></li> <li><a href="#" id='multi-item-stocktake' title='Stocktake selected stock items'>Count stock</a></li>
<li><a href='#' id='multi-item-move' title='Move selected stock items'>Move stock</a></li> <li><a href='#' id='multi-item-move' title='Move selected stock items'>Move stock</a></li>
<li><a href='#' id='multi-item-order' title='Order selected items'>Order stock</a></li> <li><a href='#' id='multi-item-order' title='Order selected items'>Order stock</a></li>
<li><a href='#' id='multi-item-delete' title='Delete selected items'>Delete Stock</a></li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -13,7 +13,7 @@ django-import-export>=1.0.0 # Data import / export for admin interface
django-cleanup>=2.1.0 # Manage deletion of old / unused uploaded files django-cleanup>=2.1.0 # Manage deletion of old / unused uploaded files
django-qr-code==1.0.0 # Generate QR codes django-qr-code==1.0.0 # Generate QR codes
flake8==3.3.0 # PEP checking flake8==3.3.0 # PEP checking
coverage>=4.5.3 # Unit test coverage coverage==4.0.3 # Unit test coverage
python-coveralls==2.9.1 # Coveralls linking (for Travis) python-coveralls==2.9.1 # Coveralls linking (for Travis)
fuzzywuzzy>=0.17.0 # Fuzzy string matching fuzzywuzzy>=0.17.0 # Fuzzy string matching
python-Levenshtein>=0.12.0 # Required for fuzzywuzzy python-Levenshtein>=0.12.0 # Required for fuzzywuzzy