brotherton-erpnext/accounts/page/general_ledger/general_ledger.js

368 lines
12 KiB
JavaScript
Raw Normal View History

2012-09-21 14:16:24 +00:00
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
wn.pages['general-ledger'].onload = function(wrapper) {
wn.ui.make_app_page({
parent: wrapper,
title: 'General Ledger',
single_column: true
});
erpnext.general_ledger = new erpnext.GeneralLedger(wrapper);
2012-11-26 13:17:54 +00:00
2012-12-22 08:20:35 +00:00
wrapper.appframe.add_home_breadcrumb()
wrapper.appframe.add_module_breadcrumb("Accounts")
wrapper.appframe.add_breadcrumb("icon-bar-chart")
2012-09-17 13:40:36 +00:00
}
erpnext.GeneralLedger = wn.views.GridReport.extend({
init: function(wrapper) {
this._super({
title: "General Ledger",
page: wrapper,
parent: $(wrapper).find('.layout-main'),
appframe: wrapper.appframe,
doctypes: ["Company", "Account", "GL Entry", "Cost Center"],
});
},
setup_columns: function() {
this.columns = [
{id: "posting_date", name: "Posting Date", field: "posting_date", width: 100,
formatter: this.date_formatter},
{id: "account", name: "Account", field: "account", width: 240,
link_formatter: {
filter_input: "account",
open_btn: true,
2012-11-12 10:15:08 +00:00
doctype: "'Account'"
}},
{id: "against_account", name: "Against Account", field: "against_account",
width: 240, hidden: !this.account},
{id: "debit", name: "Debit", field: "debit", width: 100,
formatter: this.currency_formatter},
{id: "credit", name: "Credit", field: "credit", width: 100,
formatter: this.currency_formatter},
{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: "remarks", name: "Remarks", field: "remarks", width: 200,
formatter: this.text_formatter},
];
},
filters: [
{fieldtype:"Select", label: "Company", link:"Company", default_value: "Select Company...",
filter: function(val, item, opts) {
return item.company == val || val == opts.default_value;
}},
{fieldtype:"Link", label: "Account", link:"Account",
filter: function(val, item, opts, me) {
if(!val) {
return true;
} else {
// true if GL Entry belongs to selected
// account ledger or group
return me.is_child_account(val, item.account);
}
}},
{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);
}},
2013-01-01 13:02:49 +00:00
{fieldtype: "Check", label: "Group by Ledger"},
{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
{fieldtype:"Button", label: "Reset Filters"}
],
setup_filters: function() {
this._super();
var me = this;
this.accounts_by_company = this.make_accounts_by_company();
2013-01-01 14:22:52 +00:00
// filter accounts options by company
2013-01-01 14:22:52 +00:00
this.filter_inputs.company.change(function() {
me.setup_account_filter(this);
me.set_route()
});
2013-01-01 14:22:52 +00:00
this.filter_inputs.account.change(function() {
me.make_account_by_name();
me.filter_inputs.group_by_ledger
.parent().toggle(!!(me.account_by_name[$(this).val()]
&& me.account_by_name[$(this).val()].group_or_ledger==="Group"));
});
this.trigger_refresh_on_change(["group_by_ledger"]);
},
setup_account_filter: function(company_filter) {
var me = this;
var $account = me.filter_inputs.account;
var company = $(company_filter).val();
var default_company = this.filter_inputs.company.get(0).opts.default_value;
var opts = $account.get(0).opts;
opts.list = $.map(wn.report_dump.data["Account"], function(ac) {
return (company===default_company ||
me.accounts_by_company[company].indexOf(ac.name)!=-1) ?
ac.name : null;
});
this.set_autocomplete($account, opts.list);
},
init_filter_values: function() {
this._super();
2013-01-01 14:22:52 +00:00
this.filter_inputs.group_by_ledger.parent().toggle(false);
this.filter_inputs.company.change();
2013-01-01 13:02:49 +00:00
this.filter_inputs.account.change();
},
apply_filters_from_route: function() {
this._super();
2013-01-01 14:22:52 +00:00
this.filter_inputs.group_by_ledger.parent().toggle(false);
this.filter_inputs.company.change();
2013-01-01 13:02:49 +00:00
this.filter_inputs.account.change();
},
make_accounts_by_company: function() {
var accounts_by_company = {};
var me = this;
$.each(wn.report_dump.data["Account"], function(i, ac) {
if(!accounts_by_company[ac.company]) accounts_by_company[ac.company] = [];
accounts_by_company[ac.company].push(ac.name);
});
return accounts_by_company;
},
is_child_account: function(account, item_account) {
var opts = [account, item_account];
account = this.account_by_name[account];
item_account = this.account_by_name[item_account];
return ((item_account.lft >= account.lft) && (item_account.rgt <= account.rgt));
},
prepare_data: function() {
// add Opening, Closing, Totals rows
// if filtered by account and / or voucher
var data = wn.report_dump.data["GL Entry"];
var out = [];
2013-01-01 13:02:49 +00:00
this.make_account_by_name();
var me = this;
var from_date = dateutil.str_to_obj(this.from_date);
var to_date = dateutil.str_to_obj(this.to_date);
if(to_date < from_date) {
msgprint("From Date must be before To Date");
return;
}
2013-01-01 13:02:49 +00:00
var opening = this.make_summary_row("Opening", this.account);
var totals = this.make_summary_row("Totals", this.account);
var grouped_ledgers = {};
$.each(data, function(i, item) {
if((me.is_default("company") ? true : me.apply_filter(item, "company")) &&
(me.account ? me.is_child_account(me.account, item.account)
: true) && (me.voucher_no ? item.voucher_no==me.voucher_no : true)) {
var date = dateutil.str_to_obj(item.posting_date);
2013-01-01 13:02:49 +00:00
// create grouping by ledger
if(!grouped_ledgers[item.account]) {
grouped_ledgers[item.account] = {
entries: [],
opening: me.make_summary_row("Opening", item.account),
totals: me.make_summary_row("Totals", item.account),
closing: me.make_summary_row("Closing (Opening + Totals)",
item.account)
};
}
if(date < from_date || item.is_opening=="Yes") {
opening.debit += item.debit;
opening.credit += item.credit;
2013-01-01 13:02:49 +00:00
grouped_ledgers[item.account].opening.debit += item.debit;
grouped_ledgers[item.account].opening.credit += item.credit;
} else if(date <= to_date) {
totals.debit += item.debit;
totals.credit += item.credit;
2013-01-01 13:02:49 +00:00
grouped_ledgers[item.account].totals.debit += item.debit;
grouped_ledgers[item.account].totals.credit += item.credit;
2012-09-17 04:34:07 +00:00
}
if(me.account) {
item.against_account = me.voucher_accounts[item.voucher_type + ":"
2013-01-01 14:22:52 +00:00
+ item.voucher_no][(item.debit > 0 ? "credits" : "debits")].join(", ");
}
if(me.apply_filters(item) && item.is_opening=="No") {
out.push(item);
2013-01-01 13:02:49 +00:00
grouped_ledgers[item.account].entries.push(item);
}
2012-09-17 04:34:07 +00:00
}
2013-01-01 13:02:49 +00:00
});
var closing = this.make_summary_row("Closing (Opening + Totals)", this.account);
closing.debit = opening.debit + totals.debit;
closing.credit = opening.credit + totals.credit;
if(me.account) {
me.appframe.set_title("General Ledger: " + me.account);
2013-01-01 13:02:49 +00:00
// group by ledgers
if(this.account_by_name[this.account].group_or_ledger==="Group"
&& this.group_by_ledger) {
out = this.group_data_by_ledger(grouped_ledgers);
}
opening = me.get_balance(me.account_by_name[me.account].debit_or_credit, opening)
closing = me.get_balance(me.account_by_name[me.account].debit_or_credit, closing)
2013-01-01 13:02:49 +00:00
out = [opening].concat(out).concat([totals, closing]);
} else {
me.appframe.set_title("General Ledger");
2013-01-01 13:02:49 +00:00
out = out.concat([totals]);
}
2013-01-01 13:02:49 +00:00
this.data = out;
},
2013-01-01 13:02:49 +00:00
group_data_by_ledger: function(grouped_ledgers) {
var me = this;
2013-01-01 13:02:49 +00:00
var out = []
$.each(Object.keys(grouped_ledgers).sort(), function(i, account) {
if(grouped_ledgers[account].entries.length) {
grouped_ledgers[account].closing.debit =
grouped_ledgers[account].opening.debit
+ grouped_ledgers[account].totals.debit;
grouped_ledgers[account].closing.credit =
grouped_ledgers[account].opening.credit
+ grouped_ledgers[account].totals.credit;
grouped_ledgers[account].opening =
me.get_balance(me.account_by_name[me.account].debit_or_credit,
grouped_ledgers[account].opening)
grouped_ledgers[account].closing =
me.get_balance(me.account_by_name[me.account].debit_or_credit,
grouped_ledgers[account].closing)
2013-01-01 13:02:49 +00:00
out = out.concat([grouped_ledgers[account].opening])
.concat(grouped_ledgers[account].entries)
.concat([grouped_ledgers[account].totals,
2013-01-01 14:22:52 +00:00
grouped_ledgers[account].closing,
{id: "_blank" + i, _no_format: true, debit: "", credit: ""}]);
2013-01-01 13:02:49 +00:00
}
});
2013-01-01 14:22:52 +00:00
return [{id: "_blank_first", _no_format: true, debit: "", credit: ""}].concat(out);
2013-01-01 13:02:49 +00:00
},
get_balance: function(debit_or_credit, balance) {
if(debit_or_credit == "Debit") {
balance.debit -= balance.credit; balance.credit = 0;
} else {
balance.credit -= balance.debit; balance.debit = 0;
}
return balance
},
2013-01-01 13:02:49 +00:00
make_summary_row: function(label, item_account) {
return {
account: label,
debit: 0.0,
credit: 0.0,
id: ["", label, item_account].join("_").replace(" ", "_").toLowerCase(),
_show: true,
_style: "font-weight: bold"
}
},
make_account_by_name: function() {
this.account_by_name = this.make_name_map(wn.report_dump.data["Account"]);
this.make_voucher_acconuts_map();
2013-01-01 13:02:49 +00:00
},
make_voucher_acconuts_map: function() {
this.voucher_accounts = {};
var data = wn.report_dump.data["GL Entry"];
for(var i=0, j=data.length; i<j; i++) {
var gl = data[i];
if(!this.voucher_accounts[gl.voucher_type + ":" + gl.voucher_no])
this.voucher_accounts[gl.voucher_type + ":" + gl.voucher_no] = {
debits: [],
credits: []
}
var va = this.voucher_accounts[gl.voucher_type + ":" + gl.voucher_no];
if(gl.debit > 0) {
va.debits.push(gl.account);
} else {
va.credits.push(gl.account);
}
}
},
get_plot_data: function() {
var data = [];
var me = this;
if(!me.account || me.voucher_no) return false;
var debit_or_credit = me.account_by_name[me.account].debit_or_credit;
var balance = debit_or_credit=="Debit" ? me.data[0].debit : me.data[0].credit;
data.push({
label: me.account,
data: [[dateutil.str_to_obj(me.from_date).getTime(), balance]]
.concat($.map(me.data, function(col, idx) {
if (col.posting_date) {
var diff = (debit_or_credit == "Debit" ? 1 : -1) * (flt(col.debit) - flt(col.credit));
balance += diff;
return [[dateutil.str_to_obj(col.posting_date).getTime(), balance - diff],
[dateutil.str_to_obj(col.posting_date).getTime(), balance]]
}
return null;
})).concat([
// closing
[dateutil.str_to_obj(me.to_date).getTime(), 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() }
}
},
});