mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 12:06:44 +00:00
client side form for assigning stock items to customers
This commit is contained in:
parent
c36687af22
commit
96a885e4e1
@ -21,20 +21,6 @@ from part.models import Part
|
|||||||
from .models import StockLocation, StockItem, StockItemTracking
|
from .models import StockLocation, StockItem, StockItemTracking
|
||||||
|
|
||||||
|
|
||||||
class AssignStockItemToCustomerForm(HelperForm):
|
|
||||||
"""
|
|
||||||
Form for manually assigning a StockItem to a Customer
|
|
||||||
|
|
||||||
TODO: This could be a simple API driven form!
|
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = StockItem
|
|
||||||
fields = [
|
|
||||||
'customer',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class ReturnStockItemForm(HelperForm):
|
class ReturnStockItemForm(HelperForm):
|
||||||
"""
|
"""
|
||||||
Form for manually returning a StockItem into stock
|
Form for manually returning a StockItem into stock
|
||||||
|
@ -568,11 +568,19 @@ $("#stock-convert").click(function() {
|
|||||||
|
|
||||||
{% if item.in_stock %}
|
{% if item.in_stock %}
|
||||||
$("#stock-assign-to-customer").click(function() {
|
$("#stock-assign-to-customer").click(function() {
|
||||||
launchModalForm("{% url 'stock-item-assign' item.id %}",
|
|
||||||
{
|
inventreeGet('{% url "api-stock-detail" item.pk %}', {}, {
|
||||||
reload: true,
|
success: function(response) {
|
||||||
|
assignStockToCustomer(
|
||||||
|
[response],
|
||||||
|
{
|
||||||
|
success: function() {
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#stock-move").click(function() {
|
$("#stock-move").click(function() {
|
||||||
|
@ -23,7 +23,6 @@ stock_item_detail_urls = [
|
|||||||
url(r'^delete/', views.StockItemDelete.as_view(), name='stock-item-delete'),
|
url(r'^delete/', views.StockItemDelete.as_view(), name='stock-item-delete'),
|
||||||
url(r'^qr_code/', views.StockItemQRCode.as_view(), name='stock-item-qr'),
|
url(r'^qr_code/', views.StockItemQRCode.as_view(), name='stock-item-qr'),
|
||||||
url(r'^delete_test_data/', views.StockItemDeleteTestData.as_view(), name='stock-item-delete-test-data'),
|
url(r'^delete_test_data/', views.StockItemDeleteTestData.as_view(), name='stock-item-delete-test-data'),
|
||||||
url(r'^assign/', views.StockItemAssignToCustomer.as_view(), name='stock-item-assign'),
|
|
||||||
url(r'^return/', views.StockItemReturnToStock.as_view(), name='stock-item-return'),
|
url(r'^return/', views.StockItemReturnToStock.as_view(), name='stock-item-return'),
|
||||||
url(r'^install/', views.StockItemInstall.as_view(), name='stock-item-install'),
|
url(r'^install/', views.StockItemInstall.as_view(), name='stock-item-install'),
|
||||||
|
|
||||||
|
@ -294,39 +294,6 @@ class StockLocationQRCode(QRCodeView):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class StockItemAssignToCustomer(AjaxUpdateView):
|
|
||||||
"""
|
|
||||||
View for manually assigning a StockItem to a Customer
|
|
||||||
"""
|
|
||||||
|
|
||||||
model = StockItem
|
|
||||||
ajax_form_title = _("Assign to Customer")
|
|
||||||
context_object_name = "item"
|
|
||||||
form_class = StockForms.AssignStockItemToCustomerForm
|
|
||||||
|
|
||||||
def validate(self, item, form, **kwargs):
|
|
||||||
|
|
||||||
customer = form.cleaned_data.get('customer', None)
|
|
||||||
|
|
||||||
if not customer:
|
|
||||||
form.add_error('customer', _('Customer must be specified'))
|
|
||||||
|
|
||||||
def save(self, item, form, **kwargs):
|
|
||||||
"""
|
|
||||||
Assign the stock item to the customer.
|
|
||||||
"""
|
|
||||||
|
|
||||||
customer = form.cleaned_data.get('customer', None)
|
|
||||||
|
|
||||||
if customer:
|
|
||||||
item = item.allocateToCustomer(
|
|
||||||
customer,
|
|
||||||
user=self.request.user
|
|
||||||
)
|
|
||||||
|
|
||||||
item.clearAllocations()
|
|
||||||
|
|
||||||
|
|
||||||
class StockItemReturnToStock(AjaxUpdateView):
|
class StockItemReturnToStock(AjaxUpdateView):
|
||||||
"""
|
"""
|
||||||
View for returning a stock item (which is assigned to a customer) to stock.
|
View for returning a stock item (which is assigned to a customer) to stock.
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* exported
|
/* exported
|
||||||
|
assignStockToCustomer,
|
||||||
createNewStockItem,
|
createNewStockItem,
|
||||||
createStockLocation,
|
createStockLocation,
|
||||||
duplicateStockItem,
|
duplicateStockItem,
|
||||||
@ -533,13 +534,166 @@ function exportStock(params={}) {
|
|||||||
url += `&${key}=${params[key]}`;
|
url += `&${key}=${params[key]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(url);
|
|
||||||
location.href = url;
|
location.href = url;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign multiple stock items to a customer
|
||||||
|
*/
|
||||||
|
function assignStockToCustomer(items, options={}) {
|
||||||
|
|
||||||
|
// Generate HTML content for the form
|
||||||
|
var html = `
|
||||||
|
<table class='table table-striped table-condensed' id='stock-assign-table'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Part" %}</th>
|
||||||
|
<th>{% trans "Stock Item" %}</th>
|
||||||
|
<th>{% trans "Location" %}</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
`;
|
||||||
|
|
||||||
|
for (var idx = 0; idx < items.length; idx++) {
|
||||||
|
|
||||||
|
var item = items[idx];
|
||||||
|
|
||||||
|
var pk = item.pk;
|
||||||
|
|
||||||
|
var part = item.part_detail;
|
||||||
|
|
||||||
|
var thumbnail = thumbnailImage(part.thumbnail || part.image);
|
||||||
|
|
||||||
|
var status = stockStatusDisplay(item.status, {classes: 'float-right'});
|
||||||
|
|
||||||
|
var quantity = '';
|
||||||
|
|
||||||
|
if (item.serial && item.quantity == 1) {
|
||||||
|
quantity = `{% trans "Serial" %}: ${item.serial}`;
|
||||||
|
} else {
|
||||||
|
quantity = `{% trans "Quantity" %}: ${item.quantity}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
quantity += status;
|
||||||
|
|
||||||
|
var location = locationDetail(item, false);
|
||||||
|
|
||||||
|
var buttons = `<div class='btn-group' role='group'>`;
|
||||||
|
|
||||||
|
buttons += makeIconButton(
|
||||||
|
'fa-times icon-red',
|
||||||
|
'button-stock-item-remove',
|
||||||
|
pk,
|
||||||
|
'{% trans "Remove row" %}',
|
||||||
|
);
|
||||||
|
|
||||||
|
buttons += '</div>';
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<tr id='stock_item_${pk}' class='stock-item'row'>
|
||||||
|
<td id='part_${pk}'>${thumbnail} ${part.full_name}</td>
|
||||||
|
<td id='stock_${pk}'>
|
||||||
|
<div id='div_id_items_item_${pk}'>
|
||||||
|
${quantity}
|
||||||
|
<div id='errors-items_item_${pk}'></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td id='location_${pk}'>${location}</td>
|
||||||
|
<td id='buttons_${pk}'>${buttons}</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `</tbody></table>`;
|
||||||
|
|
||||||
|
constructForm('{% url "api-stock-assign" %}', {
|
||||||
|
method: 'POST',
|
||||||
|
preFormContent: html,
|
||||||
|
fields: {
|
||||||
|
'customer': {
|
||||||
|
value: options.customer,
|
||||||
|
filters: {
|
||||||
|
is_customer: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'notes': {},
|
||||||
|
},
|
||||||
|
confirm: true,
|
||||||
|
confirmMessage: '{% trans "Confirm stock assignment" %}',
|
||||||
|
title: '{% trans "Assign Stock to Customer" %}',
|
||||||
|
afterRender: function(fields, opts) {
|
||||||
|
// Add button callbacks to remove rows
|
||||||
|
$(opts.modal).find('.button-stock-item-remove').click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
$(opts.modal).find(`#stock_item_${pk}`).remove();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSubmit: function(fields, opts) {
|
||||||
|
|
||||||
|
// Extract data elements from the form
|
||||||
|
var data = {
|
||||||
|
customer: getFormFieldValue('customer', {}, opts),
|
||||||
|
notes: getFormFieldValue('notes', {}, opts),
|
||||||
|
items: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
var item_pk_values = [];
|
||||||
|
|
||||||
|
items.forEach(function(item) {
|
||||||
|
var pk = item.pk;
|
||||||
|
|
||||||
|
// Does the row exist in the form?
|
||||||
|
var row = $(opts.modal).find(`#stock_item_${pk}`);
|
||||||
|
|
||||||
|
if (row) {
|
||||||
|
item_pk_values.push(pk);
|
||||||
|
|
||||||
|
data.items.push({
|
||||||
|
item: pk,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
opts.nested = {
|
||||||
|
'items': item_pk_values,
|
||||||
|
}
|
||||||
|
|
||||||
|
inventreePut(
|
||||||
|
'{% url "api-stock-assign" %}',
|
||||||
|
data,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
success: function(response) {
|
||||||
|
$(opts.modal).modal('hide');
|
||||||
|
|
||||||
|
if (options.success) {
|
||||||
|
options.success(response);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
switch (xhr.status) {
|
||||||
|
case 400:
|
||||||
|
handleFormErrors(xhr.responseJSON, fields, opts);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$(opts.modal).modal('hide');
|
||||||
|
showApiError(xhr, opts.url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform stock adjustments
|
* Perform stock adjustments
|
||||||
*/
|
*/
|
||||||
@ -1098,7 +1252,7 @@ function locationDetail(row, showLink=true) {
|
|||||||
// StockItem has been assigned to a sales order
|
// StockItem has been assigned to a sales order
|
||||||
text = '{% trans "Assigned to Sales Order" %}';
|
text = '{% trans "Assigned to Sales Order" %}';
|
||||||
url = `/order/sales-order/${row.sales_order}/`;
|
url = `/order/sales-order/${row.sales_order}/`;
|
||||||
} else if (row.location) {
|
} else if (row.location && row.location_detail) {
|
||||||
text = row.location_detail.pathstring;
|
text = row.location_detail.pathstring;
|
||||||
url = `/stock/location/${row.location}/`;
|
url = `/stock/location/${row.location}/`;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user