[feature] New document for Budget
diff --git a/erpnext/accounts/doctype/budget/__init__.py b/erpnext/accounts/doctype/budget/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/budget/__init__.py
diff --git a/erpnext/accounts/doctype/budget/budget.js b/erpnext/accounts/doctype/budget/budget.js
new file mode 100644
index 0000000..e39393e
--- /dev/null
+++ b/erpnext/accounts/doctype/budget/budget.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Budget', {
+ onload: function(frm) {
+ frm.set_query("cost_center", function() {
+ return {
+ filters: {
+ company: frm.doc.company
+ }
+ }
+ })
+
+ frm.set_query("account", "accounts", function() {
+ return {
+ filters: {
+ company: frm.doc.company,
+ report_type: "Profit and Loss"
+ }
+ }
+ })
+
+ frm.set_query("monthly_distribution", function() {
+ return {
+ filters: {
+ fiscal_year: frm.doc.fiscal_year
+ }
+ }
+ })
+ }
+});
diff --git a/erpnext/accounts/doctype/budget/budget.json b/erpnext/accounts/doctype/budget/budget.json
new file mode 100644
index 0000000..4de6fa8
--- /dev/null
+++ b/erpnext/accounts/doctype/budget/budget.json
@@ -0,0 +1,314 @@
+{
+ "allow_copy": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-05-16 11:42:29.632528",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Cost Center",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Cost Center",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "fiscal_year",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Fiscal Year",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Fiscal Year",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "monthly_distribution",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Monthly Distribution",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Monthly Distribution",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "default": "Stop",
+ "fieldname": "action_if_annual_budget_exceeded",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Action if Annual Budget Exceeded",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nStop\nWarn\nIgnore",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "default": "Warn",
+ "description": "",
+ "fieldname": "action_if_accumulated_monthly_budget_exceeded",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Action if Accumulated Monthly Budget Exceeded",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nStop\nWarn\nIgnore",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Budget",
+ "permlevel": 0,
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "accounts",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Budget Accounts",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Budget Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-05-16 13:12:10.439375",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Budget",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py
new file mode 100644
index 0000000..cb8eff7
--- /dev/null
+++ b/erpnext/accounts/doctype/budget/budget.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import flt, getdate, add_months, get_last_day
+from frappe.model.naming import make_autoname
+from frappe.model.document import Document
+
+class BudgetError(frappe.ValidationError): pass
+
+class Budget(Document):
+ def autoname(self):
+ self.name = make_autoname(self.cost_center + "/" + self.fiscal_year + "/.###")
+
+ def validate(self):
+ self.validate_duplicate()
+
+ def validate_duplicate(self):
+ existing_budget = frappe.db.get_value("Budget", {"cost_center": self.cost_center,
+ "fiscal_year": self.fiscal_year, "name": ["!=", self.name], "docstatus": ["!=", 2]})
+ if existing_budget:
+ frappe.throw(_("Another Budget record {0} already exists against {1} for fiscal year {2}")
+ .format(existing_budget, self.cost_center, self.fiscal_year))
+
+
+def validate_expense_against_budget(args):
+ args = frappe._dict(args)
+ if frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}):
+ budget = frappe.db.sql("""
+ select ba.budget_amount, b.monthly_distribution,
+ b.action_if_annual_budget_exceeded, b.action_if_accumulated_monthly_budget_exceeded
+ from `tabBudget` b, `tabBudget Account` ba
+ where b.name=ba.parent and b.cost_center=%s and b.fiscal_year=%s and ba.account=%s
+ """, (args.cost_center, args.fiscal_year, args.account), as_dict=True)
+
+ if budget and budget[0].budget_amount:
+ yearly_action = budget[0].action_if_annual_budget_exceeded
+ monthly_action = budget[0].action_if_accumulated_monthly_budget_exceeded
+
+ action_for = action = ""
+
+ if monthly_action in ["Stop", "Warn"]:
+ budget_amount = get_accumulated_monthly_budget(budget[0].monthly_distribution,
+ args.posting_date, args.fiscal_year, budget[0].budget_amount)
+
+ args["month_end_date"] = get_last_day(args.posting_date)
+
+ action_for, action = _("Accumulated Monthly"), monthly_action
+
+ elif yearly_action in ["Stop", "Warn"]:
+ budget_amount = flt(budget[0].budget_amount)
+ action_for, action = _("Annual"), yearly_action
+
+ if action_for:
+ actual_expense = get_actual_expense(args)
+ if actual_expense > budget_amount:
+ diff = actual_expense - budget_amount
+
+ msg = _("{0} Budget for Account {1} against Cost Center {2} is {3}. It will exceed by {4}").format(_(action_for), args.account, args.cost_center, budget_amount, diff)
+
+ if action=="Stop":
+ frappe.throw(msg, BudgetError)
+ else:
+ frappe.msgprint(msg)
+
+def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget):
+ distribution = {}
+ if monthly_distribution:
+ for d in frappe.db.sql("""select mdp.month, mdp.percentage_allocation
+ from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
+ where mdp.parent=md.name and md.fiscal_year=%s""", fiscal_year, as_dict=1):
+ distribution.setdefault(d.month, d.percentage_allocation)
+
+ dt = frappe.db.get_value("Fiscal Year", fiscal_year, "year_start_date")
+ accumulated_percentage = 0.0
+
+ while(dt <= getdate(posting_date)):
+ if monthly_distribution:
+ accumulated_percentage += distribution.get(getdate(dt).strftime("%B"), 0)
+ else:
+ accumulated_percentage += 100.0/12
+
+ dt = add_months(dt, 1)
+
+ return annual_budget * accumulated_percentage / 100
+
+def get_actual_expense(args):
+ args["condition"] = " and posting_date <= '%s'" % \
+ args.month_end_date if args.get("month_end_date") else ""
+
+ return flt(frappe.db.sql("""
+ select sum(debit) - sum(credit)
+ from `tabGL Entry`
+ where account='%(account)s' and cost_center='%(cost_center)s'
+ and fiscal_year='%(fiscal_year)s' and company='%(company)s' and docstatus=1 %(condition)s
+ """ % (args))[0][0])
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
new file mode 100644
index 0000000..7b92915
--- /dev/null
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+# test_records = frappe.get_test_records('Budget')
+
+class TestBudget(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/budget_account/__init__.py b/erpnext/accounts/doctype/budget_account/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/budget_account/__init__.py
diff --git a/erpnext/accounts/doctype/budget_account/budget_account.json b/erpnext/accounts/doctype/budget_account/budget_account.json
new file mode 100644
index 0000000..43dbbd9
--- /dev/null
+++ b/erpnext/accounts/doctype/budget_account/budget_account.json
@@ -0,0 +1,110 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-05-16 11:54:09.286135",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "budget_amount",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Budget Amount",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-05-16 11:55:29.586591",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Budget Account",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/budget_account/budget_account.py b/erpnext/accounts/doctype/budget_account/budget_account.py
new file mode 100644
index 0000000..81b2709
--- /dev/null
+++ b/erpnext/accounts/doctype/budget_account/budget_account.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class BudgetAccount(Document):
+ pass
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
index bad7f98..f94d4ed 100644
--- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import unittest, frappe
from frappe.utils import flt
-from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
+from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError, get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index a8a090f..bdee391 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -6,7 +6,7 @@
from frappe.utils import flt, cstr, cint
from frappe import _
from frappe.model.meta import get_field_precision
-from erpnext.accounts.utils import validate_expense_against_budget
+from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
class StockAccountInvalidTransaction(frappe.ValidationError): pass
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 683b84b..3b78683 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import nowdate, cstr, flt, cint, now, getdate, add_months
+from frappe.utils import nowdate, cstr, flt, cint, now, getdate
from frappe import throw, _
from frappe.utils import formatdate
import frappe.desk.reportview
@@ -13,7 +13,6 @@
from erpnext.accounts.doctype.account.account import get_account_currency
class FiscalYearError(frappe.ValidationError): pass
-class BudgetError(frappe.ValidationError): pass
@frappe.whitelist()
def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False):
@@ -321,72 +320,6 @@
return difference
-def validate_expense_against_budget(args):
- args = frappe._dict(args)
- if frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}):
- budget = frappe.db.sql("""
- select bd.budget_allocated, cc.distribution_id
- from `tabCost Center` cc, `tabBudget Detail` bd
- where cc.name=bd.parent and cc.name=%s and account=%s and bd.fiscal_year=%s
- """, (args.cost_center, args.account, args.fiscal_year), as_dict=True)
-
- if budget and budget[0].budget_allocated:
- yearly_action, monthly_action = frappe.db.get_value("Company", args.company,
- ["yearly_bgt_flag", "monthly_bgt_flag"])
- action_for = action = ""
-
- if monthly_action in ["Stop", "Warn"]:
- budget_amount = get_allocated_budget(budget[0].distribution_id,
- args.posting_date, args.fiscal_year, budget[0].budget_allocated)
-
- args["month_end_date"] = frappe.db.sql("select LAST_DAY(%s)",
- args.posting_date)[0][0]
- action_for, action = _("Monthly"), monthly_action
-
- elif yearly_action in ["Stop", "Warn"]:
- budget_amount = budget[0].budget_allocated
- action_for, action = _("Annual"), yearly_action
-
- if action_for:
- actual_expense = get_actual_expense(args)
- if actual_expense > budget_amount:
- frappe.msgprint(_("{0} budget for Account {1} against Cost Center {2} will exceed by {3}").format(
- _(action_for), args.account, args.cost_center, cstr(actual_expense - budget_amount)))
- if action=="Stop":
- raise BudgetError
-
-def get_allocated_budget(distribution_id, posting_date, fiscal_year, yearly_budget):
- if distribution_id:
- distribution = {}
- for d in frappe.db.sql("""select mdp.month, mdp.percentage_allocation
- from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
- where mdp.parent=md.name and md.fiscal_year=%s""", fiscal_year, as_dict=1):
- distribution.setdefault(d.month, d.percentage_allocation)
-
- dt = frappe.db.get_value("Fiscal Year", fiscal_year, "year_start_date")
- budget_percentage = 0.0
-
- while(dt <= getdate(posting_date)):
- if distribution_id:
- budget_percentage += distribution.get(getdate(dt).strftime("%B"), 0)
- else:
- budget_percentage += 100.0/12
-
- dt = add_months(dt, 1)
-
- return yearly_budget * budget_percentage / 100
-
-def get_actual_expense(args):
- args["condition"] = " and posting_date<='%s'" % args.month_end_date \
- if args.get("month_end_date") else ""
-
- return flt(frappe.db.sql("""
- select sum(debit) - sum(credit)
- from `tabGL Entry`
- where account='%(account)s' and cost_center='%(cost_center)s'
- and fiscal_year='%(fiscal_year)s' and company='%(company)s' %(condition)s
- """ % (args))[0][0])
-
def get_currency_precision(currency=None):
if not currency:
currency = frappe.db.get_value("Company",
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index d0629e7..1b445fe 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -201,6 +201,11 @@
"doctype": "Cost Center",
},
{
+ "type": "doctype",
+ "name": "Budget",
+ "description": _("Define budget for a financial year.")
+ },
+ {
"type": "report",
"name": "Budget Variance Report",
"is_query_report": True,