From 6ca8054d55c53c21bb76209e0713d86ae2535e57 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 20 Sep 2012 19:03:14 +0530 Subject: [PATCH] added stock analytics --- .../financial_analytics.js | 95 +---- .../page/general_ledger/general_ledger.js | 12 +- .../page/trial_balance/trial_balance.js | 1 - erpnext/startup/report_data_map.py | 4 +- .../stock/page/stock_analytics/__init__.py | 0 .../page/stock_analytics/stock_analytics.js | 238 ++++++++++++ .../page/stock_analytics/stock_analytics.txt | 28 ++ .../stock/page/stock_ledger/stock_ledger.js | 345 +++++++++--------- public/js/all-app.js | 65 ++-- public/js/app/account_tree_grid.js | 123 ++----- .../{account_tree_grid.css => tree_grid.css} | 0 11 files changed, 513 insertions(+), 398 deletions(-) create mode 100644 erpnext/stock/page/stock_analytics/__init__.py create mode 100644 erpnext/stock/page/stock_analytics/stock_analytics.js create mode 100644 erpnext/stock/page/stock_analytics/stock_analytics.txt rename public/js/app/{account_tree_grid.css => tree_grid.css} (100%) diff --git a/erpnext/accounts/page/financial_analytics/financial_analytics.js b/erpnext/accounts/page/financial_analytics/financial_analytics.js index 5445fc96df..1f0a01d4a5 100644 --- a/erpnext/accounts/page/financial_analytics/financial_analytics.js +++ b/erpnext/accounts/page/financial_analytics/financial_analytics.js @@ -15,7 +15,6 @@ // along with this program. If not, see . wn.require("js/app/account_tree_grid.js"); -wn.require("js/app/account_tree_grid.css"); wn.pages['financial-analytics'].onload = function(wrapper) { wn.ui.make_app_page({ @@ -57,80 +56,13 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ {id: "check", name: "Plot", field: "check", width: 30, formatter: this.check_formatter}, {id: "name", name: "Account", field: "name", width: 300, - formatter: this.account_formatter}, + formatter: this.tree_formatter}, {id: "opening", name: "Opening", field: "opening", hidden: true, formatter: this.currency_formatter} ]; - this.columns = []; - var me = this; - var range = this.filter_inputs.range.val(); - this.from_date = dateutil.user_to_str(this.filter_inputs.from_date.val()); - this.to_date = dateutil.user_to_str(this.filter_inputs.to_date.val()); - var date_diff = dateutil.get_diff(this.to_date, this.from_date); - - me.column_map = {}; - - var add_column = function(date) { - me.columns.push({ - id: date, - name: dateutil.str_to_user(date), - field: date, - formatter: me.currency_formatter, - width: 100 - }); - } - - var build_columns = function(condition) { - // add column for each date range - for(var i=0; i < date_diff; i++) { - var date = dateutil.add_days(me.from_date, i); - if(!condition) condition = function() { return true; } - - if(condition(date)) add_column(date); - me.last_date = date; - - if(me.columns.length) { - me.column_map[date] = me.columns[me.columns.length-1]; - } - } - } - - // make columns for all date ranges - if(range=='Daily') { - build_columns(); - } else if(range=='Weekly') { - build_columns(function(date) { - if(!me.last_date) return true; - return !(dateutil.get_diff(date, me.from_date) % 7) - }); - } else if(range=='Monthly') { - build_columns(function(date) { - if(!me.last_date) return true; - return dateutil.str_to_obj(me.last_date).getMonth() != dateutil.str_to_obj(date).getMonth() - }); - } else if(range=='Quarterly') { - build_columns(function(date) { - if(!me.last_date) return true; - return dateutil.str_to_obj(date).getDate()==1 && in_list([0,3,6,9], dateutil.str_to_obj(date).getMonth()) - }); - } else if(range=='Yearly') { - build_columns(function(date) { - if(!me.last_date) return true; - return $.map(wn.report_dump.data['Fiscal Year'], function(v) { - return date==v.year_start_date ? true : null; - }).length; - }); - } - - // set label as last date of period - $.each(this.columns, function(i, col) { - col.name = me.columns[i+1] - ? dateutil.str_to_user(dateutil.add_days(me.columns[i+1].id, -1)) - : dateutil.str_to_user(me.to_date); - }); - - me.columns = std_columns.concat(me.columns); + this.make_date_range_columns(); + this.columns = std_columns.concat(this.columns); }, setup_filters: function() { var me = this; @@ -138,13 +70,7 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ this.filter_inputs.pl_or_bs.change(function() { me.filter_inputs.refresh.click(); }); - this.wrapper.bind('make', function() { - me.wrapper.on("click", ".plot-check", function() { - var checked = $(this).attr("checked"); - me.account_by_name[$(this).attr("data-id")].checked = checked ? true : false; - me.render_plot(); - }); - }); + this.setup_plot_check(); }, init_filter_values: function() { this._super(); @@ -155,7 +81,7 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ $.each(wn.report_dump.data['GL Entry'], function(i, gl) { var posting_date = dateutil.str_to_obj(gl.posting_date); - var account = me.account_by_name[gl.account]; + var account = me.item_by_name[gl.account]; var col = me.column_map[gl.posting_date]; if(col) { @@ -176,7 +102,7 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ // make balances as cumulative if(me.filter_inputs.pl_or_bs.val()=='Balance Sheet') { - $.each(me.accounts, function(i, ac) { + $.each(me.data, function(i, ac) { if((ac.rgt - ac.lft)==1 && ac.is_pl_account!='Yes') { var opening = flt(ac.opening); //if(opening) throw opening; @@ -198,12 +124,7 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ }, init_account: function(d) { // set 0 values for all columns - var me = this; - $.each(this.columns, function(i, col) { - if (col.formatter==me.currency_formatter) { - d[col.id] = 0; - } - }); + this.reset_item_values(d); // check for default graphs if(!this.accounts_initialized && !d.parent_account) { @@ -215,7 +136,7 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ var data = []; var me = this; var pl_or_bs = this.filter_inputs.pl_or_bs.val(); - $.each(this.accounts, function(i, account) { + $.each(this.data, function(i, account) { var show = pl_or_bs == "Profit and Loss" ? account.is_pl_account=="Yes" : account.is_pl_account!="Yes"; if (show && account.checked && me.apply_filter(account, "company")) { data.push({ diff --git a/erpnext/accounts/page/general_ledger/general_ledger.js b/erpnext/accounts/page/general_ledger/general_ledger.js index 8a57b06f2a..a47c076148 100644 --- a/erpnext/accounts/page/general_ledger/general_ledger.js +++ b/erpnext/accounts/page/general_ledger/general_ledger.js @@ -68,13 +68,6 @@ wn.pages['general-ledger'].onload = function(wrapper) { {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, {fieldtype:"Button", label: "Reset Filters"} ], - init_filter_values: function() { - this.filter_inputs.company.val(sys_defaults.company); - this.filter_inputs.from_date.val(dateutil.str_to_user(sys_defaults.year_start_date)); - this.filter_inputs.to_date.val(dateutil.str_to_user(sys_defaults.year_end_date)); - this.filter_inputs.voucher_no.val(""); - this.filter_inputs.account.get(0).selectedIndex = 0; - }, is_child_account: function(account, item_account) { account = this.account_by_name[account]; item_account = this.account_by_name[item_account]; @@ -148,11 +141,8 @@ wn.pages['general-ledger'].onload = function(wrapper) { } else { var out = out.concat([totals]); } - - // sanitize opening / closing - + this.data = out; - this.prepare_data_view(out); }, get_plot_data: function() { var data = []; diff --git a/erpnext/accounts/page/trial_balance/trial_balance.js b/erpnext/accounts/page/trial_balance/trial_balance.js index 91ab82aa2a..071af67eec 100644 --- a/erpnext/accounts/page/trial_balance/trial_balance.js +++ b/erpnext/accounts/page/trial_balance/trial_balance.js @@ -15,7 +15,6 @@ // along with this program. If not, see . wn.require("js/app/account_tree_grid.js"); -wn.require("js/app/account_tree_grid.css"); wn.pages['trial-balance'].onload = function(wrapper) { wn.ui.make_app_page({ diff --git a/erpnext/startup/report_data_map.py b/erpnext/startup/report_data_map.py index b13218014f..506685397e 100644 --- a/erpnext/startup/report_data_map.py +++ b/erpnext/startup/report_data_map.py @@ -50,7 +50,7 @@ data_map = { }, "Stock Ledger Entry": { "columns": ["posting_date", "posting_time", "item_code", "warehouse", "actual_qty as qty", - "voucher_type", "voucher_no"], + "voucher_type", "voucher_no", "ifnull(incoming_rate,0) as incoming_rate"], "conditions": ["ifnull(is_cancelled, 'No')='No'"], "order_by": "posting_date, posting_time, name", "links": { @@ -61,7 +61,7 @@ data_map = { }, "Item": { "columns": ["name", "if(item_name=name, '', item_name) as item_name", - "item_group", "stock_uom", "brand"], + "item_group as parent_item_group", "stock_uom", "brand"], "order_by": "name" }, "Item Group": { diff --git a/erpnext/stock/page/stock_analytics/__init__.py b/erpnext/stock/page/stock_analytics/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/page/stock_analytics/stock_analytics.js b/erpnext/stock/page/stock_analytics/stock_analytics.js new file mode 100644 index 0000000000..2e65f5c5ef --- /dev/null +++ b/erpnext/stock/page/stock_analytics/stock_analytics.js @@ -0,0 +1,238 @@ +wn.pages['stock-analytics'].onload = function(wrapper) { + wn.ui.make_app_page({ + parent: wrapper, + title: 'Stock Analytics', + single_column: true + }); + + new erpnext.StockAnalytics(wrapper); +} + +erpnext.StockAnalytics = wn.views.GridReportWithPlot.extend({ + init: function(wrapper) { + this._super({ + title: "Stock Analytics", + page: wrapper, + parent: $(wrapper).find('.layout-main'), + appframe: wrapper.appframe, + doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Fiscal Year"], + tree_grid: { + show: true, + parent_field: "parent_item_group", + formatter: function(item) { + return repl('%(value)s', { + value: item.name, + enc_value: encodeURIComponent(item.name) + }); + } + } + }) + }, + setup_columns: function() { + var std_columns = [ + {id: "check", name: "Plot", field: "check", width: 30, + formatter: this.check_formatter}, + {id: "name", name: "Item", field: "name", width: 300, + formatter: this.tree_formatter, doctype: "Item"}, + {id: "opening", name: "Opening", field: "opening", hidden: true, + formatter: this.currency_formatter}, + {id: "balance_qty", name: "Balance Qty", field: "balance_qty", hidden: true, + formatter: this.currency_formatter}, + {id: "balance_value", name: "Balance Value", field: "balance_value", hidden: true, + formatter: this.currency_formatter} + ]; + + this.make_date_range_columns(); + this.columns = std_columns.concat(this.columns); + }, + filters: [ + {fieldtype:"Select", label: "Value or Qty", options:["Value", "Quantity"], + filter: function(val, item, opts, me) { + return me.apply_zero_filter(val, item, opts, me); + }}, + {fieldtype:"Select", label: "Warehouse", link:"Warehouse", + default_value: "Select Warehouse..."}, + {fieldtype:"Select", label: "Fiscal Year", link:"Fiscal Year", + default_value: "Select Fiscal Year..."}, + {fieldtype:"Date", label: "From Date"}, + {fieldtype:"Label", label: "To"}, + {fieldtype:"Date", label: "To Date"}, + {fieldtype:"Select", label: "Range", + options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]}, + {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: "Reset Filters"} + ], + setup_filters: function() { + var me = this; + this._super(); + + this.filter_inputs.fiscal_year.change(function() { + var fy = $(this).val(); + $.each(wn.report_dump.data["Fiscal Year"], function(i, v) { + if (v.name==fy) { + me.filter_inputs.from_date.val(dateutil.str_to_user(v.year_start_date)); + me.filter_inputs.to_date.val(dateutil.str_to_user(v.year_end_date)); + } + }); + me.set_route(); + }); + + this.filter_inputs.value_or_qty.change(function() { + me.filter_inputs.refresh.click(); + }); + + this.show_zero_check() + this.setup_plot_check(); + }, + init_filter_values: function() { + this._super(); + this.filter_inputs.range.val('Weekly'); + }, + prepare_data: function() { + var me = this; + + if(!this.data) { + var items = this.get_item_tree(); + + me.parent_map = {}; + me.item_by_name = {}; + me.data = []; + + $.each(items, function(i, v) { + var d = copy_dict(v); + + me.data.push(d); + me.item_by_name[d.name] = d; + if(d.parent_item_group) { + me.parent_map[d.name] = d.parent_item_group; + } + me.reset_item_values(d); + }); + this.set_indent(); + } else { + // otherwise, only reset values + $.each(this.data, function(i, d) { + me.reset_item_values(d); + }); + } + + this.prepare_balances(); + this.update_groups(); + + }, + get_item_tree: function() { + // prepare map with items in respective item group + var item_group_map = {}; + $.each(wn.report_dump.data["Item"], function(i, item) { + var parent = item.parent_item_group + if(!item_group_map[parent]) item_group_map[parent] = []; + item_group_map[parent].push(item); + }); + + // arrange items besides their parent item groups + var items = []; + $.each(wn.report_dump.data["Item Group"], function(i, group){ + group.is_group = true; + items.push(group); + items = items.concat(item_group_map[group.name] || []); + }); + return items; + }, + prepare_balances: function() { + var me = this; + var from_date = dateutil.str_to_obj(this.from_date); + var to_date = dateutil.str_to_obj(this.to_date); + var data = wn.report_dump.data["Stock Ledger Entry"]; + var is_value = me.value_or_qty == "Value"; + + for(var i=0, j=data.length; i 0 ? sl.incoming_rate : + (item.balance_qty.toFixed(2) == 0.00 ? 0 : flt(item.balance_value) / flt(item.balance_qty)); + var value_diff = (rate * sl.qty); + + // update balance + item.balance_qty += sl.qty; + item.balance_value += value_diff; + + var diff = is_value ? value_diff : sl.qty; + + if(posting_datetime < from_date) { + item.opening += diff; + } else if(posting_datetime <= to_date) { + item[me.column_map[sl.posting_date].field] += diff; + } else { + break; + } + } + } + }, + update_groups: function() { + var me = this; + + $.each(this.data, function(i, item) { + // update groups + if(!item.is_group) { + var balance = item.opening; + $.each(me.columns, function(i, col) { + if(col.formatter==me.currency_formatter && !col.hidden) { + item[col.field] = balance + item[col.field]; + balance = item[col.field]; + } + }); + + var parent = me.parent_map[item.name]; + while(parent) { + parent_group = me.item_by_name[parent]; + $.each(me.columns, function(c, col) { + if (col.formatter == me.currency_formatter) { + parent_group[col.field] = + flt(parent_group[col.field]) + + flt(item[col.field]); + } + }); + parent = me.parent_map[parent]; + } + } + }); + }, + get_plot_data: function() { + var data = []; + var me = this; + $.each(this.data, function(i, item) { + if (item.checked) { + data.push({ + label: item.name, + data: $.map(me.columns, function(col, idx) { + if(col.formatter==me.currency_formatter && !col.hidden) { + return [[dateutil.user_to_obj(col.name).getTime(), item[col.field]]] + } + }), + points: {show: true}, + lines: {show: true, fill: true}, + }); + + // prepend opening + data[data.length-1].data = [[dateutil.str_to_obj(me.from_date).getTime(), + item.opening]].concat(data[data.length-1].data); + } + }); + + return data; + }, + get_plot_options: function() { + return { + grid: { hoverable: true, clickable: true }, + xaxis: { mode: "time", + min: dateutil.str_to_obj(this.from_date).getTime(), + max: dateutil.str_to_obj(this.to_date).getTime() } + } + } +}); diff --git a/erpnext/stock/page/stock_analytics/stock_analytics.txt b/erpnext/stock/page/stock_analytics/stock_analytics.txt new file mode 100644 index 0000000000..3d9510df2e --- /dev/null +++ b/erpnext/stock/page/stock_analytics/stock_analytics.txt @@ -0,0 +1,28 @@ +# Page, stock-analytics +[ + + # These values are common in all dictionaries + { + u'creation': '2012-09-20 12:13:45', + u'docstatus': 0, + u'modified': '2012-09-20 12:13:45', + u'modified_by': u'Administrator', + u'owner': u'Administrator' + }, + + # These values are common for all Page + { + u'doctype': u'Page', + 'module': u'Stock', + u'name': u'__common__', + 'page_name': u'stock-analytics', + 'standard': u'Yes', + 'title': u'Stock Analytics' + }, + + # Page, stock-analytics + { + u'doctype': u'Page', + u'name': u'stock-analytics' + } +] \ No newline at end of file diff --git a/erpnext/stock/page/stock_ledger/stock_ledger.js b/erpnext/stock/page/stock_ledger/stock_ledger.js index 3f6d4a5284..deb3743102 100644 --- a/erpnext/stock/page/stock_ledger/stock_ledger.js +++ b/erpnext/stock/page/stock_ledger/stock_ledger.js @@ -5,183 +5,180 @@ wn.pages['stock-ledger'].onload = function(wrapper) { single_column: true }); - erpnext.stock_ledger = new wn.views.GridReport({ - title: "Stock Ledger", - page: wrapper, - parent: $(wrapper).find('.layout-main'), - appframe: wrapper.appframe, - doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry"], + new erpnext.StockLedger(wrapper); +} - setup_columns: function() { - this.hide_balance = (this.is_default("item_code") || this.voucher_no) ? true : false; - this.columns = [ - {id: "posting_datetime", name: "Posting Date", field: "posting_datetime", width: 120, - formatter: this.date_formatter}, - {id: "item_code", name: "Item Code", field: "item_code", width: 160, - link_formatter: { - filter_input: "item_code", - open_btn: true, - doctype: '"Item"' - }}, - {id: "warehouse", name: "Warehouse", field: "warehouse", width: 100, - link_formatter: {filter_input: "warehouse"}}, - {id: "qty", name: "Qty", field: "qty", width: 100, - formatter: this.currency_formatter}, - {id: "balance", name: "Balance", field: "balance", width: 100, - formatter: this.currency_formatter, - hidden: this.hide_balance}, - {id: "voucher_type", name: "Voucher Type", field: "voucher_type", width: 120}, - {id: "voucher_no", name: "Voucher No", field: "voucher_no", width: 160, - link_formatter: { - filter_input: "voucher_no", - open_btn: true, - doctype: "dataContext.voucher_type" - }}, - {id: "description", name: "Description", field: "description", width: 200, - formatter: this.text_formatter}, - ]; - - }, - filters: [ - {fieldtype:"Select", label: "Warehouse", link:"Warehouse", default_value: "Select Warehouse...", - filter: function(val, item, opts) { - return item.warehouse == val || val == opts.default_value; - }}, - {fieldtype:"Select", label: "Item Code", link:"Item", default_value: "Select Item...", - filter: function(val, item, opts) { - return item.item_code == val || val == opts.default_value; - }}, - {fieldtype:"Data", label: "Voucher No", - filter: function(val, item, opts) { - if(!val) return true; - return (item.voucher_no && item.voucher_no.indexOf(val)!=-1); - }}, - {fieldtype:"Date", label: "From Date", filter: function(val, item) { - return dateutil.str_to_obj(val) <= dateutil.str_to_obj(item.posting_date); - }}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date", filter: function(val, item) { - return dateutil.str_to_obj(val) >= dateutil.str_to_obj(item.posting_date); - }}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} - ], - init_filter_values: function() { - this.filter_inputs.warehouse.get(0).selectedIndex = 0; - this.filter_inputs.item_code.get(0).selectedIndex = 0; - this.filter_inputs.from_date.val(dateutil.str_to_user(sys_defaults.year_start_date)); - this.filter_inputs.to_date.val(dateutil.str_to_user(sys_defaults.year_end_date)); - this.filter_inputs.voucher_no.val(""); - }, - prepare_data: function() { - var me = this; - if(!this.item_by_name) - this.item_by_name = this.make_name_map(wn.report_dump.data["Item"]); - var data = wn.report_dump.data["Stock Ledger Entry"]; - var out = []; - - if(this.to_date < this.from_date) { - msgprint("From Date must be before To Date"); - return; - } +erpnext.StockLedger = wn.views.GridReportWithPlot.extend({ + init: function(wrapper) { + this._super({ + title: "Stock Ledger", + page: wrapper, + parent: $(wrapper).find('.layout-main'), + appframe: wrapper.appframe, + doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry"] + }) + }, - var opening = { - item_code: "On " + dateutil.str_to_user(this.from_date), qty: 0.0, balance: 0.0, - id:"_opening", _show: true, _style: "font-weight: bold" - } - var total_in = { - item_code: "Total In", qty: 0.0, balance: 0.0, - id:"_total_in", _show: true, _style: "font-weight: bold" - } - var total_out = { - item_code: "Total Out", qty: 0.0, balance: 0.0, - id:"_total_out", _show: true, _style: "font-weight: bold" + setup_columns: function() { + this.hide_balance = (this.is_default("item_code") || this.voucher_no) ? true : false; + this.columns = [ + {id: "posting_datetime", name: "Posting Date", field: "posting_datetime", width: 120, + formatter: this.date_formatter}, + {id: "item_code", name: "Item Code", field: "item_code", width: 160, + link_formatter: { + filter_input: "item_code", + open_btn: true, + doctype: '"Item"' + }}, + {id: "warehouse", name: "Warehouse", field: "warehouse", width: 100, + link_formatter: {filter_input: "warehouse"}}, + {id: "qty", name: "Qty", field: "qty", width: 100, + formatter: this.currency_formatter}, + {id: "balance", name: "Balance", field: "balance", width: 100, + formatter: this.currency_formatter, + hidden: this.hide_balance}, + {id: "voucher_type", name: "Voucher Type", field: "voucher_type", width: 120}, + {id: "voucher_no", name: "Voucher No", field: "voucher_no", width: 160, + link_formatter: { + filter_input: "voucher_no", + open_btn: true, + doctype: "dataContext.voucher_type" + }}, + {id: "description", name: "Description", field: "description", width: 200, + formatter: this.text_formatter}, + ]; + + }, + filters: [ + {fieldtype:"Select", label: "Warehouse", link:"Warehouse", default_value: "Select Warehouse...", + filter: function(val, item, opts) { + return item.warehouse == val || val == opts.default_value; + }}, + {fieldtype:"Select", label: "Item Code", link:"Item", default_value: "Select Item...", + filter: function(val, item, opts) { + return item.item_code == val || val == opts.default_value; + }}, + {fieldtype:"Data", label: "Voucher No", + filter: function(val, item, opts) { + if(!val) return true; + return (item.voucher_no && item.voucher_no.indexOf(val)!=-1); + }}, + {fieldtype:"Date", label: "From Date", filter: function(val, item) { + return dateutil.str_to_obj(val) <= dateutil.str_to_obj(item.posting_date); + }}, + {fieldtype:"Label", label: "To"}, + {fieldtype:"Date", label: "To Date", filter: function(val, item) { + return dateutil.str_to_obj(val) >= dateutil.str_to_obj(item.posting_date); + }}, + {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: "Reset Filters"} + ], + init_filter_values: function() { + this._super(); + this.filter_inputs.warehouse.get(0).selectedIndex = 0; + }, + prepare_data: function() { + var me = this; + if(!this.item_by_name) + this.item_by_name = this.make_name_map(wn.report_dump.data["Item"]); + var data = wn.report_dump.data["Stock Ledger Entry"]; + var out = []; + + var opening = { + item_code: "On " + dateutil.str_to_user(this.from_date), qty: 0.0, balance: 0.0, + id:"_opening", _show: true, _style: "font-weight: bold" + } + var total_in = { + item_code: "Total In", qty: 0.0, balance: 0.0, + id:"_total_in", _show: true, _style: "font-weight: bold" + } + var total_out = { + item_code: "Total Out", qty: 0.0, balance: 0.0, + id:"_total_out", _show: true, _style: "font-weight: bold" + } + + // clear balance + $.each(wn.report_dump.data["Item"], function(i, item) { item.balance = 0.0; }); + + // + for(var i=0, j=data.length; i 0) total_in.qty += sl.qty; + else total_out.qty += (-1 * sl.qty); + } } - // clear balance - $.each(wn.report_dump.data["Item"], function(i, item) { item.balance = 0.0; }); + if(!before_end) break; - // - for(var i=0, j=data.length; i 0) total_in.qty += sl.qty; - else total_out.qty += (-1 * sl.qty); + // apply filters + if(me.apply_filters(sl)) { + out.push(sl); + } + + // update balance + if((!me.is_default("warehouse") ? me.apply_filter(sl, "warehouse") : true)) { + sl.balance = me.item_by_name[sl.item_code].balance + sl.qty; + me.item_by_name[sl.item_code].balance = sl.balance; + } + } + + if(me.item_code != me.item_code_default && !me.voucher_no) { + var closing = { + item_code: "On " + dateutil.str_to_user(this.to_date), + balance: (out ? out[out.length-1].balance : 0), qty: 0, + id:"_closing", _show: true, _style: "font-weight: bold" + }; + var out = [opening].concat(out).concat([total_in, total_out, closing]); + } + + this.data = out; + }, + get_plot_data: function() { + var data = []; + var me = this; + if(me.hide_balance) return false; + data.push({ + label: me.item_code, + data: [[dateutil.str_to_obj(me.from_date).getTime(), me.data[0].balance]] + .concat($.map(me.data, function(col, idx) { + if (col.posting_datetime) { + return [[dateutil.str_to_obj(col.posting_datetime).getTime(), col.balance - col.qty], + [dateutil.str_to_obj(col.posting_datetime).getTime(), col.balance]] } - } - - if(!before_end) break; - - // apply filters - if(me.apply_filters(sl)) { - out.push(sl); - } - - // update balance - if((!me.is_default("warehouse") ? me.apply_filter(sl, "warehouse") : true)) { - sl.balance = me.item_by_name[sl.item_code].balance + sl.qty; - me.item_by_name[sl.item_code].balance = sl.balance; - } - } - - if(me.item_code != me.item_code_default && !me.voucher_no) { - var closing = { - item_code: "On " + dateutil.str_to_user(this.to_date), - balance: (out ? out[out.length-1].balance : 0), qty: 0, - id:"_closing", _show: true, _style: "font-weight: bold" - }; - var out = [opening].concat(out).concat([total_in, total_out, closing]); - } - - this.data = out; - this.prepare_data_view(out); - }, - get_plot_data: function() { - var data = []; - var me = this; - if(me.hide_balance) return false; - data.push({ - label: me.item_code, - data: [[dateutil.str_to_obj(me.from_date).getTime(), me.data[0].balance]] - .concat($.map(me.data, function(col, idx) { - if (col.posting_datetime) { - return [[dateutil.str_to_obj(col.posting_datetime).getTime(), col.balance - col.qty], - [dateutil.str_to_obj(col.posting_datetime).getTime(), col.balance]] - } - return null; - })).concat([ - // closing - [dateutil.str_to_obj(me.to_date).getTime(), me.data[me.data.length - 1].balance] - ]), - points: {show: true}, - lines: {show: true, fill: true}, - }); - return data; - }, - get_plot_options: function() { - return { - grid: { hoverable: true, clickable: true }, - xaxis: { mode: "time", - min: dateutil.str_to_obj(this.from_date).getTime(), - max: dateutil.str_to_obj(this.to_date).getTime(), - }, - } - }, - get_tooltip_text: function(label, x, y) { - var d = new Date(x); - var date = dateutil.obj_to_user(d) + " " + d.getHours() + ":" + d.getMinutes(); - var value = fmt_money(y); - return value.bold() + " on " + date; - }, - }); -} \ No newline at end of file + return null; + })).concat([ + // closing + [dateutil.str_to_obj(me.to_date).getTime(), me.data[me.data.length - 1].balance] + ]), + points: {show: true}, + lines: {show: true, fill: true}, + }); + return data; + }, + get_plot_options: function() { + return { + grid: { hoverable: true, clickable: true }, + xaxis: { mode: "time", + min: dateutil.str_to_obj(this.from_date).getTime(), + max: dateutil.str_to_obj(this.to_date).getTime(), + }, + } + }, + get_tooltip_text: function(label, x, y) { + var d = new Date(x); + var date = dateutil.obj_to_user(d) + " " + d.getHours() + ":" + d.getMinutes(); + var value = fmt_money(y); + return value.bold() + " on " + date; + } +}); \ No newline at end of file diff --git a/public/js/all-app.js b/public/js/all-app.js index 68f70b560e..fdd710bf67 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -1077,17 +1077,22 @@ me.list.run();});this.dialog.show();},add_column:function(c){var w=$('
').appendTo(this.parent);if(this.filters){this.make_filters();} -this.make_waiting();this.import_slickgrid();var me=this;this.get_data();},bind_show:function(){var me=this;$(this.page).bind('show',function(){wn.cur_grid_report=me;me.apply_filters_from_route();me.refresh();});},get_data:function(){var me=this;wn.report_dump.with_data(this.doctypes,function(){me.setup_filters();me.init_filter_values();me.refresh();},this.wrapper.find(".progress .bar"));},setup_filters:function(){var me=this;$.each(me.filter_inputs,function(i,v){var opts=v.get(0).opts;if(opts.fieldtype=="Select"&&inList(me.doctypes,opts.link)){$(v).add_options($.map(wn.report_dump.data[opts.link],function(d){return d.name;}));}});this.filter_inputs.refresh&&this.filter_inputs.refresh.click(function(){me.set_route();});this.filter_inputs.reset_filters&&this.filter_inputs.reset_filters.click(function(){me.init_filter_values();me.set_route();});},make_waiting:function(){this.waiting=$('
\ -

Loading Report...

\ -
\ -
').appendTo(this.wrapper);},make_filters:function(){var me=this;$.each(this.filters,function(i,v){v.fieldname=v.fieldname||v.label.replace(/ /g,'_').toLowerCase();var input=null;if(v.fieldtype=='Select'){input=me.appframe.add_select(v.label,v.options||[v.default_value]);}else if(v.fieldtype=='Button'){input=me.appframe.add_button(v.label);if(v.icon){$('').prependTo(input);}}else if(v.fieldtype=='Date'){input=me.appframe.add_date(v.label);}else if(v.fieldtype=='Label'){input=me.appframe.add_label(v.label);}else if(v.fieldtype=='Data'){input=me.appframe.add_data(v.label);} +data.push(row);});wn.report_dump.data[doctype]=data;});$.each(r.message,function(doctype,doctype_data){if(doctype_data.links){$.each(wn.report_dump.data[doctype],function(row_idx,row){$.each(doctype_data.links,function(link_key,link){row[link_key]=wn.report_dump.data[link[0]][row[link_key]][link[1]];})})}});callback();},progress_bar:progress_bar})}else{callback();}}});wn.provide("wn.views");wn.views.GridReport=Class.extend({init:function(opts){this.filter_inputs={};this.preset_checks=[];this.tree_grid={show:false};$.extend(this,opts);this.wrapper=$('
').appendTo(this.parent);if(this.filters){this.make_filters();} +this.make_waiting();this.import_slickgrid();var me=this;this.get_data();},bind_show:function(){var me=this;$(this.page).bind('show',function(){wn.cur_grid_report=me;me.apply_filters_from_route();me.refresh();});},get_data:function(){var me=this;wn.report_dump.with_data(this.doctypes,function(){me.setup_filters();me.init_filter_values();me.refresh();},this.wrapper.find(".progress .bar"));},setup_filters:function(){var me=this;$.each(me.filter_inputs,function(i,v){var opts=v.get(0).opts;if(opts.fieldtype=="Select"&&inList(me.doctypes,opts.link)){$(v).add_options($.map(wn.report_dump.data[opts.link],function(d){return d.name;}));}});this.filter_inputs.refresh&&this.filter_inputs.refresh.click(function(){me.set_route();});this.filter_inputs.reset_filters&&this.filter_inputs.reset_filters.click(function(){me.init_filter_values();me.set_route();});},init_filter_values:function(){var me=this;$.each(this.filter_inputs,function(key,filter){var opts=filter.get(0).opts;if(sys_defaults[key]){filter.val(sys_defaults[key]);}else if(opts.fieldtype=='Select'){filter.get(0).selectedIndex=0;}else if(opts.fieldtype=='Data'){filter.val("");}}) +if(this.filter_inputs.from_date) +this.filter_inputs.from_date.val(dateutil.str_to_user(sys_defaults.year_start_date));if(this.filter_inputs.to_date) +this.filter_inputs.to_date.val(dateutil.str_to_user(sys_defaults.year_end_date));},make_filters:function(){var me=this;$.each(this.filters,function(i,v){v.fieldname=v.fieldname||v.label.replace(/ /g,'_').toLowerCase();var input=null;if(v.fieldtype=='Select'){input=me.appframe.add_select(v.label,v.options||[v.default_value]);}else if(v.fieldtype=='Button'){input=me.appframe.add_button(v.label);if(v.icon){$('').prependTo(input);}}else if(v.fieldtype=='Date'){input=me.appframe.add_date(v.label);}else if(v.fieldtype=='Label'){input=me.appframe.add_label(v.label);}else if(v.fieldtype=='Data'){input=me.appframe.add_data(v.label);} if(input){input&&(input.get(0).opts=v);if(v.cssClass){input.addClass(v.cssClass);} input.keypress(function(e){if(e.which==13){me.set_route();}})} -me.filter_inputs[v.fieldname]=input;});},load_filter_values:function(){var me=this;$.each(this.filter_inputs,function(i,f){var opts=f.get(0).opts;if(opts.fieldtype!='Button'){me[opts.fieldname]=f.val();if(opts.fieldtype=="Date"){me[opts.fieldname]=dateutil.user_to_str(me[opts.fieldname]);}else if(opts.fieldtype=="Select"){me[opts.fieldname+'_default']=opts.default_value;}}});},make_name_map:function(data,key){var map={};key=key||"name";$.each(data,function(i,v){map[v[key]]=v;}) -return map;},import_slickgrid:function(){wn.require('js/lib/slickgrid/slick.grid.css');wn.require('js/lib/slickgrid/slick-default-theme.css');wn.require('js/lib/slickgrid/jquery.event.drag.min.js');wn.require('js/lib/slickgrid/slick.core.js');wn.require('js/lib/slickgrid/slick.grid.js');wn.require('js/lib/slickgrid/slick.dataview.js');wn.dom.set_style('.slick-cell { font-size: 12px; }');},refresh:function(){this.waiting.toggle(false);if(!this.grid_wrapper) -this.make();this.show_zero=$('.show-zero input:checked').length;this.load_filter_values();this.setup_columns();this.setup_dataview_columns();this.apply_link_formatters();this.prepare_data();this.render();this.render_plot();},setup_dataview_columns:function(){this.dataview_columns=$.map(this.columns,function(col){return!col.hidden?col:null;});},make:function(){$('').appendTo(this.wrapper);$('
\ + \ Print \ | \ Export \ @@ -1096,27 +1101,37 @@ this.make();this.show_zero=$('.show-zero input:checked').length;this.load_filter Show rows with zero values\
').appendTo(this.wrapper);this.bind_show();wn.cur_grid_report=this;this.apply_filters_from_route();$(this.wrapper).trigger('make');},apply_filters_from_route:function(){var hash=decodeURIComponent(window.location.hash);var me=this;if(hash.indexOf('/')!=-1){$.each(hash.split('/').splice(1).join('/').split('&'),function(i,f){var f=f.split("=");if(me.filter_inputs[f[0]]){me.filter_inputs[f[0]].val(decodeURIComponent(f[1]));}else{console.log("Invalid filter: "+f[0]);}});}else{this.init_filter_values();}},set_route:function(){wn.set_route(wn.container.page.page_name,$.map(this.filter_inputs,function(v){var val=v.val();var opts=v.get(0).opts;if(val&&val!=opts.default_value) return encodeURIComponent(opts.fieldname) -+'='+encodeURIComponent(val);}).join('&'))},render:function(){this.grid=new Slick.Grid("#"+this.id,this.dataView,this.dataview_columns,this.options);var me=this;this.dataView.onRowsChanged.subscribe(function(e,args){me.grid.invalidateRows(args.rows);me.grid.render();});this.dataView.onRowCountChanged.subscribe(function(e,args){me.grid.updateRowCount();me.grid.render();});this.add_grid_events&&this.add_grid_events();},prepare_data_view:function(items){this.dataView=new Slick.Data.DataView({inlineFilters:true});this.dataView.beginUpdate();this.dataView.setItems(items);if(this.dataview_filter)this.dataView.setFilter(this.dataview_filter);this.dataView.endUpdate();},export:function(){var me=this;var res=[$.map(this.columns,function(v){return v.name;})].concat(this.get_view_data());wn.require("js/lib/downloadify/downloadify.min.js");wn.require("js/lib/downloadify/swfobject.js");var id=wn.dom.set_unique_id();var msgobj=msgprint('

You must have Flash 10 installed to download this file.

');Downloadify.create(id,{filename:function(){return me.title+'.csv';},data:function(){return wn.to_csv(res);},swf:'js/lib/downloadify/downloadify.swf',downloadImage:'js/lib/downloadify/download.png',onComplete:function(){msgobj.hide();},onCancel:function(){msgobj.hide();},onError:function(){msgobj.hide();},width:100,height:30,transparent:true,append:false});return false;},render_plot:function(){var plot_data=this.get_plot_data?this.get_plot_data():null;if(!plot_data){this.wrapper.find('.plot').toggle(false);return;} -wn.require('js/lib/flot/jquery.flot.js');this.plot=$.plot(this.wrapper.find('.plot').toggle(true),plot_data,this.get_plot_options());this.setup_plot_hover();},setup_plot_hover:function(){var me=this;this.tooltip_id=wn.dom.set_unique_id();function showTooltip(x,y,contents){$('
'+contents+'
').css({position:'absolute',display:'none',top:y+5,left:x+5,border:'1px solid #fdd',padding:'2px','background-color':'#fee',opacity:0.80}).appendTo("body").fadeIn(200);} ++'='+encodeURIComponent(val);}).join('&'))},options:{editable:false,enableColumnReorder:false},render:function(){this.grid=new Slick.Grid("#"+this.id,this.dataView,this.dataview_columns,this.options);var me=this;this.dataView.onRowsChanged.subscribe(function(e,args){me.grid.invalidateRows(args.rows);me.grid.render();});this.dataView.onRowCountChanged.subscribe(function(e,args){me.grid.updateRowCount();me.grid.render();});this.tree_grid.show&&this.add_tree_grid_events();},prepare_data_view:function(){this.dataView=new Slick.Data.DataView({inlineFilters:true});this.dataView.beginUpdate();this.dataView.setItems(this.data);if(this.dataview_filter)this.dataView.setFilter(this.dataview_filter);if(this.tree_grid.show)this.dataView.setFilter(this.tree_dataview_filter);this.dataView.endUpdate();},export:function(){var me=this;var res=[$.map(this.columns,function(v){return v.name;})].concat(this.get_view_data());wn.require("js/lib/downloadify/downloadify.min.js");wn.require("js/lib/downloadify/swfobject.js");var id=wn.dom.set_unique_id();var msgobj=msgprint('

You must have Flash 10 installed to download this file.

');Downloadify.create(id,{filename:function(){return me.title+'.csv';},data:function(){return wn.to_csv(res);},swf:'js/lib/downloadify/downloadify.swf',downloadImage:'js/lib/downloadify/download.png',onComplete:function(){msgobj.hide();},onCancel:function(){msgobj.hide();},onError:function(){msgobj.hide();},width:100,height:30,transparent:true,append:false});return false;},add_tree_grid_events:function(){var me=this;this.grid.onClick.subscribe(function(e,args){if($(e.target).hasClass("toggle")){var item=me.dataView.getItem(args.row);if(item){if(!item._collapsed){item._collapsed=true;}else{item._collapsed=false;} +me.dataView.updateItem(item.id,item);} +e.stopImmediatePropagation();}});},tree_formatter:function(row,cell,value,columnDef,dataContext){var me=wn.cur_grid_report;value=value.replace(/&/g,"&").replace(//g,">");var data=me.data;var spacer="";var idx=me.dataView.getIdxById(dataContext.id);var link=me.tree_grid.formatter(dataContext);if(columnDef.doctype){link+=me.get_link_open_icon(columnDef.doctype,value);} +if(data[idx+1]&&data[idx+1].indent>data[idx].indent){if(dataContext._collapsed){return spacer+"  "+link;}else{return spacer+"  "+link;}}else{return spacer+"  "+link;}},tree_dataview_filter:function(item){var me=wn.cur_grid_report;if(!me.apply_filters(item))return false;var parent=item[me.tree_grid.parent_field];while(parent){if(me.item_by_name[parent]._collapsed){return false;} +parent=me.parent_map[parent];} +return true;},set_indent:function(){var me=this;$.each(this.data,function(i,d){var indent=0;var parent=me.parent_map[d.name];if(parent){while(parent){indent++;parent=me.parent_map[parent];}} +d.indent=indent;});},apply_filters:function(item){var filters=this.filter_inputs;if(item._show)return true;for(i in filters){if(!this.apply_filter(item,i))return false;} +return true;},apply_filter:function(item,fieldname){var filter=this.filter_inputs[fieldname].get(0);if(filter.opts.filter){if(!filter.opts.filter(this[filter.opts.fieldname],item,filter.opts,this)){return false;}} +return true;},apply_zero_filter:function(val,item,opts,me){if(!me.show_zero){for(var i=0,j=me.columns.length;i0.001||flt(item[col.field])<-0.001){return true;}}} +return false;} +return true;},show_zero_check:function(){var me=this;this.wrapper.bind('make',function(){me.wrapper.find('.show-zero').toggle(true).find('input').click(function(){me.refresh();});});},is_default:function(fieldname){return this[fieldname]==this[fieldname+"_default"];},date_formatter:function(row,cell,value,columnDef,dataContext){return dateutil.str_to_user(value);},currency_formatter:function(row,cell,value,columnDef,dataContext){return repl('
%(value)s
',{_style:dataContext._style||"",value:fmt_money(value)});},text_formatter:function(row,cell,value,columnDef,dataContext){return repl('%(value)s',{_style:dataContext._style||"",esc_value:cstr(value).replace(/"/g,'\"'),value:cstr(value)});},check_formatter:function(row,cell,value,columnDef,dataContext){return repl("",{"id":dataContext.id,"checked":dataContext.checked?"checked":""})},apply_link_formatters:function(){var me=this;$.each(this.dataview_columns,function(i,col){if(col.link_formatter){col.formatter=function(row,cell,value,columnDef,dataContext){if(!value)return"";var me=wn.cur_grid_report;if(dataContext._show){return repl('%(value)s',{_style:dataContext._style||"",value:value});} +var link_formatter=me.dataview_columns[cell].link_formatter;var html=repl('\ + %(value)s',{value:value,col_name:link_formatter.filter_input,page_name:wn.container.page.page_name}) +if(link_formatter.open_btn){html+=me.get_link_open_icon(eval(link_formatter.doctype),value);} +return html;}}})},get_link_open_icon:function(doctype,name){return repl(' \ + ',{name:name,doctype:doctype});},make_date_range_columns:function(){this.columns=[];var me=this;var range=this.filter_inputs.range.val();this.from_date=dateutil.user_to_str(this.filter_inputs.from_date.val());this.to_date=dateutil.user_to_str(this.filter_inputs.to_date.val());var date_diff=dateutil.get_diff(this.to_date,this.from_date);me.column_map={};var add_column=function(date){me.columns.push({id:date,name:dateutil.str_to_user(date),field:date,formatter:me.currency_formatter,width:100});} +var build_columns=function(condition){for(var i=0;i'+contents+'
').css({position:'absolute',display:'none',top:y+5,left:x+5,border:'1px solid #fdd',padding:'2px','background-color':'#fee',opacity:0.80}).appendTo("body").fadeIn(200);} this.previousPoint=null;this.wrapper.find('.plot').bind("plothover",function(event,pos,item){if(item){if(me.previousPoint!=item.dataIndex){me.previousPoint=item.dataIndex;$("#"+me.tooltip_id).remove();showTooltip(item.pageX,item.pageY,me.get_tooltip_text(item.series.label,item.datapoint[0],item.datapoint[1]));}} else{$("#"+me.tooltip_id).remove();me.previousPoint=null;}});},get_tooltip_text:function(label,x,y){var date=dateutil.obj_to_user(new Date(x));var value=fmt_money(y);return value+" on "+date;},get_view_data:function(){var res=[];var col_map=$.map(this.columns,function(v){return v.field;});for(var i=0,len=this.dataView.getLength();i0.001||flt(item[col.field])<-0.001){return true;}}} -return false;} -return true;},show_zero_check:function(){var me=this;this.wrapper.bind('make',function(){me.wrapper.find('.show-zero').toggle(true).find('input').click(function(){me.refresh();});});},is_default:function(fieldname){return this[fieldname]==this[fieldname+"_default"];},date_formatter:function(row,cell,value,columnDef,dataContext){return dateutil.str_to_user(value);},currency_formatter:function(row,cell,value,columnDef,dataContext){return repl('
%(value)s
',{_style:dataContext._style||"",value:fmt_money(value)});},text_formatter:function(row,cell,value,columnDef,dataContext){return repl('%(value)s',{_style:dataContext._style||"",esc_value:cstr(value).replace(/"/g,'\"'),value:cstr(value)});},check_formatter:function(row,cell,value,columnDef,dataContext){return repl("",{"id":dataContext.id,"checked":dataContext.checked?"checked":""})},apply_link_formatters:function(){var me=this;$.each(this.dataview_columns,function(i,col){if(col.link_formatter){col.formatter=function(row,cell,value,columnDef,dataContext){if(!value)return"";if(dataContext._show){return repl('%(value)s',{_style:dataContext._style||"",value:value});} -var link_formatter=wn.cur_grid_report.dataview_columns[cell].link_formatter;var html=repl('\ - %(value)s',{value:value,col_name:link_formatter.filter_input,page_name:wn.container.page.page_name}) -if(link_formatter.open_btn){html+=repl(' \ - ',{value:value,doctype:eval(link_formatter.doctype)});} -return html;}}})}}) +return res;},}) /* * lib/js/legacy/widgets/dialog.js */ diff --git a/public/js/app/account_tree_grid.js b/public/js/app/account_tree_grid.js index b1e7fb5686..56d1c0907a 100644 --- a/public/js/app/account_tree_grid.js +++ b/public/js/app/account_tree_grid.js @@ -11,20 +11,30 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -erpnext.AccountTreeGrid = wn.views.GridReport.extend({ +erpnext.AccountTreeGrid = wn.views.GridReportWithPlot.extend({ init: function(wrapper, title) { this._super({ title: title, page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, - doctypes: ["Company", "Fiscal Year", "Account", "GL Entry"] + doctypes: ["Company", "Fiscal Year", "Account", "GL Entry"], + tree_grid: { + show: true, + parent_field: "parent_account", + formatter: function(item) { + return repl('%(value)s', { + value: item.name, + enc_value: encodeURIComponent(item.name) + }); + } + }, }); }, setup_columns: function() { this.columns = [ {id: "name", name: "Account", field: "name", width: 300, cssClass: "cell-title", - formatter: this.account_formatter}, + formatter: this.tree_formatter}, {id: "opening_debit", name: "Opening (Dr)", field: "opening_debit", width: 100, formatter: this.currency_formatter}, {id: "opening_credit", name: "Opening (Cr)", field: "opening_credit", width: 100, @@ -72,31 +82,24 @@ erpnext.AccountTreeGrid = wn.views.GridReport.extend({ }); me.show_zero_check() }, - init_filter_values: function() { - this.filter_inputs.company.val(sys_defaults.company); - this.filter_inputs.fiscal_year.val(sys_defaults.fiscal_year); - this.filter_inputs.from_date.val(dateutil.str_to_user(sys_defaults.year_start_date)); - this.filter_inputs.to_date.val(dateutil.str_to_user(sys_defaults.year_end_date)); - }, prepare_data: function() { var me = this; - this.data = [] - if(this.accounts) { + if(this.data) { // refresh -- only initialize - $.each(this.accounts, function(i, d) { + $.each(this.data, function(i, d) { me.init_account(d); }) } else { // make accounts list - me.accounts = []; + me.data = []; me.parent_map = {}; - me.account_by_name = {}; + me.item_by_name = {}; $.each(wn.report_dump.data["Account"], function(i, v) { var d = copy_dict(v); - me.accounts.push(d); - me.account_by_name[d.name] = d; + me.data.push(d); + me.item_by_name[d.name] = d; if(d.parent_account) { me.parent_map[d.name] = d.parent_account; } @@ -106,18 +109,9 @@ erpnext.AccountTreeGrid = wn.views.GridReport.extend({ } this.set_indent(); this.prepare_balances(); - this.prepare_data_view(this.accounts); - }, - init_account: function(d) { - $.extend(d, { - "opening_debit": 0, - "opening_credit": 0, - "debit": 0, - "credit": 0, - "closing_debit": 0, - "closing_credit": 0 - }); + }, + prepare_balances: function() { var gl = wn.report_dump.data['GL Entry']; var me = this; @@ -127,14 +121,14 @@ erpnext.AccountTreeGrid = wn.views.GridReport.extend({ this.set_fiscal_year(); if (!this.fiscal_year) return; - $.each(this.accounts, function(i, v) { + $.each(this.data, function(i, v) { v.opening_debit = v.opening_credit = v.debit = v.credit = v.closing_debit = v.closing_credit = 0; }); $.each(gl, function(i, v) { var posting_date = dateutil.str_to_obj(v.posting_date); - var account = me.account_by_name[v.account]; + var account = me.item_by_name[v.account]; me.update_balances(account, posting_date, v) }); @@ -169,12 +163,12 @@ erpnext.AccountTreeGrid = wn.views.GridReport.extend({ update_groups: function() { // update groups var me= this; - $.each(this.accounts, function(i, account) { + $.each(this.data, function(i, account) { // update groups if(account.rgt - account.lft == 1) { var parent = me.parent_map[account.name]; while(parent) { - parent_account = me.account_by_name[parent]; + parent_account = me.item_by_name[parent]; $.each(me.columns, function(c, col) { if (col.formatter == me.currency_formatter) { parent_account[col.field] = @@ -208,71 +202,4 @@ erpnext.AccountTreeGrid = wn.views.GridReport.extend({ return; } }, - set_indent: function() { - var me = this; - $.each(this.accounts, function(i, d) { - var indent = 0; - var parent = me.parent_map[d.name]; - if(parent) { - while(parent) { - indent++; - parent = me.parent_map[parent]; - } - } - d.indent = indent; - }); - }, - account_formatter: function (row, cell, value, columnDef, dataContext) { - value = value.replace(/&/g,"&").replace(//g,">"); - var data = wn.cur_grid_report.accounts; - var spacer = ""; - var idx = wn.cur_grid_report.dataView.getIdxById(dataContext.id); - var account_link = repl('%(value)s', { - value: value, - enc_value: encodeURIComponent(value) - }); - - if (data[idx + 1] && data[idx + 1].indent > data[idx].indent) { - if (dataContext._collapsed) { - return spacer + "  " + account_link; - } else { - return spacer + "  " + account_link; - } - } else { - return spacer + "  " + account_link; - } - }, - add_grid_events: function() { - var me = this; - this.grid.onClick.subscribe(function (e, args) { - if ($(e.target).hasClass("toggle")) { - var item = me.dataView.getItem(args.row); - if (item) { - if (!item._collapsed) { - item._collapsed = true; - } else { - item._collapsed = false; - } - - me.dataView.updateItem(item.id, item); - } - e.stopImmediatePropagation(); - } - }); - }, - dataview_filter: function(item) { - if(!wn.cur_grid_report.apply_filters(item)) return false; - - if (item.parent_account) { - var parent = item.parent_account; - while (parent) { - if (wn.cur_grid_report.account_by_name[parent]._collapsed) { - return false; - } - parent = wn.cur_grid_report.parent_map[parent]; - } - } - return true; - } }); \ No newline at end of file diff --git a/public/js/app/account_tree_grid.css b/public/js/app/tree_grid.css similarity index 100% rename from public/js/app/account_tree_grid.css rename to public/js/app/tree_grid.css