Merge pull request #44409 from frappe/mergify/bp/version-14-hotfix/pr-44195
fix: Data Should be Computed in Backend to Maintain Consistent Behaviour (backport #44195)
This commit is contained in:
@@ -7,6 +7,7 @@ from frappe import _
|
|||||||
from frappe.utils import cint, flt
|
from frappe.utils import cint, flt
|
||||||
|
|
||||||
from erpnext.accounts.report.financial_statements import (
|
from erpnext.accounts.report.financial_statements import (
|
||||||
|
compute_growth_view_data,
|
||||||
get_columns,
|
get_columns,
|
||||||
get_data,
|
get_data,
|
||||||
get_filtered_list_for_consolidated_report,
|
get_filtered_list_for_consolidated_report,
|
||||||
@@ -101,6 +102,9 @@ def execute(filters=None):
|
|||||||
period_list, asset, liability, equity, provisional_profit_loss, currency, filters
|
period_list, asset, liability, equity, provisional_profit_loss, currency, filters
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if filters.get("selected_view") == "Growth":
|
||||||
|
compute_growth_view_data(data, period_list)
|
||||||
|
|
||||||
return columns, data, message, chart, report_summary, primitive_summary
|
return columns, data, message, chart, report_summary, primitive_summary
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
|
import copy
|
||||||
import functools
|
import functools
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
@@ -653,3 +654,67 @@ def get_filtered_list_for_consolidated_report(filters, period_list):
|
|||||||
filtered_summary_list.append(period)
|
filtered_summary_list.append(period)
|
||||||
|
|
||||||
return filtered_summary_list
|
return filtered_summary_list
|
||||||
|
|
||||||
|
|
||||||
|
def compute_growth_view_data(data, columns):
|
||||||
|
data_copy = copy.deepcopy(data)
|
||||||
|
|
||||||
|
for row_idx in range(len(data_copy)):
|
||||||
|
for column_idx in range(1, len(columns)):
|
||||||
|
previous_period_key = columns[column_idx - 1].get("key")
|
||||||
|
current_period_key = columns[column_idx].get("key")
|
||||||
|
current_period_value = data_copy[row_idx].get(current_period_key)
|
||||||
|
previous_period_value = data_copy[row_idx].get(previous_period_key)
|
||||||
|
annual_growth = 0
|
||||||
|
|
||||||
|
if current_period_value is None:
|
||||||
|
data[row_idx][current_period_key] = None
|
||||||
|
continue
|
||||||
|
|
||||||
|
if previous_period_value == 0 and current_period_value > 0:
|
||||||
|
annual_growth = 1
|
||||||
|
|
||||||
|
elif previous_period_value > 0:
|
||||||
|
annual_growth = (current_period_value - previous_period_value) / previous_period_value
|
||||||
|
|
||||||
|
growth_percent = round(annual_growth * 100, 2)
|
||||||
|
|
||||||
|
data[row_idx][current_period_key] = growth_percent
|
||||||
|
|
||||||
|
|
||||||
|
def compute_margin_view_data(data, columns, accumulated_values):
|
||||||
|
if not columns:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not accumulated_values:
|
||||||
|
columns.append({"key": "total"})
|
||||||
|
|
||||||
|
data_copy = copy.deepcopy(data)
|
||||||
|
|
||||||
|
base_row = None
|
||||||
|
for row in data_copy:
|
||||||
|
if row.get("account_name") == _("Income"):
|
||||||
|
base_row = row
|
||||||
|
break
|
||||||
|
|
||||||
|
if not base_row:
|
||||||
|
return
|
||||||
|
|
||||||
|
for row_idx in range(len(data_copy)):
|
||||||
|
# Taking the total income from each column (for all the financial years) as the base (100%)
|
||||||
|
row = data_copy[row_idx]
|
||||||
|
if not row:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for column in columns:
|
||||||
|
curr_period = column.get("key")
|
||||||
|
base_value = base_row[curr_period]
|
||||||
|
curr_value = row[curr_period]
|
||||||
|
|
||||||
|
if curr_value is None or base_value <= 0:
|
||||||
|
data[row_idx][curr_period] = None
|
||||||
|
continue
|
||||||
|
|
||||||
|
margin_percent = round((curr_value / base_value) * 100, 2)
|
||||||
|
|
||||||
|
data[row_idx][curr_period] = margin_percent
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ from frappe import _
|
|||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
|
|
||||||
from erpnext.accounts.report.financial_statements import (
|
from erpnext.accounts.report.financial_statements import (
|
||||||
|
compute_growth_view_data,
|
||||||
|
compute_margin_view_data,
|
||||||
get_columns,
|
get_columns,
|
||||||
get_data,
|
get_data,
|
||||||
get_filtered_list_for_consolidated_report,
|
get_filtered_list_for_consolidated_report,
|
||||||
@@ -68,6 +70,12 @@ def execute(filters=None):
|
|||||||
period_list, filters.periodicity, income, expense, net_profit_loss, currency, filters
|
period_list, filters.periodicity, income, expense, net_profit_loss, currency, filters
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if filters.get("selected_view") == "Growth":
|
||||||
|
compute_growth_view_data(data, period_list)
|
||||||
|
|
||||||
|
if filters.get("selected_view") == "Margin":
|
||||||
|
compute_margin_view_data(data, period_list, filters.accumulated_values)
|
||||||
|
|
||||||
return columns, data, None, chart, report_summary, primitive_summary
|
return columns, data, None, chart, report_summary, primitive_summary
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,40 +9,29 @@ erpnext.financial_statements = {
|
|||||||
data &&
|
data &&
|
||||||
column.colIndex >= 3
|
column.colIndex >= 3
|
||||||
) {
|
) {
|
||||||
//Assuming that the first three columns are s.no, account name and the very first year of the accounting values, to calculate the relative percentage values of the successive columns.
|
const growthPercent = data[column.fieldname];
|
||||||
const lastAnnualValue = row[column.colIndex - 1].content;
|
|
||||||
const currentAnnualvalue = data[column.fieldname];
|
|
||||||
if (currentAnnualvalue == undefined) return "NA"; //making this not applicable for undefined/null values
|
|
||||||
let annualGrowth = 0;
|
|
||||||
if (lastAnnualValue == 0 && currentAnnualvalue > 0) {
|
|
||||||
//If the previous year value is 0 and the current value is greater than 0
|
|
||||||
annualGrowth = 1;
|
|
||||||
} else if (lastAnnualValue > 0) {
|
|
||||||
annualGrowth = (currentAnnualvalue - lastAnnualValue) / lastAnnualValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const growthPercent = Math.round(annualGrowth * 10000) / 100; //calculating the rounded off percentage
|
if (growthPercent == undefined) return "NA"; //making this not applicable for undefined/null values
|
||||||
|
|
||||||
value = $(`<span>${(growthPercent >= 0 ? "+" : "") + growthPercent + "%"}</span>`);
|
if (column.fieldname === "total") {
|
||||||
if (growthPercent < 0) {
|
value = $(`<span>${growthPercent}</span>`);
|
||||||
value = $(value).addClass("text-danger");
|
|
||||||
} else {
|
} else {
|
||||||
value = $(value).addClass("text-success");
|
value = $(`<span>${(growthPercent >= 0 ? "+" : "") + growthPercent + "%"}</span>`);
|
||||||
|
|
||||||
|
if (growthPercent < 0) {
|
||||||
|
value = $(value).addClass("text-danger");
|
||||||
|
} else {
|
||||||
|
value = $(value).addClass("text-success");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
value = $(value).wrap("<p></p>").parent().html();
|
value = $(value).wrap("<p></p>").parent().html();
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
} else if (frappe.query_report.get_filter_value("selected_view") == "Margin" && data) {
|
} else if (frappe.query_report.get_filter_value("selected_view") == "Margin" && data) {
|
||||||
if (column.fieldname == "account" && data.account_name == __("Income")) {
|
|
||||||
//Taking the total income from each column (for all the financial years) as the base (100%)
|
|
||||||
this.baseData = row;
|
|
||||||
}
|
|
||||||
if (column.colIndex >= 2) {
|
if (column.colIndex >= 2) {
|
||||||
//Assuming that the first two columns are s.no and account name, to calculate the relative percentage values of the successive columns.
|
const marginPercent = data[column.fieldname];
|
||||||
const currentAnnualvalue = data[column.fieldname];
|
|
||||||
const baseValue = this.baseData[column.colIndex].content;
|
if (marginPercent == undefined) return "NA"; //making this not applicable for undefined/null values
|
||||||
if (currentAnnualvalue == undefined || baseValue <= 0) return "NA";
|
|
||||||
const marginPercent = Math.round((currentAnnualvalue / baseValue) * 10000) / 100;
|
|
||||||
|
|
||||||
value = $(`<span>${marginPercent + "%"}</span>`);
|
value = $(`<span>${marginPercent + "%"}</span>`);
|
||||||
if (marginPercent < 0) value = $(value).addClass("text-danger");
|
if (marginPercent < 0) value = $(value).addClass("text-danger");
|
||||||
|
|||||||
Reference in New Issue
Block a user