[Fix] Multi-batch selection issue in POS (#13407)

This commit is contained in:
rohitwaghchaure 2018-03-28 12:33:15 +05:30 committed by Nabin Hait
parent a3c3dec5a2
commit 68ba4fd697
2 changed files with 104 additions and 52 deletions

View File

@ -85,8 +85,6 @@ erpnext.SerialNoBatchSelector = Class.extend({
fields: fields
});
this.bind_qty();
this.dialog.set_primary_action(__('Insert'), function() {
me.values = me.dialog.get_values();
if(me.validate()) {
@ -102,17 +100,24 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
if (d.batch_no) {
this.dialog.fields_dict.batches.df.data.push({
'batch_no': d.batch_no,
'actual_qty': d.actual_qty,
'selected_qty': d.qty,
'available_qty': d.actual_batch_qty
this.frm.doc.items.forEach(data => {
if(data.item_code == d.item_code) {
this.dialog.fields_dict.batches.df.data.push({
'batch_no': data.batch_no,
'actual_qty': data.actual_qty,
'selected_qty': data.qty,
'available_qty': data.actual_batch_qty
});
}
});
this.dialog.fields_dict.batches.grid.refresh();
}
}
if (this.has_batch) {
this.update_total_qty();
}
this.dialog.show();
},
@ -161,18 +166,44 @@ erpnext.SerialNoBatchSelector = Class.extend({
var me = this;
if(this.has_batch) {
this.values.batches.map((batch, i) => {
let item_code_field = {};
let row = (i !== 0) ? this.frm.add_child("items", this.item) : this.item;
let batch_no = batch.batch_no;
let row = '';
if (i !== 0 && !this.batch_exists(batch_no)) {
row = this.frm.add_child("items", {
'item_code': this.item.item_code,
'item_name': this.item.item_name,
'price_list_rate': this.item.price_list_rate,
'rate': this.item.rate,
'qty': batch.selected_qty,
'batch_no': batch_no,
'actual_qty': this.item.actual_qty,
'discount_percentage': this.item.discount_percentage
});
} else {
row = this.frm.doc.items.find(i => i.batch_no === batch_no);
}
if (!row) {
row = this.item;
}
this.map_row_values(row, batch, 'batch_no',
'selected_qty', this.values.warehouse);
});
} else {
this.map_row_values(this.item, this.values, 'serial_no', 'qty');
}
refresh_field("items");
this.callback && this.callback(this.item);
},
batch_exists: function(batch) {
const batches = this.frm.doc.items.map(data => data.batch_no);
return (batches && in_list(batches, batch)) ? true : false;
},
map_row_values: function(row, values, number, qty_field, warehouse) {
row.qty = values[qty_field];
row[number] = values[number];
@ -185,20 +216,15 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
},
bind_qty: function() {
let batches_field = this.dialog.fields_dict.batches;
update_total_qty: function() {
let qty_field = this.dialog.fields_dict.qty;
if(batches_field) {
batches_field.grid.wrapper.on('change', function() {
let total_qty = 0;
batches_field.grid.wrapper.find(
'input[data-fieldname="selected_qty"]').each(function() {
let total_qty = 0;
total_qty += Number($(this).val());
});
qty_field.set_input(total_qty);
});
}
this.dialog.fields_dict.batches.df.data.forEach(data => {
total_qty += flt(data.selected_qty);
});
qty_field.set_input(total_qty);
},
get_batch_fields: function() {
@ -230,7 +256,10 @@ erpnext.SerialNoBatchSelector = Class.extend({
if(row === this.grid_row) {
return "";
}
return row.on_grid_fields_dict.batch_no.get_value();
if (row.on_grid_fields_dict.batch_no) {
return row.on_grid_fields_dict.batch_no.get_value();
}
});
if(selected_batches.includes(val)) {
this.set_value("");
@ -293,6 +322,8 @@ erpnext.SerialNoBatchSelector = Class.extend({
} else {
this.grid.refresh();
}
me.update_total_qty();
}
},
],

View File

@ -23,7 +23,7 @@ frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
frappe.pages['point-of-sale'].refresh = function(wrapper) {
if (wrapper.pos) {
cur_frm = wrapper.pos.frm;
wrapper.pos.make_new_invoice();
}
if (frappe.flags.is_offline) {
@ -96,8 +96,8 @@ erpnext.pos.PointOfSale = class PointOfSale {
wrapper: this.wrapper.find('.cart-container'),
events: {
on_customer_change: (customer) => this.frm.set_value('customer', customer),
on_field_change: (item_code, field, value) => {
this.update_item_in_cart(item_code, field, value);
on_field_change: (item_code, field, value, batch_no) => {
this.update_item_in_cart(item_code, field, value, batch_no);
},
on_numpad: (value) => {
if (value == 'Pay') {
@ -158,10 +158,12 @@ erpnext.pos.PointOfSale = class PointOfSale {
});
}
update_item_in_cart(item_code, field='qty', value=1) {
update_item_in_cart(item_code, field='qty', value=1, batch_no) {
frappe.dom.freeze();
if(this.cart.exists(item_code)) {
const item = this.frm.doc.items.find(i => i.item_code === item_code);
if(this.cart.exists(item_code, batch_no)) {
const search_field = batch_no ? 'batch_no' : 'item_code';
const search_value = batch_no || item_code;
const item = this.frm.doc.items.find(i => i[search_field] === search_value);
frappe.flags.hide_serial_batch_dialog = false;
if (typeof value === 'string' && !in_list(['serial_no', 'batch_no'], field)) {
@ -219,29 +221,31 @@ erpnext.pos.PointOfSale = class PointOfSale {
]);
}
select_batch_and_serial_no(item) {
select_batch_and_serial_no(row) {
frappe.dom.unfreeze();
erpnext.show_serial_batch_selector(this.frm, item, () => {
this.update_item_in_frm(item, 'qty', item.qty)
.then(() => {
// update cart
frappe.run_serially([
() => {
if (item.qty === 0) {
frappe.model.clear_doc(item.doctype, item.name);
}
},
() => this.update_cart_data(item)
]);
});
erpnext.show_serial_batch_selector(this.frm, row, () => {
this.frm.doc.items.forEach(item => {
this.update_item_in_frm(item, 'qty', item.qty)
.then(() => {
// update cart
frappe.run_serially([
() => {
if (item.qty === 0) {
frappe.model.clear_doc(item.doctype, item.name);
}
},
() => this.update_cart_data(item)
]);
});
})
}, () => {
this.on_close(item);
this.on_close(row);
}, true);
}
on_close(item) {
if (!this.cart.exists(item.item_code) && item.qty) {
if (!this.cart.exists(item.item_code, item.batch_no) && item.qty) {
frappe.model.clear_doc(item.doctype, item.name);
}
}
@ -492,6 +496,11 @@ erpnext.pos.PointOfSale = class PointOfSale {
//
// }).addClass('visible-xs');
this.page.add_menu_item(__("Form View"), function () {
frappe.model.sync(me.frm.doc);
frappe.set_route("Form", me.frm.doc.doctype, me.frm.doc.name);
});
this.page.add_menu_item(__("POS Profile"), function () {
frappe.set_route('List', 'POS Profile');
});
@ -602,11 +611,15 @@ class POSCart {
this.customer_field.set_value("");
this.frm.msgbox = "";
let total_item_qty = 0.0;
this.frm.set_value("pos_total_qty",total_item_qty);
this.$discount_amount.find('input:text').val('');
this.wrapper.find('.grand-total-value').text(
format_currency(this.frm.doc.grand_total, this.frm.currency));
this.wrapper.find('.rounded-total-value').text(
format_currency(this.frm.doc.rounded_total, this.frm.currency));
this.$qty_total.find(".quantity-total").text(total_item_qty);
const customer = this.frm.doc.customer;
this.customer_field.set_value(customer);
@ -721,7 +734,7 @@ class POSCart {
total_item_qty += d.qty;
}
});
this.$qty_total.find('.quantity-total').text(total_item_qty)
this.$qty_total.find('.quantity-total').text(total_item_qty);
this.frm.set_value("pos_total_qty",total_item_qty);
}
@ -804,10 +817,11 @@ class POSCart {
this.numpad.reset_value();
} else {
const item_code = this.selected_item.attr('data-item-code');
const batch_no = this.selected_item.attr('data-batch-no');
const field = this.selected_item.active_field;
const value = this.numpad.get_value();
this.events.on_field_change(item_code, field, value);
this.events.on_field_change(item_code, field, value, batch_no);
}
}
@ -835,7 +849,7 @@ class POSCart {
add_item(item) {
this.$empty_state.hide();
if (this.exists(item.item_code)) {
if (this.exists(item.item_code, item.batch_no)) {
// update quantity
this.update_item(item);
} else if (flt(item.qty) > 0.0) {
@ -848,7 +862,10 @@ class POSCart {
}
update_item(item) {
const $item = this.$cart_items.find(`[data-item-code="${item.item_code}"]`);
const item_selector = item.batch_no ?
`[data-batch-no="${item.batch_no}"]` : `[data-item-code="${item.item_code}"]`;
const $item = this.$cart_items.find(item_selector);
if(item.qty > 0) {
const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
@ -870,7 +887,8 @@ class POSCart {
const rate = format_currency(item.rate, this.frm.doc.currency);
const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
return `
<div class="list-item indicator ${indicator_class}" data-item-code="${item.item_code}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
<div class="list-item indicator ${indicator_class}" data-item-code="${item.item_code}"
data-batch-no="${item.batch_no}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
<div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
${item.item_name}
</div>
@ -911,8 +929,11 @@ class POSCart {
return this.item_data[item_code];
}
exists(item_code) {
let $item = this.$cart_items.find(`[data-item-code="${item_code}"]`);
exists(item_code, batch_no) {
const is_exists = batch_no ?
`[data-batch-no="${batch_no}"]` : `[data-item-code="${item_code}"]`;
let $item = this.$cart_items.find(is_exists);
return $item.length > 0;
}