Merge pull request #47867 from frappe/version-14-hotfix

chore: release v14
This commit is contained in:
ruthra kumar
2025-06-03 17:20:36 +05:30
committed by GitHub
5 changed files with 70 additions and 37 deletions

View File

@@ -118,7 +118,8 @@ class ReceivablePayableReport:
self.build_data()
def fetch_ple_in_buffered_cursor(self):
self.ple_entries = frappe.db.sql(self.ple_query.get_sql(), as_dict=True)
query, param = self.ple_query.walk()
self.ple_entries = frappe.db.sql(query, param, as_dict=True)
for ple in self.ple_entries:
self.init_voucher_balance(ple) # invoiced, paid, credit_note, outstanding
@@ -131,8 +132,9 @@ class ReceivablePayableReport:
def fetch_ple_in_unbuffered_cursor(self):
self.ple_entries = []
query, param = self.ple_query.walk()
with frappe.db.unbuffered_cursor():
for ple in frappe.db.sql(self.ple_query.get_sql(), as_dict=True, as_iterator=True):
for ple in frappe.db.sql(query, param, as_dict=True, as_iterator=True):
self.init_voucher_balance(ple) # invoiced, paid, credit_note, outstanding
self.ple_entries.append(ple)

View File

@@ -23,6 +23,7 @@ def get_columns():
"""return columns"""
columns = [
_("Item") + ":Link/Item:150",
_("Item Name") + "::240",
_("Description") + "::300",
_("BOM Qty") + ":Float:160",
_("BOM UoM") + "::160",
@@ -73,6 +74,7 @@ def get_bom_stock(filters):
.on((BOM_ITEM.item_code == BIN.item_code) & (CONDITIONS))
.select(
BOM_ITEM.item_code,
BOM_ITEM.item_name,
BOM_ITEM.description,
BOM_ITEM.stock_qty,
BOM_ITEM.stock_uom,

View File

@@ -94,6 +94,7 @@ def get_expected_data(bom, warehouse, qty_to_produce, show_exploded_view=False):
expected_data.append(
[
item.item_code,
item.item_name,
item.description,
item.stock_qty,
item.stock_uom,

View File

@@ -497,26 +497,23 @@ erpnext.buying.MaterialRequestController = class MaterialRequestController exten
}
onload(doc, cdt, cdn) {
this.frm.set_query("item_code", "items", function() {
this.frm.set_query("item_code", "items", function () {
let filters = { is_stock_item: 1 };
if (doc.material_request_type == "Customer Provided") {
return{
query: "erpnext.controllers.queries.item_query",
filters:{
'customer': me.frm.doc.customer,
'is_stock_item':1
}
}
} else if (doc.material_request_type == "Purchase") {
return{
query: "erpnext.controllers.queries.item_query",
filters: {'is_purchase_item': 1}
}
} else {
return{
query: "erpnext.controllers.queries.item_query",
filters: {'is_stock_item': 1}
}
filters.customer = doc.customer;
} else if (
doc.material_request_type == "Purchase"
) {
filters = { is_purchase_item: 1 };
} else if (doc.material_request_type == "Manufacture") {
filters.include_item_in_manufacturing = 1;
}
return {
query: "erpnext.controllers.queries.item_query",
filters: filters,
};
});
}

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _
from frappe.query_builder.functions import IfNull
from frappe.query_builder.functions import IfNull, Max
from frappe.utils import flt
from pypika.terms import ExistsCriterion
@@ -208,30 +208,21 @@ def get_stock_ledger_entries(filters, items):
if not items:
return []
sle = frappe.qb.DocType("Stock Ledger Entry")
sle2 = frappe.qb.DocType("Stock Ledger Entry")
max_posting_datetime_query = get_item_wise_max_posting_datetime(filters, items)
sle = frappe.qb.DocType("Stock Ledger Entry")
query = (
frappe.qb.from_(sle)
.left_join(sle2)
.join(max_posting_datetime_query)
.on(
(sle.item_code == sle2.item_code)
& (sle.warehouse == sle2.warehouse)
& (sle.posting_datetime < sle2.posting_datetime)
& (sle.name < sle2.name)
(sle.item_code == max_posting_datetime_query.item_code)
& (sle.warehouse == max_posting_datetime_query.warehouse)
& (sle.posting_datetime == max_posting_datetime_query.posting_datetime)
)
.select(sle.item_code, sle.warehouse, sle.qty_after_transaction, sle.company)
.where((sle2.name.isnull()) & (sle.docstatus < 2) & (sle.item_code.isin(items)))
.where(sle.is_cancelled == 0)
)
if filters.get("company"):
query = query.where(sle.company == filters.get("company"))
if date := filters.get("date"):
query = query.where(sle.posting_date <= date)
else:
frappe.throw(_("'Date' is required"))
if filters.get("warehouse"):
warehouse_details = frappe.db.get_value(
"Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1
@@ -247,4 +238,44 @@ def get_stock_ledger_entries(filters, items):
)
)
if filters.get("company"):
query = query.where(sle.company == filters.get("company"))
if filters.get("data"):
query = query.where(sle.posting_date <= filters.get("data"))
return query.run(as_dict=True)
def get_item_wise_max_posting_datetime(filters, items):
"""Get the maximum Stock Ledger Entry name for the given filters and items."""
sle = frappe.qb.DocType("Stock Ledger Entry")
query = (
frappe.qb.from_(sle)
.select(sle.item_code, sle.warehouse, sle.name, Max(sle.posting_datetime).as_("posting_datetime"))
.where(sle.item_code.isin(items) & (sle.is_cancelled == 0))
.groupby(sle.item_code, sle.warehouse)
)
if filters.get("warehouse"):
warehouse_details = frappe.db.get_value(
"Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1
)
if warehouse_details:
wh = frappe.qb.DocType("Warehouse")
query = query.where(
sle.warehouse.isin(
frappe.qb.from_(wh)
.select(wh.name)
.where((wh.lft >= warehouse_details.lft) & (wh.rgt <= warehouse_details.rgt))
)
)
if filters.get("company"):
query = query.where(sle.company == filters.get("company"))
if filters.get("data"):
query = query.where(sle.posting_date <= filters.get("data"))
return query