[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 fields: fields
}); });
this.bind_qty();
this.dialog.set_primary_action(__('Insert'), function() { this.dialog.set_primary_action(__('Insert'), function() {
me.values = me.dialog.get_values(); me.values = me.dialog.get_values();
if(me.validate()) { if(me.validate()) {
@ -102,17 +100,24 @@ erpnext.SerialNoBatchSelector = Class.extend({
} }
if (d.batch_no) { if (d.batch_no) {
this.dialog.fields_dict.batches.df.data.push({ this.frm.doc.items.forEach(data => {
'batch_no': d.batch_no, if(data.item_code == d.item_code) {
'actual_qty': d.actual_qty, this.dialog.fields_dict.batches.df.data.push({
'selected_qty': d.qty, 'batch_no': data.batch_no,
'available_qty': d.actual_batch_qty 'actual_qty': data.actual_qty,
'selected_qty': data.qty,
'available_qty': data.actual_batch_qty
});
}
}); });
this.dialog.fields_dict.batches.grid.refresh(); this.dialog.fields_dict.batches.grid.refresh();
} }
} }
if (this.has_batch) {
this.update_total_qty();
}
this.dialog.show(); this.dialog.show();
}, },
@ -161,18 +166,44 @@ erpnext.SerialNoBatchSelector = Class.extend({
var me = this; var me = this;
if(this.has_batch) { if(this.has_batch) {
this.values.batches.map((batch, i) => { this.values.batches.map((batch, i) => {
let item_code_field = {}; let batch_no = batch.batch_no;
let row = (i !== 0) ? this.frm.add_child("items", this.item) : this.item; 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', this.map_row_values(row, batch, 'batch_no',
'selected_qty', this.values.warehouse); 'selected_qty', this.values.warehouse);
}); });
} else { } else {
this.map_row_values(this.item, this.values, 'serial_no', 'qty'); this.map_row_values(this.item, this.values, 'serial_no', 'qty');
} }
refresh_field("items"); refresh_field("items");
this.callback && this.callback(this.item); 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) { map_row_values: function(row, values, number, qty_field, warehouse) {
row.qty = values[qty_field]; row.qty = values[qty_field];
row[number] = values[number]; row[number] = values[number];
@ -185,20 +216,15 @@ erpnext.SerialNoBatchSelector = Class.extend({
} }
}, },
bind_qty: function() { update_total_qty: function() {
let batches_field = this.dialog.fields_dict.batches;
let qty_field = this.dialog.fields_dict.qty; let qty_field = this.dialog.fields_dict.qty;
if(batches_field) { let total_qty = 0;
batches_field.grid.wrapper.on('change', function() {
let total_qty = 0;
batches_field.grid.wrapper.find(
'input[data-fieldname="selected_qty"]').each(function() {
total_qty += Number($(this).val()); this.dialog.fields_dict.batches.df.data.forEach(data => {
}); total_qty += flt(data.selected_qty);
qty_field.set_input(total_qty); });
});
} qty_field.set_input(total_qty);
}, },
get_batch_fields: function() { get_batch_fields: function() {
@ -230,7 +256,10 @@ erpnext.SerialNoBatchSelector = Class.extend({
if(row === this.grid_row) { if(row === this.grid_row) {
return ""; 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)) { if(selected_batches.includes(val)) {
this.set_value(""); this.set_value("");
@ -293,6 +322,8 @@ erpnext.SerialNoBatchSelector = Class.extend({
} else { } else {
this.grid.refresh(); 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) { frappe.pages['point-of-sale'].refresh = function(wrapper) {
if (wrapper.pos) { if (wrapper.pos) {
cur_frm = wrapper.pos.frm; wrapper.pos.make_new_invoice();
} }
if (frappe.flags.is_offline) { if (frappe.flags.is_offline) {
@ -96,8 +96,8 @@ erpnext.pos.PointOfSale = class PointOfSale {
wrapper: this.wrapper.find('.cart-container'), wrapper: this.wrapper.find('.cart-container'),
events: { events: {
on_customer_change: (customer) => this.frm.set_value('customer', customer), on_customer_change: (customer) => this.frm.set_value('customer', customer),
on_field_change: (item_code, field, value) => { on_field_change: (item_code, field, value, batch_no) => {
this.update_item_in_cart(item_code, field, value); this.update_item_in_cart(item_code, field, value, batch_no);
}, },
on_numpad: (value) => { on_numpad: (value) => {
if (value == 'Pay') { 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(); frappe.dom.freeze();
if(this.cart.exists(item_code)) { if(this.cart.exists(item_code, batch_no)) {
const item = this.frm.doc.items.find(i => i.item_code === item_code); 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; frappe.flags.hide_serial_batch_dialog = false;
if (typeof value === 'string' && !in_list(['serial_no', 'batch_no'], field)) { 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(); frappe.dom.unfreeze();
erpnext.show_serial_batch_selector(this.frm, item, () => { erpnext.show_serial_batch_selector(this.frm, row, () => {
this.update_item_in_frm(item, 'qty', item.qty) this.frm.doc.items.forEach(item => {
.then(() => { this.update_item_in_frm(item, 'qty', item.qty)
// update cart .then(() => {
frappe.run_serially([ // update cart
() => { frappe.run_serially([
if (item.qty === 0) { () => {
frappe.model.clear_doc(item.doctype, item.name); if (item.qty === 0) {
} frappe.model.clear_doc(item.doctype, item.name);
}, }
() => this.update_cart_data(item) },
]); () => this.update_cart_data(item)
}); ]);
});
})
}, () => { }, () => {
this.on_close(item); this.on_close(row);
}, true); }, true);
} }
on_close(item) { 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); frappe.model.clear_doc(item.doctype, item.name);
} }
} }
@ -492,6 +496,11 @@ erpnext.pos.PointOfSale = class PointOfSale {
// //
// }).addClass('visible-xs'); // }).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 () { this.page.add_menu_item(__("POS Profile"), function () {
frappe.set_route('List', 'POS Profile'); frappe.set_route('List', 'POS Profile');
}); });
@ -602,11 +611,15 @@ class POSCart {
this.customer_field.set_value(""); this.customer_field.set_value("");
this.frm.msgbox = ""; 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.$discount_amount.find('input:text').val('');
this.wrapper.find('.grand-total-value').text( this.wrapper.find('.grand-total-value').text(
format_currency(this.frm.doc.grand_total, this.frm.currency)); format_currency(this.frm.doc.grand_total, this.frm.currency));
this.wrapper.find('.rounded-total-value').text( this.wrapper.find('.rounded-total-value').text(
format_currency(this.frm.doc.rounded_total, this.frm.currency)); 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; const customer = this.frm.doc.customer;
this.customer_field.set_value(customer); this.customer_field.set_value(customer);
@ -721,7 +734,7 @@ class POSCart {
total_item_qty += d.qty; 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); this.frm.set_value("pos_total_qty",total_item_qty);
} }
@ -804,10 +817,11 @@ class POSCart {
this.numpad.reset_value(); this.numpad.reset_value();
} else { } else {
const item_code = this.selected_item.attr('data-item-code'); 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 field = this.selected_item.active_field;
const value = this.numpad.get_value(); 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) { add_item(item) {
this.$empty_state.hide(); this.$empty_state.hide();
if (this.exists(item.item_code)) { if (this.exists(item.item_code, item.batch_no)) {
// update quantity // update quantity
this.update_item(item); this.update_item(item);
} else if (flt(item.qty) > 0.0) { } else if (flt(item.qty) > 0.0) {
@ -848,7 +862,10 @@ class POSCart {
} }
update_item(item) { 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) { if(item.qty > 0) {
const is_stock_item = this.get_item_details(item.item_code).is_stock_item; 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 rate = format_currency(item.rate, this.frm.doc.currency);
const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red'; const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
return ` 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"> <div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
${item.item_name} ${item.item_name}
</div> </div>
@ -911,8 +929,11 @@ class POSCart {
return this.item_data[item_code]; return this.item_data[item_code];
} }
exists(item_code) { exists(item_code, batch_no) {
let $item = this.$cart_items.find(`[data-item-code="${item_code}"]`); 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; return $item.length > 0;
} }