fix: not able to reconcile expired batches (#44012)
(cherry picked from commit 8805e74784)
This commit is contained in:
@@ -415,7 +415,6 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, p
|
||||
stock_ledger_entry.batch_no,
|
||||
Sum(stock_ledger_entry.actual_qty).as_("qty"),
|
||||
)
|
||||
.where((batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull()))
|
||||
.where(stock_ledger_entry.is_cancelled == 0)
|
||||
.where(
|
||||
(stock_ledger_entry.item_code == filters.get("item_code"))
|
||||
@@ -428,6 +427,9 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, p
|
||||
.limit(page_len)
|
||||
)
|
||||
|
||||
if not filters.get("include_expired_batches"):
|
||||
query = query.where((batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull()))
|
||||
|
||||
query = query.select(
|
||||
Concat("MFG-", batch_table.manufacturing_date).as_("manufacturing_date"),
|
||||
Concat("EXP-", batch_table.expiry_date).as_("expiry_date"),
|
||||
@@ -466,7 +468,6 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0
|
||||
bundle.batch_no,
|
||||
Sum(bundle.qty).as_("qty"),
|
||||
)
|
||||
.where((batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull()))
|
||||
.where(stock_ledger_entry.is_cancelled == 0)
|
||||
.where(
|
||||
(stock_ledger_entry.item_code == filters.get("item_code"))
|
||||
@@ -479,6 +480,11 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0
|
||||
.limit(page_len)
|
||||
)
|
||||
|
||||
if not filters.get("include_expired_batches"):
|
||||
bundle_query = bundle_query.where(
|
||||
(batch_table.expiry_date >= expiry_date) | (batch_table.expiry_date.isnull())
|
||||
)
|
||||
|
||||
bundle_query = bundle_query.select(
|
||||
Concat("MFG-", batch_table.manufacturing_date),
|
||||
Concat("EXP-", batch_table.expiry_date),
|
||||
|
||||
@@ -462,6 +462,8 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
is_inward = true;
|
||||
}
|
||||
|
||||
let include_expired_batches = me.include_expired_batches();
|
||||
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_batch_no",
|
||||
filters: {
|
||||
@@ -469,6 +471,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
warehouse:
|
||||
this.item.s_warehouse || this.item.t_warehouse || this.item.warehouse,
|
||||
is_inward: is_inward,
|
||||
include_expired_batches: include_expired_batches,
|
||||
},
|
||||
};
|
||||
},
|
||||
@@ -497,6 +500,14 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||
return fields;
|
||||
}
|
||||
|
||||
include_expired_batches() {
|
||||
return (
|
||||
this.frm.doc.doctype === "Stock Reconciliation" ||
|
||||
(this.frm.doc.doctype === "Stock Entry" &&
|
||||
["Material Receipt", "Material Transfer", "Material Issue"].includes(this.frm.doc.purpose))
|
||||
);
|
||||
}
|
||||
|
||||
get_auto_data() {
|
||||
let { qty, based_on } = this.dialog.get_values();
|
||||
|
||||
|
||||
@@ -689,6 +689,9 @@ class SerialandBatchBundle(Document):
|
||||
serial_batches = {}
|
||||
for row in self.entries:
|
||||
if not row.qty and row.batch_no and not row.serial_no:
|
||||
if self.voucher_type == "Stock Reconciliation" and self.type_of_transaction == "Inward":
|
||||
continue
|
||||
|
||||
frappe.throw(
|
||||
_("At row {0}: Qty is mandatory for the batch {1}").format(
|
||||
bold(row.idx), bold(row.batch_no)
|
||||
|
||||
@@ -117,6 +117,10 @@ frappe.ui.form.on("Stock Entry", {
|
||||
filters["is_inward"] = 1;
|
||||
}
|
||||
|
||||
if (["Material Receipt", "Material Transfer", "Material Issue"].includes(doc.purpose)) {
|
||||
filters["include_expired_batches"] = 1;
|
||||
}
|
||||
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_batch_no",
|
||||
filters: filters,
|
||||
|
||||
@@ -324,6 +324,7 @@ class StockReconciliation(StockController):
|
||||
row.item_code,
|
||||
posting_date=self.posting_date,
|
||||
posting_time=self.posting_time,
|
||||
for_stock_levels=True,
|
||||
)
|
||||
|
||||
total_current_qty += current_qty
|
||||
@@ -1322,7 +1323,16 @@ def get_stock_balance_for(
|
||||
qty, rate = data
|
||||
|
||||
if item_dict.get("has_batch_no"):
|
||||
qty = get_batch_qty(batch_no, warehouse, posting_date=posting_date, posting_time=posting_time) or 0
|
||||
qty = (
|
||||
get_batch_qty(
|
||||
batch_no,
|
||||
warehouse,
|
||||
posting_date=posting_date,
|
||||
posting_time=posting_time,
|
||||
for_stock_levels=True,
|
||||
)
|
||||
or 0
|
||||
)
|
||||
|
||||
return {
|
||||
"qty": qty,
|
||||
|
||||
@@ -124,7 +124,7 @@ class SerialBatchBundle:
|
||||
"Outward": self.sle.actual_qty < 0,
|
||||
}.get(sn_doc.type_of_transaction)
|
||||
|
||||
if not condition:
|
||||
if not condition and self.sle.actual_qty:
|
||||
correct_type = "Inward"
|
||||
if sn_doc.type_of_transaction == "Inward":
|
||||
correct_type = "Outward"
|
||||
@@ -133,7 +133,7 @@ class SerialBatchBundle:
|
||||
frappe.throw(_(msg), title=_("Incorrect Type of Transaction"))
|
||||
|
||||
precision = sn_doc.precision("total_qty")
|
||||
if flt(sn_doc.total_qty, precision) != flt(self.sle.actual_qty, precision):
|
||||
if self.sle.actual_qty and flt(sn_doc.total_qty, precision) != flt(self.sle.actual_qty, precision):
|
||||
msg = f"Total qty {flt(sn_doc.total_qty, precision)} of Serial and Batch Bundle {link} is not equal to Actual Qty {flt(self.sle.actual_qty, precision)} in the {self.sle.voucher_type} {self.sle.voucher_no}"
|
||||
frappe.throw(_(msg))
|
||||
|
||||
|
||||
@@ -1183,6 +1183,7 @@ class update_entries_after:
|
||||
stock_entry.calculate_rate_and_amount(reset_outgoing_rate=False, raise_error_if_no_rate=False)
|
||||
stock_entry.db_update()
|
||||
for d in stock_entry.items:
|
||||
# Update only the row that matches the voucher_detail_no or the row containing the FG/Scrap Item.
|
||||
if d.name == voucher_detail_no or (not d.s_warehouse and d.t_warehouse):
|
||||
d.db_update()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user