mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-13 11:55:11 +00:00
fix: adapt to query builder
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe.query_builder import functions
|
||||
from frappe.query_builder.utils import DocType
|
||||
from frappe.tests import IntegrationTestCase
|
||||
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_credit, 8500.0)
|
||||
|
||||
gl = DocType("GL Entry")
|
||||
acc_balance = frappe.db.get_all(
|
||||
"GL Entry",
|
||||
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]
|
||||
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_credit, 500.0)
|
||||
|
||||
gl = DocType("GL Entry")
|
||||
acc_balance = frappe.db.get_all(
|
||||
"GL Entry",
|
||||
filters={"account": self.debtors_usd, "is_cancelled": 0},
|
||||
fields=[
|
||||
"sum(debit)-sum(credit) as balance",
|
||||
"sum(debit_in_account_currency)-sum(credit_in_account_currency) as balance_in_account_currency",
|
||||
(functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance"),
|
||||
(
|
||||
functions.Sum(gl.debit_in_account_currency) - functions.Sum(gl.credit_in_account_currency)
|
||||
).as_("balance_in_account_currency"),
|
||||
],
|
||||
)[0]
|
||||
# account shouldn't have balance in base and account currency
|
||||
@@ -193,12 +199,15 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
|
||||
pe.references = []
|
||||
pe.save().submit()
|
||||
|
||||
gl = DocType("GL Entry")
|
||||
acc_balance = frappe.db.get_all(
|
||||
"GL Entry",
|
||||
filters={"account": self.debtors_usd, "is_cancelled": 0},
|
||||
fields=[
|
||||
"sum(debit)-sum(credit) as balance",
|
||||
"sum(debit_in_account_currency)-sum(credit_in_account_currency) as balance_in_account_currency",
|
||||
(functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance"),
|
||||
(
|
||||
functions.Sum(gl.debit_in_account_currency) - functions.Sum(gl.credit_in_account_currency)
|
||||
).as_("balance_in_account_currency"),
|
||||
],
|
||||
)[0]
|
||||
# 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_credit, precision), 0.0)
|
||||
|
||||
gl = DocType("GL Entry")
|
||||
acc_balance = frappe.db.get_all(
|
||||
"GL Entry",
|
||||
filters={"account": self.debtors_usd, "is_cancelled": 0},
|
||||
fields=[
|
||||
"sum(debit)-sum(credit) as balance",
|
||||
"sum(debit_in_account_currency)-sum(credit_in_account_currency) as balance_in_account_currency",
|
||||
(functions.Sum(gl.debit) - functions.Sum(gl.credit)).as_("balance"),
|
||||
(
|
||||
functions.Sum(gl.debit_in_account_currency) - functions.Sum(gl.credit_in_account_currency)
|
||||
).as_("balance_in_account_currency"),
|
||||
],
|
||||
)[0]
|
||||
# account shouldn't have balance in base and account currency post revaluation
|
||||
|
||||
@@ -72,7 +72,7 @@ class OpeningInvoiceCreationTool(Document):
|
||||
fields = [
|
||||
"company",
|
||||
{"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"])
|
||||
if not companies:
|
||||
|
||||
@@ -669,7 +669,7 @@ class PaymentReconciliation(Document):
|
||||
"party": self.party,
|
||||
},
|
||||
fields=[
|
||||
"parent as `name`",
|
||||
"parent as name",
|
||||
"exchange_rate",
|
||||
],
|
||||
as_list=1,
|
||||
|
||||
@@ -975,7 +975,7 @@ class TestPaymentReconciliation(IntegrationTestCase):
|
||||
total_credit_amount = frappe.db.get_all(
|
||||
"Journal Entry Account",
|
||||
{"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name},
|
||||
"sum(credit) as amount",
|
||||
[{"SUM": "credit", "as": "amount"}],
|
||||
group_by="reference_name",
|
||||
)[0].amount
|
||||
|
||||
@@ -1069,7 +1069,7 @@ class TestPaymentReconciliation(IntegrationTestCase):
|
||||
total_credit_amount = frappe.db.get_all(
|
||||
"Journal Entry Account",
|
||||
{"account": self.debtors_eur, "docstatus": 1, "reference_name": si.name},
|
||||
"sum(credit) as amount",
|
||||
[{"SUM": "credit", "as": "amount"}],
|
||||
group_by="reference_name",
|
||||
)[0].amount
|
||||
|
||||
|
||||
@@ -713,6 +713,7 @@ def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.get_all(
|
||||
"UOM Conversion Detail",
|
||||
filters={"parent": ("in", items), "uom": ("like", f"{txt}%")},
|
||||
fields=["distinct uom"],
|
||||
fields=["uom"],
|
||||
as_list=1,
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
@@ -1374,7 +1374,7 @@ class TestPurchaseInvoice(IntegrationTestCase, StockTestMixin):
|
||||
total_debit_amount = frappe.db.get_all(
|
||||
"Journal Entry Account",
|
||||
{"account": creditors_account, "docstatus": 1, "reference_name": pi.name},
|
||||
"sum(debit) as amount",
|
||||
[{"SUM": "debit", "as": "amount"}],
|
||||
group_by="reference_name",
|
||||
)[0].amount
|
||||
self.assertEqual(flt(total_debit_amount, 2), 2500)
|
||||
@@ -1456,7 +1456,7 @@ class TestPurchaseInvoice(IntegrationTestCase, StockTestMixin):
|
||||
total_debit_amount = frappe.db.get_all(
|
||||
"Journal Entry Account",
|
||||
{"account": creditors_account, "docstatus": 1, "reference_name": pi_2.name},
|
||||
"sum(debit) as amount",
|
||||
[{"SUM": "debit", "as": "amount"}],
|
||||
group_by="reference_name",
|
||||
)[0].amount
|
||||
self.assertEqual(flt(total_debit_amount, 2), 1500)
|
||||
|
||||
@@ -213,7 +213,10 @@ def get_allowed_types_from_settings(child_doc: bool = False):
|
||||
repost_docs = [
|
||||
x.document_type
|
||||
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
|
||||
@@ -287,7 +290,11 @@ def get_repost_allowed_types(doctype, txt, searchfield, start, page_len, filters
|
||||
filters.update({"document_type": ("like", f"%{txt}%")})
|
||||
|
||||
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 []
|
||||
|
||||
@@ -3612,7 +3612,7 @@ class TestSalesInvoice(ERPNextTestSuite):
|
||||
frappe.db.get_all(
|
||||
"Payment Ledger Entry",
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
gl_entries = frappe.db.get_all(
|
||||
"GL Entry",
|
||||
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",
|
||||
)
|
||||
self.assertEqual(len(gl_entries), 3)
|
||||
|
||||
@@ -854,8 +854,8 @@ def get_dashboard_info(party_type, party, loyalty_program=None):
|
||||
group_by="company",
|
||||
fields=[
|
||||
"company",
|
||||
"sum(grand_total) as grand_total",
|
||||
"sum(base_grand_total) as base_grand_total",
|
||||
{"SUM": "grand_total", "as": "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()),
|
||||
},
|
||||
group_by="company",
|
||||
fields=["company", "sum(loyalty_points) as loyalty_points"],
|
||||
fields=["company", {"SUM": "loyalty_points", "as": "loyalty_points"}],
|
||||
as_list=1,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -210,7 +210,7 @@ def get_gl_balance(report_date, company):
|
||||
return frappe._dict(
|
||||
frappe.db.get_all(
|
||||
"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},
|
||||
group_by="party",
|
||||
as_list=1,
|
||||
|
||||
@@ -323,22 +323,24 @@ def get_returned_qty_map_for_row(return_against, party, row_name, doctype):
|
||||
party_type = "customer"
|
||||
|
||||
fields = [
|
||||
f"sum(abs(`tab{child_doctype}`.qty)) as qty",
|
||||
{"SUM": [{"ABS": f"`tab{child_doctype}`.qty"}], "as": "qty"},
|
||||
]
|
||||
|
||||
if doctype != "Subcontracting Receipt":
|
||||
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"):
|
||||
fields += [
|
||||
f"sum(abs(`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}`.rejected_qty"}], "as": "rejected_qty"},
|
||||
{"SUM": [{"ABS": f"`tab{child_doctype}`.received_qty"}], "as": "received_qty"},
|
||||
]
|
||||
|
||||
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
|
||||
data = frappe.get_all(
|
||||
|
||||
@@ -563,11 +563,14 @@ class StatusUpdater(Document):
|
||||
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:
|
||||
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
|
||||
* 100,
|
||||
6,
|
||||
|
||||
@@ -1320,7 +1320,7 @@ class StockController(AccountsController):
|
||||
total_returned += flt(item.returned_qty * item.rate)
|
||||
|
||||
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(
|
||||
{
|
||||
|
||||
@@ -292,7 +292,7 @@ class SubcontractingController(StockController):
|
||||
):
|
||||
for row in frappe.get_all(
|
||||
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)},
|
||||
):
|
||||
self.qty_to_be_received[(row.item_code, row.parent)] += row.qty
|
||||
@@ -553,7 +553,9 @@ class SubcontractingController(StockController):
|
||||
data = []
|
||||
|
||||
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 = {
|
||||
"item_code": "rm_item_code",
|
||||
|
||||
@@ -328,7 +328,7 @@ class TestItemWiseInventoryAccount(IntegrationTestCase):
|
||||
"voucher_no": pr.name,
|
||||
"item_code": ("in", items),
|
||||
},
|
||||
fields=["sum(stock_value_difference) as value"],
|
||||
fields=[{"SUM": "stock_value_difference", "as": "value"}],
|
||||
)
|
||||
|
||||
gl_value = frappe.db.get_value(
|
||||
@@ -435,7 +435,7 @@ class TestItemWiseInventoryAccount(IntegrationTestCase):
|
||||
sle_value = frappe.get_all(
|
||||
"Stock Ledger Entry",
|
||||
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 = (
|
||||
|
||||
@@ -8,6 +8,7 @@ from itertools import groupby
|
||||
import frappe
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from frappe import _
|
||||
from frappe.query_builder.custom import Month, MonthName, Quarter
|
||||
from frappe.utils import cint, flt, getdate
|
||||
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
@@ -82,40 +83,52 @@ class SalesPipelineAnalytics:
|
||||
self.filters.get("pipeline_by")
|
||||
]
|
||||
|
||||
self.group_by_period = {
|
||||
"Monthly": "month(expected_closing)",
|
||||
"Quarterly": "QUARTER(expected_closing)",
|
||||
}[self.filters.get("range")]
|
||||
opp = frappe.qb.DocType("Opportunity")
|
||||
|
||||
if self.filters.get("range") == "Monthly":
|
||||
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.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")]
|
||||
|
||||
def get_data(self):
|
||||
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":
|
||||
self.query_result = frappe.db.get_list(
|
||||
"Opportunity",
|
||||
filters=self.get_conditions(),
|
||||
fields=[self.based_on, self.data_based_on, self.duration],
|
||||
group_by=f"{self.group_by_based_on},{self.group_by_period}",
|
||||
order_by=self.group_by_period,
|
||||
self.query_result = (
|
||||
query.select(
|
||||
pipeline_field.as_(self.pipeline_by),
|
||||
frappe.query_builder.functions.Count("*").as_("count"),
|
||||
self.duration,
|
||||
)
|
||||
.groupby(pipeline_field, self.group_by_period)
|
||||
.orderby(self.group_by_period)
|
||||
.run(as_dict=True)
|
||||
)
|
||||
|
||||
if self.filters.get("based_on") == "Amount":
|
||||
self.query_result = frappe.db.get_list(
|
||||
"Opportunity",
|
||||
filters=self.get_conditions(),
|
||||
fields=[self.based_on, self.data_based_on, self.duration, "currency"],
|
||||
)
|
||||
self.query_result = query.select(
|
||||
pipeline_field.as_(self.pipeline_by),
|
||||
opp.opportunity_amount.as_("amount"),
|
||||
self.duration,
|
||||
opp.currency,
|
||||
).run(as_dict=True)
|
||||
|
||||
self.convert_to_base_currency()
|
||||
|
||||
|
||||
@@ -1740,8 +1740,9 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
barcodes = frappe.get_all(
|
||||
"Item Barcode",
|
||||
fields=["distinct parent as item_code"],
|
||||
fields=["parent as item_code"],
|
||||
filters={"barcode": ("like", f"%{txt}%")},
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
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"):
|
||||
has_variants = frappe.get_cached_value("Item", filters.get("item_code"), "has_variants")
|
||||
if not has_variants:
|
||||
query_filters["has_variants"] = 0
|
||||
query_filters.append(["has_variants", "=", 0])
|
||||
|
||||
if filters:
|
||||
for fieldname, value in filters.items():
|
||||
query_filters[fieldname] = value
|
||||
query_filters.append([fieldname, "=", value])
|
||||
|
||||
return frappe.get_list(
|
||||
"Item",
|
||||
|
||||
@@ -207,7 +207,7 @@ class JobCard(Document):
|
||||
|
||||
job_card_qty = frappe.get_all(
|
||||
"Job Card",
|
||||
fields=["sum(for_quantity)"],
|
||||
fields=[{"SUM": "for_quantity"}],
|
||||
filters={
|
||||
"work_order": self.work_order,
|
||||
"operation_id": self.operation_id,
|
||||
@@ -933,9 +933,9 @@ class JobCard(Document):
|
||||
return frappe.get_all(
|
||||
"Job Card",
|
||||
fields=[
|
||||
"sum(total_time_in_mins) as time_in_mins",
|
||||
"sum(total_completed_qty) as completed_qty",
|
||||
"sum(process_loss_qty) as process_loss_qty",
|
||||
{"SUM": "total_time_in_mins", "as": "time_in_mins"},
|
||||
{"SUM": "total_completed_qty", "as": "completed_qty"},
|
||||
{"SUM": "process_loss_qty", "as": "process_loss_qty"},
|
||||
],
|
||||
filters={
|
||||
"docstatus": 1,
|
||||
@@ -1423,11 +1423,12 @@ def get_operations(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.get_all(
|
||||
"Work Order Operation",
|
||||
filters=args,
|
||||
fields=["distinct operation as operation"],
|
||||
fields=["operation"],
|
||||
limit_start=start,
|
||||
limit_page_length=page_len,
|
||||
order_by="idx asc",
|
||||
as_list=1,
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -624,7 +624,7 @@ class ProductionPlan(Document):
|
||||
so_wise_planned_qty = frappe._dict()
|
||||
data = frappe.get_all(
|
||||
"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={
|
||||
"sales_order": ("in", sales_orders),
|
||||
"docstatus": 1,
|
||||
|
||||
@@ -73,9 +73,10 @@ class TestProductionPlan(IntegrationTestCase):
|
||||
|
||||
material_requests = frappe.get_all(
|
||||
"Material Request Item",
|
||||
fields=["distinct parent"],
|
||||
fields=["parent"],
|
||||
filters={"production_plan": pln.name},
|
||||
as_list=1,
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
self.assertTrue(len(material_requests), 2)
|
||||
|
||||
@@ -976,8 +976,9 @@ class TestWorkOrder(IntegrationTestCase):
|
||||
|
||||
job_cards = frappe.get_all(
|
||||
"Job Card Time Log",
|
||||
fields=["distinct parent as name", "docstatus"],
|
||||
fields=["parent as name", "docstatus"],
|
||||
order_by="creation asc",
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
for job_card in job_cards:
|
||||
|
||||
@@ -166,7 +166,7 @@ class WorkOrder(Document):
|
||||
operation_details = frappe._dict(
|
||||
frappe.get_all(
|
||||
"Job Card",
|
||||
fields=["operation", "sum(for_quantity)"],
|
||||
fields=["operation", {"SUM": "for_quantity"}],
|
||||
filters={"docstatus": ("<", 2), "work_order": self.name},
|
||||
as_list=1,
|
||||
group_by="operation_id",
|
||||
@@ -718,7 +718,7 @@ class WorkOrder(Document):
|
||||
if self.production_plan_item:
|
||||
total_qty = frappe.get_all(
|
||||
"Work Order",
|
||||
fields="sum(produced_qty) as produced_qty",
|
||||
fields=[{"SUM": "produced_qty", "as": "produced_qty"}],
|
||||
filters={
|
||||
"docstatus": 1,
|
||||
"production_plan": self.production_plan,
|
||||
@@ -1347,7 +1347,7 @@ class WorkOrder(Document):
|
||||
else:
|
||||
data = frappe.get_all(
|
||||
"Stock Entry",
|
||||
fields=["timestamp(posting_date, posting_time) as posting_datetime"],
|
||||
fields=[{"TIMESTAMP": ["posting_date", "posting_time"], "as": "posting_datetime"}],
|
||||
filters={
|
||||
"work_order": self.name,
|
||||
"purpose": ("in", ["Material Transfer for Manufacture", "Manufacture"]),
|
||||
|
||||
@@ -59,7 +59,7 @@ def get_data(filters):
|
||||
job_card_time_details = {}
|
||||
for job_card_data in frappe.get_all(
|
||||
"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,
|
||||
group_by="parent",
|
||||
):
|
||||
|
||||
@@ -230,7 +230,12 @@ class ProductionPlanReport:
|
||||
|
||||
purchased_items = frappe.get_all(
|
||||
"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={
|
||||
"item_code": ("in", self.item_codes),
|
||||
"warehouse": ("in", self.warehouses),
|
||||
|
||||
@@ -10,7 +10,7 @@ def execute():
|
||||
frappe.reload_doc("stock", "doctype", "item")
|
||||
|
||||
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.quality_inspection_template_name = "QIT/%s" % data.parent
|
||||
|
||||
@@ -401,8 +401,6 @@ def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20, o
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
|
||||
fields = "distinct *"
|
||||
|
||||
or_filters = []
|
||||
|
||||
if txt:
|
||||
@@ -424,13 +422,14 @@ def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20, o
|
||||
|
||||
return frappe.get_list(
|
||||
doctype,
|
||||
fields=fields,
|
||||
fields="*",
|
||||
filters=filters,
|
||||
or_filters=or_filters,
|
||||
limit_start=limit_start,
|
||||
limit_page_length=limit_page_length,
|
||||
order_by=order_by,
|
||||
ignore_permissions=ignore_permissions,
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -179,7 +179,11 @@ def get_reverse_charge_total(filters):
|
||||
try:
|
||||
return (
|
||||
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]
|
||||
or 0
|
||||
)
|
||||
@@ -219,7 +223,11 @@ def get_reverse_charge_recoverable_total(filters):
|
||||
try:
|
||||
return (
|
||||
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]
|
||||
or 0
|
||||
)
|
||||
@@ -274,7 +282,11 @@ def get_standard_rated_expenses_total(filters):
|
||||
try:
|
||||
return (
|
||||
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]
|
||||
or 0
|
||||
)
|
||||
@@ -292,7 +304,7 @@ def get_standard_rated_expenses_tax(filters):
|
||||
frappe.db.get_all(
|
||||
"Purchase Invoice",
|
||||
filters=query_filters,
|
||||
fields=["sum(recoverable_standard_rated_expenses)"],
|
||||
fields=[{"SUM": "recoverable_standard_rated_expenses"}],
|
||||
as_list=True,
|
||||
limit=1,
|
||||
)[0][0]
|
||||
@@ -310,7 +322,7 @@ def get_tourist_tax_return_total(filters):
|
||||
try:
|
||||
return (
|
||||
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]
|
||||
or 0
|
||||
)
|
||||
@@ -328,7 +340,7 @@ def get_tourist_tax_return_tax(filters):
|
||||
frappe.db.get_all(
|
||||
"Sales Invoice",
|
||||
filters=query_filters,
|
||||
fields=["sum(tourist_tax_return)"],
|
||||
fields=[{"SUM": "tourist_tax_return"}],
|
||||
as_list=True,
|
||||
limit=1,
|
||||
)[0][0]
|
||||
|
||||
@@ -14,6 +14,7 @@ from frappe.contacts.address_and_contact import (
|
||||
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.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.user import get_users_with_role
|
||||
|
||||
@@ -503,11 +504,11 @@ def get_loyalty_programs(doc):
|
||||
loyalty_programs = frappe.get_all(
|
||||
"Loyalty Program",
|
||||
fields=["name", "customer_group", "customer_territory"],
|
||||
filters={
|
||||
"auto_opt_in": 1,
|
||||
"from_date": ["<=", today()],
|
||||
"ifnull(to_date, '2500-01-01')": [">=", today()],
|
||||
},
|
||||
filters=[
|
||||
["auto_opt_in", "=", 1],
|
||||
["from_date", "<=", today()],
|
||||
[functions.IfNull(Field("to_date"), "2500-01-01"), ">=", today()],
|
||||
],
|
||||
)
|
||||
|
||||
for loyalty_program in loyalty_programs:
|
||||
|
||||
@@ -630,7 +630,7 @@ def get_ordered_items(quotation: str):
|
||||
frappe.get_all(
|
||||
"Sales Order Item",
|
||||
filters={"prevdoc_docname": quotation, "docstatus": 1},
|
||||
fields=["quotation_item", "sum(qty)"],
|
||||
fields=["quotation_item", {"SUM": "qty"}],
|
||||
group_by="quotation_item",
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
@@ -992,7 +992,11 @@ def get_requested_item_qty(sales_order):
|
||||
for d in frappe.db.get_all(
|
||||
"Material Request Item",
|
||||
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",
|
||||
):
|
||||
result[d.sales_order_item] = frappe._dict({"qty": d.qty, "received_qty": d.received_qty})
|
||||
|
||||
@@ -95,7 +95,7 @@ def get_data(filters=None):
|
||||
|
||||
items = get_selling_items(filters)
|
||||
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}
|
||||
price_list_map = fetch_item_prices(
|
||||
|
||||
@@ -799,7 +799,7 @@ class EmailDigest(Document):
|
||||
"status": ["not in", ("Cancelled")],
|
||||
"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):
|
||||
|
||||
@@ -63,7 +63,7 @@ def get_all_customers(date_range, company, field, limit=None):
|
||||
|
||||
return frappe.get_list(
|
||||
"Sales Invoice",
|
||||
fields=["customer as name", "sum(outstanding_amount) as value"],
|
||||
fields=["customer as name", {"SUM": "outstanding_amount", "as": "value"}],
|
||||
filters=filters,
|
||||
group_by="customer",
|
||||
order_by="value desc",
|
||||
@@ -80,7 +80,7 @@ def get_all_customers(date_range, company, field, limit=None):
|
||||
|
||||
return frappe.get_list(
|
||||
"Sales Order",
|
||||
fields=["customer as name", f"sum({select_field}) as value"],
|
||||
fields=["customer as name", {"SUM": select_field, "as": "value"}],
|
||||
filters=filters,
|
||||
group_by="customer",
|
||||
order_by="value desc",
|
||||
@@ -91,10 +91,10 @@ def get_all_customers(date_range, company, field, limit=None):
|
||||
@frappe.whitelist()
|
||||
def get_all_items(date_range, company, field, limit=None):
|
||||
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(
|
||||
"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",
|
||||
order_by="value desc",
|
||||
limit=limit,
|
||||
@@ -125,7 +125,7 @@ def get_all_items(date_range, company, field, limit=None):
|
||||
select_doctype,
|
||||
fields=[
|
||||
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,
|
||||
order_by="value desc",
|
||||
@@ -145,7 +145,7 @@ def get_all_suppliers(date_range, company, field, limit=None):
|
||||
|
||||
return frappe.get_list(
|
||||
"Purchase Invoice",
|
||||
fields=["supplier as name", "sum(outstanding_amount) as value"],
|
||||
fields=["supplier as name", {"SUM": "outstanding_amount", "as": "value"}],
|
||||
filters=filters,
|
||||
group_by="supplier",
|
||||
order_by="value desc",
|
||||
@@ -162,7 +162,7 @@ def get_all_suppliers(date_range, company, field, limit=None):
|
||||
|
||||
return frappe.get_list(
|
||||
"Purchase Order",
|
||||
fields=["supplier as name", f"sum({select_field}) as value"],
|
||||
fields=["supplier as name", {"SUM": select_field, "as": "value"}],
|
||||
filters=filters,
|
||||
group_by="supplier",
|
||||
order_by="value desc",
|
||||
@@ -186,7 +186,7 @@ def get_all_sales_partner(date_range, company, field, limit=None):
|
||||
"Sales Order",
|
||||
fields=[
|
||||
"sales_partner as name",
|
||||
f"sum({select_field}) as value",
|
||||
{"SUM": select_field, "as": "value"},
|
||||
],
|
||||
filters=filters,
|
||||
group_by="sales_partner",
|
||||
@@ -210,7 +210,7 @@ def get_all_sales_person(date_range, company, field=None, limit=0):
|
||||
"Sales Order",
|
||||
fields=[
|
||||
"`tabSales Team`.sales_person as name",
|
||||
"sum(`tabSales Team`.allocated_amount) as value",
|
||||
{"SUM": "`tabSales Team`.allocated_amount", "as": "value"},
|
||||
],
|
||||
filters=filters,
|
||||
group_by="`tabSales Team`.sales_person",
|
||||
|
||||
@@ -31,7 +31,7 @@ def get(
|
||||
|
||||
warehouses = frappe.get_list(
|
||||
"Bin",
|
||||
fields=["warehouse", "sum(stock_value) stock_value"],
|
||||
fields=["warehouse", {"SUM": "stock_value", "as": "stock_value"}],
|
||||
filters={"warehouse": ["IN", warehouses], "stock_value": [">", 0]},
|
||||
group_by="warehouse",
|
||||
order_by="stock_value DESC",
|
||||
|
||||
@@ -405,8 +405,9 @@ def get_batches(item_code, warehouse, qty=1, throw=False, serial_no=None):
|
||||
serial_nos = get_serial_nos(serial_no)
|
||||
batches = frappe.get_all(
|
||||
"Serial No",
|
||||
fields=["distinct batch_no"],
|
||||
fields=["batch_no"],
|
||||
filters={"item_code": item_code, "warehouse": warehouse, "name": ("in", serial_nos)},
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
if not batches:
|
||||
|
||||
@@ -320,12 +320,13 @@ def get_inventory_documents(
|
||||
|
||||
return frappe.get_all(
|
||||
"DocField",
|
||||
fields=["distinct parent"],
|
||||
fields=["parent"],
|
||||
filters=and_filters,
|
||||
or_filters=or_filters,
|
||||
start=start,
|
||||
page_length=page_len,
|
||||
as_list=1,
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -382,7 +383,7 @@ def get_inventory_dimensions():
|
||||
return frappe.get_all(
|
||||
"Inventory Dimension",
|
||||
fields=[
|
||||
"distinct target_fieldname as fieldname",
|
||||
"target_fieldname as fieldname",
|
||||
"source_fieldname",
|
||||
"reference_document as doctype",
|
||||
"validate_negative_stock",
|
||||
@@ -390,6 +391,7 @@ def get_inventory_dimensions():
|
||||
],
|
||||
filters={"disabled": 0},
|
||||
order_by="creation",
|
||||
distinct=True,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -593,7 +593,7 @@ class TestPickList(IntegrationTestCase):
|
||||
for dn in frappe.get_all(
|
||||
"Delivery Note",
|
||||
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"):
|
||||
self.assertEqual(dn_item.item_code, "_Test Item")
|
||||
@@ -604,7 +604,7 @@ class TestPickList(IntegrationTestCase):
|
||||
for dn in frappe.get_all(
|
||||
"Delivery Note",
|
||||
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"):
|
||||
self.assertEqual(dn_item.item_code, "_Test Item 2")
|
||||
@@ -637,7 +637,7 @@ class TestPickList(IntegrationTestCase):
|
||||
pick_list_1.submit()
|
||||
create_delivery_note(pick_list_1.name)
|
||||
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"):
|
||||
if dn_item.item_code == "_Test Item":
|
||||
|
||||
@@ -1333,7 +1333,7 @@ def get_item_wise_returned_qty(pr_doc):
|
||||
"Purchase Receipt",
|
||||
fields=[
|
||||
"`tabPurchase Receipt Item`.purchase_receipt_item",
|
||||
"sum(abs(`tabPurchase Receipt Item`.qty)) as qty",
|
||||
{"SUM": [{"ABS": "`tabPurchase Receipt Item`.qty"}], "as": "qty"},
|
||||
],
|
||||
filters=[
|
||||
["Purchase Receipt", "docstatus", "=", 1],
|
||||
|
||||
@@ -1900,7 +1900,7 @@ class TestPurchaseReceipt(IntegrationTestCase):
|
||||
data = frappe.get_all(
|
||||
"Stock Ledger Entry",
|
||||
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]
|
||||
|
||||
self.assertEqual(abs(data["stock_value_difference"]), 400.00)
|
||||
|
||||
@@ -2420,7 +2420,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
data = frappe.get_all(
|
||||
"Work Order Operation",
|
||||
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:
|
||||
@@ -3145,7 +3145,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
stock_entries_child_list.append(d.ste_detail)
|
||||
transferred_qty = frappe.get_all(
|
||||
"Stock Entry Detail",
|
||||
fields=["sum(qty) as qty"],
|
||||
fields=[{"SUM": "qty", "as": "qty"}],
|
||||
filters={
|
||||
"against_stock_entry": d.against_stock_entry,
|
||||
"ste_detail": d.ste_detail,
|
||||
|
||||
@@ -8,6 +8,7 @@ from uuid import uuid4
|
||||
import frappe
|
||||
from frappe.core.page.permission_manager.permission_manager import reset
|
||||
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.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
|
||||
)
|
||||
|
||||
filters = {"voucher_no": transfer.name, "voucher_type": transfer.doctype, "is_cancelled": 0}
|
||||
sles = frappe.get_all(
|
||||
"Stock Ledger Entry",
|
||||
fields=["*"],
|
||||
filters=filters,
|
||||
order_by="timestamp(posting_date, posting_time), creation",
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
sles = (
|
||||
frappe.qb.from_(sle)
|
||||
.select("*")
|
||||
.where(sle.voucher_no == transfer.name)
|
||||
.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)
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ def get_stock_ledger_entries(report_filters):
|
||||
"posting_time",
|
||||
"company",
|
||||
"warehouse",
|
||||
"(stock_value_difference / actual_qty) as valuation_rate",
|
||||
{"DIV": ["stock_value_difference", "actual_qty"], "as": "valuation_rate"},
|
||||
]
|
||||
|
||||
filters = {"is_cancelled": 0}
|
||||
|
||||
@@ -143,9 +143,9 @@ def get_stock_details_map(variant_list):
|
||||
stock_details = frappe.db.get_all(
|
||||
"Bin",
|
||||
fields=[
|
||||
"sum(planned_qty) as planned_qty",
|
||||
"sum(actual_qty) as actual_qty",
|
||||
"sum(projected_qty) as projected_qty",
|
||||
{"SUM": "planned_qty", "as": "planned_qty"},
|
||||
{"SUM": "actual_qty", "as": "actual_qty"},
|
||||
{"SUM": "projected_qty", "as": "projected_qty"},
|
||||
"item_code",
|
||||
],
|
||||
filters={"item_code": ["in", variant_list]},
|
||||
@@ -167,7 +167,7 @@ def get_buying_price_map(variant_list):
|
||||
buying = frappe.db.get_all(
|
||||
"Item Price",
|
||||
fields=[
|
||||
"avg(price_list_rate) as avg_rate",
|
||||
{"AVG": "price_list_rate", "as": "avg_rate"},
|
||||
"item_code",
|
||||
],
|
||||
filters={"item_code": ["in", variant_list], "buying": 1},
|
||||
@@ -185,7 +185,7 @@ def get_selling_price_map(variant_list):
|
||||
selling = frappe.db.get_all(
|
||||
"Item Price",
|
||||
fields=[
|
||||
"avg(price_list_rate) as avg_rate",
|
||||
{"AVG": "price_list_rate", "as": "avg_rate"},
|
||||
"item_code",
|
||||
],
|
||||
filters={"item_code": ["in", variant_list], "selling": 1},
|
||||
|
||||
@@ -183,14 +183,15 @@ def get_voucher_type(doctype, txt, searchfield, start, page_len, filters):
|
||||
child_doctypes = frappe.get_all(
|
||||
"DocField",
|
||||
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]]}
|
||||
if 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()
|
||||
|
||||
@@ -61,7 +61,7 @@ def get_stock_ledger_data(report_filters, filters):
|
||||
"name",
|
||||
"voucher_type",
|
||||
"voucher_no",
|
||||
"sum(stock_value_difference) as stock_value",
|
||||
{"SUM": "stock_value_difference", "as": "stock_value"},
|
||||
"posting_date",
|
||||
"posting_time",
|
||||
],
|
||||
@@ -88,7 +88,10 @@ def get_gl_data(report_filters, filters):
|
||||
"name",
|
||||
"voucher_type",
|
||||
"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",
|
||||
)
|
||||
|
||||
@@ -546,7 +546,10 @@ def get_opening_balance_from_batch(filters, columns, sl_entries):
|
||||
|
||||
opening_data = frappe.get_all(
|
||||
"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,
|
||||
)[0]
|
||||
|
||||
|
||||
@@ -1511,7 +1511,7 @@ def get_batchwise_qty(voucher_type, voucher_no):
|
||||
batches = frappe.get_all(
|
||||
"Serial and Batch Entry",
|
||||
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",
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe.query_builder.functions import Timestamp
|
||||
from frappe.tests import IntegrationTestCase
|
||||
|
||||
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}
|
||||
if sle_filters:
|
||||
filters.update(sle_filters)
|
||||
sles = frappe.get_all(
|
||||
"Stock Ledger Entry",
|
||||
fields=["*"],
|
||||
filters=filters,
|
||||
order_by="timestamp(posting_date, posting_time), creation",
|
||||
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
query = (
|
||||
frappe.qb.from_(sle)
|
||||
.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))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user