diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 9267801839b2..0de6774393a0 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -31,8 +31,19 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { secondary_action: () => this.edit_full_form(), }); - this.dialog.set_value("qty", this.item.qty); + this.dialog.set_value("qty", this.item.qty).then(() => { + if (this.item.serial_no) { + this.dialog.set_value("scan_serial_no", this.item.serial_no); + frappe.model.set_value(this.item.doctype, this.item.name, 'serial_no', ''); + } else if (this.item.batch_no) { + this.dialog.set_value("scan_batch_no", this.item.batch_no); + frappe.model.set_value(this.item.doctype, this.item.name, 'batch_no', ''); + } + }); + this.dialog.show(); + this.$scan_btn = this.dialog.$wrapper.find(".link-btn"); + this.$scan_btn.css("display", "inline"); } get_serial_no_filters() { @@ -95,6 +106,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { if (this.item.has_serial_no) { fields.push({ fieldtype: 'Data', + options: 'Barcode', fieldname: 'scan_serial_no', label: __('Scan Serial No'), get_query: () => { @@ -106,15 +118,10 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { }); } - if (this.item.has_batch_no && this.item.has_serial_no) { - fields.push({ - fieldtype: 'Column Break', - }); - } - - if (this.item.has_batch_no) { + if (this.item.has_batch_no && !this.item.has_serial_no) { fields.push({ fieldtype: 'Data', + options: 'Barcode', fieldname: 'scan_batch_no', label: __('Scan Batch No'), onchange: () => this.update_serial_batch_no() @@ -309,6 +316,14 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } get_auto_data() { + if (this.item.serial_and_batch_bundle || this.item.rejected_serial_and_batch_bundle) { + return; + } + + if (this.item.serial_no || this.item.batch_no) { + return; + } + let { qty, based_on } = this.dialog.get_values(); if (!based_on) { @@ -340,16 +355,57 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { const { scan_serial_no, scan_batch_no } = this.dialog.get_values(); if (scan_serial_no) { - this.dialog.fields_dict.entries.df.data.push({ - serial_no: scan_serial_no + let existing_row = this.dialog.fields_dict.entries.df.data.filter(d => { + if (d.serial_no === scan_serial_no) { + return d + } }); - this.dialog.fields_dict.scan_serial_no.set_value(''); + if (existing_row?.length) { + frappe.throw(__('Serial No {0} already exists', [scan_serial_no])); + } + + if (!this.item.has_batch_no) { + this.dialog.fields_dict.entries.df.data.push({ + serial_no: scan_serial_no + }); + + this.dialog.fields_dict.scan_serial_no.set_value(''); + } else { + frappe.call({ + method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_batch_no_from_serial_no', + args: { + serial_no: scan_serial_no, + }, + callback: (r) => { + if (r.message) { + this.dialog.fields_dict.entries.df.data.push({ + serial_no: scan_serial_no, + batch_no: r.message + }); + + this.dialog.fields_dict.scan_serial_no.set_value(''); + } + } + + }) + } } else if (scan_batch_no) { - this.dialog.fields_dict.entries.df.data.push({ - batch_no: scan_batch_no + let existing_row = this.dialog.fields_dict.entries.df.data.filter(d => { + if (d.batch_no === scan_batch_no) { + return d + } }); + if (existing_row?.length) { + existing_row[0].qty += 1; + } else { + this.dialog.fields_dict.entries.df.data.push({ + batch_no: scan_batch_no, + qty: 1 + }); + } + this.dialog.fields_dict.scan_batch_no.set_value(''); } diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 66edba59dbba..f9392934aae6 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1740,3 +1740,8 @@ def get_stock_ledgers_batches(kwargs): batches[key].qty += d.qty return batches + + +@frappe.whitelist() +def get_batch_no_from_serial_no(serial_no): + return frappe.get_cached_value("Serial No", serial_no, "batch_no")