diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index 6ac3350c3b..637ac7a04c 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -107,7 +107,7 @@ class Budget(Document): self.naming_series = f"{{{frappe.scrub(self.budget_against)}}}./.{self.fiscal_year}/.###" -def validate_expense_against_budget(args): +def validate_expense_against_budget(args, expense_amount=0): args = frappe._dict(args) if args.get("company") and not args.fiscal_year: @@ -175,13 +175,13 @@ def validate_expense_against_budget(args): ) # nosec if budget_records: - validate_budget_records(args, budget_records) + validate_budget_records(args, budget_records, expense_amount) -def validate_budget_records(args, budget_records): +def validate_budget_records(args, budget_records, expense_amount): for budget in budget_records: if flt(budget.budget_amount): - amount = get_amount(args, budget) + amount = expense_amount or get_amount(args, budget) yearly_action, monthly_action = get_actions(args, budget) if monthly_action in ["Stop", "Warn"]: diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py index c48c7d97a2..11af9a29f6 100644 --- a/erpnext/accounts/doctype/budget/test_budget.py +++ b/erpnext/accounts/doctype/budget/test_budget.py @@ -334,6 +334,39 @@ class TestBudget(unittest.TestCase): budget.cancel() jv.cancel() + def test_monthly_budget_against_main_cost_center(self): + from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center + from erpnext.accounts.doctype.cost_center_allocation.test_cost_center_allocation import ( + create_cost_center_allocation, + ) + + cost_centers = [ + "Main Budget Cost Center 1", + "Sub Budget Cost Center 1", + "Sub Budget Cost Center 2", + ] + + for cc in cost_centers: + create_cost_center(cost_center_name=cc, company="_Test Company") + + create_cost_center_allocation( + "_Test Company", + "Main Budget Cost Center 1 - _TC", + {"Sub Budget Cost Center 1 - _TC": 60, "Sub Budget Cost Center 2 - _TC": 40}, + ) + + make_budget(budget_against="Cost Center", cost_center="Main Budget Cost Center 1 - _TC") + + jv = make_journal_entry( + "_Test Account Cost for Goods Sold - _TC", + "_Test Bank - _TC", + 400000, + "Main Budget Cost Center 1 - _TC", + posting_date=nowdate(), + ) + + self.assertRaises(BudgetError, jv.submit) + def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None): if budget_against_field == "project": diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index f4a50a5f91..6d164eef2b 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -128,6 +128,12 @@ def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None): new_gl_map = [] for d in gl_map: cost_center = d.get("cost_center") + + # Validate budget against main cost center + validate_expense_against_budget( + d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision) + ) + if cost_center and cost_center_allocation.get(cost_center): for sub_cost_center, percentage in cost_center_allocation.get(cost_center, {}).items(): gle = copy.deepcopy(d)