[Fix] Multi-batch selection issue in POS (#13407)
This commit is contained in:
parent
a3c3dec5a2
commit
68ba4fd697
@ -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();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user