Skip to content

Commit

Permalink
fix: replacing serial and batch bundle on pos with auto fetch serial …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
diptanilsaha authored Mar 5, 2025
1 parent f50d479 commit 35512d4
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 37 deletions.
69 changes: 43 additions & 26 deletions erpnext/selling/page/point_of_sale/pos_item_details.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}

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

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,
});
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 : "";

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);
});
});
}
Expand Down
19 changes: 8 additions & 11 deletions erpnext/stock/doctype/serial_no/serial_no.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)
)
Expand Down

0 comments on commit 35512d4

Please sign in to comment.