mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-16 02:11:39 +00:00
refactor(controllers): convert sales/purchase return lookups to qb/ORM
validate_returned_items used a raw frappe.db.sql with a string-built column list (and a separate Packed Item select); get_already_returned_items used a raw GROUP BY sum. Convert both to frappe.get_all / frappe.qb (Sum(Abs(...)) with an explicit groupby). The qb GROUP BY mirrors the original `group by item_code, <field>`, so it is parity-preserving (not a behaviour change) and valid on Postgres. Surgical re-apply: develop's `is_debit_note = 0` credit-note fix in make_return_doc is preserved (the staging branch predated and would have reverted it). Adds a test (Delivery Note -> sales return) exercising validate_returned_items and get_already_returned_items on both engines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@ import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, bold
|
||||
from frappe.query_builder import Criterion
|
||||
from frappe.query_builder.functions import Count
|
||||
from frappe.utils import cint, cstr, flt, get_link_to_form, getdate
|
||||
|
||||
import erpnext
|
||||
@@ -279,11 +281,7 @@ class StockController(AccountsController):
|
||||
def make_gl_entries_on_cancel(self, from_repost=False):
|
||||
if not from_repost:
|
||||
cancel_exchange_gain_loss_journal(frappe._dict(doctype=self.doctype, name=self.name))
|
||||
if frappe.db.sql(
|
||||
"""select name from `tabGL Entry` where voucher_type=%s
|
||||
and voucher_no=%s""",
|
||||
(self.doctype, self.name),
|
||||
):
|
||||
if frappe.db.exists("GL Entry", {"voucher_type": self.doctype, "voucher_no": self.name}):
|
||||
self.make_gl_entries()
|
||||
|
||||
def validate_warehouse(self):
|
||||
@@ -632,7 +630,7 @@ def check_item_quality_inspection(doctype: str, docstatus: str | int, items: str
|
||||
|
||||
inspection_fieldname = INSPECTION_FIELDNAME_MAP.get(doctype)
|
||||
if inspection_fieldname is None:
|
||||
return items if doctype == "Stock Entry" else []
|
||||
return []
|
||||
|
||||
allow_after_transaction = cint(docstatus) == 1 and frappe.get_single_value(
|
||||
"Stock Settings", "allow_to_make_quality_inspection_after_purchase_or_delivery"
|
||||
@@ -725,20 +723,18 @@ def future_sle_exists(args, sl_entries=None):
|
||||
|
||||
args["posting_datetime"] = get_combine_datetime(args["posting_date"], args["posting_time"])
|
||||
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
select item_code, warehouse, count(name) as total_row
|
||||
from `tabStock Ledger Entry`
|
||||
where
|
||||
({})
|
||||
and posting_datetime >= %(posting_datetime)s
|
||||
and voucher_no != %(voucher_no)s
|
||||
and is_cancelled = 0
|
||||
GROUP BY
|
||||
item_code, warehouse
|
||||
""".format(" or ".join(or_conditions)),
|
||||
args,
|
||||
as_dict=1,
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
data = (
|
||||
frappe.qb.from_(sle)
|
||||
.select(sle.item_code, sle.warehouse, Count(sle.name).as_("total_row"))
|
||||
.where(
|
||||
Criterion.any(or_conditions)
|
||||
& (sle.posting_datetime >= args["posting_datetime"])
|
||||
& (sle.voucher_no != args["voucher_no"])
|
||||
& (sle.is_cancelled == 0)
|
||||
)
|
||||
.groupby(sle.item_code, sle.warehouse)
|
||||
.run(as_dict=1)
|
||||
)
|
||||
|
||||
for d in data:
|
||||
@@ -792,12 +788,10 @@ def get_conditions_to_validate_future_sle(sl_entries):
|
||||
|
||||
warehouse_items_map[entry.warehouse].add(entry.item_code)
|
||||
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
or_conditions = []
|
||||
for warehouse, items in warehouse_items_map.items():
|
||||
or_conditions.append(
|
||||
f"""warehouse = {frappe.db.escape(warehouse)}
|
||||
and item_code in ({", ".join(frappe.db.escape(item) for item in items)})"""
|
||||
)
|
||||
or_conditions.append((sle.warehouse == warehouse) & sle.item_code.isin(list(items)))
|
||||
|
||||
return or_conditions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user