mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 16:04:46 +00:00
refactor: add budget start and end date field on the parent
This commit is contained in:
@@ -17,7 +17,8 @@
|
|||||||
"amended_from",
|
"amended_from",
|
||||||
"from_fiscal_year",
|
"from_fiscal_year",
|
||||||
"to_fiscal_year",
|
"to_fiscal_year",
|
||||||
"distribution_type",
|
"budget_start_date",
|
||||||
|
"budget_end_date",
|
||||||
"allocation_frequency",
|
"allocation_frequency",
|
||||||
"budget_amount",
|
"budget_amount",
|
||||||
"section_break_nwug",
|
"section_break_nwug",
|
||||||
@@ -237,15 +238,6 @@
|
|||||||
"read_only_depends_on": "eval: doc.revision_of",
|
"read_only_depends_on": "eval: doc.revision_of",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "Percent",
|
|
||||||
"fieldname": "distribution_type",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Distribution Type",
|
|
||||||
"options": "Amount\nPercent",
|
|
||||||
"read_only_depends_on": "eval: doc.revision_of",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "Monthly",
|
"default": "Monthly",
|
||||||
"fieldname": "allocation_frequency",
|
"fieldname": "allocation_frequency",
|
||||||
@@ -298,13 +290,25 @@
|
|||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"read_only_depends_on": "eval: doc.revision_of",
|
"read_only_depends_on": "eval: doc.revision_of",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "budget_start_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Budget Start Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "budget_end_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Budget End Date"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-10-31 01:13:15.114440",
|
"modified": "2025-11-05 01:00:46.470251",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Budget",
|
"name": "Budget",
|
||||||
|
|||||||
@@ -54,10 +54,11 @@ class Budget(Document):
|
|||||||
budget_against: DF.Literal["", "Cost Center", "Project"]
|
budget_against: DF.Literal["", "Cost Center", "Project"]
|
||||||
budget_amount: DF.Currency
|
budget_amount: DF.Currency
|
||||||
budget_distribution: DF.Table[BudgetDistribution]
|
budget_distribution: DF.Table[BudgetDistribution]
|
||||||
|
budget_end_date: DF.Date | None
|
||||||
|
budget_start_date: DF.Date | None
|
||||||
company: DF.Link
|
company: DF.Link
|
||||||
cost_center: DF.Link | None
|
cost_center: DF.Link | None
|
||||||
distribute_equally: DF.Check
|
distribute_equally: DF.Check
|
||||||
distribution_type: DF.Literal["Amount", "Percent"]
|
|
||||||
from_fiscal_year: DF.Link
|
from_fiscal_year: DF.Link
|
||||||
naming_series: DF.Literal["BUDGET-.YYYY.-"]
|
naming_series: DF.Literal["BUDGET-.YYYY.-"]
|
||||||
project: DF.Link | None
|
project: DF.Link | None
|
||||||
@@ -68,11 +69,23 @@ class Budget(Document):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
if not self.get(frappe.scrub(self.budget_against)):
|
if not self.get(frappe.scrub(self.budget_against)):
|
||||||
frappe.throw(_("{0} is mandatory").format(self.budget_against))
|
frappe.throw(_("{0} is mandatory").format(self.budget_against))
|
||||||
|
self.set_fiscal_year_dates()
|
||||||
self.validate_duplicate()
|
self.validate_duplicate()
|
||||||
self.validate_account()
|
self.validate_account()
|
||||||
self.set_null_value()
|
self.set_null_value()
|
||||||
self.validate_applicable_for()
|
self.validate_applicable_for()
|
||||||
|
|
||||||
|
def set_fiscal_year_dates(self):
|
||||||
|
if self.from_fiscal_year:
|
||||||
|
self.budget_start_date = frappe.get_cached_value(
|
||||||
|
"Fiscal Year", self.from_fiscal_year, "year_start_date"
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.to_fiscal_year:
|
||||||
|
self.budget_end_date = frappe.get_cached_value(
|
||||||
|
"Fiscal Year", self.to_fiscal_year, "year_end_date"
|
||||||
|
)
|
||||||
|
|
||||||
def validate_duplicate(self):
|
def validate_duplicate(self):
|
||||||
budget_against_field = frappe.scrub(self.budget_against)
|
budget_against_field = frappe.scrub(self.budget_against)
|
||||||
budget_against = self.get(budget_against_field)
|
budget_against = self.get(budget_against_field)
|
||||||
@@ -275,7 +288,7 @@ class Budget(Document):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if round(total_percent, 2) != 100:
|
if flt(abs(total_percent - 100), 2) > 0.10:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Total distribution percent must equal 100 (currently {0})").format(round(total_percent, 2))
|
_("Total distribution percent must equal 100 (currently {0})").format(round(total_percent, 2))
|
||||||
)
|
)
|
||||||
@@ -361,6 +374,8 @@ def validate_expense_against_budget(args, expense_amount=0):
|
|||||||
b.budget_amount,
|
b.budget_amount,
|
||||||
b.from_fiscal_year,
|
b.from_fiscal_year,
|
||||||
b.to_fiscal_year,
|
b.to_fiscal_year,
|
||||||
|
b.budget_start_date,
|
||||||
|
b.budget_end_date,
|
||||||
IFNULL(b.applicable_on_material_request, 0) AS for_material_request,
|
IFNULL(b.applicable_on_material_request, 0) AS for_material_request,
|
||||||
IFNULL(b.applicable_on_purchase_order, 0) AS for_purchase_order,
|
IFNULL(b.applicable_on_purchase_order, 0) AS for_purchase_order,
|
||||||
IFNULL(b.applicable_on_booking_actual_expenses, 0) AS for_actual_expenses,
|
IFNULL(b.applicable_on_booking_actual_expenses, 0) AS for_actual_expenses,
|
||||||
@@ -375,12 +390,7 @@ def validate_expense_against_budget(args, expense_amount=0):
|
|||||||
WHERE
|
WHERE
|
||||||
b.company = %s
|
b.company = %s
|
||||||
AND b.docstatus = 1
|
AND b.docstatus = 1
|
||||||
AND (
|
AND %s BETWEEN b.budget_start_date AND b.budget_end_date
|
||||||
%s BETWEEN
|
|
||||||
(SELECT year_start_date FROM `tabFiscal Year` WHERE name = b.from_fiscal_year)
|
|
||||||
AND
|
|
||||||
(SELECT year_end_date FROM `tabFiscal Year` WHERE name = b.to_fiscal_year)
|
|
||||||
)
|
|
||||||
AND b.account = %s
|
AND b.account = %s
|
||||||
{condition}
|
{condition}
|
||||||
""",
|
""",
|
||||||
@@ -627,14 +637,7 @@ def get_actual_expense(args):
|
|||||||
budget_against_field = args.get("budget_against_field")
|
budget_against_field = args.get("budget_against_field")
|
||||||
condition1 = " and gle.posting_date <= %(month_end_date)s" if args.get("month_end_date") else ""
|
condition1 = " and gle.posting_date <= %(month_end_date)s" if args.get("month_end_date") else ""
|
||||||
|
|
||||||
from_start, _ = frappe.get_cached_value(
|
date_condition = f"and gle.posting_date between '{args.budget_start_date}' and '{args.budget_end_date}'"
|
||||||
"Fiscal Year", args.from_fiscal_year, ["year_start_date", "year_end_date"]
|
|
||||||
)
|
|
||||||
_, to_end = frappe.get_cached_value(
|
|
||||||
"Fiscal Year", args.to_fiscal_year, ["year_start_date", "year_end_date"]
|
|
||||||
)
|
|
||||||
|
|
||||||
date_condition = f"and gle.posting_date between '{from_start}' and '{to_end}'"
|
|
||||||
|
|
||||||
if args.is_tree:
|
if args.is_tree:
|
||||||
lft_rgt = frappe.db.get_value(
|
lft_rgt = frappe.db.get_value(
|
||||||
@@ -687,7 +690,7 @@ def get_accumulated_monthly_budget(budget_name, posting_date):
|
|||||||
.on(bd.parent == b.name)
|
.on(bd.parent == b.name)
|
||||||
.select(Sum(bd.amount).as_("accumulated_amount"))
|
.select(Sum(bd.amount).as_("accumulated_amount"))
|
||||||
.where(b.name == budget_name)
|
.where(b.name == budget_name)
|
||||||
.where(bd.end_date >= posting_date)
|
.where(bd.start_date <= posting_date)
|
||||||
.run(as_dict=True)
|
.run(as_dict=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -725,7 +725,6 @@ def make_budget(**args):
|
|||||||
budget.budget_against = budget_against
|
budget.budget_against = budget_against
|
||||||
|
|
||||||
budget.allocation_frequency = "Monthly"
|
budget.allocation_frequency = "Monthly"
|
||||||
budget.distribution_type = "Amount"
|
|
||||||
budget.distribute_equally = args.get("distribute_equally", 1)
|
budget.distribute_equally = args.get("distribute_equally", 1)
|
||||||
|
|
||||||
if args.applicable_on_material_request:
|
if args.applicable_on_material_request:
|
||||||
|
|||||||
@@ -31,22 +31,20 @@
|
|||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Amount",
|
"label": "Amount"
|
||||||
"read_only_depends_on": "eval:doc.end_date < frappe.datetime.get_today()"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "percent",
|
"fieldname": "percent",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Percent",
|
"label": "Percent"
|
||||||
"read_only_depends_on": "eval:doc.end_date < frappe.datetime.get_today()"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-10-30 12:35:31.310931",
|
"modified": "2025-11-03 13:18:28.398198",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Budget Distribution",
|
"name": "Budget Distribution",
|
||||||
|
|||||||
Reference in New Issue
Block a user