fix: serial and batch no selector (#43387)
(cherry picked from commit e4e96d2a44)
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
This commit is contained in:
@@ -342,12 +342,15 @@ erpnext.buying = {
|
||||
add_serial_batch_bundle(doc, cdt, cdn) {
|
||||
let item = locals[cdt][cdn];
|
||||
let me = this;
|
||||
let fields = ["has_batch_no", "has_serial_no"];
|
||||
|
||||
frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"])
|
||||
frappe.db.get_value("Item", item.item_code, fields)
|
||||
.then((r) => {
|
||||
if (r.message && (r.message.has_batch_no || r.message.has_serial_no)) {
|
||||
item.has_serial_no = r.message.has_serial_no;
|
||||
item.has_batch_no = r.message.has_batch_no;
|
||||
fields.forEach((field) => {
|
||||
item[field] = r.message[field];
|
||||
});
|
||||
|
||||
item.type_of_transaction = item.qty > 0 ? "Inward" : "Outward";
|
||||
item.is_rejected = false;
|
||||
|
||||
@@ -380,12 +383,15 @@ erpnext.buying = {
|
||||
add_serial_batch_for_rejected_qty(doc, cdt, cdn) {
|
||||
let item = locals[cdt][cdn];
|
||||
let me = this;
|
||||
let fields = ["has_batch_no", "has_serial_no"];
|
||||
|
||||
frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"])
|
||||
frappe.db.get_value("Item", item.item_code, fields)
|
||||
.then((r) => {
|
||||
if (r.message && (r.message.has_batch_no || r.message.has_serial_no)) {
|
||||
item.has_serial_no = r.message.has_serial_no;
|
||||
item.has_batch_no = r.message.has_batch_no;
|
||||
fields.forEach((field) => {
|
||||
item[field] = r.message[field];
|
||||
});
|
||||
|
||||
item.type_of_transaction = item.rejected_qty > 0 ? "Inward" : "Outward";
|
||||
item.is_rejected = true;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
let label = this.item?.has_serial_no ? __("Serial Nos") : __("Batch Nos");
|
||||
let primary_label = this.bundle ? __("Update") : __("Add");
|
||||
|
||||
if (this.item?.has_serial_no && this.item?.batch_no) {
|
||||
if (this.item?.has_serial_no && this.item?.has_batch_no) {
|
||||
label = __("Serial Nos / Batch Nos");
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
|
||||
this.dialog = new frappe.ui.Dialog({
|
||||
title: this.item?.title || primary_label,
|
||||
size: "large",
|
||||
fields: this.get_dialog_fields(),
|
||||
primary_action_label: primary_label,
|
||||
primary_action: () => this.update_bundle_entries(),
|
||||
@@ -164,12 +165,14 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
|
||||
fields.push({
|
||||
fieldtype: "Section Break",
|
||||
depends_on: "eval:doc.enter_manually !== 1 || doc.entries?.length > 0",
|
||||
});
|
||||
|
||||
fields.push({
|
||||
fieldname: "entries",
|
||||
fieldtype: "Table",
|
||||
allow_bulk_edit: true,
|
||||
depends_on: "eval:doc.enter_manually !== 1 || doc.entries?.length > 0",
|
||||
data: [],
|
||||
fields: this.get_dialog_table_fields(),
|
||||
});
|
||||
@@ -178,6 +181,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
}
|
||||
|
||||
get_attach_field() {
|
||||
let me = this;
|
||||
let label = this.item?.has_serial_no ? __("Serial Nos") : __("Batch Nos");
|
||||
let primary_label = this.bundle ? __("Update") : __("Add");
|
||||
|
||||
@@ -185,66 +189,41 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
label = __("Serial Nos / Batch Nos");
|
||||
}
|
||||
|
||||
let fields = [
|
||||
{
|
||||
fieldtype: "Section Break",
|
||||
label: __("{0} {1} via CSV File", [primary_label, label]),
|
||||
},
|
||||
];
|
||||
|
||||
if (this.item?.has_serial_no) {
|
||||
fields = [
|
||||
...fields,
|
||||
{
|
||||
fieldtype: "Check",
|
||||
label: __("Import Using CSV file"),
|
||||
fieldname: "import_using_csv_file",
|
||||
default: 0,
|
||||
let fields = [];
|
||||
if (this.item.has_serial_no) {
|
||||
fields.push({
|
||||
fieldtype: "Check",
|
||||
label: __("Enter Manually"),
|
||||
fieldname: "enter_manually",
|
||||
default: 1,
|
||||
depends_on: "eval:doc.import_using_csv_file !== 1",
|
||||
change() {
|
||||
if (me.dialog.get_value("enter_manually")) {
|
||||
me.dialog.set_value("import_using_csv_file", 0);
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldtype: "Section Break",
|
||||
label: __("{0} {1} Manually", [primary_label, label]),
|
||||
depends_on: "eval:doc.import_using_csv_file === 0",
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("Enter Serial No Range"),
|
||||
fieldname: "serial_no_range",
|
||||
depends_on: "eval:doc.import_using_csv_file === 0",
|
||||
description: __('Enter "ABC-001::100" for serial nos "ABC-001" to "ABC-100".'),
|
||||
onchange: () => {
|
||||
this.set_serial_nos_from_range();
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "Small Text",
|
||||
label: __("Enter Serial Nos"),
|
||||
fieldname: "upload_serial_nos",
|
||||
depends_on: "eval:doc.import_using_csv_file === 0",
|
||||
description: __("Enter each serial no in a new line"),
|
||||
},
|
||||
{
|
||||
fieldtype: "Column Break",
|
||||
depends_on: "eval:doc.import_using_csv_file === 0",
|
||||
},
|
||||
{
|
||||
fieldtype: "Button",
|
||||
fieldname: "make_serial_nos",
|
||||
label: __("Create Serial Nos"),
|
||||
depends_on: "eval:doc.import_using_csv_file === 0",
|
||||
click: () => {
|
||||
this.create_serial_nos();
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "Section Break",
|
||||
depends_on: "eval:doc.import_using_csv_file === 1",
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
fields = [
|
||||
...fields,
|
||||
{
|
||||
fieldtype: "Check",
|
||||
label: __("Import Using CSV file"),
|
||||
fieldname: "import_using_csv_file",
|
||||
depends_on: "eval:doc.enter_manually !== 1",
|
||||
default: !this.item.has_serial_no ? 1 : 0,
|
||||
change() {
|
||||
if (me.dialog.get_value("import_using_csv_file")) {
|
||||
me.dialog.set_value("enter_manually", 0);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "Section Break",
|
||||
depends_on: "eval:doc.import_using_csv_file === 1",
|
||||
label: __("{0} {1} via CSV File", [primary_label, label]),
|
||||
},
|
||||
{
|
||||
fieldtype: "Button",
|
||||
fieldname: "download_csv",
|
||||
@@ -262,9 +241,51 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
},
|
||||
];
|
||||
|
||||
if (this.item?.has_serial_no) {
|
||||
fields = [
|
||||
...fields,
|
||||
{
|
||||
fieldtype: "Section Break",
|
||||
label: __("{0} {1} Manually", [primary_label, label]),
|
||||
depends_on: "eval:doc.enter_manually === 1",
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("Serial No Range"),
|
||||
fieldname: "serial_no_range",
|
||||
depends_on: "eval:doc.enter_manually === 1 && !doc.serial_no_series",
|
||||
description: __('"SN-01::10" for "SN-01" to "SN-10"'),
|
||||
onchange: () => {
|
||||
this.set_serial_nos_from_range();
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (this.item?.has_serial_no) {
|
||||
fields = [
|
||||
...fields,
|
||||
{
|
||||
fieldtype: "Column Break",
|
||||
depends_on: "eval:doc.enter_manually === 1",
|
||||
},
|
||||
{
|
||||
fieldtype: "Small Text",
|
||||
label: __("Enter Serial Nos"),
|
||||
fieldname: "upload_serial_nos",
|
||||
depends_on: "eval:doc.enter_manually === 1",
|
||||
description: __("Enter each serial no in a new line"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
set_serial_nos_from_series() {}
|
||||
|
||||
set_batch_nos_from_series() {}
|
||||
|
||||
set_serial_nos_from_range() {
|
||||
const serial_no_range = this.dialog.get_value("serial_no_range");
|
||||
|
||||
@@ -511,6 +532,8 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
scan_barcode_data() {
|
||||
const { scan_serial_no, scan_batch_no } = this.dialog.get_values();
|
||||
|
||||
this.dialog.set_value("enter_manually", 0);
|
||||
|
||||
if (scan_serial_no || scan_batch_no) {
|
||||
frappe.call({
|
||||
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.is_serial_batch_no_exists",
|
||||
@@ -554,14 +577,13 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
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.entries.df.data.push({
|
||||
serial_no: scan_serial_no,
|
||||
batch_no: r.message,
|
||||
});
|
||||
|
||||
this.dialog.fields_dict.scan_serial_no.set_value("");
|
||||
}
|
||||
this.dialog.fields_dict.scan_serial_no.set_value("");
|
||||
this.dialog.fields_dict.entries.grid.refresh();
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -590,6 +612,12 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
update_bundle_entries() {
|
||||
let entries = this.dialog.get_values().entries;
|
||||
let warehouse = this.dialog.get_value("warehouse");
|
||||
let upload_serial_nos = this.dialog.get_value("upload_serial_nos");
|
||||
|
||||
if (!entries?.length && upload_serial_nos) {
|
||||
this.create_serial_nos();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((entries && !entries.length) || !entries) {
|
||||
frappe.throw(__("Please add atleast one Serial No / Batch No"));
|
||||
@@ -610,9 +638,13 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
},
|
||||
})
|
||||
.then((r) => {
|
||||
this.callback && this.callback(r.message);
|
||||
this.frm.save();
|
||||
this.dialog.hide();
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
this.callback && this.callback(r.message);
|
||||
},
|
||||
() => this.frm.save(),
|
||||
() => this.dialog.hide(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1329,6 +1329,15 @@ def create_serial_batch_no_ledgers(
|
||||
}
|
||||
)
|
||||
|
||||
batch_no = None
|
||||
|
||||
if (
|
||||
not entries[0].get("batch_no")
|
||||
and entries[0].get("serial_no")
|
||||
and frappe.get_cached_value("Item", child_row.item_code, "has_batch_no")
|
||||
):
|
||||
batch_no = get_batch(child_row.item_code)
|
||||
|
||||
for row in entries:
|
||||
row = frappe._dict(row)
|
||||
doc.append(
|
||||
@@ -1336,7 +1345,7 @@ def create_serial_batch_no_ledgers(
|
||||
{
|
||||
"qty": (flt(row.qty) or 1.0) * (1 if type_of_transaction == "Inward" else -1),
|
||||
"warehouse": warehouse,
|
||||
"batch_no": row.batch_no,
|
||||
"batch_no": row.batch_no or batch_no,
|
||||
"serial_no": row.serial_no,
|
||||
},
|
||||
)
|
||||
@@ -1351,6 +1360,18 @@ def create_serial_batch_no_ledgers(
|
||||
return doc
|
||||
|
||||
|
||||
def get_batch(item_code):
|
||||
from erpnext.stock.doctype.batch.batch import make_batch
|
||||
|
||||
return make_batch(
|
||||
frappe._dict(
|
||||
{
|
||||
"item": item_code,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def get_type_of_transaction(parent_doc, child_row):
|
||||
type_of_transaction = child_row.get("type_of_transaction")
|
||||
if parent_doc.get("doctype") == "Stock Entry":
|
||||
|
||||
Reference in New Issue
Block a user