mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-28 01:14:46 +00:00
Merge pull request #55342 from frappe/mergify/bp/version-16-hotfix/pr-55333
fix(custom_financial_template): sum account closing balances across dimensions (backport #55333)
This commit is contained in:
@@ -565,18 +565,19 @@ class FinancialQueryBuilder:
|
|||||||
frappe.qb.from_(acb_table)
|
frappe.qb.from_(acb_table)
|
||||||
.select(
|
.select(
|
||||||
acb_table.account,
|
acb_table.account,
|
||||||
(acb_table.debit - acb_table.credit).as_("balance"),
|
Sum(acb_table.debit - acb_table.credit).as_("balance"),
|
||||||
)
|
)
|
||||||
.where(acb_table.company == self.company)
|
.where(acb_table.company == self.company)
|
||||||
.where(acb_table.account.isin(account_names))
|
.where(acb_table.account.isin(account_names))
|
||||||
.where(acb_table.period_closing_voucher == closing_voucher)
|
.where(acb_table.period_closing_voucher == closing_voucher)
|
||||||
|
.groupby(acb_table.account)
|
||||||
)
|
)
|
||||||
|
|
||||||
query = self._apply_standard_filters(query, acb_table, "Account Closing Balance")
|
query = self._apply_standard_filters(query, acb_table, "Account Closing Balance")
|
||||||
results = self._execute_with_permissions(query, "Account Closing Balance")
|
results = self._execute_with_permissions(query, "Account Closing Balance")
|
||||||
|
|
||||||
for row in results:
|
for row in results:
|
||||||
closing_balances[row["account"]] = row["balance"]
|
closing_balances[row["account"]] = row["balance"] or 0.0
|
||||||
|
|
||||||
return closing_balances
|
return closing_balances
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from erpnext.accounts.doctype.financial_report_template.test_financial_report_te
|
|||||||
)
|
)
|
||||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||||
from erpnext.accounts.utils import get_currency_precision, get_fiscal_year
|
from erpnext.accounts.utils import get_currency_precision, get_fiscal_year
|
||||||
|
from erpnext.tests.utils import change_settings
|
||||||
|
|
||||||
|
|
||||||
class TestDependencyResolver(FinancialReportTemplateTestCase):
|
class TestDependencyResolver(FinancialReportTemplateTestCase):
|
||||||
@@ -1953,6 +1954,104 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase):
|
|||||||
|
|
||||||
jv_2023.cancel()
|
jv_2023.cancel()
|
||||||
|
|
||||||
|
@change_settings("Accounts Settings", {"use_legacy_controller_for_pcv": 1})
|
||||||
|
def test_opening_balance_sums_acb_rows_across_dimensions(self):
|
||||||
|
"""
|
||||||
|
Account Closing Balance stores one row per (account, cost_center,
|
||||||
|
project, finance_book). The closing-balance fetch must sum all rows.
|
||||||
|
"""
|
||||||
|
company = "_Test Company"
|
||||||
|
cash_account = "_Test Cash - _TC"
|
||||||
|
sales_account = "Sales - _TC"
|
||||||
|
cc_1 = "_Test Cost Center - _TC"
|
||||||
|
cc_2 = "_Test Cost Center 2 - _TC"
|
||||||
|
docs = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
jv_2023_cc1 = make_journal_entry(
|
||||||
|
account1=cash_account,
|
||||||
|
account2=sales_account,
|
||||||
|
amount=3000,
|
||||||
|
posting_date="2023-06-15",
|
||||||
|
cost_center=cc_1,
|
||||||
|
company=company,
|
||||||
|
submit=True,
|
||||||
|
)
|
||||||
|
docs.append(jv_2023_cc1)
|
||||||
|
jv_2023_cc2 = make_journal_entry(
|
||||||
|
account1=cash_account,
|
||||||
|
account2=sales_account,
|
||||||
|
amount=2000,
|
||||||
|
posting_date="2023-06-15",
|
||||||
|
cost_center=cc_2,
|
||||||
|
company=company,
|
||||||
|
submit=True,
|
||||||
|
)
|
||||||
|
docs.append(jv_2023_cc2)
|
||||||
|
|
||||||
|
fy_2023 = get_fiscal_year("2023-06-15", company=company)
|
||||||
|
|
||||||
|
pcv = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Period Closing Voucher",
|
||||||
|
"transaction_date": "2023-12-31",
|
||||||
|
"period_start_date": fy_2023[1],
|
||||||
|
"period_end_date": fy_2023[2],
|
||||||
|
"company": company,
|
||||||
|
"fiscal_year": fy_2023[0],
|
||||||
|
"cost_center": cc_1,
|
||||||
|
"closing_account_head": "Deferred Revenue - _TC",
|
||||||
|
"remarks": "Test multi-dim PCV",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
pcv.insert()
|
||||||
|
pcv.submit()
|
||||||
|
docs.append(pcv)
|
||||||
|
|
||||||
|
jv_2024 = make_journal_entry(
|
||||||
|
account1=cash_account,
|
||||||
|
account2=sales_account,
|
||||||
|
amount=100,
|
||||||
|
posting_date="2024-01-15",
|
||||||
|
cost_center=cc_1,
|
||||||
|
company=company,
|
||||||
|
submit=True,
|
||||||
|
)
|
||||||
|
docs.append(jv_2024)
|
||||||
|
|
||||||
|
filters = {
|
||||||
|
"company": company,
|
||||||
|
"from_fiscal_year": "2024",
|
||||||
|
"to_fiscal_year": "2024",
|
||||||
|
"period_start_date": "2024-01-01",
|
||||||
|
"period_end_date": "2024-03-31",
|
||||||
|
"filter_based_on": "Date Range",
|
||||||
|
"periodicity": "Monthly",
|
||||||
|
"ignore_closing_entries": True,
|
||||||
|
}
|
||||||
|
periods = [
|
||||||
|
{"key": "2024_jan", "from_date": "2024-01-01", "to_date": "2024-01-31"},
|
||||||
|
{"key": "2024_feb", "from_date": "2024-02-01", "to_date": "2024-02-29"},
|
||||||
|
{"key": "2024_mar", "from_date": "2024-03-01", "to_date": "2024-03-31"},
|
||||||
|
]
|
||||||
|
|
||||||
|
query_builder = FinancialQueryBuilder(filters, periods)
|
||||||
|
accounts = [
|
||||||
|
frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}),
|
||||||
|
]
|
||||||
|
|
||||||
|
balances_data = query_builder.fetch_account_balances(accounts)
|
||||||
|
cash_data = balances_data.get(cash_account)
|
||||||
|
self.assertIsNotNone(cash_data, "Cash account must appear in results")
|
||||||
|
|
||||||
|
jan_cash = cash_data.get_period("2024_jan")
|
||||||
|
self.assertEqual(jan_cash.opening, 5000.0)
|
||||||
|
self.assertEqual(jan_cash.movement, 100.0)
|
||||||
|
self.assertEqual(jan_cash.closing, 5100.0)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self.cancel_docs(docs)
|
||||||
|
|
||||||
def test_opening_entries_roll_into_opening_after_period_closing(self):
|
def test_opening_entries_roll_into_opening_after_period_closing(self):
|
||||||
"""
|
"""
|
||||||
Sequence:
|
Sequence:
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ from erpnext.tests.utils import ERPNextTestSuite
|
|||||||
class FinancialReportTemplateTestCase(ERPNextTestSuite):
|
class FinancialReportTemplateTestCase(ERPNextTestSuite):
|
||||||
"""Utility class with common setup and helper methods for all test classes"""
|
"""Utility class with common setup and helper methods for all test classes"""
|
||||||
|
|
||||||
|
def cancel_docs(self, docs):
|
||||||
|
"""Cancel submitted docs in reverse creation order to avoid dependency issues."""
|
||||||
|
for doc in reversed(docs):
|
||||||
|
if doc:
|
||||||
|
doc.reload()
|
||||||
|
if doc.docstatus == 1:
|
||||||
|
doc.cancel()
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up test data"""
|
"""Set up test data"""
|
||||||
self.create_test_template()
|
self.create_test_template()
|
||||||
|
|||||||
Reference in New Issue
Block a user