mirror of
https://github.com/frappe/erpnext.git
synced 2026-10-29 22:57:42 +00:00
fix(accounts): run snapshot reports on live data for users with permission restrictions
This commit is contained in:
@@ -22,6 +22,7 @@ from erpnext.accounts.report.financial_statements import (
|
||||
get_period_list,
|
||||
prepare_data,
|
||||
)
|
||||
from erpnext.accounts.report.utils import has_gl_entry_restrictions
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -271,6 +272,9 @@ def get_chart_data(filters, chart_columns, asset, liability, equity, currency):
|
||||
|
||||
|
||||
def execute_snapshot_report(filters):
|
||||
if has_gl_entry_restrictions():
|
||||
return execute(filters)
|
||||
|
||||
from frappe.database.duckdb.database import get_latest_sync
|
||||
|
||||
if not (conn := get_latest_sync("GL Entry")):
|
||||
|
||||
@@ -16,7 +16,11 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_dimension_with_children,
|
||||
)
|
||||
from erpnext.accounts.report.financial_statements import get_cost_centers_with_children
|
||||
from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency
|
||||
from erpnext.accounts.report.utils import (
|
||||
convert_to_presentation_currency,
|
||||
get_currency,
|
||||
has_gl_entry_restrictions,
|
||||
)
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
|
||||
|
||||
@@ -795,6 +799,9 @@ def get_columns(filters):
|
||||
|
||||
|
||||
def execute_snapshot_report(filters):
|
||||
if has_gl_entry_restrictions():
|
||||
return execute(filters)
|
||||
|
||||
from frappe.database.duckdb.database import get_latest_sync
|
||||
|
||||
if conn := get_latest_sync("GL Entry"):
|
||||
|
||||
@@ -12,6 +12,33 @@ from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
|
||||
|
||||
class TestGeneralLedger(FrappeTestCase):
|
||||
def test_snapshot_reports_use_live_data_for_restricted_users(self):
|
||||
from importlib import import_module
|
||||
from unittest.mock import patch
|
||||
|
||||
from erpnext.tests.permission_test_utils import as_user, make_fenced_user
|
||||
|
||||
restricted = make_fenced_user(
|
||||
"gl-snapshot-fenced@example.com", ["Accounts User"], [("Company", "_Test Company")]
|
||||
)
|
||||
unrestricted = make_fenced_user("gl-snapshot-open@example.com", ["Accounts User"])
|
||||
for report in ("general_ledger", "balance_sheet", "profit_and_loss_statement", "trial_balance"):
|
||||
module = import_module(f"erpnext.accounts.report.{report}.{report}")
|
||||
for user, expect_live in ((restricted, True), (unrestricted, False)):
|
||||
with (
|
||||
as_user(user),
|
||||
patch.object(module, "execute", return_value="live") as live,
|
||||
patch(
|
||||
"frappe.database.duckdb.database.get_latest_sync", side_effect=frappe.ValidationError
|
||||
),
|
||||
):
|
||||
try:
|
||||
result = module.execute_snapshot_report(frappe._dict(company="_Test Company"))
|
||||
except frappe.ValidationError:
|
||||
result = "snapshot"
|
||||
self.assertEqual(result, "live" if expect_live else "snapshot", f"{report} as {user}")
|
||||
self.assertEqual(live.called, expect_live)
|
||||
|
||||
def setUp(self):
|
||||
self.company = "_Test Company"
|
||||
self.clear_old_entries()
|
||||
|
||||
@@ -22,6 +22,7 @@ from erpnext.accounts.report.financial_statements import (
|
||||
get_period_list,
|
||||
prepare_data,
|
||||
)
|
||||
from erpnext.accounts.report.utils import has_gl_entry_restrictions
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -204,6 +205,9 @@ def get_chart_data(filters, chart_columns, income, expense, net_profit_loss, cur
|
||||
|
||||
|
||||
def execute_snapshot_report(filters):
|
||||
if has_gl_entry_restrictions():
|
||||
return execute(filters)
|
||||
|
||||
from frappe.database.duckdb.database import get_latest_sync
|
||||
|
||||
if not (conn := get_latest_sync("GL Entry")):
|
||||
|
||||
@@ -18,7 +18,11 @@ from erpnext.accounts.report.financial_statements import (
|
||||
get_cost_centers_with_children,
|
||||
set_gl_entries_by_account,
|
||||
)
|
||||
from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency
|
||||
from erpnext.accounts.report.utils import (
|
||||
convert_to_presentation_currency,
|
||||
get_currency,
|
||||
has_gl_entry_restrictions,
|
||||
)
|
||||
from erpnext.accounts.utils import get_zero_cutoff
|
||||
|
||||
value_fields = (
|
||||
@@ -513,6 +517,9 @@ def hide_group_accounts(data):
|
||||
|
||||
|
||||
def execute_snapshot_report(filters):
|
||||
if has_gl_entry_restrictions():
|
||||
return execute(filters)
|
||||
|
||||
from frappe.database.duckdb.database import get_latest_sync
|
||||
|
||||
if conn := get_latest_sync("GL Entry"):
|
||||
|
||||
@@ -436,3 +436,10 @@ def get_opening_row(party_type, party, from_date, company):
|
||||
& (gle.is_cancelled == 0)
|
||||
)
|
||||
).run(as_dict=True)
|
||||
|
||||
|
||||
def has_gl_entry_restrictions() -> bool:
|
||||
"""Snapshot reports read a DuckDB copy that cannot apply the user's GL Entry permission conditions."""
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
|
||||
return bool(build_match_conditions("GL Entry"))
|
||||
|
||||
Reference in New Issue
Block a user