mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +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
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
Form for manually returning a StockItem into stock
|
||||
|
@ -568,11 +568,19 @@ $("#stock-convert").click(function() {
|
||||
|
||||
{% if item.in_stock %}
|
||||
$("#stock-assign-to-customer").click(function() {
|
||||
launchModalForm("{% url 'stock-item-assign' item.id %}",
|
||||
{
|
||||
reload: true,
|
||||
|
||||
inventreeGet('{% url "api-stock-detail" item.pk %}', {}, {
|
||||
success: function(response) {
|
||||
assignStockToCustomer(
|
||||
[response],
|
||||
{
|
||||
success: function() {
|
||||
location.reload();
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$("#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'^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'^assign/', views.StockItemAssignToCustomer.as_view(), name='stock-item-assign'),
|
||||
url(r'^return/', views.StockItemReturnToStock.as_view(), name='stock-item-return'),
|
||||
url(r'^install/', views.StockItemInstall.as_view(), name='stock-item-install'),
|
||||
|
||||
|
@ -294,39 +294,6 @@ class StockLocationQRCode(QRCodeView):
|
||||
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):
|
||||
"""
|
||||
View for returning a stock item (which is assigned to a customer) to stock.
|
||||
|
@ -38,6 +38,7 @@
|
||||
*/
|
||||
|
||||
/* exported
|
||||
assignStockToCustomer,
|
||||
createNewStockItem,
|
||||
createStockLocation,
|
||||
duplicateStockItem,
|
||||
@ -533,13 +534,166 @@ function exportStock(params={}) {
|
||||
url += `&${key}=${params[key]}`;
|
||||
}
|
||||
|
||||
console.log(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
|
||||
*/
|
||||
@ -1098,7 +1252,7 @@ function locationDetail(row, showLink=true) {
|
||||
// StockItem has been assigned to a sales order
|
||||
text = '{% trans "Assigned to 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;
|
||||
url = `/stock/location/${row.location}/`;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user