blob: 43e58c2efd0aa81376c17ec570f99c04114f0c42 [file] [log] [blame]
Anand Doshi825d0142014-07-18 18:05:26 +05301frappe.provide("erpnext.financial_statements");
2
3erpnext.financial_statements = {
Rohit Waghchaure4275c302016-08-19 11:48:58 +05304 "filters": get_filters(),
nitmit92649de2024-01-27 10:18:35 +05305 "baseData": null,
Shariq Ansari08ed3cd2023-12-07 19:39:24 +05306 "formatter": function(value, row, column, data, default_formatter, filter) {
nitmit92649de2024-01-27 10:18:35 +05307 if(frappe.query_report.get_filter_value("selected_view") == "Growth" && data && column.colIndex >= 3){
8 //Assuming that the first three columns are s.no, account name and the very first year of the accounting values, to calculate the relative percentage values of the successive columns.
9 const lastAnnualValue = row[column.colIndex - 1].content;
10 const currentAnnualvalue = data[column.fieldname];
11 if(currentAnnualvalue == undefined) return 'NA'; //making this not applicable for undefined/null values
12 let annualGrowth = 0;
13 if(lastAnnualValue == 0 && currentAnnualvalue > 0){
14 //If the previous year value is 0 and the current value is greater than 0
15 annualGrowth = 1;
16 }
17 else if(lastAnnualValue > 0){
18 annualGrowth = (currentAnnualvalue - lastAnnualValue) / lastAnnualValue;
19 }
20
21 const growthPercent = (Math.round(annualGrowth*10000)/100); //calculating the rounded off percentage
22
23 value = $(`<span>${((growthPercent >=0)? '+':'' )+growthPercent+'%'}</span>`);
24 if(growthPercent < 0){
25 value = $(value).addClass("text-danger");
26 }
27 else{
28 value = $(value).addClass("text-success");
29 }
30 value = $(value).wrap("<p></p>").parent().html();
31
32 return value;
33 }
34 else if(frappe.query_report.get_filter_value("selected_view") == "Margin" && data){
35 if(column.fieldname =="account" && data.account_name == __("Income")){
36 //Taking the total income from each column (for all the financial years) as the base (100%)
37 this.baseData = row;
38 }
39 if(column.colIndex >= 2){
40 //Assuming that the first two columns are s.no and account name, to calculate the relative percentage values of the successive columns.
41 const currentAnnualvalue = data[column.fieldname];
42 const baseValue = this.baseData[column.colIndex].content;
43 if(currentAnnualvalue == undefined || baseValue <= 0) return 'NA';
44 const marginPercent = Math.round((currentAnnualvalue/baseValue)*10000)/100;
45
46 value = $(`<span>${marginPercent+'%'}</span>`);
47 if(marginPercent < 0)
48 value = $(value).addClass("text-danger");
49 else
50 value = $(value).addClass("text-success");
51 value = $(value).wrap("<p></p>").parent().html();
52 return value;
53 }
54
55 }
56
Diksha Jadhav09b8caf2020-07-21 17:35:10 +053057 if (data && column.fieldname=="account") {
thefalconx33a639f162019-12-04 09:46:42 +053058 value = data.account_name || value;
Anand Doshi825d0142014-07-18 18:05:26 +053059
Shariq Ansari08ed3cd2023-12-07 19:39:24 +053060 if (filter && filter?.text && filter?.type == "contains") {
61 if (!value.toLowerCase().includes(filter.text)) {
62 return value;
63 }
64 }
65
Ankush Menat2dc95e52023-09-27 12:34:40 +053066 if (data.account) {
67 column.link_onclick =
68 "erpnext.financial_statements.open_general_ledger(" + JSON.stringify(data) + ")";
69 }
Faris Ansari5986d592018-07-20 15:11:55 +053070 column.is_tree = true;
Anand Doshi825d0142014-07-18 18:05:26 +053071 }
72
Faris Ansari5986d592018-07-20 15:11:55 +053073 value = default_formatter(value, row, column, data);
Anand Doshicb86d592014-07-22 19:02:11 +053074
Diksha Jadhav09b8caf2020-07-21 17:35:10 +053075 if (data && !data.parent_account) {
Faris Ansari5986d592018-07-20 15:11:55 +053076 value = $(`<span>${value}</span>`);
77
Anand Doshi5f0459c2014-07-21 16:13:06 +053078 var $value = $(value).css("font-weight", "bold");
Faris Ansari5986d592018-07-20 15:11:55 +053079 if (data.warn_if_negative && data[column.fieldname] < 0) {
Anand Doshi5f0459c2014-07-21 16:13:06 +053080 $value.addClass("text-danger");
81 }
82
83 value = $value.wrap("<p></p>").parent().html();
Anand Doshi825d0142014-07-18 18:05:26 +053084 }
85
86 return value;
87 },
Anand Doshi5f0459c2014-07-21 16:13:06 +053088 "open_general_ledger": function(data) {
89 if (!data.account) return;
FinByz Tech Pvt. Ltdc52b41d2022-10-19 23:14:10 +053090 let project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; });
Anand Doshi825d0142014-07-18 18:05:26 +053091
92 frappe.route_options = {
Anand Doshi5f0459c2014-07-21 16:13:06 +053093 "account": data.account,
Faris Ansari9e874af2018-07-18 09:28:44 +053094 "company": frappe.query_report.get_filter_value('company'),
Anand Doshi561e6cd2016-02-16 11:56:53 +053095 "from_date": data.from_date || data.year_start_date,
Ricardo Johann34354232017-01-24 06:42:24 -030096 "to_date": data.to_date || data.year_end_date,
Rohit Waghchaure019501e2017-04-19 17:53:31 +053097 "project": (project && project.length > 0) ? project[0].$input.val() : ""
Anand Doshi825d0142014-07-18 18:05:26 +053098 };
FinByz Tech Pvt. Ltdc52b41d2022-10-19 23:14:10 +053099
100 let report = "General Ledger";
101
102 if (["Payable", "Receivable"].includes(data.account_type)) {
103 report = data.account_type == "Payable" ? "Accounts Payable" : "Accounts Receivable";
104 frappe.route_options["party_account"] = data.account;
105 frappe.route_options["report_date"] = data.year_end_date;
106 }
107
108 frappe.set_route("query-report", report);
Anand Doshicb86d592014-07-22 19:02:11 +0530109 },
110 "tree": true,
111 "name_field": "account",
112 "parent_field": "parent_account",
Rushabh Mehta05253872016-04-18 19:27:36 +0530113 "initial_depth": 3,
114 onload: function(report) {
115 // dropdown for links to other financial statements
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530116 erpnext.financial_statements.filters = get_filters()
117
Deepesh Garg62706072023-07-16 12:58:42 +0530118 let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today());
Deepesh Garg1f3fe592020-05-28 18:36:21 +0530119
120 frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
121 var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
122 frappe.query_report.set_filter_value({
123 period_start_date: fy.year_start_date,
124 period_end_date: fy.year_end_date
125 });
126 });
127
Gursheen Anand2486b642024-01-27 23:30:17 +0530128 if (report.page){
129 const views_menu = report.page.add_custom_button_group(__('Financial Statements'));
Shivam Mishrab6fb1322020-07-09 16:51:36 +0530130
Gursheen Anand2486b642024-01-27 23:30:17 +0530131 report.page.add_custom_menu_item(views_menu, __("Balance Sheet"), function() {
132 var filters = report.get_values();
133 frappe.set_route('query-report', 'Balance Sheet', {company: filters.company});
134 });
Shivam Mishrab6fb1322020-07-09 16:51:36 +0530135
Gursheen Anand2486b642024-01-27 23:30:17 +0530136 report.page.add_custom_menu_item(views_menu, __("Profit and Loss"), function() {
137 var filters = report.get_values();
138 frappe.set_route('query-report', 'Profit and Loss Statement', {company: filters.company});
139 });
Shivam Mishrab6fb1322020-07-09 16:51:36 +0530140
Gursheen Anand2486b642024-01-27 23:30:17 +0530141 report.page.add_custom_menu_item(views_menu, __("Cash Flow Statement"), function() {
142 var filters = report.get_values();
143 frappe.set_route('query-report', 'Cash Flow', {company: filters.company});
144 });
145 }
Nabin Hait44c1b8e2016-05-20 11:44:08 +0530146 }
Anand Doshi825d0142014-07-18 18:05:26 +0530147};
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530148
Deepesh Garg11ea0b12020-05-26 19:23:45 +0530149function get_filters() {
deepeshgarg007d83cf652019-05-12 18:34:23 +0530150 let filters = [
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530151 {
152 "fieldname":"company",
153 "label": __("Company"),
154 "fieldtype": "Link",
155 "options": "Company",
156 "default": frappe.defaults.get_user_default("Company"),
157 "reqd": 1
158 },
159 {
Gaurav Naik8cbbdfd2018-04-23 03:36:02 +0530160 "fieldname":"finance_book",
161 "label": __("Finance Book"),
162 "fieldtype": "Link",
Nabin Haitb9fed2a2018-05-09 15:10:29 +0530163 "options": "Finance Book"
Gaurav Naik8cbbdfd2018-04-23 03:36:02 +0530164 },
165 {
Deepesh Garg24a2c9b2020-04-07 12:16:25 +0530166 "fieldname":"filter_based_on",
167 "label": __("Filter Based On"),
168 "fieldtype": "Select",
169 "options": ["Fiscal Year", "Date Range"],
170 "default": ["Fiscal Year"],
171 "reqd": 1,
172 on_change: function() {
173 let filter_based_on = frappe.query_report.get_filter_value('filter_based_on');
174 frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range');
175 frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range');
176 frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year');
177 frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year');
178
179 frappe.query_report.refresh();
180 }
181 },
182 {
183 "fieldname":"period_start_date",
184 "label": __("Start Date"),
185 "fieldtype": "Date",
Deepesh Garg3a6894f2021-10-27 19:39:18 +0530186 "reqd": 1,
187 "depends_on": "eval:doc.filter_based_on == 'Date Range'"
Deepesh Garg24a2c9b2020-04-07 12:16:25 +0530188 },
189 {
190 "fieldname":"period_end_date",
191 "label": __("End Date"),
192 "fieldtype": "Date",
Deepesh Garg3a6894f2021-10-27 19:39:18 +0530193 "reqd": 1,
194 "depends_on": "eval:doc.filter_based_on == 'Date Range'"
Deepesh Garg24a2c9b2020-04-07 12:16:25 +0530195 },
196 {
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530197 "fieldname":"from_fiscal_year",
Rohit Waghchaure26b646f2016-08-21 17:14:12 +0530198 "label": __("Start Year"),
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530199 "fieldtype": "Link",
200 "options": "Fiscal Year",
Deepesh Garg3a6894f2021-10-27 19:39:18 +0530201 "reqd": 1,
202 "depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530203 },
204 {
205 "fieldname":"to_fiscal_year",
Rohit Waghchaure26b646f2016-08-21 17:14:12 +0530206 "label": __("End Year"),
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530207 "fieldtype": "Link",
208 "options": "Fiscal Year",
Deepesh Garg3a6894f2021-10-27 19:39:18 +0530209 "reqd": 1,
210 "depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530211 },
212 {
213 "fieldname": "periodicity",
214 "label": __("Periodicity"),
215 "fieldtype": "Select",
216 "options": [
217 { "value": "Monthly", "label": __("Monthly") },
218 { "value": "Quarterly", "label": __("Quarterly") },
219 { "value": "Half-Yearly", "label": __("Half-Yearly") },
220 { "value": "Yearly", "label": __("Yearly") }
221 ],
Nabin Haitf6b784e2018-08-30 18:42:35 +0530222 "default": "Yearly",
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530223 "reqd": 1
tundebabzyc8978252018-02-12 10:34:50 +0100224 },
225 // Note:
226 // If you are modifying this array such that the presentation_currency object
227 // is no longer the last object, please make adjustments in cash_flow.js
228 // accordingly.
229 {
230 "fieldname": "presentation_currency",
231 "label": __("Currency"),
232 "fieldtype": "Select",
233 "options": erpnext.get_presentation_currency_list()
deepeshgarg007f5b6ee92019-05-28 12:15:56 +0530234 },
235 {
Faris Ansari26321072019-06-19 12:15:37 +0530236 "fieldname": "cost_center",
deepeshgarg007f5b6ee92019-05-28 12:15:56 +0530237 "label": __("Cost Center"),
Faris Ansari26321072019-06-19 12:15:37 +0530238 "fieldtype": "MultiSelectList",
239 get_data: function(txt) {
240 return frappe.db.get_link_options('Cost Center', txt, {
241 company: frappe.query_report.get_filter_value("company")
deepeshgarg007f5b6ee92019-05-28 12:15:56 +0530242 });
deepeshgarg007f5b6ee92019-05-28 12:15:56 +0530243 }
Gursheen Kaur Anand596a14e2023-07-12 15:49:17 +0530244 },
245 {
246 "fieldname": "project",
247 "label": __("Project"),
248 "fieldtype": "MultiSelectList",
249 get_data: function(txt) {
250 return frappe.db.get_link_options('Project', txt, {
251 company: frappe.query_report.get_filter_value("company")
252 });
253 },
Rohit Waghchaure4275c302016-08-19 11:48:58 +0530254 }
255 ]
deepeshgarg007d83cf652019-05-12 18:34:23 +0530256
ruthra kumarc31ee8e2023-11-14 06:44:49 +0530257 // Dynamically set 'default' values for fiscal year filters
258 let fy_filters = filters.filter(x=>{return ["from_fiscal_year", "to_fiscal_year"].includes(x.fieldname);})
259 let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), false, true);
260 if (fiscal_year) {
261 let fy = erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), false, false);
262 fy_filters.forEach(x=>{x.default = fy;})
263 }
264
deepeshgarg007d83cf652019-05-12 18:34:23 +0530265 return filters;
266}