fix: scan for serial or batch in bundle (#38534)
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 9267801..0de6774 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 @@
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 @@
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 @@
});
}
- 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 @@
}
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 @@
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 88929ea..108a2e0 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
@@ -1745,3 +1745,8 @@
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")