fix: Simplify get_dimension_account_month_map
This commit updates get_dimension_account_month_map to no longer show the actual expense when there is no budget. This also removes the other functions and queries related to it. Spaces are also converted to tabs.
This commit is contained in:
parent
b3ee6314f9
commit
bc05855805
@ -13,164 +13,165 @@ from erpnext.controllers.trends import get_period_date_ranges, get_period_month_
|
|||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
if not filters:
|
if not filters:
|
||||||
filters = {}
|
filters = {}
|
||||||
|
|
||||||
columns = get_columns(filters)
|
columns = get_columns(filters)
|
||||||
|
if filters.get("budget_against_filter"):
|
||||||
|
dimensions = filters.get("budget_against_filter")
|
||||||
|
else:
|
||||||
|
dimensions = get_cost_centers(filters)
|
||||||
|
|
||||||
if filters.get("budget_against_filter"):
|
period_month_ranges = get_period_month_ranges(
|
||||||
dimensions = filters.get("budget_against_filter")
|
filters["period"], filters["from_fiscal_year"]
|
||||||
else:
|
)
|
||||||
dimensions = get_cost_centers(filters)
|
cam_map = get_dimension_account_month_map(filters)
|
||||||
|
|
||||||
period_month_ranges = get_period_month_ranges(
|
data = []
|
||||||
filters["period"], filters["from_fiscal_year"]
|
for dimension in dimensions:
|
||||||
)
|
dimension_items = cam_map.get(dimension)
|
||||||
|
if dimension_items:
|
||||||
|
for account, monthwise_data in iteritems(dimension_items):
|
||||||
|
row = [dimension, account]
|
||||||
|
totals = [0, 0, 0]
|
||||||
|
for year in get_fiscal_years(filters):
|
||||||
|
last_total = 0
|
||||||
|
for relevant_months in period_month_ranges:
|
||||||
|
period_data = [0, 0, 0]
|
||||||
|
for month in relevant_months:
|
||||||
|
if monthwise_data.get(year[0]):
|
||||||
|
month_data = monthwise_data.get(year[0]).get(month, {})
|
||||||
|
for i, fieldname in enumerate(
|
||||||
|
["target", "actual", "variance"]
|
||||||
|
):
|
||||||
|
value = flt(month_data.get(fieldname))
|
||||||
|
period_data[i] += value
|
||||||
|
totals[i] += value
|
||||||
|
|
||||||
cam_map = get_dimension_account_month_map(filters)
|
period_data[0] += last_total
|
||||||
|
|
||||||
data = []
|
if filters.get("show_cumulative"):
|
||||||
for dimension in dimensions:
|
last_total = period_data[0] - period_data[1]
|
||||||
dimension_items = cam_map.get(dimension)
|
|
||||||
if dimension_items:
|
|
||||||
for account, monthwise_data in iteritems(dimension_items):
|
|
||||||
row = [dimension, account]
|
|
||||||
totals = [0, 0, 0]
|
|
||||||
for year in get_fiscal_years(filters):
|
|
||||||
last_total = 0
|
|
||||||
for relevant_months in period_month_ranges:
|
|
||||||
period_data = [0, 0, 0]
|
|
||||||
for month in relevant_months:
|
|
||||||
if monthwise_data.get(year[0]):
|
|
||||||
month_data = monthwise_data.get(year[0]).get(month, {})
|
|
||||||
for i, fieldname in enumerate(
|
|
||||||
["target", "actual", "variance"]
|
|
||||||
):
|
|
||||||
value = flt(month_data.get(fieldname))
|
|
||||||
period_data[i] += value
|
|
||||||
totals[i] += value
|
|
||||||
|
|
||||||
period_data[0] += last_total
|
period_data[2] = period_data[0] - period_data[1]
|
||||||
|
row += period_data
|
||||||
|
totals[2] = totals[0] - totals[1]
|
||||||
|
if filters["period"] != "Yearly":
|
||||||
|
row += totals
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
if filters.get("show_cumulative"):
|
return columns, data
|
||||||
last_total = period_data[0] - period_data[1]
|
|
||||||
|
|
||||||
period_data[2] = period_data[0] - period_data[1]
|
|
||||||
row += period_data
|
|
||||||
totals[2] = totals[0] - totals[1]
|
|
||||||
if filters["period"] != "Yearly":
|
|
||||||
row += totals
|
|
||||||
data.append(row)
|
|
||||||
|
|
||||||
return columns, data
|
|
||||||
|
|
||||||
|
|
||||||
def get_columns(filters):
|
def get_columns(filters):
|
||||||
columns = [
|
columns = [
|
||||||
_(filters.get("budget_against"))
|
_(filters.get("budget_against"))
|
||||||
+ ":Link/%s:150" % (filters.get("budget_against")),
|
+ ":Link/%s:150" % (filters.get("budget_against")),
|
||||||
_("Account") + ":Link/Account:150",
|
_("Account") + ":Link/Account:150",
|
||||||
]
|
]
|
||||||
|
|
||||||
group_months = False if filters["period"] == "Monthly" else True
|
group_months = False if filters["period"] == "Monthly" else True
|
||||||
|
|
||||||
fiscal_year = get_fiscal_years(filters)
|
fiscal_year = get_fiscal_years(filters)
|
||||||
|
|
||||||
for year in fiscal_year:
|
for year in fiscal_year:
|
||||||
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
|
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
|
||||||
if filters["period"] == "Yearly":
|
if filters["period"] == "Yearly":
|
||||||
labels = [
|
labels = [
|
||||||
_("Budget") + " " + str(year[0]),
|
_("Budget") + " " + str(year[0]),
|
||||||
_("Actual ") + " " + str(year[0]),
|
_("Actual ") + " " + str(year[0]),
|
||||||
_("Variance ") + " " + str(year[0]),
|
_("Variance ") + " " + str(year[0]),
|
||||||
]
|
]
|
||||||
for label in labels:
|
for label in labels:
|
||||||
columns.append(label + ":Float:150")
|
columns.append(label + ":Float:150")
|
||||||
else:
|
else:
|
||||||
for label in [
|
for label in [
|
||||||
_("Budget") + " (%s)" + " " + str(year[0]),
|
_("Budget") + " (%s)" + " " + str(year[0]),
|
||||||
_("Actual") + " (%s)" + " " + str(year[0]),
|
_("Actual") + " (%s)" + " " + str(year[0]),
|
||||||
_("Variance") + " (%s)" + " " + str(year[0]),
|
_("Variance") + " (%s)" + " " + str(year[0]),
|
||||||
]:
|
]:
|
||||||
if group_months:
|
if group_months:
|
||||||
label = label % (
|
label = label % (
|
||||||
formatdate(from_date, format_string="MMM")
|
formatdate(from_date, format_string="MMM")
|
||||||
+ "-"
|
+ "-"
|
||||||
+ formatdate(to_date, format_string="MMM")
|
+ formatdate(to_date, format_string="MMM")
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
label = label % formatdate(from_date, format_string="MMM")
|
label = label % formatdate(from_date, format_string="MMM")
|
||||||
|
|
||||||
columns.append(label + ":Float:150")
|
columns.append(label + ":Float:150")
|
||||||
|
|
||||||
if filters["period"] != "Yearly":
|
if filters["period"] != "Yearly":
|
||||||
return columns + [
|
return columns + [
|
||||||
_("Total Budget") + ":Float:150",
|
_("Total Budget") + ":Float:150",
|
||||||
_("Total Actual") + ":Float:150",
|
_("Total Actual") + ":Float:150",
|
||||||
_("Total Variance") + ":Float:150",
|
_("Total Variance") + ":Float:150",
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
|
|
||||||
def get_cost_centers(filters):
|
def get_cost_centers(filters):
|
||||||
order_by = ""
|
order_by = ""
|
||||||
if filters.get("budget_against") == "Cost Center":
|
if filters.get("budget_against") == "Cost Center":
|
||||||
order_by = "order by lft"
|
order_by = "order by lft"
|
||||||
|
|
||||||
if filters.get("budget_against") in ["Cost Center", "Project"]:
|
if filters.get("budget_against") in ["Cost Center", "Project"]:
|
||||||
return frappe.db.sql_list(
|
return frappe.db.sql_list(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
name
|
name
|
||||||
from
|
from
|
||||||
`tab{tab}`
|
`tab{tab}`
|
||||||
where
|
where
|
||||||
company=%s
|
company = %s
|
||||||
{order_by}
|
{order_by}
|
||||||
""".format(
|
""".format(
|
||||||
tab=filters.get("budget_against"), order_by=order_by
|
tab=filters.get("budget_against"), order_by=order_by
|
||||||
),
|
),
|
||||||
filters.get("company"),
|
filters.get("company"),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return frappe.db.sql_list(
|
return frappe.db.sql_list(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
name
|
name
|
||||||
from
|
from
|
||||||
`tab{tab}`
|
`tab{tab}`
|
||||||
""".format(
|
""".format(
|
||||||
tab=filters.get("budget_against")
|
tab=filters.get("budget_against")
|
||||||
)
|
)
|
||||||
) # nosec
|
) # nosec
|
||||||
|
|
||||||
|
|
||||||
# Get dimension & target details
|
# Get dimension & target details
|
||||||
def get_dimension_target_details(filters):
|
def get_dimension_target_details(filters):
|
||||||
budget_against = frappe.scrub(filters.get("budget_against"))
|
budget_against = frappe.scrub(filters.get("budget_against"))
|
||||||
|
cond = ""
|
||||||
|
if filters.get("budget_against_filter"):
|
||||||
|
cond += """
|
||||||
|
and
|
||||||
|
b.{budget_against} in (
|
||||||
|
%s
|
||||||
|
)
|
||||||
|
""".format(
|
||||||
|
budget_against=budget_against
|
||||||
|
) % ", ".join(["%s"] * len(filters.get("budget_against_filter")))
|
||||||
|
|
||||||
cond = ""
|
return frappe.db.sql(
|
||||||
if filters.get("budget_against_filter"):
|
"""
|
||||||
cond += """
|
select
|
||||||
and
|
b.{budget_against} as budget_against,
|
||||||
b.{budget_against} in (
|
b.monthly_distribution,
|
||||||
%s
|
ba.account,
|
||||||
)
|
ba.budget_amount,
|
||||||
""".format(
|
b.fiscal_year
|
||||||
budget_against=budget_against
|
|
||||||
) % ", ".join(
|
|
||||||
["%s"] * len(filters.get("budget_against_filter"))
|
|
||||||
)
|
|
||||||
|
|
||||||
return frappe.db.sql(
|
|
||||||
"""
|
|
||||||
select distinct
|
|
||||||
b.{budget_against} as name
|
|
||||||
from
|
from
|
||||||
`tabBudget` b
|
`tabBudget` b,
|
||||||
|
`tabBudget Account` ba
|
||||||
where
|
where
|
||||||
b.docstatus = 1
|
b.name = ba.parent
|
||||||
|
and b.docstatus = 1
|
||||||
and b.fiscal_year between %s and %s
|
and b.fiscal_year between %s and %s
|
||||||
and b.budget_against = %s
|
and b.budget_against = %s
|
||||||
and b.company = %s
|
and b.company = %s
|
||||||
@ -178,65 +179,66 @@ def get_dimension_target_details(filters):
|
|||||||
order by
|
order by
|
||||||
b.fiscal_year
|
b.fiscal_year
|
||||||
""".format(
|
""".format(
|
||||||
budget_against=budget_against, cond=cond
|
budget_against=budget_against,
|
||||||
),
|
cond=cond,
|
||||||
tuple(
|
),
|
||||||
[
|
tuple(
|
||||||
filters.from_fiscal_year,
|
[
|
||||||
filters.to_fiscal_year,
|
filters.from_fiscal_year,
|
||||||
filters.budget_against,
|
filters.to_fiscal_year,
|
||||||
filters.company,
|
filters.budget_against,
|
||||||
]
|
filters.company,
|
||||||
+ filters.get("budget_against_filter")
|
]
|
||||||
),
|
+ filters.get("budget_against_filter")
|
||||||
as_dict=True,
|
),
|
||||||
)
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Get target distribution details of accounts of cost center
|
# Get target distribution details of accounts of cost center
|
||||||
def get_target_distribution_details(filters):
|
def get_target_distribution_details(filters):
|
||||||
target_details = {}
|
target_details = {}
|
||||||
for d in frappe.db.sql(
|
for d in frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
md.name,
|
md.name,
|
||||||
mdp.month,
|
mdp.month,
|
||||||
mdp.percentage_allocation
|
mdp.percentage_allocation
|
||||||
from
|
from
|
||||||
`tabMonthly Distribution Percentage` mdp,
|
`tabMonthly Distribution Percentage` mdp,
|
||||||
`tabMonthly Distribution` md
|
`tabMonthly Distribution` md
|
||||||
where
|
where
|
||||||
mdp.parent = md.name
|
mdp.parent = md.name
|
||||||
and md.fiscal_year between %s
|
and md.fiscal_year between %s and %s
|
||||||
and %s
|
order by
|
||||||
order by md.fiscal_year
|
md.fiscal_year
|
||||||
""",
|
""",
|
||||||
(filters.from_fiscal_year, filters.to_fiscal_year),
|
(filters.from_fiscal_year, filters.to_fiscal_year),
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
):
|
):
|
||||||
target_details.setdefault(d.name, {}).setdefault(
|
target_details.setdefault(d.name, {}).setdefault(
|
||||||
d.month, flt(d.percentage_allocation)
|
d.month, flt(d.percentage_allocation)
|
||||||
)
|
)
|
||||||
|
|
||||||
return target_details
|
return target_details
|
||||||
|
|
||||||
|
|
||||||
# Get actual details from gl entry
|
# Get actual details from gl entry
|
||||||
def get_actual_details(name, filters):
|
def get_actual_details(name, filters):
|
||||||
budget_against = frappe.scrub(filters.get("budget_against"))
|
budget_against = frappe.scrub(filters.get("budget_against"))
|
||||||
|
|
||||||
cond = ""
|
cond = ""
|
||||||
if filters.get("budget_against") == "Cost Center":
|
if filters.get("budget_against") == "Cost Center":
|
||||||
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
|
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
|
||||||
cond = """
|
cond = """
|
||||||
and lft >= \'{lft}\'
|
and lft >= "{lft}"
|
||||||
and rgt <= \'{rgt}\'
|
and rgt <= "{rgt}"
|
||||||
""".format(
|
""".format(
|
||||||
lft=cc_lft, rgt=cc_rgt
|
lft=cc_lft, rgt=cc_rgt
|
||||||
)
|
)
|
||||||
|
|
||||||
ac_details = frappe.db.sql(
|
ac_details = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
gl.account,
|
gl.account,
|
||||||
gl.debit,
|
gl.debit,
|
||||||
@ -268,65 +270,56 @@ def get_actual_details(name, filters):
|
|||||||
gl.name
|
gl.name
|
||||||
order by gl.fiscal_year
|
order by gl.fiscal_year
|
||||||
""".format(
|
""".format(
|
||||||
tab=filters.budget_against, budget_against=budget_against, cond=cond
|
tab=filters.budget_against, budget_against=budget_against, cond=cond
|
||||||
),
|
),
|
||||||
(filters.from_fiscal_year, filters.to_fiscal_year, name),
|
(filters.from_fiscal_year, filters.to_fiscal_year, name),
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_actual_details = {}
|
cc_actual_details = {}
|
||||||
for d in ac_details:
|
for d in ac_details:
|
||||||
cc_actual_details.setdefault(d.account, []).append(d)
|
cc_actual_details.setdefault(d.account, []).append(d)
|
||||||
|
|
||||||
return cc_actual_details
|
return cc_actual_details
|
||||||
|
|
||||||
|
|
||||||
def get_dimension_account_month_map(filters):
|
def get_dimension_account_month_map(filters):
|
||||||
dimension_target_details = get_dimension_target_details(filters)
|
dimension_target_details = get_dimension_target_details(filters)
|
||||||
tdd = get_target_distribution_details(filters)
|
tdd = get_target_distribution_details(filters)
|
||||||
|
|
||||||
cam_map = {}
|
cam_map = {}
|
||||||
|
|
||||||
for ccd in dimension_target_details:
|
for ccd in dimension_target_details:
|
||||||
accounts = get_accounts(ccd.name, filters)
|
actual_details = get_actual_details(ccd.budget_against, filters)
|
||||||
actual_details = get_actual_details(ccd.name, filters)
|
|
||||||
|
|
||||||
for year in get_fiscal_years(filters):
|
for month_id in range(1, 13):
|
||||||
year = year[0]
|
month = datetime.date(2013, month_id, 1).strftime("%B")
|
||||||
monthly_distribution = get_monthly_distribution(ccd.name, year, filters)
|
cam_map.setdefault(ccd.budget_against, {}).setdefault(
|
||||||
for month_id in range(1, 13):
|
ccd.account, {}
|
||||||
month = datetime.date(2013, month_id, 1).strftime(
|
).setdefault(ccd.fiscal_year, {}).setdefault(
|
||||||
"%B"
|
month, frappe._dict({"target": 0.0, "actual": 0.0})
|
||||||
) # Get month string
|
)
|
||||||
|
|
||||||
for account in accounts:
|
tav_dict = cam_map[ccd.budget_against][ccd.account][ccd.fiscal_year][month]
|
||||||
account = account[0]
|
month_percentage = (
|
||||||
cam_map.setdefault(ccd.name, {}).setdefault(account, {}).setdefault(
|
tdd.get(ccd.monthly_distribution, {}).get(month, 0)
|
||||||
year, {}
|
if ccd.monthly_distribution
|
||||||
).setdefault(month, frappe._dict({"target": 0.0, "actual": 0.0}))
|
else 100.0 / 12
|
||||||
|
)
|
||||||
|
|
||||||
tav_dict = cam_map[ccd.name][account][year][month]
|
tav_dict.target = flt(ccd.budget_amount) * month_percentage / 100
|
||||||
|
|
||||||
month_percentage = (
|
for ad in actual_details.get(ccd.account, []):
|
||||||
tdd.get(monthly_distribution, {}).get(month, 0)
|
if ad.month_name == month and ad.fiscal_year == ccd.fiscal_year:
|
||||||
if monthly_distribution
|
tav_dict.actual += flt(ad.debit) - flt(ad.credit)
|
||||||
else 100.0 / 12
|
|
||||||
)
|
|
||||||
|
|
||||||
budget_amount = get_budget_amount(ccd.name, year, account, filters)
|
return cam_map
|
||||||
|
|
||||||
tav_dict.target = flt(budget_amount) * month_percentage / 100
|
|
||||||
|
|
||||||
for ad in actual_details.get(account, []):
|
|
||||||
if ad.month_name == month and ad.fiscal_year == year:
|
|
||||||
tav_dict.actual += flt(ad.debit) - flt(ad.credit)
|
|
||||||
return cam_map
|
|
||||||
|
|
||||||
|
|
||||||
def get_fiscal_years(filters):
|
def get_fiscal_years(filters):
|
||||||
|
|
||||||
fiscal_year = frappe.db.sql(
|
fiscal_year = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
name
|
name
|
||||||
from
|
from
|
||||||
@ -336,85 +329,10 @@ def get_fiscal_years(filters):
|
|||||||
order by
|
order by
|
||||||
year
|
year
|
||||||
""",
|
""",
|
||||||
{
|
{
|
||||||
"from_fiscal_year": filters["from_fiscal_year"],
|
"from_fiscal_year": filters["from_fiscal_year"],
|
||||||
"to_fiscal_year": filters["to_fiscal_year"],
|
"to_fiscal_year": filters["to_fiscal_year"],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return fiscal_year
|
return fiscal_year
|
||||||
|
|
||||||
|
|
||||||
def get_accounts(name, filters):
|
|
||||||
budget_against = frappe.scrub(filters.get("budget_against"))
|
|
||||||
|
|
||||||
accounts = frappe.db.sql(
|
|
||||||
"""
|
|
||||||
select
|
|
||||||
distinct(ba.account)
|
|
||||||
from
|
|
||||||
`tabBudget Account` ba
|
|
||||||
join
|
|
||||||
`tabBudget` b
|
|
||||||
on b.name = ba.parent
|
|
||||||
where
|
|
||||||
b.docstatus = 1
|
|
||||||
and b.fiscal_year between %s and %s
|
|
||||||
and b.{budget_against} = %s
|
|
||||||
order by
|
|
||||||
ba.account
|
|
||||||
""".format(
|
|
||||||
budget_against=budget_against
|
|
||||||
),
|
|
||||||
(filters.from_fiscal_year, filters.to_fiscal_year, name),
|
|
||||||
)
|
|
||||||
|
|
||||||
return accounts
|
|
||||||
|
|
||||||
|
|
||||||
def get_monthly_distribution(name, year, filters):
|
|
||||||
budget_against = frappe.scrub(filters.get("budget_against"))
|
|
||||||
|
|
||||||
monthly_distribution = frappe.db.sql(
|
|
||||||
"""
|
|
||||||
select
|
|
||||||
monthly_distribution
|
|
||||||
from
|
|
||||||
`tabBudget`
|
|
||||||
where
|
|
||||||
docstatus = 1
|
|
||||||
and {budget_against} = %s
|
|
||||||
and fiscal_year = %s
|
|
||||||
""".format(
|
|
||||||
budget_against=budget_against
|
|
||||||
),
|
|
||||||
(name, year),
|
|
||||||
)
|
|
||||||
|
|
||||||
return monthly_distribution[0][0] if monthly_distribution else None
|
|
||||||
|
|
||||||
|
|
||||||
def get_budget_amount(name, year, account, filters):
|
|
||||||
budget_against = frappe.scrub(filters.get("budget_against"))
|
|
||||||
|
|
||||||
budget_amount = frappe.db.sql(
|
|
||||||
"""
|
|
||||||
select
|
|
||||||
ba.budget_amount
|
|
||||||
from
|
|
||||||
`tabBudget Account` ba
|
|
||||||
join
|
|
||||||
`tabBudget` b
|
|
||||||
on b.name = ba.parent
|
|
||||||
where
|
|
||||||
b.docstatus = 1
|
|
||||||
and b.{budget_against} = %s
|
|
||||||
and b.fiscal_year = %s
|
|
||||||
and ba.account = %s
|
|
||||||
""".format(
|
|
||||||
budget_against=budget_against
|
|
||||||
),
|
|
||||||
(name, year, account),
|
|
||||||
)
|
|
||||||
|
|
||||||
return budget_amount[0][0] if budget_amount else 0
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user