fix: adapt to query builder

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
This commit is contained in:
Akhil Narang
2025-11-16 22:50:58 +05:30
parent d40e660a52
commit 1cf9f903e5
49 changed files with 225 additions and 132 deletions

View File

@@ -3,6 +3,8 @@
import frappe import frappe
from frappe.query_builder import functions
from frappe.query_builder.utils import DocType
from frappe.tests import IntegrationTestCase from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, flt, today from frappe.utils import add_days, flt, today
@@ -81,10 +83,11 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(je.total_debit, 8500.0) self.assertEqual(je.total_debit, 8500.0)
self.assertEqual(je.total_credit, 8500.0) self.assertEqual(je.total_credit, 8500.0)
gl = DocType("GL Entry")
acc_balance = frappe.db.get_all( acc_balance = frappe.db.get_all(
"GL Entry", "GL Entry",
filters={"account": self.debtors_usd, "is_cancelled": 0}, filters={"account": self.debtors_usd, "is_cancelled": 0},
fields=["sum(debit)-sum(credit) as balance"], fields=[(functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance")],
)[0] )[0]
self.assertEqual(acc_balance.balance, 8500.0) self.assertEqual(acc_balance.balance, 8500.0)
@@ -146,12 +149,15 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(je.total_debit, 500.0) self.assertEqual(je.total_debit, 500.0)
self.assertEqual(je.total_credit, 500.0) self.assertEqual(je.total_credit, 500.0)
gl = DocType("GL Entry")
acc_balance = frappe.db.get_all( acc_balance = frappe.db.get_all(
"GL Entry", "GL Entry",
filters={"account": self.debtors_usd, "is_cancelled": 0}, filters={"account": self.debtors_usd, "is_cancelled": 0},
fields=[ fields=[
"sum(debit)-sum(credit) as balance", (functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance"),
"sum(debit_in_account_currency)-sum(credit_in_account_currency) as balance_in_account_currency", (
functions.Sum(gl.debit_in_account_currency) - functions.Sum(gl.credit_in_account_currency)
).as_("balance_in_account_currency"),
], ],
)[0] )[0]
# account shouldn't have balance in base and account currency # account shouldn't have balance in base and account currency
@@ -193,12 +199,15 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
pe.references = [] pe.references = []
pe.save().submit() pe.save().submit()
gl = DocType("GL Entry")
acc_balance = frappe.db.get_all( acc_balance = frappe.db.get_all(
"GL Entry", "GL Entry",
filters={"account": self.debtors_usd, "is_cancelled": 0}, filters={"account": self.debtors_usd, "is_cancelled": 0},
fields=[ fields=[
"sum(debit)-sum(credit) as balance", (functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance"),
"sum(debit_in_account_currency)-sum(credit_in_account_currency) as balance_in_account_currency", (
functions.Sum(gl.debit_in_account_currency) - functions.Sum(gl.credit_in_account_currency)
).as_("balance_in_account_currency"),
], ],
)[0] )[0]
# account should have balance only in account currency # account should have balance only in account currency
@@ -235,12 +244,15 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(flt(je.total_debit, precision), 0.0) self.assertEqual(flt(je.total_debit, precision), 0.0)
self.assertEqual(flt(je.total_credit, precision), 0.0) self.assertEqual(flt(je.total_credit, precision), 0.0)
gl = DocType("GL Entry")
acc_balance = frappe.db.get_all( acc_balance = frappe.db.get_all(
"GL Entry", "GL Entry",
filters={"account": self.debtors_usd, "is_cancelled": 0}, filters={"account": self.debtors_usd, "is_cancelled": 0},
fields=[ fields=[
"sum(debit)-sum(credit) as balance", (functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance"),
"sum(debit_in_account_currency)-sum(credit_in_account_currency) as balance_in_account_currency", (
functions.Sum(gl.debit_in_account_currency) - functions.Sum(gl.credit_in_account_currency)
).as_("balance_in_account_currency"),
], ],
)[0] )[0]
# account shouldn't have balance in base and account currency post revaluation # account shouldn't have balance in base and account currency post revaluation

View File

@@ -72,7 +72,7 @@ class OpeningInvoiceCreationTool(Document):
fields = [ fields = [
"company", "company",
{"COUNT": "*", "as": "total_invoices"}, {"COUNT": "*", "as": "total_invoices"},
"sum(outstanding_amount) as outstanding_amount", {"SUM": "outstanding_amount", "as": "outstanding_amount"},
] ]
companies = frappe.get_all("Company", fields=["name as company", "default_currency as currency"]) companies = frappe.get_all("Company", fields=["name as company", "default_currency as currency"])
if not companies: if not companies:

View File

@@ -669,7 +669,7 @@ class PaymentReconciliation(Document):
"party": self.party, "party": self.party,
}, },
fields=[ fields=[
"parent as `name`", "parent as name",
"exchange_rate", "exchange_rate",
], ],
as_list=1, as_list=1,

View File

@@ -975,7 +975,7 @@ class TestPaymentReconciliation(IntegrationTestCase):
total_credit_amount = frappe.db.get_all( total_credit_amount = frappe.db.get_all(
"Journal Entry Account", "Journal Entry Account",
{"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name}, {"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name},
"sum(credit) as amount", [{"SUM": "credit", "as": "amount"}],
group_by="reference_name", group_by="reference_name",
)[0].amount )[0].amount
@@ -1069,7 +1069,7 @@ class TestPaymentReconciliation(IntegrationTestCase):
total_credit_amount = frappe.db.get_all( total_credit_amount = frappe.db.get_all(
"Journal Entry Account", "Journal Entry Account",
{"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name}, {"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name},
"sum(credit) as amount", [{"SUM": "credit", "as": "amount"}],
group_by="reference_name", group_by="reference_name",
)[0].amount )[0].amount

View File

@@ -713,6 +713,7 @@ def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
return frappe.get_all( return frappe.get_all(
"UOM Conversion Detail", "UOM Conversion Detail",
filters={"parent": ("in", items), "uom": ("like", f"{txt}%")}, filters={"parent": ("in", items), "uom": ("like", f"{txt}%")},
fields=["distinct uom"], fields=["uom"],
as_list=1, as_list=1,
distinct=True,
) )

View File

@@ -1374,7 +1374,7 @@ class TestPurchaseInvoice(IntegrationTestCase, StockTestMixin):
total_debit_amount = frappe.db.get_all( total_debit_amount = frappe.db.get_all(
"Journal Entry Account", "Journal Entry Account",
{"account": creditors_account, "docstatus": 1, "reference_name": pi.name}, {"account": creditors_account, "docstatus": 1, "reference_name": pi.name},
"sum(debit) as amount", [{"SUM": "debit", "as": "amount"}],
group_by="reference_name", group_by="reference_name",
)[0].amount )[0].amount
self.assertEqual(flt(total_debit_amount, 2), 2500) self.assertEqual(flt(total_debit_amount, 2), 2500)
@@ -1456,7 +1456,7 @@ class TestPurchaseInvoice(IntegrationTestCase, StockTestMixin):
total_debit_amount = frappe.db.get_all( total_debit_amount = frappe.db.get_all(
"Journal Entry Account", "Journal Entry Account",
{"account": creditors_account, "docstatus": 1, "reference_name": pi_2.name}, {"account": creditors_account, "docstatus": 1, "reference_name": pi_2.name},
"sum(debit) as amount", [{"SUM": "debit", "as": "amount"}],
group_by="reference_name", group_by="reference_name",
)[0].amount )[0].amount
self.assertEqual(flt(total_debit_amount, 2), 1500) self.assertEqual(flt(total_debit_amount, 2), 1500)

View File

@@ -213,7 +213,10 @@ def get_allowed_types_from_settings(child_doc: bool = False):
repost_docs = [ repost_docs = [
x.document_type x.document_type
for x in frappe.db.get_all( for x in frappe.db.get_all(
"Repost Allowed Types", filters={"allowed": True}, fields=["distinct(document_type)"] "Repost Allowed Types",
filters={"allowed": True},
fields=["document_type"],
distinct=True,
) )
] ]
result = repost_docs result = repost_docs
@@ -287,7 +290,11 @@ def get_repost_allowed_types(doctype, txt, searchfield, start, page_len, filters
filters.update({"document_type": ("like", f"%{txt}%")}) filters.update({"document_type": ("like", f"%{txt}%")})
if allowed_types := frappe.db.get_all( if allowed_types := frappe.db.get_all(
"Repost Allowed Types", filters=filters, fields=["distinct(document_type)"], as_list=1 "Repost Allowed Types",
filters=filters,
fields=["document_type"],
as_list=1,
distinct=True,
): ):
return allowed_types return allowed_types
return [] return []

View File

@@ -3612,7 +3612,7 @@ class TestSalesInvoice(ERPNextTestSuite):
frappe.db.get_all( frappe.db.get_all(
"Payment Ledger Entry", "Payment Ledger Entry",
filters={"against_voucher_no": si.name, "delinked": 0}, filters={"against_voucher_no": si.name, "delinked": 0},
fields=["sum(amount), sum(amount_in_account_currency)"], fields=[{"SUM": "amount"}, {"SUM": "amount_in_account_currency"}],
as_list=1, as_list=1,
) )

View File

@@ -121,7 +121,7 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
gl_entries = frappe.db.get_all( gl_entries = frappe.db.get_all(
"GL Entry", "GL Entry",
filters={"voucher_no": pi.name}, filters={"voucher_no": pi.name},
fields=["account", "sum(debit) as debit", "sum(credit) as credit"], fields=["account", {"SUM": "debit", "as": "debit"}, {"SUM": "credit", "as": "credit"}],
group_by="account", group_by="account",
) )
self.assertEqual(len(gl_entries), 3) self.assertEqual(len(gl_entries), 3)

View File

@@ -854,8 +854,8 @@ def get_dashboard_info(party_type, party, loyalty_program=None):
group_by="company", group_by="company",
fields=[ fields=[
"company", "company",
"sum(grand_total) as grand_total", {"SUM": "grand_total", "as": "grand_total"},
"sum(base_grand_total) as base_grand_total", {"SUM": "base_grand_total", "as": "base_grand_total"},
], ],
) )
@@ -870,7 +870,7 @@ def get_dashboard_info(party_type, party, loyalty_program=None):
"expiry_date": (">=", getdate()), "expiry_date": (">=", getdate()),
}, },
group_by="company", group_by="company",
fields=["company", "sum(loyalty_points) as loyalty_points"], fields=["company", {"SUM": "loyalty_points", "as": "loyalty_points"}],
as_list=1, as_list=1,
) )
) )

View File

@@ -210,7 +210,7 @@ def get_gl_balance(report_date, company):
return frappe._dict( return frappe._dict(
frappe.db.get_all( frappe.db.get_all(
"GL Entry", "GL Entry",
fields=["party", "sum(debit - credit)"], fields=["party", {"SUM": [{"SUB": ["debit", "credit"]}], "as": "balance"}],
filters={"posting_date": ("<=", report_date), "is_cancelled": 0, "company": company}, filters={"posting_date": ("<=", report_date), "is_cancelled": 0, "company": company},
group_by="party", group_by="party",
as_list=1, as_list=1,

View File

@@ -323,22 +323,24 @@ def get_returned_qty_map_for_row(return_against, party, row_name, doctype):
party_type = "customer" party_type = "customer"
fields = [ fields = [
f"sum(abs(`tab{child_doctype}`.qty)) as qty", {"SUM": [{"ABS": f"`tab{child_doctype}`.qty"}], "as": "qty"},
] ]
if doctype != "Subcontracting Receipt": if doctype != "Subcontracting Receipt":
fields += [ fields += [
f"sum(abs(`tab{child_doctype}`.stock_qty)) as stock_qty", {"SUM": [{"ABS": f"`tab{child_doctype}`.stock_qty"}], "as": "stock_qty"},
] ]
if doctype in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"): if doctype in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"):
fields += [ fields += [
f"sum(abs(`tab{child_doctype}`.rejected_qty)) as rejected_qty", {"SUM": [{"ABS": f"`tab{child_doctype}`.rejected_qty"}], "as": "rejected_qty"},
f"sum(abs(`tab{child_doctype}`.received_qty)) as received_qty", {"SUM": [{"ABS": f"`tab{child_doctype}`.received_qty"}], "as": "received_qty"},
] ]
if doctype == "Purchase Receipt": if doctype == "Purchase Receipt":
fields += [f"sum(abs(`tab{child_doctype}`.received_stock_qty)) as received_stock_qty"] fields += [
{"SUM": [{"ABS": f"`tab{child_doctype}`.received_stock_qty"}], "as": "received_stock_qty"}
]
# Used retrun against and supplier and is_retrun because there is an index added for it # Used retrun against and supplier and is_retrun because there is an index added for it
data = frappe.get_all( data = frappe.get_all(

View File

@@ -563,11 +563,14 @@ class StatusUpdater(Document):
fields=[target_ref_field, target_field], fields=[target_ref_field, target_field],
) )
sum_ref = sum(abs(record[target_ref_field]) for record in child_records) # For operator dicts, the alias is in the "as" key; for strings, use the field name directly
ref_key = target_ref_field.get("as") if isinstance(target_ref_field, dict) else target_ref_field
sum_ref = sum(abs(record[ref_key]) for record in child_records)
if sum_ref > 0: if sum_ref > 0:
percentage = round( percentage = round(
sum(min(abs(record[target_field]), abs(record[target_ref_field])) for record in child_records) sum(min(abs(record[target_field]), abs(record[ref_key])) for record in child_records)
/ sum_ref / sum_ref
* 100, * 100,
6, 6,

View File

@@ -1320,7 +1320,7 @@ class StockController(AccountsController):
total_returned += flt(item.returned_qty * item.rate) total_returned += flt(item.returned_qty * item.rate)
if total_returned < total_amount: if total_returned < total_amount:
target_ref_field = "(amount - (returned_qty * rate))" target_ref_field = {"SUB": ["amount", {"MUL": ["returned_qty", "rate"]}], "as": "ref_amount"}
self._update_percent_field( self._update_percent_field(
{ {

View File

@@ -292,7 +292,7 @@ class SubcontractingController(StockController):
): ):
for row in frappe.get_all( for row in frappe.get_all(
f"{self.subcontract_data.order_doctype} Item", f"{self.subcontract_data.order_doctype} Item",
fields=["item_code", "(qty - received_qty) as qty", "parent", "name"], fields=["item_code", {"SUB": ["qty", "received_qty"], "as": "qty"}, "parent", "name"],
filters={"docstatus": 1, "parent": ("in", self.subcontract_orders)}, filters={"docstatus": 1, "parent": ("in", self.subcontract_orders)},
): ):
self.qty_to_be_received[(row.item_code, row.parent)] += row.qty self.qty_to_be_received[(row.item_code, row.parent)] += row.qty
@@ -553,7 +553,9 @@ class SubcontractingController(StockController):
data = [] data = []
doctype = "BOM Item" if not exploded_item else "BOM Explosion Item" doctype = "BOM Item" if not exploded_item else "BOM Explosion Item"
fields = [f"`tab{doctype}`.`stock_qty` / `tabBOM`.`quantity` as qty_consumed_per_unit"] fields = [
{"DIV": [f"`tab{doctype}`.`stock_qty`", "`tabBOM`.`quantity`"], "as": "qty_consumed_per_unit"}
]
alias_dict = { alias_dict = {
"item_code": "rm_item_code", "item_code": "rm_item_code",

View File

@@ -328,7 +328,7 @@ class TestItemWiseInventoryAccount(IntegrationTestCase):
"voucher_no": pr.name, "voucher_no": pr.name,
"item_code": ("in", items), "item_code": ("in", items),
}, },
fields=["sum(stock_value_difference) as value"], fields=[{"SUM": "stock_value_difference", "as": "value"}],
) )
gl_value = frappe.db.get_value( gl_value = frappe.db.get_value(
@@ -435,7 +435,7 @@ class TestItemWiseInventoryAccount(IntegrationTestCase):
sle_value = frappe.get_all( sle_value = frappe.get_all(
"Stock Ledger Entry", "Stock Ledger Entry",
filters={"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": ("in", items)}, filters={"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": ("in", items)},
fields=["sum(stock_value_difference) as value"], fields=[{"SUM": "stock_value_difference", "as": "value"}],
) )
gl_value = ( gl_value = (

View File

@@ -8,6 +8,7 @@ from itertools import groupby
import frappe import frappe
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from frappe import _ from frappe import _
from frappe.query_builder.custom import Month, MonthName, Quarter
from frappe.utils import cint, flt, getdate from frappe.utils import cint, flt, getdate
from erpnext.setup.utils import get_exchange_rate from erpnext.setup.utils import get_exchange_rate
@@ -82,40 +83,52 @@ class SalesPipelineAnalytics:
self.filters.get("pipeline_by") self.filters.get("pipeline_by")
] ]
self.group_by_period = { opp = frappe.qb.DocType("Opportunity")
"Monthly": "month(expected_closing)",
"Quarterly": "QUARTER(expected_closing)", if self.filters.get("range") == "Monthly":
}[self.filters.get("range")] self.group_by_period = Month(opp.expected_closing)
self.duration = MonthName(opp.expected_closing).as_("month")
else:
self.group_by_period = Quarter(opp.expected_closing)
self.duration = Quarter(opp.expected_closing).as_("quarter")
self.pipeline_by = {"Owner": "opportunity_owner", "Sales Stage": "sales_stage"}[ self.pipeline_by = {"Owner": "opportunity_owner", "Sales Stage": "sales_stage"}[
self.filters.get("pipeline_by") self.filters.get("pipeline_by")
] ]
self.duration = {
"Monthly": "monthname(expected_closing) as month",
"Quarterly": "QUARTER(expected_closing) as quarter",
}[self.filters.get("range")]
self.period_by = {"Monthly": "month", "Quarterly": "quarter"}[self.filters.get("range")] self.period_by = {"Monthly": "month", "Quarterly": "quarter"}[self.filters.get("range")]
def get_data(self): def get_data(self):
self.get_fields() self.get_fields()
opp = frappe.qb.DocType("Opportunity")
query = frappe.qb.get_query(
"Opportunity",
filters=self.get_conditions(),
ignore_permissions=True,
)
pipeline_field = opp._assign if self.group_by_based_on == "_assign" else opp.sales_stage
if self.filters.get("based_on") == "Number": if self.filters.get("based_on") == "Number":
self.query_result = frappe.db.get_list( self.query_result = (
"Opportunity", query.select(
filters=self.get_conditions(), pipeline_field.as_(self.pipeline_by),
fields=[self.based_on, self.data_based_on, self.duration], frappe.query_builder.functions.Count("*").as_("count"),
group_by=f"{self.group_by_based_on},{self.group_by_period}", self.duration,
order_by=self.group_by_period, )
.groupby(pipeline_field, self.group_by_period)
.orderby(self.group_by_period)
.run(as_dict=True)
) )
if self.filters.get("based_on") == "Amount": if self.filters.get("based_on") == "Amount":
self.query_result = frappe.db.get_list( self.query_result = query.select(
"Opportunity", pipeline_field.as_(self.pipeline_by),
filters=self.get_conditions(), opp.opportunity_amount.as_("amount"),
fields=[self.based_on, self.data_based_on, self.duration, "currency"], self.duration,
) opp.currency,
).run(as_dict=True)
self.convert_to_base_currency() self.convert_to_base_currency()

View File

@@ -1740,8 +1740,9 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
barcodes = frappe.get_all( barcodes = frappe.get_all(
"Item Barcode", "Item Barcode",
fields=["distinct parent as item_code"], fields=["parent as item_code"],
filters={"barcode": ("like", f"%{txt}%")}, filters={"barcode": ("like", f"%{txt}%")},
distinct=True,
) )
barcodes = [d.item_code for d in barcodes] barcodes = [d.item_code for d in barcodes]
@@ -1751,11 +1752,11 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
if filters and filters.get("item_code"): if filters and filters.get("item_code"):
has_variants = frappe.get_cached_value("Item", filters.get("item_code"), "has_variants") has_variants = frappe.get_cached_value("Item", filters.get("item_code"), "has_variants")
if not has_variants: if not has_variants:
query_filters["has_variants"] = 0 query_filters.append(["has_variants", "=", 0])
if filters: if filters:
for fieldname, value in filters.items(): for fieldname, value in filters.items():
query_filters[fieldname] = value query_filters.append([fieldname, "=", value])
return frappe.get_list( return frappe.get_list(
"Item", "Item",

View File

@@ -207,7 +207,7 @@ class JobCard(Document):
job_card_qty = frappe.get_all( job_card_qty = frappe.get_all(
"Job Card", "Job Card",
fields=["sum(for_quantity)"], fields=[{"SUM": "for_quantity"}],
filters={ filters={
"work_order": self.work_order, "work_order": self.work_order,
"operation_id": self.operation_id, "operation_id": self.operation_id,
@@ -933,9 +933,9 @@ class JobCard(Document):
return frappe.get_all( return frappe.get_all(
"Job Card", "Job Card",
fields=[ fields=[
"sum(total_time_in_mins) as time_in_mins", {"SUM": "total_time_in_mins", "as": "time_in_mins"},
"sum(total_completed_qty) as completed_qty", {"SUM": "total_completed_qty", "as": "completed_qty"},
"sum(process_loss_qty) as process_loss_qty", {"SUM": "process_loss_qty", "as": "process_loss_qty"},
], ],
filters={ filters={
"docstatus": 1, "docstatus": 1,
@@ -1423,11 +1423,12 @@ def get_operations(doctype, txt, searchfield, start, page_len, filters):
return frappe.get_all( return frappe.get_all(
"Work Order Operation", "Work Order Operation",
filters=args, filters=args,
fields=["distinct operation as operation"], fields=["operation"],
limit_start=start, limit_start=start,
limit_page_length=page_len, limit_page_length=page_len,
order_by="idx asc", order_by="idx asc",
as_list=1, as_list=1,
distinct=True,
) )

View File

@@ -624,7 +624,7 @@ class ProductionPlan(Document):
so_wise_planned_qty = frappe._dict() so_wise_planned_qty = frappe._dict()
data = frappe.get_all( data = frappe.get_all(
"Production Plan Item", "Production Plan Item",
fields=["sales_order", "sales_order_item", "SUM(planned_qty) as qty"], fields=["sales_order", "sales_order_item", {"SUM": "planned_qty", "as": "qty"}],
filters={ filters={
"sales_order": ("in", sales_orders), "sales_order": ("in", sales_orders),
"docstatus": 1, "docstatus": 1,

View File

@@ -73,9 +73,10 @@ class TestProductionPlan(IntegrationTestCase):
material_requests = frappe.get_all( material_requests = frappe.get_all(
"Material Request Item", "Material Request Item",
fields=["distinct parent"], fields=["parent"],
filters={"production_plan": pln.name}, filters={"production_plan": pln.name},
as_list=1, as_list=1,
distinct=True,
) )
self.assertTrue(len(material_requests), 2) self.assertTrue(len(material_requests), 2)

View File

@@ -976,8 +976,9 @@ class TestWorkOrder(IntegrationTestCase):
job_cards = frappe.get_all( job_cards = frappe.get_all(
"Job Card Time Log", "Job Card Time Log",
fields=["distinct parent as name", "docstatus"], fields=["parent as name", "docstatus"],
order_by="creation asc", order_by="creation asc",
distinct=True,
) )
for job_card in job_cards: for job_card in job_cards:

View File

@@ -166,7 +166,7 @@ class WorkOrder(Document):
operation_details = frappe._dict( operation_details = frappe._dict(
frappe.get_all( frappe.get_all(
"Job Card", "Job Card",
fields=["operation", "sum(for_quantity)"], fields=["operation", {"SUM": "for_quantity"}],
filters={"docstatus": ("<", 2), "work_order": self.name}, filters={"docstatus": ("<", 2), "work_order": self.name},
as_list=1, as_list=1,
group_by="operation_id", group_by="operation_id",
@@ -718,7 +718,7 @@ class WorkOrder(Document):
if self.production_plan_item: if self.production_plan_item:
total_qty = frappe.get_all( total_qty = frappe.get_all(
"Work Order", "Work Order",
fields="sum(produced_qty) as produced_qty", fields=[{"SUM": "produced_qty", "as": "produced_qty"}],
filters={ filters={
"docstatus": 1, "docstatus": 1,
"production_plan": self.production_plan, "production_plan": self.production_plan,
@@ -1347,7 +1347,7 @@ class WorkOrder(Document):
else: else:
data = frappe.get_all( data = frappe.get_all(
"Stock Entry", "Stock Entry",
fields=["timestamp(posting_date, posting_time) as posting_datetime"], fields=[{"TIMESTAMP": ["posting_date", "posting_time"], "as": "posting_datetime"}],
filters={ filters={
"work_order": self.name, "work_order": self.name,
"purpose": ("in", ["Material Transfer for Manufacture", "Manufacture"]), "purpose": ("in", ["Material Transfer for Manufacture", "Manufacture"]),

View File

@@ -59,7 +59,7 @@ def get_data(filters):
job_card_time_details = {} job_card_time_details = {}
for job_card_data in frappe.get_all( for job_card_data in frappe.get_all(
"Job Card Time Log", "Job Card Time Log",
fields=["min(from_time) as from_time", "max(to_time) as to_time", "parent"], fields=[{"MIN": "from_time", "as": "from_time"}, {"MAX": "to_time", "as": "to_time"}, "parent"],
filters=job_card_time_filter, filters=job_card_time_filter,
group_by="parent", group_by="parent",
): ):

View File

@@ -230,7 +230,12 @@ class ProductionPlanReport:
purchased_items = frappe.get_all( purchased_items = frappe.get_all(
"Purchase Order Item", "Purchase Order Item",
fields=["item_code", "min(schedule_date) as arrival_date", "qty as arrival_qty", "warehouse"], fields=[
"item_code",
{"MIN": "schedule_date", "as": "arrival_date"},
"qty as arrival_qty",
"warehouse",
],
filters={ filters={
"item_code": ("in", self.item_codes), "item_code": ("in", self.item_codes),
"warehouse": ("in", self.warehouses), "warehouse": ("in", self.warehouses),

View File

@@ -10,7 +10,7 @@ def execute():
frappe.reload_doc("stock", "doctype", "item") frappe.reload_doc("stock", "doctype", "item")
for data in frappe.get_all( for data in frappe.get_all(
"Item Quality Inspection Parameter", fields=["distinct parent"], filters={"parenttype": "Item"} "Item Quality Inspection Parameter", fields=["parent"], filters={"parenttype": "Item"}, distinct=True
): ):
qc_doc = frappe.new_doc("Quality Inspection Template") qc_doc = frappe.new_doc("Quality Inspection Template")
qc_doc.quality_inspection_template_name = "QIT/%s" % data.parent qc_doc.quality_inspection_template_name = "QIT/%s" % data.parent

View File

@@ -401,8 +401,6 @@ def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20, o
meta = frappe.get_meta(doctype) meta = frappe.get_meta(doctype)
fields = "distinct *"
or_filters = [] or_filters = []
if txt: if txt:
@@ -424,13 +422,14 @@ def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20, o
return frappe.get_list( return frappe.get_list(
doctype, doctype,
fields=fields, fields="*",
filters=filters, filters=filters,
or_filters=or_filters, or_filters=or_filters,
limit_start=limit_start, limit_start=limit_start,
limit_page_length=limit_page_length, limit_page_length=limit_page_length,
order_by=order_by, order_by=order_by,
ignore_permissions=ignore_permissions, ignore_permissions=ignore_permissions,
distinct=True,
) )

View File

@@ -179,7 +179,11 @@ def get_reverse_charge_total(filters):
try: try:
return ( return (
frappe.db.get_all( frappe.db.get_all(
"Purchase Invoice", filters=query_filters, fields=["sum(base_total)"], as_list=True, limit=1 "Purchase Invoice",
filters=query_filters,
fields=[{"SUM": "base_total"}],
as_list=True,
limit=1,
)[0][0] )[0][0]
or 0 or 0
) )
@@ -219,7 +223,11 @@ def get_reverse_charge_recoverable_total(filters):
try: try:
return ( return (
frappe.db.get_all( frappe.db.get_all(
"Purchase Invoice", filters=query_filters, fields=["sum(base_total)"], as_list=True, limit=1 "Purchase Invoice",
filters=query_filters,
fields=[{"SUM": "base_total"}],
as_list=True,
limit=1,
)[0][0] )[0][0]
or 0 or 0
) )
@@ -274,7 +282,11 @@ def get_standard_rated_expenses_total(filters):
try: try:
return ( return (
frappe.db.get_all( frappe.db.get_all(
"Purchase Invoice", filters=query_filters, fields=["sum(base_total)"], as_list=True, limit=1 "Purchase Invoice",
filters=query_filters,
fields=[{"SUM": "base_total"}],
as_list=True,
limit=1,
)[0][0] )[0][0]
or 0 or 0
) )
@@ -292,7 +304,7 @@ def get_standard_rated_expenses_tax(filters):
frappe.db.get_all( frappe.db.get_all(
"Purchase Invoice", "Purchase Invoice",
filters=query_filters, filters=query_filters,
fields=["sum(recoverable_standard_rated_expenses)"], fields=[{"SUM": "recoverable_standard_rated_expenses"}],
as_list=True, as_list=True,
limit=1, limit=1,
)[0][0] )[0][0]
@@ -310,7 +322,7 @@ def get_tourist_tax_return_total(filters):
try: try:
return ( return (
frappe.db.get_all( frappe.db.get_all(
"Sales Invoice", filters=query_filters, fields=["sum(base_total)"], as_list=True, limit=1 "Sales Invoice", filters=query_filters, fields=[{"SUM": "base_total"}], as_list=True, limit=1
)[0][0] )[0][0]
or 0 or 0
) )
@@ -328,7 +340,7 @@ def get_tourist_tax_return_tax(filters):
frappe.db.get_all( frappe.db.get_all(
"Sales Invoice", "Sales Invoice",
filters=query_filters, filters=query_filters,
fields=["sum(tourist_tax_return)"], fields=[{"SUM": "tourist_tax_return"}],
as_list=True, as_list=True,
limit=1, limit=1,
)[0][0] )[0][0]

View File

@@ -14,6 +14,7 @@ from frappe.contacts.address_and_contact import (
from frappe.model.mapper import get_mapped_doc from frappe.model.mapper import get_mapped_doc
from frappe.model.naming import set_name_by_naming_series, set_name_from_naming_options from frappe.model.naming import set_name_by_naming_series, set_name_from_naming_options
from frappe.model.utils.rename_doc import update_linked_doctypes from frappe.model.utils.rename_doc import update_linked_doctypes
from frappe.query_builder import Field, functions
from frappe.utils import cint, cstr, flt, get_formatted_email, today from frappe.utils import cint, cstr, flt, get_formatted_email, today
from frappe.utils.user import get_users_with_role from frappe.utils.user import get_users_with_role
@@ -503,11 +504,11 @@ def get_loyalty_programs(doc):
loyalty_programs = frappe.get_all( loyalty_programs = frappe.get_all(
"Loyalty Program", "Loyalty Program",
fields=["name", "customer_group", "customer_territory"], fields=["name", "customer_group", "customer_territory"],
filters={ filters=[
"auto_opt_in": 1, ["auto_opt_in", "=", 1],
"from_date": ["<=", today()], ["from_date", "<=", today()],
"ifnull(to_date, '2500-01-01')": [">=", today()], [functions.IfNull(Field("to_date"), "2500-01-01"), ">=", today()],
}, ],
) )
for loyalty_program in loyalty_programs: for loyalty_program in loyalty_programs:

View File

@@ -630,7 +630,7 @@ def get_ordered_items(quotation: str):
frappe.get_all( frappe.get_all(
"Sales Order Item", "Sales Order Item",
filters={"prevdoc_docname": quotation, "docstatus": 1}, filters={"prevdoc_docname": quotation, "docstatus": 1},
fields=["quotation_item", "sum(qty)"], fields=["quotation_item", {"SUM": "qty"}],
group_by="quotation_item", group_by="quotation_item",
as_list=1, as_list=1,
) )

View File

@@ -992,7 +992,11 @@ def get_requested_item_qty(sales_order):
for d in frappe.db.get_all( for d in frappe.db.get_all(
"Material Request Item", "Material Request Item",
filters={"docstatus": 1, "sales_order": sales_order}, filters={"docstatus": 1, "sales_order": sales_order},
fields=["sales_order_item", "sum(qty) as qty", "sum(received_qty) as received_qty"], fields=[
"sales_order_item",
{"SUM": "qty", "as": "qty"},
{"SUM": "received_qty", "as": "received_qty"},
],
group_by="sales_order_item", group_by="sales_order_item",
): ):
result[d.sales_order_item] = frappe._dict({"qty": d.qty, "received_qty": d.received_qty}) result[d.sales_order_item] = frappe._dict({"qty": d.qty, "received_qty": d.received_qty})

View File

@@ -95,7 +95,7 @@ def get_data(filters=None):
items = get_selling_items(filters) items = get_selling_items(filters)
item_stock_map = frappe.get_all( item_stock_map = frappe.get_all(
"Bin", fields=["item_code", "sum(actual_qty) AS available"], group_by="item_code" "Bin", fields=["item_code", {"SUM": "actual_qty", "as": "available"}], group_by="item_code"
) )
item_stock_map = {item.item_code: item.available for item in item_stock_map} item_stock_map = {item.item_code: item.available for item in item_stock_map}
price_list_map = fetch_item_prices( price_list_map = fetch_item_prices(

View File

@@ -799,7 +799,7 @@ class EmailDigest(Document):
"status": ["not in", ("Cancelled")], "status": ["not in", ("Cancelled")],
"company": self.company, "company": self.company,
}, },
fields=[{"COUNT": "*", "as": "count"}, "sum(grand_total) as grand_total"], fields=[{"COUNT": "*", "as": "count"}, {"SUM": "grand_total", "as": "grand_total"}],
) )
def get_from_to_date(self): def get_from_to_date(self):

View File

@@ -63,7 +63,7 @@ def get_all_customers(date_range, company, field, limit=None):
return frappe.get_list( return frappe.get_list(
"Sales Invoice", "Sales Invoice",
fields=["customer as name", "sum(outstanding_amount) as value"], fields=["customer as name", {"SUM": "outstanding_amount", "as": "value"}],
filters=filters, filters=filters,
group_by="customer", group_by="customer",
order_by="value desc", order_by="value desc",
@@ -80,7 +80,7 @@ def get_all_customers(date_range, company, field, limit=None):
return frappe.get_list( return frappe.get_list(
"Sales Order", "Sales Order",
fields=["customer as name", f"sum({select_field}) as value"], fields=["customer as name", {"SUM": select_field, "as": "value"}],
filters=filters, filters=filters,
group_by="customer", group_by="customer",
order_by="value desc", order_by="value desc",
@@ -91,10 +91,10 @@ def get_all_customers(date_range, company, field, limit=None):
@frappe.whitelist() @frappe.whitelist()
def get_all_items(date_range, company, field, limit=None): def get_all_items(date_range, company, field, limit=None):
if field in ("available_stock_qty", "available_stock_value"): if field in ("available_stock_qty", "available_stock_value"):
select_field = "sum(actual_qty)" if field == "available_stock_qty" else "sum(stock_value)" sum_field = "actual_qty" if field == "available_stock_qty" else "stock_value"
results = frappe.db.get_all( results = frappe.db.get_all(
"Bin", "Bin",
fields=["item_code as name", f"{select_field} as value"], fields=["item_code as name", {"SUM": sum_field, "as": "value"}],
group_by="item_code", group_by="item_code",
order_by="value desc", order_by="value desc",
limit=limit, limit=limit,
@@ -125,7 +125,7 @@ def get_all_items(date_range, company, field, limit=None):
select_doctype, select_doctype,
fields=[ fields=[
f"`tab{child_doctype}`.item_code as name", f"`tab{child_doctype}`.item_code as name",
f"sum(`tab{child_doctype}`.{select_field}) as value", {"SUM": f"`tab{child_doctype}`.{select_field}", "as": "value"},
], ],
filters=filters, filters=filters,
order_by="value desc", order_by="value desc",
@@ -145,7 +145,7 @@ def get_all_suppliers(date_range, company, field, limit=None):
return frappe.get_list( return frappe.get_list(
"Purchase Invoice", "Purchase Invoice",
fields=["supplier as name", "sum(outstanding_amount) as value"], fields=["supplier as name", {"SUM": "outstanding_amount", "as": "value"}],
filters=filters, filters=filters,
group_by="supplier", group_by="supplier",
order_by="value desc", order_by="value desc",
@@ -162,7 +162,7 @@ def get_all_suppliers(date_range, company, field, limit=None):
return frappe.get_list( return frappe.get_list(
"Purchase Order", "Purchase Order",
fields=["supplier as name", f"sum({select_field}) as value"], fields=["supplier as name", {"SUM": select_field, "as": "value"}],
filters=filters, filters=filters,
group_by="supplier", group_by="supplier",
order_by="value desc", order_by="value desc",
@@ -186,7 +186,7 @@ def get_all_sales_partner(date_range, company, field, limit=None):
"Sales Order", "Sales Order",
fields=[ fields=[
"sales_partner as name", "sales_partner as name",
f"sum({select_field}) as value", {"SUM": select_field, "as": "value"},
], ],
filters=filters, filters=filters,
group_by="sales_partner", group_by="sales_partner",
@@ -210,7 +210,7 @@ def get_all_sales_person(date_range, company, field=None, limit=0):
"Sales Order", "Sales Order",
fields=[ fields=[
"`tabSales Team`.sales_person as name", "`tabSales Team`.sales_person as name",
"sum(`tabSales Team`.allocated_amount) as value", {"SUM": "`tabSales Team`.allocated_amount", "as": "value"},
], ],
filters=filters, filters=filters,
group_by="`tabSales Team`.sales_person", group_by="`tabSales Team`.sales_person",

View File

@@ -31,7 +31,7 @@ def get(
warehouses = frappe.get_list( warehouses = frappe.get_list(
"Bin", "Bin",
fields=["warehouse", "sum(stock_value) stock_value"], fields=["warehouse", {"SUM": "stock_value", "as": "stock_value"}],
filters={"warehouse": ["IN", warehouses], "stock_value": [">", 0]}, filters={"warehouse": ["IN", warehouses], "stock_value": [">", 0]},
group_by="warehouse", group_by="warehouse",
order_by="stock_value DESC", order_by="stock_value DESC",

View File

@@ -405,8 +405,9 @@ def get_batches(item_code, warehouse, qty=1, throw=False, serial_no=None):
serial_nos = get_serial_nos(serial_no) serial_nos = get_serial_nos(serial_no)
batches = frappe.get_all( batches = frappe.get_all(
"Serial No", "Serial No",
fields=["distinct batch_no"], fields=["batch_no"],
filters={"item_code": item_code, "warehouse": warehouse, "name": ("in", serial_nos)}, filters={"item_code": item_code, "warehouse": warehouse, "name": ("in", serial_nos)},
distinct=True,
) )
if not batches: if not batches:

View File

@@ -320,12 +320,13 @@ def get_inventory_documents(
return frappe.get_all( return frappe.get_all(
"DocField", "DocField",
fields=["distinct parent"], fields=["parent"],
filters=and_filters, filters=and_filters,
or_filters=or_filters, or_filters=or_filters,
start=start, start=start,
page_length=page_len, page_length=page_len,
as_list=1, as_list=1,
distinct=True,
) )
@@ -382,7 +383,7 @@ def get_inventory_dimensions():
return frappe.get_all( return frappe.get_all(
"Inventory Dimension", "Inventory Dimension",
fields=[ fields=[
"distinct target_fieldname as fieldname", "target_fieldname as fieldname",
"source_fieldname", "source_fieldname",
"reference_document as doctype", "reference_document as doctype",
"validate_negative_stock", "validate_negative_stock",
@@ -390,6 +391,7 @@ def get_inventory_dimensions():
], ],
filters={"disabled": 0}, filters={"disabled": 0},
order_by="creation", order_by="creation",
distinct=True,
) )

View File

@@ -593,7 +593,7 @@ class TestPickList(IntegrationTestCase):
for dn in frappe.get_all( for dn in frappe.get_all(
"Delivery Note", "Delivery Note",
filters={"against_pick_list": pick_list.name, "customer": "_Test Customer"}, filters={"against_pick_list": pick_list.name, "customer": "_Test Customer"},
fields={"name"}, fields=["name"],
): ):
for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"): for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"):
self.assertEqual(dn_item.item_code, "_Test Item") self.assertEqual(dn_item.item_code, "_Test Item")
@@ -604,7 +604,7 @@ class TestPickList(IntegrationTestCase):
for dn in frappe.get_all( for dn in frappe.get_all(
"Delivery Note", "Delivery Note",
filters={"against_pick_list": pick_list.name, "customer": "_Test Customer 1"}, filters={"against_pick_list": pick_list.name, "customer": "_Test Customer 1"},
fields={"name"}, fields=["name"],
): ):
for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"): for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"):
self.assertEqual(dn_item.item_code, "_Test Item 2") self.assertEqual(dn_item.item_code, "_Test Item 2")
@@ -637,7 +637,7 @@ class TestPickList(IntegrationTestCase):
pick_list_1.submit() pick_list_1.submit()
create_delivery_note(pick_list_1.name) create_delivery_note(pick_list_1.name)
for dn in frappe.get_all( for dn in frappe.get_all(
"Delivery Note", filters={"against_pick_list": pick_list_1.name}, fields={"name"} "Delivery Note", filters={"against_pick_list": pick_list_1.name}, fields=["name"]
): ):
for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"): for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"):
if dn_item.item_code == "_Test Item": if dn_item.item_code == "_Test Item":

View File

@@ -1333,7 +1333,7 @@ def get_item_wise_returned_qty(pr_doc):
"Purchase Receipt", "Purchase Receipt",
fields=[ fields=[
"`tabPurchase Receipt Item`.purchase_receipt_item", "`tabPurchase Receipt Item`.purchase_receipt_item",
"sum(abs(`tabPurchase Receipt Item`.qty)) as qty", {"SUM": [{"ABS": "`tabPurchase Receipt Item`.qty"}], "as": "qty"},
], ],
filters=[ filters=[
["Purchase Receipt", "docstatus", "=", 1], ["Purchase Receipt", "docstatus", "=", 1],

View File

@@ -1900,7 +1900,7 @@ class TestPurchaseReceipt(IntegrationTestCase):
data = frappe.get_all( data = frappe.get_all(
"Stock Ledger Entry", "Stock Ledger Entry",
filters={"voucher_no": pr_return.name, "docstatus": 1}, filters={"voucher_no": pr_return.name, "docstatus": 1},
fields=["SUM(stock_value_difference) as stock_value_difference"], fields=[{"SUM": "stock_value_difference", "as": "stock_value_difference"}],
)[0] )[0]
self.assertEqual(abs(data["stock_value_difference"]), 400.00) self.assertEqual(abs(data["stock_value_difference"]), 400.00)

View File

@@ -2420,7 +2420,7 @@ class StockEntry(StockController, SubcontractingInwardController):
data = frappe.get_all( data = frappe.get_all(
"Work Order Operation", "Work Order Operation",
filters={"parent": self.work_order}, filters={"parent": self.work_order},
fields=["max(process_loss_qty) as process_loss_qty"], fields=[{"MAX": "process_loss_qty", "as": "process_loss_qty"}],
) )
if data and data[0].process_loss_qty is not None: if data and data[0].process_loss_qty is not None:
@@ -3145,7 +3145,7 @@ class StockEntry(StockController, SubcontractingInwardController):
stock_entries_child_list.append(d.ste_detail) stock_entries_child_list.append(d.ste_detail)
transferred_qty = frappe.get_all( transferred_qty = frappe.get_all(
"Stock Entry Detail", "Stock Entry Detail",
fields=["sum(qty) as qty"], fields=[{"SUM": "qty", "as": "qty"}],
filters={ filters={
"against_stock_entry": d.against_stock_entry, "against_stock_entry": d.against_stock_entry,
"ste_detail": d.ste_detail, "ste_detail": d.ste_detail,

View File

@@ -8,6 +8,7 @@ from uuid import uuid4
import frappe import frappe
from frappe.core.page.permission_manager.permission_manager import reset from frappe.core.page.permission_manager.permission_manager import reset
from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.query_builder.functions import Timestamp
from frappe.tests import IntegrationTestCase from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, add_to_date, flt, today from frappe.utils import add_days, add_to_date, flt, today
@@ -1281,12 +1282,16 @@ class TestStockLedgerEntry(IntegrationTestCase, StockTestMixin):
item=item, from_warehouse=source_warehouse, to_warehouse=target_warehouse, qty=1_728.0 item=item, from_warehouse=source_warehouse, to_warehouse=target_warehouse, qty=1_728.0
) )
filters = {"voucher_no": transfer.name, "voucher_type": transfer.doctype, "is_cancelled": 0} sle = frappe.qb.DocType("Stock Ledger Entry")
sles = frappe.get_all( sles = (
"Stock Ledger Entry", frappe.qb.from_(sle)
fields=["*"], .select("*")
filters=filters, .where(sle.voucher_no == transfer.name)
order_by="timestamp(posting_date, posting_time), creation", .where(sle.voucher_type == transfer.doctype)
.where(sle.is_cancelled == 0)
.orderby(Timestamp(sle.posting_date, sle.posting_time))
.orderby(sle.creation)
.run(as_dict=True)
) )
self.assertEqual(abs(sles[0].stock_value_difference), sles[1].stock_value_difference) self.assertEqual(abs(sles[0].stock_value_difference), sles[1].stock_value_difference)

View File

@@ -115,7 +115,7 @@ def get_stock_ledger_entries(report_filters):
"posting_time", "posting_time",
"company", "company",
"warehouse", "warehouse",
"(stock_value_difference / actual_qty) as valuation_rate", {"DIV": ["stock_value_difference", "actual_qty"], "as": "valuation_rate"},
] ]
filters = {"is_cancelled": 0} filters = {"is_cancelled": 0}

View File

@@ -143,9 +143,9 @@ def get_stock_details_map(variant_list):
stock_details = frappe.db.get_all( stock_details = frappe.db.get_all(
"Bin", "Bin",
fields=[ fields=[
"sum(planned_qty) as planned_qty", {"SUM": "planned_qty", "as": "planned_qty"},
"sum(actual_qty) as actual_qty", {"SUM": "actual_qty", "as": "actual_qty"},
"sum(projected_qty) as projected_qty", {"SUM": "projected_qty", "as": "projected_qty"},
"item_code", "item_code",
], ],
filters={"item_code": ["in", variant_list]}, filters={"item_code": ["in", variant_list]},
@@ -167,7 +167,7 @@ def get_buying_price_map(variant_list):
buying = frappe.db.get_all( buying = frappe.db.get_all(
"Item Price", "Item Price",
fields=[ fields=[
"avg(price_list_rate) as avg_rate", {"AVG": "price_list_rate", "as": "avg_rate"},
"item_code", "item_code",
], ],
filters={"item_code": ["in", variant_list], "buying": 1}, filters={"item_code": ["in", variant_list], "buying": 1},
@@ -185,7 +185,7 @@ def get_selling_price_map(variant_list):
selling = frappe.db.get_all( selling = frappe.db.get_all(
"Item Price", "Item Price",
fields=[ fields=[
"avg(price_list_rate) as avg_rate", {"AVG": "price_list_rate", "as": "avg_rate"},
"item_code", "item_code",
], ],
filters={"item_code": ["in", variant_list], "selling": 1}, filters={"item_code": ["in", variant_list], "selling": 1},

View File

@@ -183,14 +183,15 @@ def get_voucher_type(doctype, txt, searchfield, start, page_len, filters):
child_doctypes = frappe.get_all( child_doctypes = frappe.get_all(
"DocField", "DocField",
filters={"fieldname": "serial_and_batch_bundle"}, filters={"fieldname": "serial_and_batch_bundle"},
fields=["distinct parent as parent"], fields=["parent"],
distinct=True,
) )
query_filters = {"options": ["in", [d.parent for d in child_doctypes]]} query_filters = {"options": ["in", [d.parent for d in child_doctypes]]}
if txt: if txt:
query_filters["parent"] = ["like", f"%{txt}%"] query_filters["parent"] = ["like", f"%{txt}%"]
return frappe.get_all("DocField", filters=query_filters, fields=["distinct parent"], as_list=True) return frappe.get_all("DocField", filters=query_filters, fields=["parent"], as_list=True, distinct=True)
@frappe.whitelist() @frappe.whitelist()

View File

@@ -61,7 +61,7 @@ def get_stock_ledger_data(report_filters, filters):
"name", "name",
"voucher_type", "voucher_type",
"voucher_no", "voucher_no",
"sum(stock_value_difference) as stock_value", {"SUM": "stock_value_difference", "as": "stock_value"},
"posting_date", "posting_date",
"posting_time", "posting_time",
], ],
@@ -88,7 +88,10 @@ def get_gl_data(report_filters, filters):
"name", "name",
"voucher_type", "voucher_type",
"voucher_no", "voucher_no",
"sum(debit_in_account_currency) - sum(credit_in_account_currency) as account_value", {
"SUB": [{"SUM": "debit_in_account_currency"}, {"SUM": "credit_in_account_currency"}],
"as": "account_value",
},
], ],
group_by="voucher_type, voucher_no", group_by="voucher_type, voucher_no",
) )

View File

@@ -546,7 +546,10 @@ def get_opening_balance_from_batch(filters, columns, sl_entries):
opening_data = frappe.get_all( opening_data = frappe.get_all(
"Stock Ledger Entry", "Stock Ledger Entry",
fields=["sum(actual_qty) as qty_after_transaction", "sum(stock_value_difference) as stock_value"], fields=[
{"SUM": "actual_qty", "as": "qty_after_transaction"},
{"SUM": "stock_value_difference", "as": "stock_value"},
],
filters=query_filters, filters=query_filters,
)[0] )[0]

View File

@@ -1511,7 +1511,7 @@ def get_batchwise_qty(voucher_type, voucher_no):
batches = frappe.get_all( batches = frappe.get_all(
"Serial and Batch Entry", "Serial and Batch Entry",
filters={"parent": ("in", bundles), "batch_no": ("is", "set")}, filters={"parent": ("in", bundles), "batch_no": ("is", "set")},
fields=["batch_no", "SUM(qty) as qty"], fields=["batch_no", {"SUM": "qty", "as": "qty"}],
group_by="batch_no", group_by="batch_no",
as_list=1, as_list=1,
) )

View File

@@ -1,6 +1,7 @@
import json import json
import frappe import frappe
from frappe.query_builder.functions import Timestamp
from frappe.tests import IntegrationTestCase from frappe.tests import IntegrationTestCase
from erpnext.stock.utils import scan_barcode from erpnext.stock.utils import scan_barcode
@@ -20,11 +21,23 @@ class StockTestMixin:
filters = {"voucher_no": doc.name, "voucher_type": doc.doctype, "is_cancelled": 0} filters = {"voucher_no": doc.name, "voucher_type": doc.doctype, "is_cancelled": 0}
if sle_filters: if sle_filters:
filters.update(sle_filters) filters.update(sle_filters)
sles = frappe.get_all(
"Stock Ledger Entry", sle = frappe.qb.DocType("Stock Ledger Entry")
fields=["*"], query = (
filters=filters, frappe.qb.from_(sle)
order_by="timestamp(posting_date, posting_time), creation", .select("*")
.where(sle.voucher_no == doc.name)
.where(sle.voucher_type == doc.doctype)
.where(sle.is_cancelled == 0)
)
if sle_filters:
for key, value in sle_filters.items():
query = query.where(sle[key] == value)
sles = (
query.orderby(Timestamp(sle.posting_date, sle.posting_time))
.orderby(sle.creation)
.run(as_dict=True)
) )
self.assertGreaterEqual(len(sles), len(expected_sles)) self.assertGreaterEqual(len(sles), len(expected_sles))