Skip to content

Commit

Permalink
fix: serial and batch no selector (backport frappe#43387) (frappe#43390)
Browse files Browse the repository at this point in the history
fix: serial and batch no selector (frappe#43387)

(cherry picked from commit e4e96d2)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
  • Loading branch information
2 people authored and khalandarsihan committed Oct 6, 2024
1 parent 8c41a06 commit fbfeb8f
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 66 deletions.
18 changes: 12 additions & 6 deletions erpnext/public/js/controllers/buying.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
150 changes: 91 additions & 59 deletions erpnext/public/js/utils/serial_no_batch_selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ 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");
}

primary_label += " " + label;

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(),
Expand Down Expand Up @@ -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(),
});
Expand All @@ -178,93 +181,111 @@ 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");

if (this.item?.has_serial_no && this.item?.has_batch_no) {
label = __("Serial Nos / Batch Nos");
}

let fields = [
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);
}
},
});
}

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",
label: __("Download CSV Template"),
click: () => this.download_csv_file(),
},
{
fieldtype: "Column Break",
},
{
fieldtype: "Attach",
fieldname: "attach_serial_batch_csv",
label: __("Attach CSV File"),
onchange: () => this.upload_csv_file(),
},
];

if (this.item?.has_serial_no) {
fields = [
...fields,
{
fieldtype: "Check",
label: __("Import Using CSV file"),
fieldname: "import_using_csv_file",
default: 0,
},
{
fieldtype: "Section Break",
label: __("{0} {1} Manually", [primary_label, label]),
depends_on: "eval:doc.import_using_csv_file === 0",
depends_on: "eval:doc.enter_manually === 1",
},
{
fieldtype: "Data",
label: __("Enter Serial No Range"),
label: __("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".'),
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.import_using_csv_file === 0",
depends_on: "eval:doc.enter_manually === 1",
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: "Button",
fieldname: "download_csv",
label: __("Download CSV Template"),
click: () => this.download_csv_file(),
},
{
fieldtype: "Column Break",
},
{
fieldtype: "Attach",
fieldname: "attach_serial_batch_csv",
label: __("Attach CSV File"),
onchange: () => this.upload_csv_file(),
},
];

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");

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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();
},
});
}
Expand Down Expand Up @@ -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"));
Expand All @@ -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(),
]);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1329,14 +1329,23 @@ 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(
"entries",
{
"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,
},
)
Expand All @@ -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":
Expand Down

0 comments on commit fbfeb8f

Please sign in to comment.