fix: replacing serial and batch bundle on pos with auto fetch serial nos (#46236)

* fix: replacing serial and batch bundle on pos with auto fetch serial nos

* fix: reserved serial no

added a check to look for serial no in reserved serial nos list before removing it as there might be a situation where an item is returned which was already consolidated.
This commit is contained in:
Diptanil Saha
2025-03-05 17:41:43 +05:30
committed by GitHub
parent f50d479bfd
commit 35512d40bb
2 changed files with 50 additions and 36 deletions

View File

@@ -216,22 +216,16 @@ erpnext.PointOfSale.ItemDetails = class {
}
make_auto_serial_selection_btn(item) {
if (item.has_serial_no || item.has_batch_no) {
if (item.has_serial_no && item.has_batch_no) {
this.$form_container.append(
`<div class="btn btn-sm btn-secondary auto-fetch-btn" style="margin-top: 6px">${__(
"Select Serial No / Batch No"
)}</div>`
);
} else {
const classname = item.has_serial_no ? ".serial_no-control" : ".batch_no-control";
const label = item.has_serial_no ? __("Select Serial No") : __("Select Batch No");
this.$form_container
.find(classname)
.append(
`<div class="btn btn-sm btn-secondary auto-fetch-btn" style="margin-top: 6px">${label}</div>`
);
const doc = this.events.get_frm().doc;
if (!doc.is_return && (item.has_serial_no || item.serial_no)) {
if (!item.has_batch_no) {
this.$form_container.append(`<div class="grid-filler no-select"></div>`);
}
const label = __("Auto Fetch Serial Numbers");
this.$form_container.append(
`<div class="btn btn-sm btn-secondary auto-fetch-btn">${label}</div>`
);
this.$form_container.find(".serial_no-control").find("textarea").css("height", "6rem");
}
}
@@ -416,18 +410,41 @@ erpnext.PointOfSale.ItemDetails = class {
bind_auto_serial_fetch_event() {
this.$form_container.on("click", ".auto-fetch-btn", () => {
let frm = this.events.get_frm();
let item_row = this.item_row;
item_row.type_of_transaction = "Outward";
this.batch_no_control && this.batch_no_control.set_value("");
let qty = this.qty_control.get_value();
let conversion_factor = this.conversion_factor_control.get_value();
let expiry_date = this.item_row.has_batch_no ? this.events.get_frm().doc.posting_date : "";
new erpnext.SerialBatchPackageSelector(frm, item_row, (r) => {
if (r) {
frappe.model.set_value(item_row.doctype, item_row.name, {
serial_and_batch_bundle: r.name,
qty: Math.abs(r.total_qty),
use_serial_batch_fields: 0,
});
let numbers = frappe.call({
method: "erpnext.stock.doctype.serial_no.serial_no.auto_fetch_serial_number",
args: {
qty: qty * conversion_factor,
item_code: this.current_item.item_code,
warehouse: this.warehouse_control.get_value() || "",
batch_nos: this.current_item.batch_no || "",
posting_date: expiry_date,
for_doctype: "POS Invoice",
},
});
numbers.then((data) => {
let auto_fetched_serial_numbers = data.message;
let records_length = auto_fetched_serial_numbers.length;
if (!records_length) {
const warehouse = this.warehouse_control.get_value().bold();
const item_code = this.current_item.item_code.bold();
frappe.msgprint(
__(
"Serial numbers unavailable for Item {0} under warehouse {1}. Please try changing warehouse.",
[item_code, warehouse]
)
);
} else if (records_length < qty) {
frappe.msgprint(__("Fetched only {0} available serial numbers.", [records_length]));
this.qty_control.set_value(records_length);
}
numbers = auto_fetched_serial_numbers.join(`\n`);
this.serial_no_control.set_value(numbers);
});
});
}

View File

@@ -230,15 +230,17 @@ def get_pos_reserved_serial_nos(filters):
pos_transacted_sr_nos = query.run(as_dict=True)
reserved_sr_nos = set()
returned_sr_nos = set()
reserved_sr_nos = list()
returned_sr_nos = list()
for d in pos_transacted_sr_nos:
if d.is_return == 0:
[reserved_sr_nos.add(x) for x in get_serial_nos(d.serial_no)]
[reserved_sr_nos.append(x) for x in get_serial_nos(d.serial_no)]
elif d.is_return == 1:
[returned_sr_nos.add(x) for x in get_serial_nos(d.serial_no)]
[returned_sr_nos.append(x) for x in get_serial_nos(d.serial_no)]
reserved_sr_nos = list(reserved_sr_nos - returned_sr_nos)
for x in returned_sr_nos:
if x in reserved_sr_nos:
reserved_sr_nos.remove(x)
return reserved_sr_nos
@@ -254,12 +256,7 @@ def fetch_serial_numbers(filters, qty, do_not_include=None):
query = (
frappe.qb.from_(serial_no)
.select(serial_no.name)
.where(
(serial_no.item_code == filters["item_code"])
& (serial_no.warehouse == filters["warehouse"])
& (Coalesce(serial_no.sales_invoice, "") == "")
& (Coalesce(serial_no.delivery_document_no, "") == "")
)
.where((serial_no.item_code == filters["item_code"]) & (serial_no.warehouse == filters["warehouse"]))
.orderby(serial_no.creation)
.limit(qty or 1)
)