mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-15 11:09:17 +00:00
feat: support custom financial statements (#49098)
Co-authored-by: Abdeali Chharchhoda <abdealiking786@gmail.com>
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
"account_currency",
|
"account_currency",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"parent_account",
|
"parent_account",
|
||||||
|
"account_category",
|
||||||
"account_type",
|
"account_type",
|
||||||
"tax_rate",
|
"tax_rate",
|
||||||
"freeze_account",
|
"freeze_account",
|
||||||
@@ -189,13 +190,20 @@
|
|||||||
"fieldname": "disabled",
|
"fieldname": "disabled",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Disable"
|
"label": "Disable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Used with Financial Report Template",
|
||||||
|
"fieldname": "account_category",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Account Category",
|
||||||
|
"options": "Account Category"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-money",
|
"icon": "fa fa-money",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-01-22 10:40:35.766017",
|
"modified": "2025-08-02 06:26:44.657146",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Account",
|
"name": "Account",
|
||||||
@@ -250,6 +258,7 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"row_format": "Dynamic",
|
||||||
"search_fields": "account_number",
|
"search_fields": "account_number",
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"show_preview_popup": 1,
|
"show_preview_popup": 1,
|
||||||
@@ -257,4 +266,4 @@
|
|||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class Account(NestedSet):
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
|
account_category: DF.Link | None
|
||||||
account_currency: DF.Link | None
|
account_currency: DF.Link | None
|
||||||
account_name: DF.Data
|
account_name: DF.Data
|
||||||
account_number: DF.Data | None
|
account_number: DF.Data | None
|
||||||
|
|||||||
@@ -23,15 +23,7 @@ def create_charts(
|
|||||||
if root_account:
|
if root_account:
|
||||||
root_type = child.get("root_type")
|
root_type = child.get("root_type")
|
||||||
|
|
||||||
if account_name not in [
|
if account_name not in get_chart_metadata_fields():
|
||||||
"account_name",
|
|
||||||
"account_number",
|
|
||||||
"account_type",
|
|
||||||
"root_type",
|
|
||||||
"is_group",
|
|
||||||
"tax_rate",
|
|
||||||
"account_currency",
|
|
||||||
]:
|
|
||||||
account_number = cstr(child.get("account_number")).strip()
|
account_number = cstr(child.get("account_number")).strip()
|
||||||
account_name, account_name_in_db = add_suffix_if_duplicate(
|
account_name, account_name_in_db = add_suffix_if_duplicate(
|
||||||
account_name, account_number, accounts
|
account_name, account_number, accounts
|
||||||
@@ -55,6 +47,7 @@ def create_charts(
|
|||||||
"report_type": report_type,
|
"report_type": report_type,
|
||||||
"account_number": account_number,
|
"account_number": account_number,
|
||||||
"account_type": child.get("account_type"),
|
"account_type": child.get("account_type"),
|
||||||
|
"account_category": child.get("account_category"),
|
||||||
"account_currency": child.get("account_currency")
|
"account_currency": child.get("account_currency")
|
||||||
if custom_chart
|
if custom_chart
|
||||||
else frappe.get_cached_value("Company", company, "default_currency"),
|
else frappe.get_cached_value("Company", company, "default_currency"),
|
||||||
@@ -97,20 +90,7 @@ def add_suffix_if_duplicate(account_name, account_number, accounts):
|
|||||||
def identify_is_group(child):
|
def identify_is_group(child):
|
||||||
if child.get("is_group"):
|
if child.get("is_group"):
|
||||||
is_group = child.get("is_group")
|
is_group = child.get("is_group")
|
||||||
elif len(
|
elif len(set(child.keys()) - set(get_chart_metadata_fields())):
|
||||||
set(child.keys())
|
|
||||||
- set(
|
|
||||||
[
|
|
||||||
"account_name",
|
|
||||||
"account_type",
|
|
||||||
"root_type",
|
|
||||||
"is_group",
|
|
||||||
"tax_rate",
|
|
||||||
"account_number",
|
|
||||||
"account_currency",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
):
|
|
||||||
is_group = 1
|
is_group = 1
|
||||||
else:
|
else:
|
||||||
is_group = 0
|
is_group = 0
|
||||||
@@ -253,13 +233,7 @@ def validate_bank_account(coa, bank_account):
|
|||||||
|
|
||||||
def _get_account_names(account_master):
|
def _get_account_names(account_master):
|
||||||
for account_name, child in account_master.items():
|
for account_name, child in account_master.items():
|
||||||
if account_name not in [
|
if account_name not in get_chart_metadata_fields():
|
||||||
"account_number",
|
|
||||||
"account_type",
|
|
||||||
"root_type",
|
|
||||||
"is_group",
|
|
||||||
"tax_rate",
|
|
||||||
]:
|
|
||||||
accounts.append(account_name)
|
accounts.append(account_name)
|
||||||
|
|
||||||
_get_account_names(child)
|
_get_account_names(child)
|
||||||
@@ -284,15 +258,7 @@ def build_tree_from_json(chart_template, chart_data=None, from_coa_importer=Fals
|
|||||||
"""recursively called to form a parent-child based list of dict from chart template"""
|
"""recursively called to form a parent-child based list of dict from chart template"""
|
||||||
for account_name, child in children.items():
|
for account_name, child in children.items():
|
||||||
account = {}
|
account = {}
|
||||||
if account_name in [
|
if account_name in get_chart_metadata_fields():
|
||||||
"account_name",
|
|
||||||
"account_number",
|
|
||||||
"account_type",
|
|
||||||
"root_type",
|
|
||||||
"is_group",
|
|
||||||
"tax_rate",
|
|
||||||
"account_currency",
|
|
||||||
]:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if from_coa_importer:
|
if from_coa_importer:
|
||||||
@@ -310,3 +276,16 @@ def build_tree_from_json(chart_template, chart_data=None, from_coa_importer=Fals
|
|||||||
|
|
||||||
_import_accounts(chart, None)
|
_import_accounts(chart, None)
|
||||||
return accounts
|
return accounts
|
||||||
|
|
||||||
|
|
||||||
|
def get_chart_metadata_fields():
|
||||||
|
return [
|
||||||
|
"account_name",
|
||||||
|
"account_number",
|
||||||
|
"account_type",
|
||||||
|
"account_category",
|
||||||
|
"root_type",
|
||||||
|
"is_group",
|
||||||
|
"tax_rate",
|
||||||
|
"account_currency",
|
||||||
|
]
|
||||||
|
|||||||
@@ -9,103 +9,192 @@ def get():
|
|||||||
return {
|
return {
|
||||||
_("Application of Funds (Assets)"): {
|
_("Application of Funds (Assets)"): {
|
||||||
_("Current Assets"): {
|
_("Current Assets"): {
|
||||||
_("Accounts Receivable"): {_("Debtors"): {"account_type": "Receivable"}},
|
_("Accounts Receivable"): {
|
||||||
_("Bank Accounts"): {"account_type": "Bank", "is_group": 1},
|
_("Debtors"): {"account_type": "Receivable", "account_category": "Trade Receivables"}
|
||||||
_("Cash In Hand"): {_("Cash"): {"account_type": "Cash"}, "account_type": "Cash"},
|
},
|
||||||
|
_("Bank Accounts"): {
|
||||||
|
"account_type": "Bank",
|
||||||
|
"is_group": 1,
|
||||||
|
"account_category": "Cash and Cash Equivalents",
|
||||||
|
},
|
||||||
|
_("Cash In Hand"): {
|
||||||
|
_("Cash"): {"account_type": "Cash", "account_category": "Cash and Cash Equivalents"},
|
||||||
|
"account_type": "Cash",
|
||||||
|
"account_category": "Cash and Cash Equivalents",
|
||||||
|
},
|
||||||
_("Loans and Advances (Assets)"): {
|
_("Loans and Advances (Assets)"): {
|
||||||
_("Employee Advances"): {"account_type": "Payable"},
|
_("Employee Advances"): {
|
||||||
|
"account_type": "Payable",
|
||||||
|
"account_category": "Other Receivables",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
_("Securities and Deposits"): {_("Earnest Money"): {}},
|
_("Securities and Deposits"): {
|
||||||
|
_("Earnest Money"): {"account_category": "Other Current Assets"}
|
||||||
|
},
|
||||||
|
_("Prepaid Expenses"): {"account_category": "Other Current Assets"},
|
||||||
|
_("Short-term Investments"): {"account_category": "Short-term Investments"},
|
||||||
_("Stock Assets"): {
|
_("Stock Assets"): {
|
||||||
_("Stock In Hand"): {"account_type": "Stock"},
|
_("Stock In Hand"): {"account_type": "Stock", "account_category": "Stock Assets"},
|
||||||
"account_type": "Stock",
|
"account_type": "Stock",
|
||||||
|
"account_category": "Stock Assets",
|
||||||
},
|
},
|
||||||
_("Tax Assets"): {"is_group": 1},
|
_("Tax Assets"): {"is_group": 1, "account_category": "Other Current Assets"},
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipment"): {"account_type": "Fixed Asset"},
|
_("Capital Equipment"): {
|
||||||
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
|
"account_type": "Fixed Asset",
|
||||||
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
|
"account_category": "Tangible Assets",
|
||||||
_("Office Equipment"): {"account_type": "Fixed Asset"},
|
},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
_("Electronic Equipment"): {
|
||||||
_("Buildings"): {"account_type": "Fixed Asset"},
|
"account_type": "Fixed Asset",
|
||||||
_("Software"): {"account_type": "Fixed Asset"},
|
"account_category": "Tangible Assets",
|
||||||
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
},
|
||||||
|
_("Furniture and Fixtures"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Office Equipment"): {"account_type": "Fixed Asset", "account_category": "Tangible Assets"},
|
||||||
|
_("Plants and Machineries"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Buildings"): {"account_type": "Fixed Asset", "account_category": "Tangible Assets"},
|
||||||
|
_("Software"): {"account_type": "Fixed Asset", "account_category": "Intangible Assets"},
|
||||||
|
_("Accumulated Depreciation"): {
|
||||||
|
"account_type": "Accumulated Depreciation",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
_("CWIP Account"): {
|
_("CWIP Account"): {
|
||||||
"account_type": "Capital Work in Progress",
|
"account_type": "Capital Work in Progress",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
_("Investments"): {"is_group": 1},
|
_("Investments"): {"is_group": 1, "account_category": "Long-term Investments"},
|
||||||
_("Temporary Accounts"): {_("Temporary Opening"): {"account_type": "Temporary"}},
|
_("Temporary Accounts"): {
|
||||||
|
_("Temporary Opening"): {
|
||||||
|
"account_type": "Temporary",
|
||||||
|
"account_category": "Other Non-current Assets",
|
||||||
|
}
|
||||||
|
},
|
||||||
"root_type": "Asset",
|
"root_type": "Asset",
|
||||||
},
|
},
|
||||||
_("Expenses"): {
|
_("Expenses"): {
|
||||||
_("Direct Expenses"): {
|
_("Direct Expenses"): {
|
||||||
_("Stock Expenses"): {
|
_("Stock Expenses"): {
|
||||||
_("Cost of Goods Sold"): {"account_type": "Cost of Goods Sold"},
|
_("Cost of Goods Sold"): {
|
||||||
_("Expenses Included In Asset Valuation"): {
|
"account_type": "Cost of Goods Sold",
|
||||||
"account_type": "Expenses Included In Asset Valuation"
|
"account_category": "Cost of Goods Sold",
|
||||||
|
},
|
||||||
|
_("Expenses Included In Asset Valuation"): {
|
||||||
|
"account_type": "Expenses Included In Asset Valuation",
|
||||||
|
"account_category": "Other Direct Costs",
|
||||||
|
},
|
||||||
|
_("Expenses Included In Valuation"): {
|
||||||
|
"account_type": "Expenses Included In Valuation",
|
||||||
|
"account_category": "Other Direct Costs",
|
||||||
|
},
|
||||||
|
_("Stock Adjustment"): {
|
||||||
|
"account_type": "Stock Adjustment",
|
||||||
|
"account_category": "Other Direct Costs",
|
||||||
},
|
},
|
||||||
_("Expenses Included In Valuation"): {"account_type": "Expenses Included In Valuation"},
|
|
||||||
_("Stock Adjustment"): {"account_type": "Stock Adjustment"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
_("Indirect Expenses"): {
|
_("Indirect Expenses"): {
|
||||||
_("Administrative Expenses"): {},
|
_("Administrative Expenses"): {"account_category": "Operating Expenses"},
|
||||||
_("Commission on Sales"): {},
|
_("Commission on Sales"): {"account_category": "Operating Expenses"},
|
||||||
_("Depreciation"): {"account_type": "Depreciation"},
|
_("Depreciation"): {"account_type": "Depreciation", "account_category": "Operating Expenses"},
|
||||||
_("Entertainment Expenses"): {},
|
_("Entertainment Expenses"): {"account_category": "Operating Expenses"},
|
||||||
_("Freight and Forwarding Charges"): {"account_type": "Chargeable"},
|
_("Freight and Forwarding Charges"): {
|
||||||
_("Legal Expenses"): {},
|
"account_type": "Chargeable",
|
||||||
_("Marketing Expenses"): {"account_type": "Chargeable"},
|
"account_category": "Operating Expenses",
|
||||||
_("Miscellaneous Expenses"): {"account_type": "Chargeable"},
|
},
|
||||||
_("Office Maintenance Expenses"): {},
|
_("Legal Expenses"): {"account_category": "Operating Expenses"},
|
||||||
_("Office Rent"): {},
|
_("Marketing Expenses"): {
|
||||||
_("Postal Expenses"): {},
|
"account_type": "Chargeable",
|
||||||
_("Print and Stationery"): {},
|
"account_category": "Operating Expenses",
|
||||||
_("Round Off"): {"account_type": "Round Off"},
|
},
|
||||||
_("Salary"): {},
|
_("Miscellaneous Expenses"): {
|
||||||
_("Sales Expenses"): {},
|
"account_type": "Chargeable",
|
||||||
_("Telephone Expenses"): {},
|
"account_category": "Operating Expenses",
|
||||||
_("Travel Expenses"): {},
|
},
|
||||||
_("Utility Expenses"): {},
|
_("Office Maintenance Expenses"): {"account_category": "Operating Expenses"},
|
||||||
_("Write Off"): {},
|
_("Office Rent"): {"account_category": "Operating Expenses"},
|
||||||
_("Exchange Gain/Loss"): {},
|
_("Postal Expenses"): {"account_category": "Operating Expenses"},
|
||||||
_("Gain/Loss on Asset Disposal"): {},
|
_("Print and Stationery"): {"account_category": "Operating Expenses"},
|
||||||
_("Impairment"): {},
|
_("Round Off"): {"account_type": "Round Off", "account_category": "Operating Expenses"},
|
||||||
|
_("Salary"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Sales Expenses"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Telephone Expenses"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Travel Expenses"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Utility Expenses"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Write Off"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Exchange Gain/Loss"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Interest Expense"): {"account_category": "Finance Costs"},
|
||||||
|
_("Bank Charges"): {"account_category": "Finance Costs"},
|
||||||
|
_("Gain/Loss on Asset Disposal"): {"account_category": "Other Operating Income"},
|
||||||
|
_("Impairment"): {"account_category": "Operating Expenses"},
|
||||||
|
_("Tax Expense"): {"account_category": "Tax Expense"},
|
||||||
},
|
},
|
||||||
"root_type": "Expense",
|
"root_type": "Expense",
|
||||||
},
|
},
|
||||||
_("Income"): {
|
_("Income"): {
|
||||||
_("Direct Income"): {_("Sales"): {}, _("Service"): {}},
|
_("Direct Income"): {
|
||||||
_("Indirect Income"): {"is_group": 1},
|
_("Sales"): {"account_category": "Revenue from Operations"},
|
||||||
|
_("Service"): {"account_category": "Revenue from Operations"},
|
||||||
|
},
|
||||||
|
_("Indirect Income"): {
|
||||||
|
_("Interest Income"): {"account_category": "Investment Income"},
|
||||||
|
_("Interest on Fixed Deposits"): {"account_category": "Investment Income"},
|
||||||
|
"is_group": 1,
|
||||||
|
},
|
||||||
"root_type": "Income",
|
"root_type": "Income",
|
||||||
},
|
},
|
||||||
_("Source of Funds (Liabilities)"): {
|
_("Source of Funds (Liabilities)"): {
|
||||||
_("Current Liabilities"): {
|
_("Current Liabilities"): {
|
||||||
_("Accounts Payable"): {
|
_("Accounts Payable"): {
|
||||||
_("Creditors"): {"account_type": "Payable"},
|
_("Creditors"): {"account_type": "Payable", "account_category": "Trade Payables"},
|
||||||
_("Payroll Payable"): {},
|
_("Payroll Payable"): {"account_category": "Other Payables"},
|
||||||
},
|
},
|
||||||
|
_("Accrued Expenses"): {"account_category": "Other Current Liabilities"},
|
||||||
|
_("Customer Advances"): {"account_category": "Other Current Liabilities"},
|
||||||
_("Stock Liabilities"): {
|
_("Stock Liabilities"): {
|
||||||
_("Stock Received But Not Billed"): {"account_type": "Stock Received But Not Billed"},
|
_("Stock Received But Not Billed"): {
|
||||||
_("Asset Received But Not Billed"): {"account_type": "Asset Received But Not Billed"},
|
"account_type": "Stock Received But Not Billed",
|
||||||
|
"account_category": "Trade Payables",
|
||||||
|
},
|
||||||
|
_("Asset Received But Not Billed"): {
|
||||||
|
"account_type": "Asset Received But Not Billed",
|
||||||
|
"account_category": "Trade Payables",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
_("Duties and Taxes"): {"account_type": "Tax", "is_group": 1},
|
_("Duties and Taxes"): {
|
||||||
|
"account_type": "Tax",
|
||||||
|
"is_group": 1,
|
||||||
|
"account_category": "Current Tax Liabilities",
|
||||||
|
},
|
||||||
|
_("Short-term Provisions"): {"account_category": "Short-term Provisions"},
|
||||||
_("Loans (Liabilities)"): {
|
_("Loans (Liabilities)"): {
|
||||||
_("Secured Loans"): {},
|
_("Secured Loans"): {"account_category": "Long-term Borrowings"},
|
||||||
_("Unsecured Loans"): {},
|
_("Unsecured Loans"): {"account_category": "Long-term Borrowings"},
|
||||||
_("Bank Overdraft Account"): {},
|
_("Bank Overdraft Account"): {"account_category": "Short-term Borrowings"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
_("Non-Current Liabilities"): {
|
||||||
|
_("Long-term Provisions"): {"account_category": "Long-term Provisions"},
|
||||||
|
_("Employee Benefits Obligation"): {"account_category": "Other Non-current Liabilities"},
|
||||||
|
"is_group": 1,
|
||||||
|
},
|
||||||
"root_type": "Liability",
|
"root_type": "Liability",
|
||||||
},
|
},
|
||||||
_("Equity"): {
|
_("Equity"): {
|
||||||
_("Capital Stock"): {"account_type": "Equity"},
|
_("Capital Stock"): {"account_type": "Equity", "account_category": "Share Capital"},
|
||||||
_("Dividends Paid"): {"account_type": "Equity"},
|
_("Dividends Paid"): {"account_type": "Equity", "account_category": "Reserves and Surplus"},
|
||||||
_("Opening Balance Equity"): {"account_type": "Equity"},
|
_("Opening Balance Equity"): {
|
||||||
_("Retained Earnings"): {"account_type": "Equity"},
|
"account_type": "Equity",
|
||||||
_("Revaluation Surplus"): {"account_type": "Equity"},
|
"account_category": "Reserves and Surplus",
|
||||||
|
},
|
||||||
|
_("Retained Earnings"): {"account_type": "Equity", "account_category": "Reserves and Surplus"},
|
||||||
|
_("Revaluation Surplus"): {"account_type": "Equity", "account_category": "Reserves and Surplus"},
|
||||||
"root_type": "Equity",
|
"root_type": "Equity",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,49 +10,128 @@ def get():
|
|||||||
_("Application of Funds (Assets)"): {
|
_("Application of Funds (Assets)"): {
|
||||||
_("Current Assets"): {
|
_("Current Assets"): {
|
||||||
_("Accounts Receivable"): {
|
_("Accounts Receivable"): {
|
||||||
_("Debtors"): {"account_type": "Receivable", "account_number": "1310"},
|
_("Debtors"): {
|
||||||
|
"account_type": "Receivable",
|
||||||
|
"account_number": "1310",
|
||||||
|
"account_category": "Trade Receivables",
|
||||||
|
},
|
||||||
"account_number": "1300",
|
"account_number": "1300",
|
||||||
},
|
},
|
||||||
_("Bank Accounts"): {"account_type": "Bank", "is_group": 1, "account_number": "1200"},
|
_("Bank Accounts"): {
|
||||||
|
"account_type": "Bank",
|
||||||
|
"is_group": 1,
|
||||||
|
"account_number": "1200",
|
||||||
|
"account_category": "Cash and Cash Equivalents",
|
||||||
|
},
|
||||||
_("Cash In Hand"): {
|
_("Cash In Hand"): {
|
||||||
_("Cash"): {"account_type": "Cash", "account_number": "1110"},
|
_("Cash"): {
|
||||||
|
"account_type": "Cash",
|
||||||
|
"account_number": "1110",
|
||||||
|
"account_category": "Cash and Cash Equivalents",
|
||||||
|
},
|
||||||
"account_type": "Cash",
|
"account_type": "Cash",
|
||||||
"account_number": "1100",
|
"account_number": "1100",
|
||||||
|
"account_category": "Cash and Cash Equivalents",
|
||||||
},
|
},
|
||||||
_("Loans and Advances (Assets)"): {
|
_("Loans and Advances (Assets)"): {
|
||||||
_("Employee Advances"): {"account_number": "1610", "account_type": "Payable"},
|
_("Employee Advances"): {
|
||||||
|
"account_number": "1610",
|
||||||
|
"account_type": "Payable",
|
||||||
|
"account_category": "Other Receivables",
|
||||||
|
},
|
||||||
"account_number": "1600",
|
"account_number": "1600",
|
||||||
},
|
},
|
||||||
_("Securities and Deposits"): {
|
_("Securities and Deposits"): {
|
||||||
_("Earnest Money"): {"account_number": "1651"},
|
_("Earnest Money"): {
|
||||||
|
"account_number": "1651",
|
||||||
|
"account_category": "Other Current Assets",
|
||||||
|
},
|
||||||
"account_number": "1650",
|
"account_number": "1650",
|
||||||
},
|
},
|
||||||
|
_("Prepaid Expenses"): {
|
||||||
|
"account_number": "1660",
|
||||||
|
"account_category": "Other Current Assets",
|
||||||
|
},
|
||||||
|
_("Short-term Investments"): {
|
||||||
|
"account_number": "1670",
|
||||||
|
"account_category": "Short-term Investments",
|
||||||
|
},
|
||||||
_("Stock Assets"): {
|
_("Stock Assets"): {
|
||||||
_("Stock In Hand"): {"account_type": "Stock", "account_number": "1410"},
|
_("Stock In Hand"): {
|
||||||
|
"account_type": "Stock",
|
||||||
|
"account_number": "1410",
|
||||||
|
"account_category": "Stock Assets",
|
||||||
|
},
|
||||||
"account_type": "Stock",
|
"account_type": "Stock",
|
||||||
"account_number": "1400",
|
"account_number": "1400",
|
||||||
|
"account_category": "Stock Assets",
|
||||||
|
},
|
||||||
|
_("Tax Assets"): {
|
||||||
|
"is_group": 1,
|
||||||
|
"account_number": "1500",
|
||||||
|
"account_category": "Other Current Assets",
|
||||||
},
|
},
|
||||||
_("Tax Assets"): {"is_group": 1, "account_number": "1500"},
|
|
||||||
"account_number": "1100-1600",
|
"account_number": "1100-1600",
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
_("Capital Equipment"): {
|
||||||
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
"account_type": "Fixed Asset",
|
||||||
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
"account_number": "1710",
|
||||||
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
"account_category": "Tangible Assets",
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
_("Electronic Equipment"): {
|
||||||
_("Software"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
"account_type": "Fixed Asset",
|
||||||
|
"account_number": "1720",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Furniture and Fixtures"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_number": "1730",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Office Equipment"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_number": "1740",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Plants and Machineries"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_number": "1750",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Buildings"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_number": "1760",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("Software"): {
|
||||||
|
"account_type": "Fixed Asset",
|
||||||
|
"account_number": "1770",
|
||||||
|
"account_category": "Intangible Assets",
|
||||||
|
},
|
||||||
_("Accumulated Depreciation"): {
|
_("Accumulated Depreciation"): {
|
||||||
"account_type": "Accumulated Depreciation",
|
"account_type": "Accumulated Depreciation",
|
||||||
"account_number": "1780",
|
"account_number": "1780",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
|
},
|
||||||
|
_("CWIP Account"): {
|
||||||
|
"account_type": "Capital Work in Progress",
|
||||||
|
"account_number": "1790",
|
||||||
|
"account_category": "Tangible Assets",
|
||||||
},
|
},
|
||||||
_("CWIP Account"): {"account_type": "Capital Work in Progress", "account_number": "1790"},
|
|
||||||
"account_number": "1700",
|
"account_number": "1700",
|
||||||
},
|
},
|
||||||
_("Investments"): {"is_group": 1, "account_number": "1800"},
|
_("Investments"): {
|
||||||
|
"is_group": 1,
|
||||||
|
"account_number": "1800",
|
||||||
|
"account_category": "Long-term Investments",
|
||||||
|
},
|
||||||
_("Temporary Accounts"): {
|
_("Temporary Accounts"): {
|
||||||
_("Temporary Opening"): {"account_type": "Temporary", "account_number": "1910"},
|
_("Temporary Opening"): {
|
||||||
|
"account_type": "Temporary",
|
||||||
|
"account_number": "1910",
|
||||||
|
"account_category": "Other Non-current Assets",
|
||||||
|
},
|
||||||
"account_number": "1900",
|
"account_number": "1900",
|
||||||
},
|
},
|
||||||
"root_type": "Asset",
|
"root_type": "Asset",
|
||||||
@@ -61,97 +140,220 @@ def get():
|
|||||||
_("Expenses"): {
|
_("Expenses"): {
|
||||||
_("Direct Expenses"): {
|
_("Direct Expenses"): {
|
||||||
_("Stock Expenses"): {
|
_("Stock Expenses"): {
|
||||||
_("Cost of Goods Sold"): {"account_type": "Cost of Goods Sold", "account_number": "5111"},
|
_("Cost of Goods Sold"): {
|
||||||
|
"account_type": "Cost of Goods Sold",
|
||||||
|
"account_number": "5111",
|
||||||
|
"account_category": "Cost of Goods Sold",
|
||||||
|
},
|
||||||
_("Expenses Included In Asset Valuation"): {
|
_("Expenses Included In Asset Valuation"): {
|
||||||
"account_type": "Expenses Included In Asset Valuation",
|
"account_type": "Expenses Included In Asset Valuation",
|
||||||
"account_number": "5112",
|
"account_number": "5112",
|
||||||
|
"account_category": "Other Direct Costs",
|
||||||
},
|
},
|
||||||
_("Expenses Included In Valuation"): {
|
_("Expenses Included In Valuation"): {
|
||||||
"account_type": "Expenses Included In Valuation",
|
"account_type": "Expenses Included In Valuation",
|
||||||
"account_number": "5118",
|
"account_number": "5118",
|
||||||
|
"account_category": "Other Direct Costs",
|
||||||
|
},
|
||||||
|
_("Stock Adjustment"): {
|
||||||
|
"account_type": "Stock Adjustment",
|
||||||
|
"account_number": "5119",
|
||||||
|
"account_category": "Other Direct Costs",
|
||||||
},
|
},
|
||||||
_("Stock Adjustment"): {"account_type": "Stock Adjustment", "account_number": "5119"},
|
|
||||||
"account_number": "5110",
|
"account_number": "5110",
|
||||||
},
|
},
|
||||||
"account_number": "5100",
|
"account_number": "5100",
|
||||||
},
|
},
|
||||||
_("Indirect Expenses"): {
|
_("Indirect Expenses"): {
|
||||||
_("Administrative Expenses"): {"account_number": "5201"},
|
_("Administrative Expenses"): {
|
||||||
_("Commission on Sales"): {"account_number": "5202"},
|
"account_number": "5201",
|
||||||
_("Depreciation"): {"account_type": "Depreciation", "account_number": "5203"},
|
"account_category": "Operating Expenses",
|
||||||
_("Entertainment Expenses"): {"account_number": "5204"},
|
},
|
||||||
_("Freight and Forwarding Charges"): {"account_type": "Chargeable", "account_number": "5205"},
|
_("Commission on Sales"): {
|
||||||
_("Legal Expenses"): {"account_number": "5206"},
|
"account_number": "5202",
|
||||||
_("Marketing Expenses"): {"account_type": "Chargeable", "account_number": "5207"},
|
"account_category": "Operating Expenses",
|
||||||
_("Office Maintenance Expenses"): {"account_number": "5208"},
|
},
|
||||||
_("Office Rent"): {"account_number": "5209"},
|
_("Depreciation"): {
|
||||||
_("Postal Expenses"): {"account_number": "5210"},
|
"account_type": "Depreciation",
|
||||||
_("Print and Stationery"): {"account_number": "5211"},
|
"account_number": "5203",
|
||||||
_("Round Off"): {"account_type": "Round Off", "account_number": "5212"},
|
"account_category": "Operating Expenses",
|
||||||
_("Salary"): {"account_number": "5213"},
|
},
|
||||||
_("Sales Expenses"): {"account_number": "5214"},
|
_("Entertainment Expenses"): {
|
||||||
_("Telephone Expenses"): {"account_number": "5215"},
|
"account_number": "5204",
|
||||||
_("Travel Expenses"): {"account_number": "5216"},
|
"account_category": "Operating Expenses",
|
||||||
_("Utility Expenses"): {"account_number": "5217"},
|
},
|
||||||
_("Write Off"): {"account_number": "5218"},
|
_("Freight and Forwarding Charges"): {
|
||||||
_("Exchange Gain/Loss"): {"account_number": "5219"},
|
"account_type": "Chargeable",
|
||||||
_("Gain/Loss on Asset Disposal"): {"account_number": "5220"},
|
"account_number": "5205",
|
||||||
_("Miscellaneous Expenses"): {"account_type": "Chargeable", "account_number": "5221"},
|
"account_category": "Operating Expenses",
|
||||||
"account_number": "5200",
|
},
|
||||||
|
_("Legal Expenses"): {"account_number": "5206", "account_category": "Operating Expenses"},
|
||||||
|
_("Marketing Expenses"): {
|
||||||
|
"account_type": "Chargeable",
|
||||||
|
"account_number": "5207",
|
||||||
|
"account_category": "Operating Expenses",
|
||||||
|
},
|
||||||
|
_("Office Maintenance Expenses"): {
|
||||||
|
"account_number": "5208",
|
||||||
|
"account_category": "Operating Expenses",
|
||||||
|
},
|
||||||
|
_("Office Rent"): {"account_number": "5209", "account_category": "Operating Expenses"},
|
||||||
|
_("Postal Expenses"): {"account_number": "5210", "account_category": "Operating Expenses"},
|
||||||
|
_("Print and Stationery"): {
|
||||||
|
"account_number": "5211",
|
||||||
|
"account_category": "Operating Expenses",
|
||||||
|
},
|
||||||
|
_("Round Off"): {
|
||||||
|
"account_type": "Round Off",
|
||||||
|
"account_number": "5212",
|
||||||
|
"account_category": "Operating Expenses",
|
||||||
|
},
|
||||||
|
_("Salary"): {"account_number": "5213", "account_category": "Operating Expenses"},
|
||||||
|
_("Sales Expenses"): {"account_number": "5214", "account_category": "Operating Expenses"},
|
||||||
|
_("Telephone Expenses"): {"account_number": "5215", "account_category": "Operating Expenses"},
|
||||||
|
_("Travel Expenses"): {"account_number": "5216", "account_category": "Operating Expenses"},
|
||||||
|
_("Utility Expenses"): {"account_number": "5217", "account_category": "Operating Expenses"},
|
||||||
|
_("Write Off"): {"account_number": "5218", "account_category": "Operating Expenses"},
|
||||||
|
_("Exchange Gain/Loss"): {"account_number": "5219", "account_category": "Operating Expenses"},
|
||||||
|
_("Interest Expense"): {"account_number": "5220", "account_category": "Finance Costs"},
|
||||||
|
_("Bank Charges"): {"account_number": "5221", "account_category": "Finance Costs"},
|
||||||
|
_("Gain/Loss on Asset Disposal"): {
|
||||||
|
"account_number": "5222",
|
||||||
|
"account_category": "Other Operating Income",
|
||||||
|
},
|
||||||
|
_("Miscellaneous Expenses"): {
|
||||||
|
"account_type": "Chargeable",
|
||||||
|
"account_number": "5223",
|
||||||
|
"account_category": "Operating Expenses",
|
||||||
|
},
|
||||||
|
_("Impairment"): {"account_number": "5224", "account_category": "Operating Expenses"},
|
||||||
|
_("Tax Expense"): {"account_number": "5225", "account_category": "Tax Expense"},
|
||||||
},
|
},
|
||||||
"root_type": "Expense",
|
"root_type": "Expense",
|
||||||
"account_number": "5000",
|
"account_number": "5000",
|
||||||
},
|
},
|
||||||
_("Income"): {
|
_("Income"): {
|
||||||
_("Direct Income"): {
|
_("Direct Income"): {
|
||||||
_("Sales"): {"account_number": "4110"},
|
_("Sales"): {"account_number": "4110", "account_category": "Revenue from Operations"},
|
||||||
_("Service"): {"account_number": "4120"},
|
_("Service"): {"account_number": "4120", "account_category": "Revenue from Operations"},
|
||||||
"account_number": "4100",
|
"account_number": "4100",
|
||||||
},
|
},
|
||||||
_("Indirect Income"): {"is_group": 1, "account_number": "4200"},
|
_("Indirect Income"): {
|
||||||
|
_("Interest Income"): {"account_number": "4210", "account_category": "Investment Income"},
|
||||||
|
_("Interest on Fixed Deposits"): {
|
||||||
|
"account_number": "4220",
|
||||||
|
"account_category": "Investment Income",
|
||||||
|
},
|
||||||
|
"is_group": 1,
|
||||||
|
"account_number": "4200",
|
||||||
|
},
|
||||||
"root_type": "Income",
|
"root_type": "Income",
|
||||||
"account_number": "4000",
|
"account_number": "4000",
|
||||||
},
|
},
|
||||||
_("Source of Funds (Liabilities)"): {
|
_("Source of Funds (Liabilities)"): {
|
||||||
_("Current Liabilities"): {
|
_("Current Liabilities"): {
|
||||||
_("Accounts Payable"): {
|
_("Accounts Payable"): {
|
||||||
_("Creditors"): {"account_type": "Payable", "account_number": "2110"},
|
_("Creditors"): {
|
||||||
_("Payroll Payable"): {"account_number": "2120"},
|
"account_type": "Payable",
|
||||||
|
"account_number": "2110",
|
||||||
|
"account_category": "Trade Payables",
|
||||||
|
},
|
||||||
|
_("Payroll Payable"): {"account_number": "2120", "account_category": "Other Payables"},
|
||||||
"account_number": "2100",
|
"account_number": "2100",
|
||||||
},
|
},
|
||||||
|
_("Accrued Expenses"): {
|
||||||
|
"account_number": "2150",
|
||||||
|
"account_category": "Other Current Liabilities",
|
||||||
|
},
|
||||||
|
_("Customer Advances"): {
|
||||||
|
"account_number": "2160",
|
||||||
|
"account_category": "Other Current Liabilities",
|
||||||
|
},
|
||||||
_("Stock Liabilities"): {
|
_("Stock Liabilities"): {
|
||||||
_("Stock Received But Not Billed"): {
|
_("Stock Received But Not Billed"): {
|
||||||
"account_type": "Stock Received But Not Billed",
|
"account_type": "Stock Received But Not Billed",
|
||||||
"account_number": "2210",
|
"account_number": "2210",
|
||||||
|
"account_category": "Trade Payables",
|
||||||
},
|
},
|
||||||
_("Asset Received But Not Billed"): {
|
_("Asset Received But Not Billed"): {
|
||||||
"account_type": "Asset Received But Not Billed",
|
"account_type": "Asset Received But Not Billed",
|
||||||
"account_number": "2211",
|
"account_number": "2211",
|
||||||
|
"account_category": "Trade Payables",
|
||||||
},
|
},
|
||||||
"account_number": "2200",
|
"account_number": "2200",
|
||||||
},
|
},
|
||||||
_("Duties and Taxes"): {
|
_("Duties and Taxes"): {
|
||||||
_("TDS Payable"): {"account_number": "2310"},
|
_("TDS Payable"): {
|
||||||
|
"account_number": "2310",
|
||||||
|
"account_category": "Current Tax Liabilities",
|
||||||
|
},
|
||||||
"account_type": "Tax",
|
"account_type": "Tax",
|
||||||
"is_group": 1,
|
"is_group": 1,
|
||||||
"account_number": "2300",
|
"account_number": "2300",
|
||||||
|
"account_category": "Current Tax Liabilities",
|
||||||
|
},
|
||||||
|
_("Short-term Provisions"): {
|
||||||
|
"account_number": "2350",
|
||||||
|
"account_category": "Short-term Provisions",
|
||||||
},
|
},
|
||||||
_("Loans (Liabilities)"): {
|
_("Loans (Liabilities)"): {
|
||||||
_("Secured Loans"): {"account_number": "2410"},
|
_("Secured Loans"): {
|
||||||
_("Unsecured Loans"): {"account_number": "2420"},
|
"account_number": "2410",
|
||||||
_("Bank Overdraft Account"): {"account_number": "2430"},
|
"account_category": "Long-term Borrowings",
|
||||||
|
},
|
||||||
|
_("Unsecured Loans"): {
|
||||||
|
"account_number": "2420",
|
||||||
|
"account_category": "Long-term Borrowings",
|
||||||
|
},
|
||||||
|
_("Bank Overdraft Account"): {
|
||||||
|
"account_number": "2430",
|
||||||
|
"account_category": "Short-term Borrowings",
|
||||||
|
},
|
||||||
"account_number": "2400",
|
"account_number": "2400",
|
||||||
},
|
},
|
||||||
"account_number": "2100-2400",
|
"account_number": "2100-2400",
|
||||||
},
|
},
|
||||||
|
_("Non-Current Liabilities"): {
|
||||||
|
_("Long-term Provisions"): {
|
||||||
|
"account_number": "2510",
|
||||||
|
"account_category": "Long-term Provisions",
|
||||||
|
},
|
||||||
|
_("Employee Benefits Obligation"): {
|
||||||
|
"account_number": "2520",
|
||||||
|
"account_category": "Other Non-current Liabilities",
|
||||||
|
},
|
||||||
|
"is_group": 1,
|
||||||
|
"account_number": "2500",
|
||||||
|
},
|
||||||
"root_type": "Liability",
|
"root_type": "Liability",
|
||||||
"account_number": "2000",
|
"account_number": "2000",
|
||||||
},
|
},
|
||||||
_("Equity"): {
|
_("Equity"): {
|
||||||
_("Capital Stock"): {"account_type": "Equity", "account_number": "3100"},
|
_("Capital Stock"): {
|
||||||
_("Dividends Paid"): {"account_type": "Equity", "account_number": "3200"},
|
"account_type": "Equity",
|
||||||
_("Opening Balance Equity"): {"account_type": "Equity", "account_number": "3300"},
|
"account_number": "3100",
|
||||||
_("Retained Earnings"): {"account_type": "Equity", "account_number": "3400"},
|
"account_category": "Share Capital",
|
||||||
|
},
|
||||||
|
_("Dividends Paid"): {
|
||||||
|
"account_type": "Equity",
|
||||||
|
"account_number": "3200",
|
||||||
|
"account_category": "Reserves and Surplus",
|
||||||
|
},
|
||||||
|
_("Opening Balance Equity"): {
|
||||||
|
"account_type": "Equity",
|
||||||
|
"account_number": "3300",
|
||||||
|
"account_category": "Reserves and Surplus",
|
||||||
|
},
|
||||||
|
_("Retained Earnings"): {
|
||||||
|
"account_type": "Equity",
|
||||||
|
"account_number": "3400",
|
||||||
|
"account_category": "Reserves and Surplus",
|
||||||
|
},
|
||||||
|
_("Revaluation Surplus"): {
|
||||||
|
"account_type": "Equity",
|
||||||
|
"account_number": "3500",
|
||||||
|
"account_category": "Reserves and Surplus",
|
||||||
|
},
|
||||||
"root_type": "Equity",
|
"root_type": "Equity",
|
||||||
"account_number": "3000",
|
"account_number": "3000",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
// frappe.ui.form.on("Account Category", {
|
||||||
|
// refresh(frm) {
|
||||||
|
|
||||||
|
// },
|
||||||
|
// });
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "field:account_category_name",
|
||||||
|
"creation": "2025-08-02 06:22:31.835063",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"account_category_name",
|
||||||
|
"description"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "account_category_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Account Category Name",
|
||||||
|
"reqd": 1,
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Description"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grid_page_length": 50,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2025-10-15 03:19:47.171349",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Account Category",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Auditor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"row_format": "Dynamic",
|
||||||
|
"search_fields": "account_category_name, description",
|
||||||
|
"sort_field": "creation",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document, bulk_insert
|
||||||
|
|
||||||
|
DOCTYPE = "Account Category"
|
||||||
|
|
||||||
|
|
||||||
|
class AccountCategory(Document):
|
||||||
|
# begin: auto-generated types
|
||||||
|
# This code is auto-generated. Do not modify anything in this block.
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
|
account_category_name: DF.Data
|
||||||
|
description: DF.SmallText | None
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
|
def after_rename(self, old_name, new_name, merge):
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_engine import (
|
||||||
|
FormulaFieldUpdater,
|
||||||
|
)
|
||||||
|
|
||||||
|
# get all template rows with this account category being used
|
||||||
|
row = frappe.qb.DocType("Financial Report Row")
|
||||||
|
rows = frappe._dict(
|
||||||
|
frappe.qb.from_(row)
|
||||||
|
.select(row.name, row.calculation_formula)
|
||||||
|
.where(row.calculation_formula.like(f"%{old_name}%"))
|
||||||
|
.run()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not rows:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Update formulas with new name
|
||||||
|
updater = FormulaFieldUpdater(
|
||||||
|
field_name="account_category",
|
||||||
|
value_mapping={old_name: new_name},
|
||||||
|
exclude_operators=["like", "not like"],
|
||||||
|
)
|
||||||
|
|
||||||
|
updated_formulas = updater.update_in_rows(rows)
|
||||||
|
|
||||||
|
if updated_formulas:
|
||||||
|
frappe.msgprint(
|
||||||
|
_("Updated {0} Financial Report Row(s) with new category name").format(len(updated_formulas))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def import_account_categories(template_path: str):
|
||||||
|
categories_file = os.path.join(template_path, "account_categories.json")
|
||||||
|
|
||||||
|
if not os.path.exists(categories_file):
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(categories_file) as f:
|
||||||
|
categories = json.load(f, object_hook=frappe._dict)
|
||||||
|
|
||||||
|
create_account_categories(categories)
|
||||||
|
|
||||||
|
|
||||||
|
def create_account_categories(categories: list[dict]):
|
||||||
|
if not categories:
|
||||||
|
return
|
||||||
|
|
||||||
|
existing_categories = set(frappe.get_all(DOCTYPE, pluck="name"))
|
||||||
|
new_categories = []
|
||||||
|
|
||||||
|
for category_data in categories:
|
||||||
|
category_name = category_data.get("account_category_name")
|
||||||
|
if not category_name or category_name in existing_categories:
|
||||||
|
continue
|
||||||
|
|
||||||
|
doc = frappe.get_doc(
|
||||||
|
{
|
||||||
|
**category_data,
|
||||||
|
"doctype": DOCTYPE,
|
||||||
|
"name": category_name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
new_categories.append(doc)
|
||||||
|
existing_categories.add(category_name)
|
||||||
|
|
||||||
|
if new_categories:
|
||||||
|
bulk_insert(DOCTYPE, new_categories)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.tests import IntegrationTestCase
|
||||||
|
|
||||||
|
# On IntegrationTestCase, the doctype test records and all
|
||||||
|
# link-field test record dependencies are recursively loaded
|
||||||
|
# Use these module variables to add/remove to/from that list
|
||||||
|
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
|
||||||
|
|
||||||
|
class IntegrationTestAccountCategory(IntegrationTestCase):
|
||||||
|
"""
|
||||||
|
Integration tests for AccountCategory.
|
||||||
|
Use this class for testing interactions between multiple components.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"creation": "2025-09-06 09:39:46.503678",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"reference_code",
|
||||||
|
"display_name",
|
||||||
|
"indentation_level",
|
||||||
|
"data_source",
|
||||||
|
"balance_type",
|
||||||
|
"column_break_hxqu",
|
||||||
|
"fieldtype",
|
||||||
|
"color",
|
||||||
|
"bold_text",
|
||||||
|
"italic_text",
|
||||||
|
"hidden_calculation",
|
||||||
|
"hide_when_empty",
|
||||||
|
"reverse_sign",
|
||||||
|
"include_in_charts",
|
||||||
|
"section_break_ornw",
|
||||||
|
"column_break_asfe",
|
||||||
|
"advanced_filtering",
|
||||||
|
"filters_editor",
|
||||||
|
"calculation_formula",
|
||||||
|
"section_break_pvro",
|
||||||
|
"formula_description"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"columns": 1,
|
||||||
|
"description": "Code to reference this line in formulas (e.g., REV100, EXP200, ASSET100)",
|
||||||
|
"fieldname": "reference_code",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Line Reference"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Text displayed on the financial statement (e.g., 'Total Revenue', 'Cash and Cash Equivalents')",
|
||||||
|
"fieldname": "display_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Display Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 1,
|
||||||
|
"description": "Indentation level: 0 = Main heading, 1 = Sub-category, 2 = Individual accounts, etc.",
|
||||||
|
"fieldname": "indentation_level",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Indent Level"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "How this line gets its data",
|
||||||
|
"fieldname": "data_source",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Data Source",
|
||||||
|
"options": "\nAccount Data\nCalculated Amount\nCustom API\nBlank Line\nColumn Break\nSection Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.data_source == 'Account Data'",
|
||||||
|
"description": "Opening Balance = Start of period, Closing Balance = End of period, Period Movement = Net change during period",
|
||||||
|
"fieldname": "balance_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Balance Type",
|
||||||
|
"mandatory_depends_on": "eval:doc.data_source == 'Account Data'",
|
||||||
|
"options": "\nOpening Balance\nClosing Balance\nPeriod Movement (Debits - Credits)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_hxqu",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Bold text for emphasis (totals, major headings)",
|
||||||
|
"fieldname": "bold_text",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Bold Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Italic text for subtotals or notes",
|
||||||
|
"fieldname": "italic_text",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Italic Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Calculate but don't show on final report",
|
||||||
|
"fieldname": "hidden_calculation",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Hidden Line (Internal Use Only)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Hide this line if amount is zero",
|
||||||
|
"fieldname": "hide_when_empty",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Hide If Zero"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 1,
|
||||||
|
"default": "0",
|
||||||
|
"description": "Show negative values as positive (for expenses in P&L)",
|
||||||
|
"fieldname": "reverse_sign",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Reverse Sign"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_ornw",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: (doc.data_source === \"Account Data\" && doc.advanced_filtering) || [\"Calculated Amount\", \"Custom API\"].includes(doc.data_source);\n",
|
||||||
|
"fieldname": "calculation_formula",
|
||||||
|
"fieldtype": "Code",
|
||||||
|
"label": "Formula or Account Filter",
|
||||||
|
"mandatory_depends_on": "eval:doc.data_source != 'Blank Line' && doc.data_source != 'Column Break' && doc.data_source != 'Section Break'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "formula_description",
|
||||||
|
"fieldtype": "HTML"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "If enabled, this row's values will be displayed on financial charts",
|
||||||
|
"fieldname": "include_in_charts",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Include in Charts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Color to highlight values (e.g., red for exceptions)",
|
||||||
|
"fieldname": "color",
|
||||||
|
"fieldtype": "Color",
|
||||||
|
"label": "Color"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "How to format and present values in the financial report (only if different from column fieldtype)",
|
||||||
|
"fieldname": "fieldtype",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Value Type",
|
||||||
|
"options": "\nCurrency\nFloat\nInt\nPercent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: doc.data_source === \"Account Data\" && !doc.advanced_filtering",
|
||||||
|
"fieldname": "filters_editor",
|
||||||
|
"fieldtype": "HTML"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: ![\"Blank Line\", \"Column Break\", \"Section Break\"].includes(doc.data_source);",
|
||||||
|
"fieldname": "column_break_asfe",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"depends_on": "eval: doc.data_source === \"Account Data\"",
|
||||||
|
"description": "Use <strong>Python</strong> filters to get Accounts",
|
||||||
|
"fieldname": "advanced_filtering",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Advanced Filtering",
|
||||||
|
"print_hide": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_pvro",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grid_page_length": 50,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2025-10-14 09:23:27.208072",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Financial Report Row",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"row_format": "Dynamic",
|
||||||
|
"sort_field": "creation",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class FinancialReportRow(Document):
|
||||||
|
# begin: auto-generated types
|
||||||
|
# This code is auto-generated. Do not modify anything in this block.
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
|
advanced_filtering: DF.Check
|
||||||
|
balance_type: DF.Literal[
|
||||||
|
"", "Opening Balance", "Closing Balance", "Period Movement (Debits - Credits)"
|
||||||
|
]
|
||||||
|
bold_text: DF.Check
|
||||||
|
calculation_formula: DF.Code | None
|
||||||
|
color: DF.Color | None
|
||||||
|
data_source: DF.Literal[
|
||||||
|
"",
|
||||||
|
"Account Data",
|
||||||
|
"Calculated Amount",
|
||||||
|
"Custom API",
|
||||||
|
"Blank Line",
|
||||||
|
"Column Break",
|
||||||
|
"Section Break",
|
||||||
|
]
|
||||||
|
display_name: DF.Data | None
|
||||||
|
fieldtype: DF.Literal["", "Currency", "Float", "Int", "Percent"]
|
||||||
|
hidden_calculation: DF.Check
|
||||||
|
hide_when_empty: DF.Check
|
||||||
|
include_in_charts: DF.Check
|
||||||
|
indentation_level: DF.Int
|
||||||
|
italic_text: DF.Check
|
||||||
|
parent: DF.Data
|
||||||
|
parentfield: DF.Data
|
||||||
|
parenttype: DF.Data
|
||||||
|
reference_code: DF.Data | None
|
||||||
|
reverse_sign: DF.Check
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
|
pass
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,433 @@
|
|||||||
|
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on("Financial Report Template", {
|
||||||
|
refresh(frm) {
|
||||||
|
// add custom button to view missed accounts
|
||||||
|
frm.add_custom_button(__("View Account Coverage"), function () {
|
||||||
|
let selected_rows = frm.get_field("rows").grid.get_selected_children();
|
||||||
|
const has_selection = selected_rows.length > 0;
|
||||||
|
if (selected_rows.length === 0) selected_rows = frm.doc.rows;
|
||||||
|
|
||||||
|
show_accounts_tree(selected_rows, has_selection);
|
||||||
|
});
|
||||||
|
|
||||||
|
// add custom button to open the financial report
|
||||||
|
frm.add_custom_button(__("View Report"), function () {
|
||||||
|
frappe.set_route("query-report", frm.doc.report_type, {
|
||||||
|
report_template: frm.doc.name,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
validate(frm) {
|
||||||
|
if (!frm.doc.rows || frm.doc.rows.length === 0) {
|
||||||
|
frappe.msgprint(__("At least one row is required for a financial report template"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("Financial Report Row", {
|
||||||
|
data_source(frm, cdt, cdn) {
|
||||||
|
const row = locals[cdt][cdn];
|
||||||
|
|
||||||
|
update_formula_label(frm, row.data_source);
|
||||||
|
update_formula_description(frm, row.data_source);
|
||||||
|
|
||||||
|
if (row.data_source !== "Account Data") {
|
||||||
|
frappe.model.set_value(cdt, cdn, "balance_type", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (["Blank Line", "Column Break", "Section Break"].includes(row.data_source)) {
|
||||||
|
frappe.model.set_value(cdt, cdn, "calculation_formula", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_up_filters_editor(frm, cdt, cdn);
|
||||||
|
},
|
||||||
|
|
||||||
|
form_render(frm, cdt, cdn) {
|
||||||
|
const row = locals[cdt][cdn];
|
||||||
|
|
||||||
|
update_formula_label(frm, row.data_source);
|
||||||
|
update_advanced_formula_property(frm, cdt, cdn);
|
||||||
|
set_up_filters_editor(frm, cdt, cdn);
|
||||||
|
update_formula_description(frm, row.data_source);
|
||||||
|
},
|
||||||
|
|
||||||
|
calculation_formula(frm, cdt, cdn) {
|
||||||
|
update_advanced_formula_property(frm, cdt, cdn);
|
||||||
|
},
|
||||||
|
|
||||||
|
advanced_filtering(frm, cdt, cdn) {
|
||||||
|
set_up_filters_editor(frm, cdt, cdn);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// FILTERS EDITOR
|
||||||
|
|
||||||
|
function set_up_filters_editor(frm, cdt, cdn) {
|
||||||
|
const row = locals[cdt][cdn];
|
||||||
|
|
||||||
|
if (row.data_source !== "Account Data" || row.advanced_filtering) return;
|
||||||
|
|
||||||
|
const grid_row = frm.fields_dict["rows"].grid.get_row(cdn);
|
||||||
|
const wrapper = grid_row.get_field("filters_editor").$wrapper;
|
||||||
|
wrapper.empty();
|
||||||
|
|
||||||
|
const ACCOUNT = "Account";
|
||||||
|
const FIELD_IDX = 1;
|
||||||
|
const OPERATOR_IDX = 2;
|
||||||
|
const VALUE_IDX = 3;
|
||||||
|
|
||||||
|
// Parse saved filters
|
||||||
|
let saved_filters = [];
|
||||||
|
|
||||||
|
if (row.calculation_formula) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(row.calculation_formula);
|
||||||
|
|
||||||
|
if (Array.isArray(parsed)) saved_filters = [parsed];
|
||||||
|
else if (parsed.and) saved_filters = parsed.and;
|
||||||
|
} catch (e) {
|
||||||
|
frappe.show_alert({
|
||||||
|
message: __("Invalid filter formula. Please check the syntax."),
|
||||||
|
indicator: "red",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saved_filters.length)
|
||||||
|
// Ensure every filter starts with "Account"
|
||||||
|
saved_filters = saved_filters.map((f) => [ACCOUNT, ...f]);
|
||||||
|
|
||||||
|
frappe.model.with_doctype(ACCOUNT, () => {
|
||||||
|
const filter_group = new frappe.ui.FilterGroup({
|
||||||
|
parent: wrapper,
|
||||||
|
doctype: ACCOUNT,
|
||||||
|
on_change: () => {
|
||||||
|
// only need [[field, operator, value]]
|
||||||
|
const filters = filter_group
|
||||||
|
.get_filters()
|
||||||
|
.map((f) => [f[FIELD_IDX], f[OPERATOR_IDX], f[VALUE_IDX]]);
|
||||||
|
|
||||||
|
const current = filters.length > 1 ? { and: filters } : filters[0];
|
||||||
|
frappe.model.set_value(cdt, cdn, "calculation_formula", JSON.stringify(current));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
filter_group.add_filters_to_filter_group(saved_filters);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_advanced_formula_property(frm, cdt, cdn) {
|
||||||
|
const row = locals[cdt][cdn];
|
||||||
|
const is_advanced = is_advanced_formula(row);
|
||||||
|
|
||||||
|
frm.set_df_property("rows", "read_only", is_advanced, frm.doc.name, "advanced_filtering", cdn);
|
||||||
|
|
||||||
|
if (is_advanced && !row.advanced_filtering) {
|
||||||
|
row.advanced_filtering = 1;
|
||||||
|
frm.refresh_field("rows");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_advanced_formula(row) {
|
||||||
|
if (!row || row.data_source !== "Account Data") return false;
|
||||||
|
|
||||||
|
let parsed = null;
|
||||||
|
if (row.calculation_formula) {
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(row.calculation_formula);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Invalid JSON in calculation_formula:", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(parsed)) return false;
|
||||||
|
if (parsed?.or) return true;
|
||||||
|
if (parsed?.and) return parsed.and.some((cond) => !Array.isArray(cond));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCOUNTS TREE VIEW
|
||||||
|
|
||||||
|
function show_accounts_tree(template_rows, has_selection) {
|
||||||
|
// filtered rows
|
||||||
|
const account_rows = template_rows.filter((row) => row.data_source === "Account Data");
|
||||||
|
|
||||||
|
if (account_rows.length === 0) {
|
||||||
|
frappe.show_alert(__("No <strong>Account Data</strong> row found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialog = new frappe.ui.Dialog({
|
||||||
|
title: __("Accounts Missing from Report"),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
fieldname: "company",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Company",
|
||||||
|
label: "Company",
|
||||||
|
reqd: 1,
|
||||||
|
default: frappe.defaults.get_user_default("Company"),
|
||||||
|
onchange: () => {
|
||||||
|
const company_field = dialog.get_field("company");
|
||||||
|
if (!company_field.value || company_field.value === company_field.last_value) return;
|
||||||
|
refresh_tree_view(dialog, account_rows);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "view_type",
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Missing Accounts", "Filtered Accounts"],
|
||||||
|
label: "View",
|
||||||
|
default: has_selection ? "Filtered Accounts" : "Missing Accounts",
|
||||||
|
reqd: 1,
|
||||||
|
onchange: () => {
|
||||||
|
dialog.set_title(
|
||||||
|
dialog.get_value("view_type") === "Missing Accounts"
|
||||||
|
? __("Accounts Missing from Report")
|
||||||
|
: __("Accounts Included in Report")
|
||||||
|
);
|
||||||
|
|
||||||
|
refresh_tree_view(dialog, account_rows);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "tip",
|
||||||
|
fieldtype: "HTML",
|
||||||
|
label: "Tip",
|
||||||
|
options: `
|
||||||
|
<div class="alert alert-success" role="alert">
|
||||||
|
Tip: Select report lines to view their accounts
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
depends_on: has_selection ? "eval: false" : "eval: true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "tree_area",
|
||||||
|
fieldtype: "HTML",
|
||||||
|
label: "Chart of Accounts",
|
||||||
|
read_only: 1,
|
||||||
|
depends_on: "eval: doc.company",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
primary_action_label: __("Done"),
|
||||||
|
primary_action() {
|
||||||
|
dialog.hide();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
refresh_tree_view(dialog, account_rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refresh_tree_view(dialog, account_rows) {
|
||||||
|
const missed = dialog.get_value("view_type") === "Missing Accounts";
|
||||||
|
const company = dialog.get_value("company");
|
||||||
|
|
||||||
|
const wrapper = dialog.get_field("tree_area").$wrapper;
|
||||||
|
wrapper.empty();
|
||||||
|
|
||||||
|
// get filtered accounts
|
||||||
|
const { message: filtered_accounts } = await frappe.call({
|
||||||
|
method: "erpnext.accounts.doctype.financial_report_template.financial_report_engine.get_filtered_accounts",
|
||||||
|
args: { company: company, account_rows: account_rows },
|
||||||
|
});
|
||||||
|
|
||||||
|
// render tree
|
||||||
|
const tree = new FilteredTree({
|
||||||
|
parent: wrapper,
|
||||||
|
label: company,
|
||||||
|
root_value: company,
|
||||||
|
method: "erpnext.accounts.doctype.financial_report_template.financial_report_engine.get_children_accounts",
|
||||||
|
args: { doctype: "Account", company: company, filtered_accounts: filtered_accounts, missed: missed },
|
||||||
|
toolbar: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
tree.load_children(tree.root_node, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilteredTree extends frappe.ui.Tree {
|
||||||
|
render_children_of_all_nodes(data_list) {
|
||||||
|
data_list = this.get_filtered_data_list(data_list);
|
||||||
|
super.render_children_of_all_nodes(data_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_filtered_data_list(data_list) {
|
||||||
|
let removed_nodes = new Set();
|
||||||
|
|
||||||
|
// Filter nodes with no data
|
||||||
|
data_list = data_list.filter((d) => {
|
||||||
|
if (d.data.length === 0) {
|
||||||
|
removed_nodes.add(d.parent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove references to removed nodes and iteratively remove empty parents
|
||||||
|
while (removed_nodes.size > 0) {
|
||||||
|
const current_removed = [...removed_nodes];
|
||||||
|
removed_nodes.clear();
|
||||||
|
|
||||||
|
data_list = data_list.filter((d) => {
|
||||||
|
d.data = d.data.filter((a) => !current_removed.includes(a.value));
|
||||||
|
|
||||||
|
if (d.data.length === 0) {
|
||||||
|
removed_nodes.add(d.parent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return data_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_formula_label(frm, data_source) {
|
||||||
|
const grid = frm.fields_dict.rows.grid;
|
||||||
|
const field = grid.fields_map.calculation_formula;
|
||||||
|
if (!field) return;
|
||||||
|
|
||||||
|
const labels = {
|
||||||
|
"Account Data": "Account Filter",
|
||||||
|
"Custom API": "API Method Path",
|
||||||
|
};
|
||||||
|
|
||||||
|
grid.update_docfield_property(
|
||||||
|
"calculation_formula",
|
||||||
|
"label",
|
||||||
|
labels[data_source] || "Calculation Formula"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FORMULA DESCRIPTION
|
||||||
|
|
||||||
|
function update_formula_description(frm, data_source) {
|
||||||
|
if (!data_source) return;
|
||||||
|
|
||||||
|
let grid = frm.fields_dict.rows.grid;
|
||||||
|
let field = grid.fields_map.formula_description;
|
||||||
|
if (!field) return;
|
||||||
|
|
||||||
|
// Common CSS styles and elements
|
||||||
|
const container_style = `style="padding: var(--padding-md); border: 1px solid var(--border-color); border-radius: var(--border-radius); margin-top: var(--margin-sm);"`;
|
||||||
|
const title_style = `style="margin-top: 0; color: var(--text-color);"`;
|
||||||
|
const subtitle_style = `style="color: var(--text-color); margin-bottom: var(--margin-xs);"`;
|
||||||
|
const text_style = `style="margin-bottom: var(--margin-sm); color: var(--text-muted);"`;
|
||||||
|
const list_style = `style="margin-bottom: var(--margin-sm); color: var(--text-muted); font-size: 0.9em;"`;
|
||||||
|
const note_style = `style="margin-bottom: 0; color: var(--text-muted); font-size: 0.9em;"`;
|
||||||
|
const tip_style = `style="margin-bottom: 0; color: var(--text-color); font-size: 0.85em;"`;
|
||||||
|
|
||||||
|
let description_html = "";
|
||||||
|
|
||||||
|
if (data_source === "Account Data") {
|
||||||
|
description_html = `
|
||||||
|
<div ${container_style}>
|
||||||
|
<h5 ${title_style}>Account Filter Guide</h5>
|
||||||
|
<p ${text_style}>Specify which accounts to include in this line.</p>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Basic Examples:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li><code>["account_type", "=", "Cash"]</code> - All Cash accounts</li>
|
||||||
|
<li><code>["root_type", "in", ["Asset", "Liability"]]</code> - All Asset and Liability accounts</li>
|
||||||
|
<li><code>["account_category", "like", "Revenue"]</code> - Revenue accounts</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Multiple Conditions (AND/OR):</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li><code>{"and": [["root_type", "=", "Asset"], ["account_type", "=", "Cash"]]}</code></li>
|
||||||
|
<li><code>{"or": [["account_category", "like", "Revenue"], ["account_category", "like", "Income"]]}</code></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p ${note_style}><strong>Available operators:</strong> <code>=, !=, in, not in, like, not like, is</code></p>
|
||||||
|
<p ${tip_style}><strong>Multi-Company Tip:</strong> Use fields like <code>account_type</code>, <code>root_type</code>, and <code>account_category</code> for templates that work across multiple companies.</p>
|
||||||
|
</div>`;
|
||||||
|
} else if (data_source === "Calculated Amount") {
|
||||||
|
description_html = `
|
||||||
|
<div ${container_style}>
|
||||||
|
<h5 ${title_style}>Formula Guide</h5>
|
||||||
|
<p ${text_style}>Create calculations using reference codes from other lines.</p>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Basic Examples:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li><code>REV100 + REV200</code> - Add two revenue lines</li>
|
||||||
|
<li><code>ASSETS - LIABILITIES</code> - Calculate equity</li>
|
||||||
|
<li><code>REVENUE * 0.1</code> - 10% of revenue</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Common Functions:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li><code>abs(value)</code> - Remove negative sign</li>
|
||||||
|
<li><code>round(value)</code> - Round to whole number</li>
|
||||||
|
<li><code>max(val1, val2)</code> - Larger of two values</li>
|
||||||
|
<li><code>min(val1, val2)</code> - Smaller of two values</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p ${note_style}><strong>Required:</strong> Use "Reference Code" from other rows in your formulas.</p>
|
||||||
|
</div>`;
|
||||||
|
} else if (data_source === "Custom API") {
|
||||||
|
description_html = `
|
||||||
|
<div ${container_style}>
|
||||||
|
<h5 ${title_style}>Custom API Setup</h5>
|
||||||
|
<p ${text_style}>Path to your custom method that returns financial data.</p>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Format:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li><code>erpnext.custom.financial_apis.get_custom_revenue</code></li>
|
||||||
|
<li><code>my_app.financial_reports.get_kpi_data</code></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Return Format:</h6>
|
||||||
|
<p ${text_style}>Numbers for each period: <code>[1000.0, 1200.0, 1150.0]</code></p>
|
||||||
|
</div>`;
|
||||||
|
} else if (data_source === "Blank Line") {
|
||||||
|
description_html = `
|
||||||
|
<div ${container_style}>
|
||||||
|
<h5 ${title_style}>Blank Line</h5>
|
||||||
|
<p ${text_style}>Adds empty space for better visual separation.</p>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Use For:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li>Separating major sections</li>
|
||||||
|
<li>Adding space before totals</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p ${note_style}><strong>Note:</strong> No formula needed - creates visual spacing only.</p>
|
||||||
|
</div>`;
|
||||||
|
} else if (data_source === "Column Break") {
|
||||||
|
description_html = `
|
||||||
|
<div ${container_style}>
|
||||||
|
<h5 ${title_style}>Column Break</h5>
|
||||||
|
<p ${text_style}>Creates a visual break for side-by-side layout.</p>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Use For:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li>Horizontal P&L statements</li>
|
||||||
|
<li>Side-by-side Balance Sheet sections</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p ${note_style}><strong>Note:</strong> No formula needed - this is for formatting only.</p>
|
||||||
|
</div>`;
|
||||||
|
} else if (data_source === "Section Break") {
|
||||||
|
description_html = `
|
||||||
|
<div ${container_style}>
|
||||||
|
<h5 ${title_style}>Section Break</h5>
|
||||||
|
<p ${text_style}>Creates a visual break for separating different sections.</p>
|
||||||
|
|
||||||
|
<h6 ${subtitle_style}>Use For:</h6>
|
||||||
|
<ul ${list_style}>
|
||||||
|
<li>Separating major sections in a report - say trading & profit and loss</li>
|
||||||
|
<li>Improving readability by adding space</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p ${note_style}><strong>Note:</strong> No formula needed - this is for formatting only.</p>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.update_docfield_property("formula_description", "options", description_html);
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "field:template_name",
|
||||||
|
"creation": "2025-08-02 04:44:15.184541",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"template_name",
|
||||||
|
"report_type",
|
||||||
|
"module",
|
||||||
|
"column_break_lvnq",
|
||||||
|
"disabled",
|
||||||
|
"section_break_fvlw",
|
||||||
|
"rows"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"description": "Descriptive name for your template (e.g., 'Standard P&L', 'Detailed Balance Sheet')",
|
||||||
|
"fieldname": "template_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Template Name",
|
||||||
|
"reqd": 1,
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Type of financial statement this template generates",
|
||||||
|
"fieldname": "report_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Report Type",
|
||||||
|
"options": "\nProfit and Loss Statement\nBalance Sheet\nCash Flow\nCustom Financial Statement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:frappe.boot.developer_mode",
|
||||||
|
"fieldname": "module",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Module (for Export)",
|
||||||
|
"options": "Module Def"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_lvnq",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_fvlw",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 1,
|
||||||
|
"fieldname": "rows",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Report Line Items",
|
||||||
|
"options": "Financial Report Row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Disable template to prevent use in reports",
|
||||||
|
"fieldname": "disabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disabled"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grid_page_length": 50,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2025-11-14 00:11:03.508139",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Financial Report Template",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Accounts User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Auditor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"row_format": "Dynamic",
|
||||||
|
"sort_field": "creation",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"title_field": "template_name"
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.account_category.account_category import import_account_categories
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_validation import TemplateValidator
|
||||||
|
|
||||||
|
|
||||||
|
class FinancialReportTemplate(Document):
|
||||||
|
# begin: auto-generated types
|
||||||
|
# This code is auto-generated. Do not modify anything in this block.
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.financial_report_row.financial_report_row import FinancialReportRow
|
||||||
|
|
||||||
|
disabled: DF.Check
|
||||||
|
module: DF.Link | None
|
||||||
|
report_type: DF.Literal[
|
||||||
|
"", "Profit and Loss Statement", "Balance Sheet", "Cash Flow", "Custom Financial Statement"
|
||||||
|
]
|
||||||
|
rows: DF.Table[FinancialReportRow]
|
||||||
|
template_name: DF.Data
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
validator = TemplateValidator(self)
|
||||||
|
result = validator.validate()
|
||||||
|
result.notify_user()
|
||||||
|
|
||||||
|
def on_update(self):
|
||||||
|
self._export_template()
|
||||||
|
|
||||||
|
def on_trash(self):
|
||||||
|
self._delete_template()
|
||||||
|
|
||||||
|
def _export_template(self):
|
||||||
|
from frappe.modules.utils import export_module_json
|
||||||
|
|
||||||
|
if not self.module:
|
||||||
|
return
|
||||||
|
|
||||||
|
export_module_json(self, True, self.module)
|
||||||
|
self._export_account_categories()
|
||||||
|
|
||||||
|
def _delete_template(self):
|
||||||
|
if not self.module or not frappe.conf.developer_mode:
|
||||||
|
return
|
||||||
|
|
||||||
|
module_path = frappe.get_module_path(self.module)
|
||||||
|
dir_path = os.path.join(module_path, "financial_report_template", frappe.scrub(self.name))
|
||||||
|
|
||||||
|
shutil.rmtree(dir_path, ignore_errors=True)
|
||||||
|
|
||||||
|
def _export_account_categories(self):
|
||||||
|
import json
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_engine import (
|
||||||
|
FormulaFieldExtractor,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not self.module or not frappe.conf.developer_mode or frappe.flags.in_import:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Extract category from rows
|
||||||
|
extractor = FormulaFieldExtractor(
|
||||||
|
field_name="account_category", exclude_operators=["like", "not like"]
|
||||||
|
)
|
||||||
|
account_data_rows = [row for row in self.rows if row.data_source == "Account Data"]
|
||||||
|
category_names = extractor.extract_from_rows(account_data_rows)
|
||||||
|
|
||||||
|
if not category_names:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get path
|
||||||
|
module_path = frappe.get_module_path(self.module)
|
||||||
|
categories_file = os.path.join(module_path, "financial_report_template", "account_categories.json")
|
||||||
|
|
||||||
|
# Load existing categories
|
||||||
|
existing_categories = {}
|
||||||
|
if os.path.exists(categories_file):
|
||||||
|
try:
|
||||||
|
with open(categories_file) as f:
|
||||||
|
existing_data = json.load(f)
|
||||||
|
existing_categories = {cat["account_category_name"]: cat for cat in existing_data}
|
||||||
|
except (json.JSONDecodeError, KeyError):
|
||||||
|
pass # Create new file
|
||||||
|
|
||||||
|
# Fetch categories from database
|
||||||
|
if category_names:
|
||||||
|
db_categories = frappe.get_all(
|
||||||
|
"Account Category",
|
||||||
|
filters={"account_category_name": ["in", list(category_names)]},
|
||||||
|
fields=["account_category_name", "description"],
|
||||||
|
)
|
||||||
|
|
||||||
|
for cat in db_categories:
|
||||||
|
existing_categories[cat["account_category_name"]] = cat
|
||||||
|
|
||||||
|
# Sort by category name
|
||||||
|
sorted_categories = sorted(existing_categories.values(), key=lambda x: x["account_category_name"])
|
||||||
|
|
||||||
|
# Write to file
|
||||||
|
os.makedirs(os.path.dirname(categories_file), exist_ok=True)
|
||||||
|
with open(categories_file, "w") as f:
|
||||||
|
json.dump(sorted_categories, f, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
def sync_financial_report_templates(chart_of_accounts=None, existing_company=None):
|
||||||
|
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import get_chart
|
||||||
|
|
||||||
|
# If COA is being created for an existing company,
|
||||||
|
# skip syncing templates as they are likely already present
|
||||||
|
if existing_company:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Allow regional templates to completely override ERPNext
|
||||||
|
# templates based on the chart of accounts selected
|
||||||
|
disable_default_financial_report_template = False
|
||||||
|
if chart_of_accounts:
|
||||||
|
coa = get_chart(chart_of_accounts)
|
||||||
|
if coa.get("disable_default_financial_report_template", False):
|
||||||
|
disable_default_financial_report_template = True
|
||||||
|
|
||||||
|
installed_apps = frappe.get_installed_apps()
|
||||||
|
|
||||||
|
for app in installed_apps:
|
||||||
|
if disable_default_financial_report_template and app == "erpnext":
|
||||||
|
continue
|
||||||
|
|
||||||
|
_sync_templates_for(app)
|
||||||
|
|
||||||
|
|
||||||
|
def _sync_templates_for(app_name):
|
||||||
|
templates = []
|
||||||
|
|
||||||
|
for module_name in frappe.local.app_modules.get(app_name) or []:
|
||||||
|
module_path = frappe.get_module_path(module_name)
|
||||||
|
template_path = os.path.join(module_path, "financial_report_template")
|
||||||
|
|
||||||
|
if not os.path.isdir(template_path):
|
||||||
|
continue
|
||||||
|
|
||||||
|
import_account_categories(template_path)
|
||||||
|
|
||||||
|
for template_dir in os.listdir(template_path):
|
||||||
|
json_file = os.path.join(template_path, template_dir, f"{template_dir}.json")
|
||||||
|
if os.path.isfile(json_file):
|
||||||
|
templates.append(json_file)
|
||||||
|
|
||||||
|
if not templates:
|
||||||
|
return
|
||||||
|
|
||||||
|
# ensure files are not exported
|
||||||
|
frappe.flags.in_import = True
|
||||||
|
|
||||||
|
for template_path in templates:
|
||||||
|
with open(template_path) as f:
|
||||||
|
template_data = frappe._dict(frappe.parse_json(f.read()))
|
||||||
|
|
||||||
|
template_name = template_data.get("name")
|
||||||
|
|
||||||
|
if not frappe.db.exists("Financial Report Template", template_name):
|
||||||
|
doc = frappe.get_doc(template_data)
|
||||||
|
doc.flags.ignore_mandatory = True
|
||||||
|
doc.flags.ignore_permissions = True
|
||||||
|
doc.flags.ignore_validate = True
|
||||||
|
doc.insert()
|
||||||
|
|
||||||
|
frappe.flags.in_import = False
|
||||||
@@ -0,0 +1,545 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any, ClassVar
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.database.operator_map import OPERATOR_MAP
|
||||||
|
from frappe.database.query import SQLFunctionParser
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ValidationIssue:
|
||||||
|
"""Represents a single validation issue"""
|
||||||
|
|
||||||
|
message: str
|
||||||
|
row_idx: int | None = None
|
||||||
|
field: str | None = None
|
||||||
|
details: dict[str, Any] = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.details is None:
|
||||||
|
self.details = {}
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
prefix = f"Row {self.row_idx}: " if self.row_idx else ""
|
||||||
|
field_info = f"[{self.field}] " if self.field else ""
|
||||||
|
message = f"{prefix}{field_info}{self.message}"
|
||||||
|
return _(message)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ValidationResult:
|
||||||
|
issues: list[ValidationIssue] = field(default_factory=list)
|
||||||
|
warnings: list[ValidationIssue] = field(default_factory=list)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_valid(self) -> bool:
|
||||||
|
return len(self.issues) == 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_warnings(self) -> bool:
|
||||||
|
return len(self.warnings) > 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def error_count(self) -> int:
|
||||||
|
return len(self.issues)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def warning_count(self) -> int:
|
||||||
|
return len(self.warnings)
|
||||||
|
|
||||||
|
def merge(self, other: "ValidationResult") -> "ValidationResult":
|
||||||
|
self.issues.extend(other.issues)
|
||||||
|
self.warnings.extend(other.warnings)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_error(self, issue: ValidationIssue) -> None:
|
||||||
|
"""Add a critical error that prevents functionality"""
|
||||||
|
self.issues.append(issue)
|
||||||
|
|
||||||
|
def add_warning(self, issue: ValidationIssue) -> None:
|
||||||
|
"""Add a warning for recommendatory validation"""
|
||||||
|
self.warnings.append(issue)
|
||||||
|
|
||||||
|
def notify_user(self) -> None:
|
||||||
|
warnings = "<br><br>".join(str(w) for w in self.warnings)
|
||||||
|
errors = "<br><br>".join(str(e) for e in self.issues)
|
||||||
|
|
||||||
|
if warnings:
|
||||||
|
frappe.msgprint(warnings, title=_("Warnings"), indicator="orange")
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
frappe.throw(errors, title=_("Errors"))
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateValidator:
|
||||||
|
"""Main validator that orchestrates all validations"""
|
||||||
|
|
||||||
|
def __init__(self, template):
|
||||||
|
self.template = template
|
||||||
|
self.validators = [
|
||||||
|
TemplateStructureValidator(),
|
||||||
|
DependencyValidator(template),
|
||||||
|
]
|
||||||
|
self.formula_validator = FormulaValidator(template)
|
||||||
|
|
||||||
|
def validate(self) -> ValidationResult:
|
||||||
|
result = ValidationResult([])
|
||||||
|
|
||||||
|
# Run template-level validators
|
||||||
|
for validator in self.validators:
|
||||||
|
result.merge(validator.validate(self.template))
|
||||||
|
|
||||||
|
# Run row-level validations
|
||||||
|
account_fields = {field.fieldname for field in frappe.get_meta("Account").fields}
|
||||||
|
for row in self.template.rows:
|
||||||
|
result.merge(self.formula_validator.validate(row, account_fields))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class Validator(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def validate(self, context: Any) -> ValidationResult:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateStructureValidator(Validator):
|
||||||
|
def validate(self, template) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
result.merge(self._validate_reference_codes(template))
|
||||||
|
result.merge(self._validate_required_fields(template))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _validate_reference_codes(self, template) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
used_codes = set()
|
||||||
|
|
||||||
|
for row in template.rows:
|
||||||
|
if not row.reference_code:
|
||||||
|
continue
|
||||||
|
|
||||||
|
ref_code = row.reference_code.strip()
|
||||||
|
|
||||||
|
# Check format
|
||||||
|
if not re.match(r"^[A-Za-z][A-Za-z0-9_-]*$", ref_code):
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Invalid line reference format: '{ref_code}'. Must start with letter and contain only letters, numbers, underscores, and hyphens",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check uniqueness
|
||||||
|
if ref_code in used_codes:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Duplicate line reference: '{ref_code}'",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
used_codes.add(ref_code)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _validate_required_fields(self, template) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
for row in template.rows:
|
||||||
|
# Balance type required
|
||||||
|
if row.data_source == "Account Data" and not row.balance_type:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message="Balance Type is required for Account Data",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Calculation formula required
|
||||||
|
if row.data_source in ["Account Data", "Calculated Amount", "Custom API"]:
|
||||||
|
if not row.calculation_formula:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Formula is required for {row.data_source}",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class DependencyValidator(Validator):
|
||||||
|
def __init__(self, template):
|
||||||
|
self.template = template
|
||||||
|
self.dependencies = self._build_dependency_graph()
|
||||||
|
|
||||||
|
def validate(self, context=None) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
result.merge(self._validate_circular_dependencies())
|
||||||
|
result.merge(self._validate_missing_dependencies())
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _build_dependency_graph(self) -> dict[str, list[str]]:
|
||||||
|
graph = {}
|
||||||
|
available_codes = {row.reference_code for row in self.template.rows if row.reference_code}
|
||||||
|
|
||||||
|
for row in self.template.rows:
|
||||||
|
if row.reference_code and row.data_source == "Calculated Amount" and row.calculation_formula:
|
||||||
|
deps = extract_reference_codes_from_formula(row.calculation_formula, list(available_codes))
|
||||||
|
if deps:
|
||||||
|
graph[row.reference_code] = deps
|
||||||
|
|
||||||
|
return graph
|
||||||
|
|
||||||
|
def _validate_circular_dependencies(self) -> ValidationResult:
|
||||||
|
"""
|
||||||
|
Efficient cycle detection using DFS (Depth-First Search) with three-color algorithm:
|
||||||
|
- WHITE (0): unvisited node
|
||||||
|
- GRAY (1): currently being processed (on recursion stack)
|
||||||
|
- BLACK (2): fully processed
|
||||||
|
|
||||||
|
Example cycle detection:
|
||||||
|
A → B → C → A (cycle detected when A is GRAY and visited again)
|
||||||
|
"""
|
||||||
|
result = ValidationResult()
|
||||||
|
WHITE, GRAY, BLACK = 0, 1, 2
|
||||||
|
colors = {node: WHITE for node in self.dependencies}
|
||||||
|
|
||||||
|
def dfs(node, path):
|
||||||
|
if node not in colors:
|
||||||
|
return # External dependency
|
||||||
|
|
||||||
|
if colors[node] == GRAY:
|
||||||
|
# Found cycle
|
||||||
|
cycle_start = path.index(node)
|
||||||
|
cycle = [*path[cycle_start:], node]
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Circular dependency detected: {' → '.join(cycle)}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if colors[node] == BLACK:
|
||||||
|
return # Already processed
|
||||||
|
|
||||||
|
colors[node] = GRAY
|
||||||
|
path.append(node)
|
||||||
|
|
||||||
|
for neighbor in self.dependencies.get(node, []):
|
||||||
|
dfs(neighbor, path.copy())
|
||||||
|
|
||||||
|
colors[node] = BLACK
|
||||||
|
|
||||||
|
for node in self.dependencies:
|
||||||
|
if colors[node] == WHITE:
|
||||||
|
dfs(node, [])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _validate_missing_dependencies(self) -> ValidationResult:
|
||||||
|
available = {row.reference_code for row in self.template.rows if row.reference_code}
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
for ref_code, deps in self.dependencies.items():
|
||||||
|
undefined = [d for d in deps if d not in available]
|
||||||
|
if undefined:
|
||||||
|
row_idx = self._get_row_idx(ref_code)
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Line References undefined in Formula: {', '.join(undefined)}",
|
||||||
|
row_idx=row_idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _get_row_idx(self, reference_code: str) -> int | None:
|
||||||
|
for row in self.template.rows:
|
||||||
|
if row.reference_code == reference_code:
|
||||||
|
return row.idx
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class CalculationFormulaValidator(Validator):
|
||||||
|
"""Validates calculation formulas used in Calculated Amount rows"""
|
||||||
|
|
||||||
|
def __init__(self, reference_codes: set[str]):
|
||||||
|
self.reference_codes = reference_codes
|
||||||
|
|
||||||
|
def validate(self, row) -> ValidationResult:
|
||||||
|
"""Validate calculation formula for a single row"""
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
if row.data_source != "Calculated Amount":
|
||||||
|
return result
|
||||||
|
|
||||||
|
if not row.calculation_formula:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message="Formula is required for Calculated Amount",
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Formula",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
formula = self._preprocess_formula(row.calculation_formula)
|
||||||
|
row.calculation_formula = formula
|
||||||
|
|
||||||
|
# Check parentheses
|
||||||
|
if not self._are_parentheses_balanced(formula):
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message="Formula has unbalanced parentheses",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Check self-reference
|
||||||
|
available_codes = list(self.reference_codes)
|
||||||
|
refs = extract_reference_codes_from_formula(formula, available_codes)
|
||||||
|
if row.reference_code and row.reference_code in refs:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Formula references itself ('{row.reference_code}')",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check undefined references
|
||||||
|
undefined = set(refs) - set(available_codes)
|
||||||
|
if undefined:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Formula references undefined codes: {', '.join(undefined)}",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try to evaluate with dummy values
|
||||||
|
eval_error = self._test_formula_evaluation(formula, available_codes)
|
||||||
|
if eval_error:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Formula evaluation error: {eval_error}",
|
||||||
|
row_idx=row.idx,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _preprocess_formula(self, formula: str) -> str:
|
||||||
|
if not formula or not isinstance(formula, str):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return formula.strip()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _are_parentheses_balanced(formula: str) -> bool:
|
||||||
|
return formula.count("(") == formula.count(")")
|
||||||
|
|
||||||
|
def _test_formula_evaluation(self, formula: str, available_codes: list[str]) -> str | None:
|
||||||
|
try:
|
||||||
|
context = {code: 1.0 for code in available_codes}
|
||||||
|
context.update(
|
||||||
|
{
|
||||||
|
"abs": abs,
|
||||||
|
"round": round,
|
||||||
|
"min": min,
|
||||||
|
"max": max,
|
||||||
|
"sum": sum,
|
||||||
|
"sqrt": lambda x: x**0.5,
|
||||||
|
"pow": pow,
|
||||||
|
"ceil": lambda x: int(x) + (1 if x % 1 else 0),
|
||||||
|
"floor": lambda x: int(x),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result = frappe.safe_eval(formula, eval_globals=None, eval_locals=context)
|
||||||
|
|
||||||
|
if not isinstance(result, (int, float)): # noqa: UP038
|
||||||
|
return f"Formula must return a numeric value, got {type(result).__name__}"
|
||||||
|
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
|
class AccountFilterValidator(Validator):
|
||||||
|
"""Validates account filter expressions used in Account Data rows"""
|
||||||
|
|
||||||
|
def __init__(self, account_fields: set | None = None):
|
||||||
|
self.account_fields = account_fields or set(frappe.get_meta("Account")._valid_columns)
|
||||||
|
|
||||||
|
def validate(self, row) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
if row.data_source != "Account Data":
|
||||||
|
return result
|
||||||
|
|
||||||
|
if not row.calculation_formula:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message="Account filter is required for Account Data",
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Formula",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
try:
|
||||||
|
filter_config = json.loads(row.calculation_formula)
|
||||||
|
error = self._validate_filter_structure(filter_config, self.account_fields)
|
||||||
|
|
||||||
|
if error:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=error,
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Account Filter",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Invalid JSON format: {e!s}",
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Account Filter",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _validate_filter_structure(self, filter_config, account_fields: set) -> str | None:
|
||||||
|
# simple condition: [field, operator, value]
|
||||||
|
if isinstance(filter_config, list):
|
||||||
|
if len(filter_config) != 3:
|
||||||
|
return "Filter must be [field, operator, value]"
|
||||||
|
|
||||||
|
field, operator, value = filter_config
|
||||||
|
|
||||||
|
if not isinstance(field, str) or not isinstance(operator, str):
|
||||||
|
return "Field and operator must be strings"
|
||||||
|
|
||||||
|
if field not in account_fields:
|
||||||
|
return f"Field '{field}' is not a valid account field"
|
||||||
|
|
||||||
|
if operator.casefold() not in OPERATOR_MAP:
|
||||||
|
return f"Invalid operator '{operator}'"
|
||||||
|
|
||||||
|
if operator in ["in", "not in"] and not isinstance(value, list):
|
||||||
|
return f"Operator '{operator}' requires a list value"
|
||||||
|
|
||||||
|
# logical condition: {"and": [condition1, condition2]}
|
||||||
|
elif isinstance(filter_config, dict):
|
||||||
|
if len(filter_config) != 1:
|
||||||
|
return "Logical condition must have exactly one operator"
|
||||||
|
|
||||||
|
op = next(iter(filter_config.keys())).lower()
|
||||||
|
if op not in ["and", "or"]:
|
||||||
|
return "Logical operators must be 'and' or 'or'"
|
||||||
|
|
||||||
|
conditions = filter_config[next(iter(filter_config.keys()))]
|
||||||
|
if not isinstance(conditions, list) or len(conditions) < 1:
|
||||||
|
return "Logical conditions need at least 1 sub-condition"
|
||||||
|
|
||||||
|
# recursive
|
||||||
|
for condition in conditions:
|
||||||
|
error = self._validate_filter_structure(condition, account_fields)
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
else:
|
||||||
|
return "Filter must be a list or dict"
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class FormulaValidator(Validator):
|
||||||
|
def __init__(self, template):
|
||||||
|
self.template = template
|
||||||
|
reference_codes = {row.reference_code for row in template.rows if row.reference_code}
|
||||||
|
self.calculation_validator = CalculationFormulaValidator(reference_codes)
|
||||||
|
self.account_filter_validator = AccountFilterValidator()
|
||||||
|
|
||||||
|
def validate(self, row, account_fields: set) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
|
||||||
|
if not row.calculation_formula:
|
||||||
|
return result
|
||||||
|
|
||||||
|
if row.data_source == "Calculated Amount":
|
||||||
|
return self.calculation_validator.validate(row)
|
||||||
|
|
||||||
|
elif row.data_source == "Account Data":
|
||||||
|
# Update account fields if provided
|
||||||
|
if account_fields:
|
||||||
|
self.account_filter_validator.account_fields = account_fields
|
||||||
|
return self.account_filter_validator.validate(row)
|
||||||
|
|
||||||
|
elif row.data_source == "Custom API":
|
||||||
|
result.merge(self._validate_custom_api(row))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _validate_custom_api(self, row) -> ValidationResult:
|
||||||
|
result = ValidationResult()
|
||||||
|
api_path = row.calculation_formula
|
||||||
|
|
||||||
|
if "." not in api_path:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message="Custom API path should be in format: app.module.method",
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Formula",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Method exists?
|
||||||
|
try:
|
||||||
|
module_path, method_name = api_path.rsplit(".", 1)
|
||||||
|
module = frappe.get_module(module_path)
|
||||||
|
|
||||||
|
if not hasattr(module, method_name):
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Method '{method_name}' not found in module '{module_path}' (might be environment-specific)",
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Formula",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(
|
||||||
|
ValidationIssue(
|
||||||
|
message=f"Could not validate API path: {e!s}",
|
||||||
|
row_idx=row.idx,
|
||||||
|
field="Formula",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def extract_reference_codes_from_formula(formula: str, available_codes: list[str]) -> list[str]:
|
||||||
|
found_codes = []
|
||||||
|
for code in available_codes:
|
||||||
|
# Match complete words only to avoid partial matches
|
||||||
|
pattern = r"\b" + re.escape(code) + r"\b"
|
||||||
|
if re.search(pattern, formula):
|
||||||
|
found_codes.append(code)
|
||||||
|
return found_codes
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.tests import IntegrationTestCase
|
||||||
|
from frappe.tests.utils import make_test_records
|
||||||
|
|
||||||
|
# On IntegrationTestCase, the doctype test records and all
|
||||||
|
# link-field test record dependencies are recursively loaded
|
||||||
|
# Use these module variables to add/remove to/from that list
|
||||||
|
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
|
||||||
|
|
||||||
|
class TestFinancialReportTemplate(IntegrationTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FinancialReportTemplateTestCase(IntegrationTestCase):
|
||||||
|
"""Utility class with common setup and helper methods for all test classes"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
"""Set up test data"""
|
||||||
|
make_test_records("Company")
|
||||||
|
make_test_records("Fiscal Year")
|
||||||
|
cls.create_test_template()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_test_template(cls):
|
||||||
|
"""Create a test financial report template"""
|
||||||
|
if not frappe.db.exists("Financial Report Template", "Test P&L Template"):
|
||||||
|
template = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Financial Report Template",
|
||||||
|
"template_name": "Test P&L Template",
|
||||||
|
"report_type": "Profit and Loss Statement",
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"reference_code": "INC001",
|
||||||
|
"display_name": "Income",
|
||||||
|
"indentation_level": 0,
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": '["root_type", "=", "Income"]',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference_code": "EXP001",
|
||||||
|
"display_name": "Expenses",
|
||||||
|
"indentation_level": 0,
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": '["root_type", "=", "Expense"]',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference_code": "NET001",
|
||||||
|
"display_name": "Net Profit/Loss",
|
||||||
|
"indentation_level": 0,
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "INC001 - EXP001",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
template.insert()
|
||||||
|
|
||||||
|
cls.test_template = frappe.get_doc("Financial Report Template", "Test P&L Template")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_test_template_with_rows(rows_data):
|
||||||
|
"""Helper method to create test template with specific rows"""
|
||||||
|
template_name = f"Test Template {frappe.generate_hash()[:8]}"
|
||||||
|
template = frappe.get_doc(
|
||||||
|
{"doctype": "Financial Report Template", "template_name": template_name, "rows": rows_data}
|
||||||
|
)
|
||||||
|
return template
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"account_category_name": "Cash and Cash Equivalents",
|
||||||
|
"description": "Cash on hand, demand deposits, and short-term highly liquid investments readily convertible to cash with original maturities of three months or less. Examples: Cash in hand, bank current accounts, money market funds, treasury bills \u22643 months."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Cost of Goods Sold",
|
||||||
|
"description": "Direct costs attributable to cost of goods sold. Examples: Raw materials, stock in trade."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Current Tax Liabilities",
|
||||||
|
"description": "Income tax obligations for current and prior periods. Examples: Provision for income tax, advance tax paid, tax deducted at source."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Finance Costs",
|
||||||
|
"description": "Interest and financing-related expenses. Examples: Interest on borrowings, bank charges, lease interest, foreign exchange losses."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Intangible Assets",
|
||||||
|
"description": "Identifiable non-monetary assets without physical substance. Examples: Software, patents, trademarks, licenses, development costs."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Investment Income",
|
||||||
|
"description": "Returns generated from financial investments and cash management. Examples: Interest income, dividend income, rental income, fair value gains."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Long-term Borrowings",
|
||||||
|
"description": "Interest-bearing debt obligations with maturity beyond one year. Examples: Term loans, bonds, debentures, mortgages."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Long-term Investments",
|
||||||
|
"description": "Investments held for strategic purposes or extended periods. Examples: Equity investments, bonds, associates, joint ventures, deposits."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Long-term Provisions",
|
||||||
|
"description": "Present obligations beyond one year with uncertain timing/amount. Examples: Asset retirement obligations, environmental remediation, legal settlements."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Operating Expenses",
|
||||||
|
"description": "Costs incurred in ordinary business operations excluding direct costs. Examples: Selling expenses, administrative costs, marketing, utilities, rent."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Current Assets",
|
||||||
|
"description": "Current assets not classified elsewhere including prepaid expenses and advances. Examples: Prepaid insurance, prepaid rent, advance to suppliers, security deposits recoverable within one year."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Current Liabilities",
|
||||||
|
"description": "Short-term obligations not classified elsewhere. Examples: Accrued expenses, statutory liabilities, employee payables."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Direct Costs",
|
||||||
|
"description": "Direct costs excluding cost of goods sold. Examples: Direct labor, manufacturing overhead, freight inward."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Non-current Assets",
|
||||||
|
"description": "Long-term assets not classified elsewhere. Examples: Security deposits, long-term prepayments, advances for capital goods."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Non-current Liabilities",
|
||||||
|
"description": "Long-term obligations not classified elsewhere. Examples: Long-term deposits, deferred income, government grants."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Operating Income",
|
||||||
|
"description": "Incidental income related to business operations but not core revenue. Examples: Scrap sales, government grants, insurance claims, foreign exchange gains."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Payables",
|
||||||
|
"description": "Non-trade payables and obligations to parties other than suppliers. Examples: Employee payables, accrued expenses, customer advances, security deposits received."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Other Receivables",
|
||||||
|
"description": "Non-trade amounts due to the entity excluding financing arrangements. Examples: Employee advances, insurance claims, tax refunds, deposits recoverable."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Reserves and Surplus",
|
||||||
|
"description": "Accumulated profits and other reserves created from profits or share premium. Examples: General reserves, retained earnings, statutory reserves, share premium."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Revenue from Operations",
|
||||||
|
"description": "Income from primary business activities in ordinary course. Examples: Sales of goods, service revenue, commission income, royalty income."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Share Capital",
|
||||||
|
"description": "Nominal value of issued and paid-up equity shares. Examples: Common stock, ordinary shares, preference shares."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Short-term Borrowings",
|
||||||
|
"description": "Interest-bearing debt obligations due within one year. Examples: Bank overdrafts, short-term loans, current portion of long-term debt."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Short-term Investments",
|
||||||
|
"description": "Financial instruments held for short-term investment purposes, readily convertible to cash. Examples: Marketable securities, fixed deposits >3 months, mutual funds."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Short-term Provisions",
|
||||||
|
"description": "Present obligations due within one year with uncertain timing or amount. Examples: Warranty provisions, legal claims, restructuring costs."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Stock Assets",
|
||||||
|
"description": "Inventory and stock-related assets including raw materials, work in progress, finished goods, and stock in trade. Examples: Raw materials, finished goods, trading merchandise, consumables."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Tangible Assets",
|
||||||
|
"description": "Physical assets used in business operations including property, plant, and equipment. Examples: Land, buildings, machinery, equipment, vehicles, furniture, capital work in progress."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Tax Expense",
|
||||||
|
"description": "Current and deferred income tax obligations. Examples: Current tax provision, deferred tax expense, withholding taxes."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Trade Payables",
|
||||||
|
"description": "Amounts owed to suppliers. Examples: Supplier invoices, accrued purchases, bills payable."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_category_name": "Trade Receivables",
|
||||||
|
"description": "Amounts due from customers for goods sold or services provided in ordinary course of business. Examples: Accounts receivable, notes receivable from customers, unbilled revenue."
|
||||||
|
}
|
||||||
|
]
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,993 @@
|
|||||||
|
{
|
||||||
|
"creation": "2025-09-07 07:24:40.762641",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Financial Report Template",
|
||||||
|
"idx": 0,
|
||||||
|
"modified": "2025-10-15 03:12:19.165699",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Horizontal Balance Sheet (Columnar)",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"report_type": "Balance Sheet",
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Section Break",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Column Break",
|
||||||
|
"display_name": "Equity & Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Capital & Reserves",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CAPITAL_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Share Capital\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Share Capital",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_SHARE_CAPITAL",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\":[[\"account_category\",\"=\",\"Reserves and Surplus\"],[\"account_name\",\"not like\",\"%Retained Earnings%\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Reserves & Surplus",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_RESERVES",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\":[[\"account_name\",\"like\",\"%Retained Earnings%\"],[\"account_category\",\"=\",\"Reserves and Surplus\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Retained Earnings",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_RETAINED_EARNINGS",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "L_SHARE_CAPITAL + L_RESERVES + L_RETAINED_EARNINGS",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Capital & Reserves",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "L_TOTAL_EQUITY",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Non-Current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCL_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Long-term Borrowings\"], [\"account_name\", \"not like\", \"Unsecured\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Secured Loans",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_SECURED_LOANS",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Long-term Borrowings\"], [\"account_name\", \"like\", \"Unsecured\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Unsecured Loans",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_UNSECURED_LOANS",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Long-term Provisions\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Long-term Provisions",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_LT_PROVISIONS",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Non-current Liabilities\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Non-current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_OTHER_NCL",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "L_SECURED_LOANS + L_UNSECURED_LOANS + L_LT_PROVISIONS + L_OTHER_NCL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Non-current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "L_TOTAL_NCL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Short-term Borrowings\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Short-term Borrowings",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_ST_BORROWINGS",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Trade Payables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Trade Payables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_TRADE_PAYABLES",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Payables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Payables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_OTHER_PAYABLES",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Current Tax Liabilities\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Current Tax Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_TAX_LIABILITIES",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Short-term Provisions\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Short-term Provisions",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_PROVISIONS",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Current Liabilities\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_OTHER_CL",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "L_ST_BORROWINGS + L_TRADE_PAYABLES + L_OTHER_PAYABLES + L_TAX_LIABILITIES + L_PROVISIONS + L_OTHER_CL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "L_TOTAL_CL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Current Year Earnings",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "PL_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "[\"root_type\", \"in\", [\"Income\", \"Expense\"]]",
|
||||||
|
"color": "#28a745",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Net Profit/(Loss) for the Year",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_CURRENT_PL",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Column Break",
|
||||||
|
"display_name": "Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Non-Current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCA_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Tangible Assets\"], [\"account_type\", \"!=\", \"Accumulated Depreciation\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Property, Plant & Equipment",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_TANGIBLE",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_type\", \"like\", \"Accumulated Depreciation\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Less: Accumulated Depreciation",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 2,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "A_ACC_DEPRECIATION",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "A_TANGIBLE - A_ACC_DEPRECIATION",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Net Tangible Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_NET_TANGIBLE",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Intangible Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Intangible Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_INTANGIBLE",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Long-term Investments\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Long-term Investments",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_LT_INVESTMENTS",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Non-current Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Non-current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_OTHER_NCA",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "(A_NET_TANGIBLE if A_ACC_DEPRECIATION else A_TANGIBLE) + A_INTANGIBLE + A_LT_INVESTMENTS + A_OTHER_NCA",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Non-current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "A_TOTAL_NCA",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Stock Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Inventories",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_STOCK",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Trade Receivables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Trade Receivables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_TRADE_RECEIVABLES",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Receivables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Receivables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_OTHER_RECEIVABLES",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Short-term Investments\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Short-term Investments",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_ST_INVESTMENTS",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Cash and Cash Equivalents\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Cash & Bank Balances",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_CASH_BANK",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Current Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_OTHER_CA",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "A_STOCK + A_TRADE_RECEIVABLES + A_OTHER_RECEIVABLES + A_ST_INVESTMENTS + A_CASH_BANK + A_OTHER_CA",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "A_TOTAL_CA",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Section Break",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "L_TOTAL_EQUITY + L_TOTAL_NCL + L_TOTAL_CL + L_CURRENT_PL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "TOTAL",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "L_GRAND_TOTAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Column Break",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "A_TOTAL_NCA + A_TOTAL_CA",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "TOTAL",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "A_GRAND_TOTAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Section Break",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "L_GRAND_TOTAL - A_GRAND_TOTAL",
|
||||||
|
"color": "#EC864B",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Balance Check (should be zero)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 1,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "BALANCE_CHECK",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "A_TOTAL_NCA + A_TOTAL_CA",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TOTAL_ASSETS",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "L_TOTAL_NCL + L_TOTAL_CL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TOTAL_LIABILITIES",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "L_TOTAL_EQUITY + L_CURRENT_PL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Equity",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TOTAL_EQUITY",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "KEY FINANCIAL RATIOS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "METRICS_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(A_TOTAL_CA / L_TOTAL_CL) if L_TOTAL_CL != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Current Ratio",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CURRENT_RATIO",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "((A_TRADE_RECEIVABLES + A_ST_INVESTMENTS + A_CASH_BANK) / L_TOTAL_CL) if L_TOTAL_CL != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Quick Ratio (Acid Test)",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "QUICK_RATIO",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "((L_SECURED_LOANS + L_UNSECURED_LOANS + L_ST_BORROWINGS) / TOTAL_EQUITY) if TOTAL_EQUITY != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Debt to Equity Ratio",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "DEBT_EQUITY_RATIO",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "A_TOTAL_CA - L_TOTAL_CL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Net Working Capital",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "WORKING_CAPITAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(TOTAL_EQUITY / TOTAL_ASSETS * 100) if TOTAL_ASSETS != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Equity Ratio %",
|
||||||
|
"fieldtype": "Percent",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "EQUITY_RATIO",
|
||||||
|
"reverse_sign": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"template_name": "Horizontal Balance Sheet (Columnar)"
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,824 @@
|
|||||||
|
{
|
||||||
|
"creation": "2025-09-06 21:47:56.970556",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Financial Report Template",
|
||||||
|
"idx": 0,
|
||||||
|
"modified": "2025-10-15 03:13:38.485684",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Standard Balance Sheet (IFRS)",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"report_type": "Balance Sheet",
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "ASSETS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "ASSETS_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "CURRENT ASSETS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Cash and Cash Equivalents\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Cash and Cash Equivalents",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA100",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Trade Receivables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Trade Receivables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA200",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Receivables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Receivables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA300",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Stock Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Inventories",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA400",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Short-term Investments\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Short-term Investments",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA500",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Current Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CA600",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CA100 + CA200 + CA300 + CA400 + CA500 + CA600",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CA_TOTAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "NON-CURRENT ASSETS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCA_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Tangible Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Property, Plant and Equipment",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCA100",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Intangible Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Intangible Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCA200",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Long-term Investments\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Long-term Investments",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCA300",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Non-current Assets\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Non-current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCA400",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "NCA100 + NCA200 + NCA300 + NCA400",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Non-current Assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "NCA_TOTAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CA_TOTAL + NCA_TOTAL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "TOTAL ASSETS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TOTAL_ASSETS",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "LIABILITIES AND EQUITY",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "LIAB_EQUITY_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "CURRENT LIABILITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Trade Payables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Trade Payables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Payables\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Payables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Short-term Borrowings\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Short-term Borrowings",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Current Tax Liabilities\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Current Tax Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL400",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Short-term Provisions\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Short-term Provisions",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL500",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Current Liabilities\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CL600",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CL100 + CL200 + CL300 + CL400 + CL500 + CL600",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CL_TOTAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "NON-CURRENT LIABILITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCL_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Long-term Borrowings\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Long-term Borrowings",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCL100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Long-term Provisions\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Long-term Provisions",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCL200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Non-current Liabilities\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Non-current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NCL300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "NCL100 + NCL200 + NCL300",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Non-current Liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "NCL_TOTAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CL_TOTAL + NCL_TOTAL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "TOTAL LIABILITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TOTAL_LIABILITIES",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "EQUITY",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "EQ_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Share Capital\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Share Capital",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "EQ100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Reserves and Surplus\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Reserves and Surplus",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "EQ200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"root_type\", \"in\", [\"Income\", \"Expense\"]]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Provisional Profit and Loss",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 1,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "EQ300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "EQ100 + EQ200 + EQ300",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Total Equity",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "TOTAL_EQUITY",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "TOTAL_EQUITY",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "TOTAL EQUITY",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "TOTAL_LIABILITIES + TOTAL_EQUITY",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "TOTAL LIABILITIES AND EQUITY",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TOTAL_LIAB_EQUITY",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "TOTAL_ASSETS - TOTAL_LIAB_EQUITY",
|
||||||
|
"color": "#CB2929",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Balance Check (should be zero)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 1,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "BALANCE_CHECK",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "CA_TOTAL / CL_TOTAL if CL_TOTAL != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Current Ratio",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CURRENT_RATIO",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(CL300 + NCL100) / TOTAL_EQUITY if TOTAL_EQUITY != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Debt to Equity Ratio",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "DEBT_EQUITY_RATIO",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "CA_TOTAL - CL_TOTAL",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Working Capital",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "WORKING_CAPITAL",
|
||||||
|
"reverse_sign": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"template_name": "Standard Balance Sheet (IFRS)"
|
||||||
|
}
|
||||||
@@ -0,0 +1,832 @@
|
|||||||
|
{
|
||||||
|
"creation": "2025-09-07 22:45:05.754628",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Financial Report Template",
|
||||||
|
"idx": 0,
|
||||||
|
"modified": "2025-10-27 08:25:12.870928",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Standard Cash Flow Statement (IFRS)",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"report_type": "Cash Flow",
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "CASH FLOWS FROM OPERATING ACTIVITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_OP_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"root_type\", \"in\", [\"Income\", \"Expense\"]], [\"account_category\", \"!=\", \"Tax Expense\"]]}",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Profit before tax",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_OP100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Adjustments for:",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_ADJ_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_type\", \"=\", \"Depreciation\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Depreciation and amortization",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_ADJ100",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Finance Costs\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Finance costs",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_ADJ200",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Investment Income\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Investment income",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_ADJ300",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_OP100 + CF_ADJ100 + CF_ADJ200 + CF_ADJ300",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Operating profit before working capital changes",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_OP_BEFORE_WC",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "Working capital changes:",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_WC_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Trade Receivables\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "(Increase)/decrease in trade receivables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_WC100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Stock Assets\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "(Increase)/decrease in inventories",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_WC200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"in\", [\"Other Receivables\", \"Other Current Assets\"]]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "(Increase)/decrease in other current assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_WC300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Trade Payables\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Increase/(decrease) in trade payables",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_WC400",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"in\", [\"Other Payables\", \"Current Tax Liabilities\", \"Short-term Borrowings\", \"Short-term Provisions\", \"Other Current Liabilities\"]]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Increase/(decrease) in other current liabilities",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_WC500",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_OP_BEFORE_WC + CF_WC100 + CF_WC200 + CF_WC300 + CF_WC400 + CF_WC500",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Cash generated from operations",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_CASH_GEN",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Finance Costs\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Interest paid",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_OP200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Tax Expense\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Income taxes paid",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_OP300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_CASH_GEN + CF_OP200 + CF_OP300",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "NET CASH FROM OPERATING ACTIVITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_OP_NET",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "CASH FLOWS FROM INVESTING ACTIVITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Tangible Assets\"], [\"account_type\", \"!=\", \"Accumulated Depreciation\"]]}",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Purchase / Sale of property, plant and equipment",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_type\", \"=\", \"Accumulated Depreciation\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Accumulated Depreciation",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV101",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "max(0, CF_ADJ100 - CF_INV101)",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Depreciation and amortization",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 1,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 1,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_INV102",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Intangible Assets\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Purchase of intangible assets",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"in\", [\"Long-term Investments\", \"Short-term Investments\"]]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Purchase of investments",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Investment Income\"], [\"account_name\", \"not like\", \"dividend\"]]}",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Interest received",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV400",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Investment Income\"], [\"account_name\", \"like\", \"dividend\"]]}",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Dividends received",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV500",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_INV100 + CF_INV102 + CF_INV200 + CF_INV300 + CF_INV400 + CF_INV500",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "NET CASH FROM INVESTING ACTIVITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_INV_NET",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "CASH FLOWS FROM FINANCING ACTIVITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_FIN_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"in\", [\"Share Capital\", \"Reserves and Surplus\"]], [\"account_name\", \"not like\", \"Dividends Paid\"]]}",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Proceeds from issue of share capital",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_FIN100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"in\", [\"Long-term Borrowings\", \"Short-term Borrowings\"]]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Proceeds from / Repayment of borrowings",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_FIN200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"in\", [\"Share Capital\", \"Reserves and Surplus\"]], [\"account_name\", \"like\", \"Dividends Paid\"]]}",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Dividends paid",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_FIN300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_FIN100 + CF_FIN200 + CF_FIN300",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "NET CASH FROM FINANCING ACTIVITIES",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_FIN_NET",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_OP_NET + CF_INV_NET + CF_FIN_NET",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "NET INCREASE/(DECREASE) IN CASH AND CASH EQUIVALENTS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_NET_INCREASE",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Opening Balance",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Cash and Cash Equivalents\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Cash and cash equivalents at beginning of period",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_CASH_BEGIN",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_type\", \"like\", \"Exchange\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Effect of exchange rate changes",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_FX_EFFECT",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Closing Balance",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Cash and Cash Equivalents\"]",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Cash and cash equivalents at end of period",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_CASH_END",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "CF_CASH_END - (CF_CASH_BEGIN + CF_NET_INCREASE + CF_FX_EFFECT)",
|
||||||
|
"color": "#CB2929",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Validation Check (should be zero)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 1,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "CF_VALIDATION",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"display_name": "CASH FLOW METRICS",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_METRICS_HEADER",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "CF_OP_NET + CF_INV100",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Free Cash Flow",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_FREE_CASH",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(CF_OP_NET / (CF_FIN300 + CF_OP200)) if (CF_FIN300 + CF_OP200) != 0 else 0",
|
||||||
|
"color": "",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Cash Flow Coverage Ratio",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "CF_COVERAGE",
|
||||||
|
"reverse_sign": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"template_name": "Standard Cash Flow Statement (IFRS)"
|
||||||
|
}
|
||||||
@@ -0,0 +1,418 @@
|
|||||||
|
{
|
||||||
|
"creation": "2025-09-06 10:23:05.259864",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Financial Report Template",
|
||||||
|
"idx": 0,
|
||||||
|
"modified": "2025-09-15 15:02:15.911105",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Standard Profit and Loss (IFRS)",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"report_type": "Profit and Loss Statement",
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\":[[\"account_category\",\"=\",\"Revenue from Operations\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Sales Revenue",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "REV100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Cost of Goods Sold\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Cost of Goods Sold",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "COGS100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Direct Costs\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Direct Costs",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "COGS200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "REV100 + COGS100 + COGS200",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "GROSS PROFIT (GP)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "GROSS_PROFIT",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Other Operating Income\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Operating Income",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "OPIN100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Operating Expenses\"], [\"account_name\", \"like\", \"Sales\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Selling & Distribution Expenses",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "OPEX100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Operating Expenses\"], [\"account_name\", \"like\", \"Administrative\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Administrative Expenses",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "OPEX200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "{\"and\": [[\"account_category\", \"=\", \"Operating Expenses\"], [\"account_name\", \"not like\", \"Sales\"], [\"account_name\", \"not like\", \"Administrative\"]]}",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Other Operating Expenses",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "OPEX300",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "GROSS_PROFIT + OPIN100 + OPEX100 + OPEX200 + OPEX300",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "OPERATING PROFIT (EBIT)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "EBIT",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Investment Income\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Investment Income",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "FIN100",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Finance Costs\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Finance Costs",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "FIN200",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "EBIT + FIN100 + FIN200",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "PROFIT BEFORE TAX (EBT)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "PBT",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"account_category\", \"=\", \"Tax Expense\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Tax Expense",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "TAX",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "PBT + TAX",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "NET PROFIT (NP)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "NET_PROFIT",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "NET_PROFIT - ACT_NET_PROFIT",
|
||||||
|
"color": "#CB2929",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "VARIANCE (Calculated vs Actual)",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 1,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "VAL_DIFF",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"data_source": "Blank Line",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(GROSS_PROFIT / REV100) * 100 if REV100 != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Gross Profit Margin %",
|
||||||
|
"fieldtype": "Percent",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "GP_MARGIN",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(EBIT / REV100) * 100 if REV100 != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Operating Profit Margin %",
|
||||||
|
"fieldtype": "Percent",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "OP_MARGIN",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "(NET_PROFIT / REV100) * 100 if REV100 != 0 else 0",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Net Profit Margin %",
|
||||||
|
"fieldtype": "Percent",
|
||||||
|
"hidden_calculation": 0,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 0,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 1,
|
||||||
|
"reference_code": "NP_MARGIN",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"root_type\", \"=\", \"Income\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Total Income",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "ACT_TOTAL_INCOME",
|
||||||
|
"reverse_sign": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "Period Movement (Debits - Credits)",
|
||||||
|
"bold_text": 0,
|
||||||
|
"calculation_formula": "[\"root_type\", \"=\", \"Expense\"]",
|
||||||
|
"data_source": "Account Data",
|
||||||
|
"display_name": "Total Expenses",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "ACT_TOTAL_EXPENSES",
|
||||||
|
"reverse_sign": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"advanced_filtering": 0,
|
||||||
|
"balance_type": "",
|
||||||
|
"bold_text": 1,
|
||||||
|
"calculation_formula": "ACT_TOTAL_INCOME - ACT_TOTAL_EXPENSES",
|
||||||
|
"data_source": "Calculated Amount",
|
||||||
|
"display_name": "Net Profit",
|
||||||
|
"fieldtype": "",
|
||||||
|
"hidden_calculation": 1,
|
||||||
|
"hide_when_empty": 0,
|
||||||
|
"include_in_charts": 1,
|
||||||
|
"indentation_level": 0,
|
||||||
|
"italic_text": 0,
|
||||||
|
"reference_code": "ACT_NET_PROFIT",
|
||||||
|
"reverse_sign": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"template_name": "Standard Profit and Loss (IFRS)"
|
||||||
|
}
|
||||||
@@ -39,6 +39,16 @@ class TestAccountBalance(IntegrationTestCase):
|
|||||||
"currency": "EUR",
|
"currency": "EUR",
|
||||||
"balance": 0.0,
|
"balance": 0.0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"account": "Interest Income - _TC2",
|
||||||
|
"currency": "EUR",
|
||||||
|
"balance": 0.0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account": "Interest on Fixed Deposits - _TC2",
|
||||||
|
"currency": "EUR",
|
||||||
|
"balance": 0.0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"account": "Sales - _TC2",
|
"account": "Sales - _TC2",
|
||||||
"currency": "EUR",
|
"currency": "EUR",
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
|
const BS_REPORT_NAME = "Balance Sheet";
|
||||||
|
|
||||||
erpnext.utils.add_dimensions("Balance Sheet", 10);
|
frappe.query_reports[BS_REPORT_NAME] = $.extend({}, erpnext.financial_statements);
|
||||||
|
|
||||||
frappe.query_reports["Balance Sheet"]["filters"].push(
|
erpnext.utils.add_dimensions(BS_REPORT_NAME, 10);
|
||||||
|
|
||||||
|
frappe.query_reports[BS_REPORT_NAME]["filters"].push(
|
||||||
|
{
|
||||||
|
fieldname: "report_template",
|
||||||
|
label: __("Report Template"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Financial Report Template",
|
||||||
|
get_query: { filters: { report_type: BS_REPORT_NAME, disabled: 0 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "show_account_details",
|
||||||
|
label: __("Account Detail Level"),
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Summary", "Account Breakdown"],
|
||||||
|
default: "Summary",
|
||||||
|
depends_on: "eval:doc.report_template",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: "selected_view",
|
fieldname: "selected_view",
|
||||||
label: __("Select View"),
|
label: __("Select View"),
|
||||||
@@ -33,7 +50,8 @@ frappe.query_reports["Balance Sheet"]["filters"].push(
|
|||||||
fieldname: "show_zero_values",
|
fieldname: "show_zero_values",
|
||||||
label: __("Show zero values"),
|
label: __("Show zero values"),
|
||||||
fieldtype: "Check",
|
fieldtype: "Check",
|
||||||
|
depends_on: "eval:!doc.report_template",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
frappe.query_reports["Balance Sheet"]["export_hidden_cols"] = true;
|
frappe.query_reports[BS_REPORT_NAME]["export_hidden_cols"] = true;
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cint, flt
|
from frappe.utils import cint, flt
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_engine import (
|
||||||
|
FinancialReportEngine,
|
||||||
|
)
|
||||||
from erpnext.accounts.report.financial_statements import (
|
from erpnext.accounts.report.financial_statements import (
|
||||||
compute_growth_view_data,
|
compute_growth_view_data,
|
||||||
get_columns,
|
get_columns,
|
||||||
@@ -16,6 +19,9 @@ from erpnext.accounts.report.financial_statements import (
|
|||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
|
if filters and filters.report_template:
|
||||||
|
return FinancialReportEngine().execute(filters)
|
||||||
|
|
||||||
period_list = get_period_list(
|
period_list = get_period_list(
|
||||||
filters.from_fiscal_year,
|
filters.from_fiscal_year,
|
||||||
filters.to_fiscal_year,
|
filters.to_fiscal_year,
|
||||||
|
|||||||
@@ -1,20 +1,37 @@
|
|||||||
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.query_reports["Cash Flow"] = $.extend(erpnext.financial_statements, {
|
const CF_REPORT_NAME = "Cash Flow";
|
||||||
|
|
||||||
|
frappe.query_reports[CF_REPORT_NAME] = $.extend(erpnext.financial_statements, {
|
||||||
name_field: "section",
|
name_field: "section",
|
||||||
parent_field: "parent_section",
|
parent_field: "parent_section",
|
||||||
});
|
});
|
||||||
|
|
||||||
erpnext.utils.add_dimensions("Cash Flow", 10);
|
erpnext.utils.add_dimensions(CF_REPORT_NAME, 10);
|
||||||
|
|
||||||
// The last item in the array is the definition for Presentation Currency
|
// The last item in the array is the definition for Presentation Currency
|
||||||
// filter. It won't be used in cash flow for now so we pop it. Please take
|
// filter. It won't be used in cash flow for now so we pop it. Please take
|
||||||
// of this if you are working here.
|
// of this if you are working here.
|
||||||
|
|
||||||
frappe.query_reports["Cash Flow"]["filters"].splice(8, 1);
|
frappe.query_reports[CF_REPORT_NAME]["filters"].splice(8, 1);
|
||||||
|
|
||||||
frappe.query_reports["Cash Flow"]["filters"].push(
|
frappe.query_reports[CF_REPORT_NAME]["filters"].push(
|
||||||
|
{
|
||||||
|
fieldname: "report_template",
|
||||||
|
label: __("Report Template"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Financial Report Template",
|
||||||
|
get_query: { filters: { report_type: CF_REPORT_NAME, disabled: 0 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "show_account_details",
|
||||||
|
label: __("Account Detail Level"),
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Summary", "Account Breakdown"],
|
||||||
|
default: "Summary",
|
||||||
|
depends_on: "eval:doc.report_template",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: "include_default_book_entries",
|
fieldname: "include_default_book_entries",
|
||||||
label: __("Include Default FB Entries"),
|
label: __("Include Default FB Entries"),
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ from frappe.query_builder import DocType
|
|||||||
from frappe.utils import cstr, flt
|
from frappe.utils import cstr, flt
|
||||||
from pypika import Order
|
from pypika import Order
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_engine import (
|
||||||
|
FinancialReportEngine,
|
||||||
|
)
|
||||||
from erpnext.accounts.report.financial_statements import (
|
from erpnext.accounts.report.financial_statements import (
|
||||||
get_columns,
|
get_columns,
|
||||||
get_cost_centers_with_children,
|
get_cost_centers_with_children,
|
||||||
@@ -25,6 +28,9 @@ from erpnext.accounts.utils import get_fiscal_year
|
|||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
|
if filters and filters.report_template:
|
||||||
|
return FinancialReportEngine().execute(filters)
|
||||||
|
|
||||||
period_list = get_period_list(
|
period_list = get_period_list(
|
||||||
filters.from_fiscal_year,
|
filters.from_fiscal_year,
|
||||||
filters.to_fiscal_year,
|
filters.to_fiscal_year,
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
const CFS_REPORT_NAME = "Custom Financial Statement";
|
||||||
|
|
||||||
|
frappe.query_reports[CFS_REPORT_NAME] = $.extend({}, erpnext.financial_statements);
|
||||||
|
|
||||||
|
erpnext.utils.add_dimensions(CFS_REPORT_NAME, 10);
|
||||||
|
|
||||||
|
frappe.query_reports[CFS_REPORT_NAME]["filters"].push(
|
||||||
|
{
|
||||||
|
fieldname: "report_template",
|
||||||
|
label: __("Report Template"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Financial Report Template",
|
||||||
|
get_query: { filters: { disabled: 0 } },
|
||||||
|
reqd: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "show_account_details",
|
||||||
|
label: __("Account Detail Level"),
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Summary", "Account Breakdown"],
|
||||||
|
default: "Summary",
|
||||||
|
depends_on: "eval:doc.report_template",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "include_default_book_entries",
|
||||||
|
label: __("Include Default FB Entries"),
|
||||||
|
fieldtype: "Check",
|
||||||
|
default: 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
frappe.query_reports[CFS_REPORT_NAME]["export_hidden_cols"] = true;
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"add_translate_data": 0,
|
||||||
|
"columns": [],
|
||||||
|
"creation": "2025-10-03 01:21:24.043064",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"filters": [],
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"letterhead": null,
|
||||||
|
"modified": "2025-10-03 01:21:24.043064",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Custom Financial Statement",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "GL Entry",
|
||||||
|
"report_name": "Custom Financial Statement",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Accounts User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Accounts Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Auditor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeout": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_engine import (
|
||||||
|
FinancialReportEngine,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def execute(filters: dict | None = None):
|
||||||
|
if filters and filters.report_template:
|
||||||
|
return FinancialReportEngine().execute(filters)
|
||||||
@@ -1,11 +1,28 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
frappe.query_reports["Profit and Loss Statement"] = $.extend({}, erpnext.financial_statements);
|
const PL_REPORT_NAME = "Profit and Loss Statement";
|
||||||
|
|
||||||
erpnext.utils.add_dimensions("Profit and Loss Statement", 10);
|
frappe.query_reports[PL_REPORT_NAME] = $.extend({}, erpnext.financial_statements);
|
||||||
|
|
||||||
frappe.query_reports["Profit and Loss Statement"]["filters"].push(
|
erpnext.utils.add_dimensions(PL_REPORT_NAME, 10);
|
||||||
|
|
||||||
|
frappe.query_reports[PL_REPORT_NAME]["filters"].push(
|
||||||
|
{
|
||||||
|
fieldname: "report_template",
|
||||||
|
label: __("Report Template"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Financial Report Template",
|
||||||
|
get_query: { filters: { report_type: PL_REPORT_NAME, disabled: 0 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "show_account_details",
|
||||||
|
label: __("Account Detail Level"),
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Summary", "Account Breakdown"],
|
||||||
|
default: "Summary",
|
||||||
|
depends_on: "eval:doc.report_template",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: "selected_view",
|
fieldname: "selected_view",
|
||||||
label: __("Select View"),
|
label: __("Select View"),
|
||||||
@@ -34,7 +51,8 @@ frappe.query_reports["Profit and Loss Statement"]["filters"].push(
|
|||||||
fieldname: "show_zero_values",
|
fieldname: "show_zero_values",
|
||||||
label: __("Show zero values"),
|
label: __("Show zero values"),
|
||||||
fieldtype: "Check",
|
fieldtype: "Check",
|
||||||
|
depends_on: "eval:!doc.report_template",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
frappe.query_reports["Profit and Loss Statement"]["export_hidden_cols"] = true;
|
frappe.query_reports[PL_REPORT_NAME]["export_hidden_cols"] = true;
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_engine import (
|
||||||
|
FinancialReportEngine,
|
||||||
|
)
|
||||||
from erpnext.accounts.report.financial_statements import (
|
from erpnext.accounts.report.financial_statements import (
|
||||||
compute_growth_view_data,
|
compute_growth_view_data,
|
||||||
compute_margin_view_data,
|
compute_margin_view_data,
|
||||||
@@ -17,6 +20,9 @@ from erpnext.accounts.report.financial_statements import (
|
|||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
|
if filters and filters.report_template:
|
||||||
|
return FinancialReportEngine().execute(filters)
|
||||||
|
|
||||||
period_list = get_period_list(
|
period_list = get_period_list(
|
||||||
filters.from_fiscal_year,
|
filters.from_fiscal_year,
|
||||||
filters.to_fiscal_year,
|
filters.to_fiscal_year,
|
||||||
|
|||||||
@@ -440,6 +440,7 @@ erpnext.patches.v16_0.make_workstation_operating_components #1
|
|||||||
erpnext.patches.v16_0.set_reporting_currency
|
erpnext.patches.v16_0.set_reporting_currency
|
||||||
erpnext.patches.v16_0.set_posting_datetime_for_sabb_and_drop_indexes
|
erpnext.patches.v16_0.set_posting_datetime_for_sabb_and_drop_indexes
|
||||||
erpnext.patches.v16_0.update_serial_no_reference_name
|
erpnext.patches.v16_0.update_serial_no_reference_name
|
||||||
|
erpnext.patches.v16_0.update_account_categories_for_existing_accounts
|
||||||
erpnext.patches.v16_0.rename_subcontracted_quantity
|
erpnext.patches.v16_0.rename_subcontracted_quantity
|
||||||
erpnext.patches.v16_0.add_new_stock_entry_types
|
erpnext.patches.v16_0.add_new_stock_entry_types
|
||||||
erpnext.patches.v15_0.set_asset_status_if_not_already_set
|
erpnext.patches.v15_0.set_asset_status_if_not_already_set
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import get_chart_metadata_fields
|
||||||
|
from erpnext.accounts.doctype.account.chart_of_accounts.verified import standard_chart_of_accounts
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_template import (
|
||||||
|
sync_financial_report_templates,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
"""
|
||||||
|
Patch to create default account categories and update existing accounts
|
||||||
|
with appropriate account categories based on standard chart of accounts mapping
|
||||||
|
"""
|
||||||
|
sync_financial_report_templates()
|
||||||
|
update_account_categories()
|
||||||
|
|
||||||
|
|
||||||
|
def update_account_categories():
|
||||||
|
account_mapping = get_standard_account_category_mapping()
|
||||||
|
companies = frappe.get_all("Company", pluck="name")
|
||||||
|
|
||||||
|
mapped_account_categories = {}
|
||||||
|
|
||||||
|
for company in companies:
|
||||||
|
map_account_categories_for_company(company, account_mapping, mapped_account_categories)
|
||||||
|
|
||||||
|
if not mapped_account_categories:
|
||||||
|
return
|
||||||
|
|
||||||
|
frappe.db.bulk_update("Account", mapped_account_categories)
|
||||||
|
|
||||||
|
|
||||||
|
def get_standard_account_category_mapping():
|
||||||
|
account_mapping = {}
|
||||||
|
|
||||||
|
def _extract_account_mapping(chart_data, prefix=""):
|
||||||
|
for account_name, account_details in chart_data.items():
|
||||||
|
if account_name in get_chart_metadata_fields():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(account_details, dict) and account_details.get("account_category"):
|
||||||
|
account_mapping[account_name] = account_details["account_category"]
|
||||||
|
|
||||||
|
if isinstance(account_details, dict):
|
||||||
|
_extract_account_mapping(account_details, prefix)
|
||||||
|
|
||||||
|
standard_chart = standard_chart_of_accounts.get()
|
||||||
|
_extract_account_mapping(standard_chart)
|
||||||
|
|
||||||
|
return account_mapping
|
||||||
|
|
||||||
|
|
||||||
|
def map_account_categories_for_company(company, account_mapping, mapped_account_categories):
|
||||||
|
accounts = frappe.get_all(
|
||||||
|
"Account",
|
||||||
|
filters={"company": company, "account_category": ["is", "not set"]},
|
||||||
|
fields=["name", "account_name"],
|
||||||
|
)
|
||||||
|
|
||||||
|
for account in accounts:
|
||||||
|
account_category = account_mapping.get(account.account_name)
|
||||||
|
|
||||||
|
if account_category:
|
||||||
|
mapped_account_categories[account.name] = {"account_category": account_category}
|
||||||
@@ -4,45 +4,160 @@ erpnext.financial_statements = {
|
|||||||
filters: get_filters(),
|
filters: get_filters(),
|
||||||
baseData: null,
|
baseData: null,
|
||||||
formatter: function (value, row, column, data, default_formatter, filter) {
|
formatter: function (value, row, column, data, default_formatter, filter) {
|
||||||
if (
|
// Growth/Margin
|
||||||
frappe.query_report.get_filter_value("selected_view") == "Growth" &&
|
if (this._is_special_view(column, data))
|
||||||
data &&
|
return this._format_special_view(value, row, column, data, default_formatter);
|
||||||
column.colIndex >= 3
|
|
||||||
) {
|
|
||||||
const growthPercent = data[column.fieldname];
|
|
||||||
|
|
||||||
if (growthPercent == undefined) return "NA"; //making this not applicable for undefined/null values
|
if (frappe.query_report.get_filter_value("report_template"))
|
||||||
|
return this._format_custom_report(value, row, column, data, default_formatter, filter);
|
||||||
|
else return this._format_standard_report(value, row, column, data, default_formatter, filter);
|
||||||
|
},
|
||||||
|
|
||||||
|
_is_special_view: function (column, data) {
|
||||||
|
if (!data) return false;
|
||||||
|
const view = frappe.query_report.get_filter_value("selected_view");
|
||||||
|
return (view === "Growth" && column.colIndex >= 3) || (view === "Margin" && column.colIndex >= 2);
|
||||||
|
},
|
||||||
|
|
||||||
|
_format_custom_report: function (value, row, column, data, default_formatter, filter) {
|
||||||
|
const columnInfo = this._parse_column_info(column.fieldname, data);
|
||||||
|
const formatting = this._get_formatting_for_column(data, columnInfo);
|
||||||
|
|
||||||
|
if (columnInfo.isAccount) {
|
||||||
|
return this._format_custom_account_column(
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
formatting,
|
||||||
|
column,
|
||||||
|
default_formatter,
|
||||||
|
row
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return this._format_custom_value_column(value, data, formatting, column, default_formatter, row);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_parse_column_info: function (fieldname, data) {
|
||||||
|
const valueMatch = fieldname.match(/^(?:seg_(\d+)_)?(.+)$/);
|
||||||
|
|
||||||
|
const periodKeys = data._segment_info?.period_keys || [];
|
||||||
|
const baseName = valueMatch ? valueMatch[2] : fieldname;
|
||||||
|
const isPeriodColumn = periodKeys.includes(baseName);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isAccount: baseName === "account",
|
||||||
|
isPeriod: isPeriodColumn,
|
||||||
|
segmentIndex: valueMatch && valueMatch[1] ? parseInt(valueMatch[1]) : null,
|
||||||
|
fieldname: baseName,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_get_formatting_for_column: function (data, columnInfo) {
|
||||||
|
let formatting = {};
|
||||||
|
|
||||||
|
if (columnInfo.segmentIndex !== null && data.segment_values)
|
||||||
|
formatting = data.segment_values[`seg_${columnInfo.segmentIndex}`] || {};
|
||||||
|
else formatting = data;
|
||||||
|
|
||||||
|
return formatting;
|
||||||
|
},
|
||||||
|
|
||||||
|
_format_custom_account_column: function (value, data, formatting, column, default_formatter, row) {
|
||||||
|
if (!value) return "";
|
||||||
|
|
||||||
|
// Link to open ledger
|
||||||
|
const should_link_to_ledger =
|
||||||
|
formatting.is_detail || (formatting.account_filters && formatting.child_accounts);
|
||||||
|
|
||||||
|
if (should_link_to_ledger) {
|
||||||
|
const glData = {
|
||||||
|
account: formatting.account_name || formatting.child_accounts || value,
|
||||||
|
from_date: formatting.from_date || formatting.period_start_date,
|
||||||
|
to_date: formatting.to_date || formatting.period_end_date,
|
||||||
|
account_type: formatting.account_type,
|
||||||
|
company: frappe.query_report.get_filter_value("company"),
|
||||||
|
};
|
||||||
|
|
||||||
|
column.link_onclick =
|
||||||
|
"erpnext.financial_statements.open_general_ledger(" + JSON.stringify(glData) + ")";
|
||||||
|
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
let formattedValue = String(value);
|
||||||
|
|
||||||
|
// Prefix
|
||||||
|
if (formatting.is_detail || formatting.prefix)
|
||||||
|
formattedValue = (formatting.prefix || "• ") + formattedValue;
|
||||||
|
|
||||||
|
// Indent
|
||||||
|
if (data._segment_info && data._segment_info.total_segments === 1) {
|
||||||
|
column.is_tree = true;
|
||||||
|
} else if (formatting.indent && formatting.indent > 0) {
|
||||||
|
const indent = " ".repeat(formatting.indent * 4);
|
||||||
|
formattedValue = indent + formattedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style
|
||||||
|
return this._style_custom_value(formattedValue, formatting, null);
|
||||||
|
},
|
||||||
|
|
||||||
|
_format_custom_value_column: function (value, data, formatting, column, default_formatter, row) {
|
||||||
|
if (formatting.is_blank_line) return "";
|
||||||
|
|
||||||
|
const col = { ...column };
|
||||||
|
col.fieldtype = formatting.fieldtype || col.fieldtype;
|
||||||
|
// Avoid formatting as currency
|
||||||
|
if (col.fieldtype === "Float") col.options = null;
|
||||||
|
|
||||||
|
let formattedValue = default_formatter(value, row, col, data);
|
||||||
|
return this._style_custom_value(formattedValue, formatting, value);
|
||||||
|
},
|
||||||
|
|
||||||
|
_style_custom_value(formattedValue, formatting, value) {
|
||||||
|
let $element = $(`<span>${formattedValue}</span>`);
|
||||||
|
|
||||||
|
if (formatting.bold) $element.css("font-weight", "bold");
|
||||||
|
if (formatting.italic) $element.css("font-style", "italic");
|
||||||
|
if (formatting.warn_if_negative && typeof value === "number" && value < 0)
|
||||||
|
$element.addClass("text-danger");
|
||||||
|
if (formatting.color) $element.css("color", formatting.color);
|
||||||
|
|
||||||
|
return $element.wrap("<p></p>").parent().html();
|
||||||
|
},
|
||||||
|
|
||||||
|
_format_special_view: function (value, row, column, data, default_formatter) {
|
||||||
|
const selectedView = frappe.query_report.get_filter_value("selected_view");
|
||||||
|
|
||||||
|
if (selectedView === "Growth") {
|
||||||
|
const growthPercent = data[column.fieldname];
|
||||||
|
if (growthPercent === undefined) return "NA";
|
||||||
|
if (growthPercent === "") return "";
|
||||||
|
|
||||||
if (column.fieldname === "total") {
|
if (column.fieldname === "total") {
|
||||||
value = $(`<span>${growthPercent}</span>`);
|
value = $(`<span>${growthPercent}</span>`);
|
||||||
} else {
|
} else {
|
||||||
value = $(`<span>${(growthPercent >= 0 ? "+" : "") + growthPercent + "%"}</span>`);
|
value = $(`<span>${(growthPercent >= 0 ? "+" : "") + growthPercent + "%"}</span>`);
|
||||||
|
|
||||||
if (growthPercent < 0) {
|
if (growthPercent < 0) {
|
||||||
value = $(value).addClass("text-danger");
|
value = $(value).addClass("text-danger");
|
||||||
} else {
|
} else {
|
||||||
value = $(value).addClass("text-success");
|
value = $(value).addClass("text-success");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = $(value).wrap("<p></p>").parent().html();
|
return $(value).wrap("<p></p>").parent().html();
|
||||||
|
} else {
|
||||||
|
const marginPercent = data[column.fieldname];
|
||||||
|
if (marginPercent === undefined) return "NA";
|
||||||
|
|
||||||
return value;
|
value = $(`<span>${marginPercent + "%"}</span>`);
|
||||||
} else if (frappe.query_report.get_filter_value("selected_view") == "Margin" && data) {
|
if (marginPercent < 0) value = $(value).addClass("text-danger");
|
||||||
if (column.colIndex >= 2) {
|
else value = $(value).addClass("text-success");
|
||||||
const marginPercent = data[column.fieldname];
|
return $(value).wrap("<p></p>").parent().html();
|
||||||
|
|
||||||
if (marginPercent == undefined) return "NA"; //making this not applicable for undefined/null values
|
|
||||||
|
|
||||||
value = $(`<span>${marginPercent + "%"}</span>`);
|
|
||||||
if (marginPercent < 0) value = $(value).addClass("text-danger");
|
|
||||||
else value = $(value).addClass("text-success");
|
|
||||||
value = $(value).wrap("<p></p>").parent().html();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_format_standard_report: function (value, row, column, data, default_formatter, filter) {
|
||||||
if (data && column.fieldname == this.name_field) {
|
if (data && column.fieldname == this.name_field) {
|
||||||
// first column
|
|
||||||
value = data.section_name || data.account_name || value;
|
value = data.section_name || data.account_name || value;
|
||||||
|
|
||||||
if (filter && filter?.text && filter?.type == "contains") {
|
if (filter && filter?.text && filter?.type == "contains") {
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ from frappe.utils import add_months, cint, formatdate, get_first_day, get_link_t
|
|||||||
from frappe.utils.nestedset import NestedSet, rebuild_tree
|
from frappe.utils.nestedset import NestedSet, rebuild_tree
|
||||||
|
|
||||||
from erpnext.accounts.doctype.account.account import get_account_currency
|
from erpnext.accounts.doctype.account.account import get_account_currency
|
||||||
|
from erpnext.accounts.doctype.financial_report_template.financial_report_template import (
|
||||||
|
sync_financial_report_templates,
|
||||||
|
)
|
||||||
from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_charges
|
from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_charges
|
||||||
|
|
||||||
|
|
||||||
@@ -294,6 +297,7 @@ class Company(NestedSet):
|
|||||||
):
|
):
|
||||||
if not frappe.local.flags.ignore_chart_of_accounts:
|
if not frappe.local.flags.ignore_chart_of_accounts:
|
||||||
frappe.flags.country_change = True
|
frappe.flags.country_change = True
|
||||||
|
sync_financial_report_templates(self.chart_of_accounts, self.existing_company)
|
||||||
self.create_default_accounts()
|
self.create_default_accounts()
|
||||||
self.create_default_warehouses()
|
self.create_default_warehouses()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user