[CHG] chart of accounts interaction impl
* move chart of accounts higher in document * rewrite text a bit * split controls to left-hand column * remove dependencies between operations * highlight result of last-applied operation (not very good looking atm)
This commit is contained in:
parent
78765edae5
commit
60822587b7
@ -77,3 +77,10 @@ li > p {
|
|||||||
.accounts-table dt span:last-child {
|
.accounts-table dt span:last-child {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlight-op {
|
||||||
|
background-color: #dce6f8;
|
||||||
|
}
|
||||||
|
.chart-of-accounts .highlight-op {
|
||||||
|
background-color: #030035;
|
||||||
|
}
|
||||||
|
@ -18,296 +18,127 @@
|
|||||||
return s.replace(/[^0-9a-z ]/gi, '').toLowerCase().split(/\s+/).join('-');
|
return s.replace(/[^0-9a-z ]/gi, '').toLowerCase().split(/\s+/).join('-');
|
||||||
|
|
||||||
}
|
}
|
||||||
var isFulfilled = (function () {
|
|
||||||
var enabledTransactions = Immutable.Seq();
|
|
||||||
// memoize enabled ops so they don't have to be recomputed all the time
|
|
||||||
data.addWatch('enableds', function (k, m, prev, next) {
|
|
||||||
enabledTransactions = next.filter(function (v, k) {
|
|
||||||
return v.get('enabled');
|
|
||||||
}).keySeq();
|
|
||||||
});
|
|
||||||
return function isFulfilled(deps) {
|
|
||||||
var d = Immutable.Set(deps);
|
|
||||||
return d.isEmpty() || d.subtract(enabledTransactions).isEmpty();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
function isEnabled(transaction) {
|
function isEnabled(transaction) {
|
||||||
var item = data.deref().get(transaction);
|
var item = data.deref().get(transaction);
|
||||||
return item.get('enabled') && isFulfilled(item.get('depends'));
|
return item.get('enabled');
|
||||||
}
|
}
|
||||||
var Controls = React.createClass({
|
var Controls = React.createClass({
|
||||||
getInitialState: function () {
|
|
||||||
return { folded: true };
|
|
||||||
},
|
|
||||||
toggle: function () {
|
|
||||||
this.setState({folded: !this.state.folded});
|
|
||||||
},
|
|
||||||
render: function () {
|
render: function () {
|
||||||
return React.DOM.div(
|
var _this = this;
|
||||||
null,
|
return React.DOM.div(null, operations.map(function (op) {
|
||||||
React.DOM.h4(
|
var label = op.get('label'), operations = op.get('operations');
|
||||||
{ onClick: this.toggle, style: { cursor: 'pointer' } },
|
return React.DOM.label(
|
||||||
this.state.folded ? "\u25B8 " : "\u25BE ",
|
{
|
||||||
"Operations"),
|
key: toKey(label),
|
||||||
this.state.folded ? undefined : this.props.p.map(function (v, k) {
|
style: {display: 'block'},
|
||||||
return React.DOM.label(
|
className: (operations === _this.props.p.last() && 'highlight-op')
|
||||||
{key: k, style: {display: 'block' } },
|
},
|
||||||
React.DOM.input({
|
React.DOM.input({
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
disabled: !isFulfilled(v.get('depends')),
|
checked: _this.props.p.contains(operations),
|
||||||
checked: v.get('enabled'),
|
onChange: function (e) {
|
||||||
onChange: function () {
|
if (e.target.checked) {
|
||||||
data.swap(function (d) {
|
data.swap(function (ops) {
|
||||||
return d.updateIn(
|
return ops.add(operations);
|
||||||
[k, 'enabled'],
|
});
|
||||||
function (check) { return !check; });
|
} else {
|
||||||
|
data.swap(function (ops) {
|
||||||
|
return ops.remove(operations);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
" ",
|
}),
|
||||||
v.get('label')
|
" ",
|
||||||
);
|
label
|
||||||
}, this).toArray()
|
);
|
||||||
);
|
}).toArray());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var Journal = React.createClass({
|
|
||||||
render: function () {
|
|
||||||
return React.DOM.div(
|
|
||||||
null,
|
|
||||||
React.createElement(Controls, this.props),
|
|
||||||
React.DOM.table(
|
|
||||||
{className: 'table'},
|
|
||||||
React.DOM.thead(
|
|
||||||
null,
|
|
||||||
React.DOM.tr(
|
|
||||||
null,
|
|
||||||
React.DOM.th(),
|
|
||||||
React.DOM.th({width: '20%'}, "Debit"),
|
|
||||||
React.DOM.th({width: '20%'}, "Credit")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
React.DOM.tbody(
|
|
||||||
null,
|
|
||||||
this.props.p
|
|
||||||
.filter(function (v, k) { return isEnabled(k); })
|
|
||||||
.valueSeq()
|
|
||||||
.flatMap(function (tx) {
|
|
||||||
if (tx.get('operations').isEmpty()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
var label = tx.get('label');
|
|
||||||
var k = toKey(label);
|
|
||||||
return tx.get('operations').toSeq().map(function (op) {
|
|
||||||
var credit = op.get('credit'), debit = op.get('debit');
|
|
||||||
return React.DOM.tr(
|
|
||||||
{key: toKey(label, op.get('account'))},
|
|
||||||
React.DOM.td(
|
|
||||||
null,
|
|
||||||
credit ? '\u2001' : '',
|
|
||||||
accounts[op.get('account')].label
|
|
||||||
),
|
|
||||||
React.DOM.td(null, debit && debit(this.props.p)),
|
|
||||||
React.DOM.td(null, credit && credit(this.props.p))
|
|
||||||
);
|
|
||||||
}, this).concat(
|
|
||||||
React.DOM.tr(
|
|
||||||
{key: k + '-label'},
|
|
||||||
React.DOM.td(
|
|
||||||
{colSpan: 3, style: {textAlign: 'center'}},
|
|
||||||
label)),
|
|
||||||
React.DOM.tr(
|
|
||||||
{key: k + '-spacer'},
|
|
||||||
React.DOM.td({colSpan: 3}, "\u00A0"))
|
|
||||||
);
|
|
||||||
}, this)
|
|
||||||
.toArray()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
data.addWatch('journals', function (k, m, prev, next) {
|
|
||||||
React.render(
|
|
||||||
React.createElement(Journal, {p: next}),
|
|
||||||
document.querySelector('.journals')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
var Chart = React.createClass({
|
var Chart = React.createClass({
|
||||||
render: function () {
|
render: function () {
|
||||||
|
var lastop = Immutable.Map(
|
||||||
|
(this.props.p.last() || Immutable.List()).map(function (op) {
|
||||||
|
return [op.get('account'), op.has('credit') ? 'credit' : 'debit'];
|
||||||
|
})
|
||||||
|
);
|
||||||
return React.DOM.div(
|
return React.DOM.div(
|
||||||
null,
|
null,
|
||||||
React.createElement(Controls, {p: this.props.p}),
|
React.DOM.table(
|
||||||
DOM.table(
|
|
||||||
{className: 'table'},
|
{className: 'table'},
|
||||||
DOM.tr(
|
React.DOM.tr(
|
||||||
null,
|
null,
|
||||||
DOM.th(),
|
React.DOM.th(),
|
||||||
DOM.th({className: 'text-right'}, "Debit"),
|
React.DOM.th({className: 'text-right'}, "Debit"),
|
||||||
DOM.th({className: 'text-right'}, "Credit"),
|
React.DOM.th({className: 'text-right'}, "Credit"),
|
||||||
DOM.th({className: 'text-right'}, "Balance")),
|
React.DOM.th({className: 'text-right'}, "Balance")),
|
||||||
this.accounts().map(function (data) {
|
this.accounts().map(function (data) {
|
||||||
return DOM.tr(
|
var highlight = lastop.get(data.get('code'));
|
||||||
{key: data.code},
|
return React.DOM.tr(
|
||||||
DOM.th(null,
|
{key: data.get('code')},
|
||||||
data.level ? '\u2001 ' : '',
|
React.DOM.th(null,
|
||||||
data.code, ' ', data.label),
|
data.get('level') ? '\u2001 ' : '',
|
||||||
DOM.td({className: 'text-right'}, data.debit),
|
data.get('code'), ' ', data.get('label')),
|
||||||
DOM.td({className: 'text-right'}, data.credit),
|
React.DOM.td({className: React.addons.classSet({
|
||||||
DOM.td({className: 'text-right'}, data.debit - data.credit)
|
'text-right': true,
|
||||||
|
'highlight-op': highlight === 'debit'
|
||||||
|
})}, data.get('debit')),
|
||||||
|
React.DOM.td({className: React.addons.classSet({
|
||||||
|
'text-right': true,
|
||||||
|
'highlight-op': highlight === 'credit'
|
||||||
|
})}, data.get('credit')),
|
||||||
|
React.DOM.td({className: 'text-right'},
|
||||||
|
data.get('debit') - data.get('credit'))
|
||||||
);
|
);
|
||||||
})
|
}).toArray()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
accounts: function() {
|
accounts: function() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var out = [];
|
var zero = function () { return 0; };
|
||||||
var zero = function () { return 0; }
|
|
||||||
var data = this.props.p;
|
var data = this.props.p;
|
||||||
// for each operated-on account, apply all operations and save the
|
|
||||||
// resulting (debit, credit) state
|
var totals = data.flatten(true).reduce(function (acc, op) {
|
||||||
var chart = data
|
return acc
|
||||||
.filter(function (v, k) { return isEnabled(k); })
|
.updateIn([op.get('account'), 'debit'], function (d) {
|
||||||
.valueSeq()
|
return (d || 0) + op.get('debit', zero)(data);
|
||||||
.flatMap(function (v) { return v.get('operations'); })
|
})
|
||||||
.reduce(function (acc, op) {
|
.updateIn([op.get('account'), 'credit'], function (c) {
|
||||||
// update operation's account debit and credit by adding
|
return (c || 0) + op.get('credit', zero)(data);
|
||||||
// operation's debit and credit to them, initialize to 0
|
});
|
||||||
// if not set yet
|
}, Immutable.Map());
|
||||||
return acc
|
|
||||||
.updateIn([op.get('account'), 'debit'], 0, function (d) {
|
return accounts.map(function (account) {
|
||||||
return d + op.get('debit', zero)(data);
|
// for each account, add sum
|
||||||
})
|
return account.merge(
|
||||||
.updateIn([op.get('account'), 'credit'], 0, function (c) {
|
account.get('accounts').map(function (code) {
|
||||||
return c + op.get('credit', zero)(data);
|
return totals.get(code, NULL);
|
||||||
});
|
}).reduce(function (acc, it) {
|
||||||
}, Immutable.Map());
|
return acc.mergeWith(function (a, b) { return a + b; }, it, NULL);
|
||||||
categories.forEach(function (cat) {
|
})
|
||||||
var current = { level: 0, label: cat.label, code: cat.code, credit: 0, debit: 0 };
|
);
|
||||||
var values = accs(cat).map(function (acc) {
|
|
||||||
// If no operation has been performed on an account, 0 debit or credit
|
|
||||||
var it = chart.get(acc.code, Immutable.Map({credit: 0, debit: 0}));
|
|
||||||
var debit = it.get('debit') || 0;
|
|
||||||
var credit = it.get('credit') || 0;
|
|
||||||
current.debit += debit;
|
|
||||||
current.credit += credit;
|
|
||||||
return {
|
|
||||||
level: 1,
|
|
||||||
code: acc.code,
|
|
||||||
label: acc.label,
|
|
||||||
debit: debit,
|
|
||||||
credit: credit
|
|
||||||
}
|
|
||||||
});
|
|
||||||
values.unshift(current);
|
|
||||||
out.push.apply(out, values);
|
|
||||||
});
|
});
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
data.addWatch('chart', function (k, m, prev, next) {
|
data.addWatch('chart', function (k, m, prev, next) {
|
||||||
|
React.render(
|
||||||
|
React.createElement(Controls, {p: next}),
|
||||||
|
document.getElementById('chart-controls'));
|
||||||
React.render(
|
React.render(
|
||||||
React.createElement(Chart, {p: next}),
|
React.createElement(Chart, {p: next}),
|
||||||
document.querySelector('.chart-of-accounts'));
|
document.querySelector('.chart-of-accounts'));
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
var sale = 100,
|
var chart = document.getElementById('chart-of-accounts'),
|
||||||
tax = sale * 0.09,
|
controls = document.createElement('div');
|
||||||
total = sale + tax,
|
controls.setAttribute('id', 'chart-controls');
|
||||||
refund = sale * 0.1,
|
chart.insertBefore(controls, chart.lastElementChild);
|
||||||
purchase = 80;
|
data.reset(Immutable.OrderedSet());
|
||||||
data.reset(Immutable.fromJS({
|
|
||||||
customer_invoice: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Customer Invoice ($100 + 9% tax)",
|
|
||||||
depends: [],
|
|
||||||
operations: [
|
|
||||||
{account: ASSETS.ACCOUNTS_RECEIVABLE.code, debit: function () { return total; }},
|
|
||||||
{account: REVENUE.SALES.code, credit: function () { return sale; }},
|
|
||||||
{account: LIABILITIES.TAXES_PAYABLE.code, credit: function () { return tax; }}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// TODO: dependencies?
|
|
||||||
customer_refund: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Customer Refund 10%",
|
|
||||||
depends: ['customer_invoice'],
|
|
||||||
operations: [
|
|
||||||
{account: REVENUE.SALES.code, debit: function () { return refund; }},
|
|
||||||
{account: ASSETS.ACCOUNTS_RECEIVABLE.code, credit: function () { return refund; }}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
customer_payment: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Customer Payment",
|
|
||||||
depends: ['customer_invoice'],
|
|
||||||
operations: [
|
|
||||||
// TODO: depends of refund
|
|
||||||
{account: ASSETS.CASH.code, debit: function (ops) {
|
|
||||||
return ops.getIn(['customer_refund', 'enabled'])
|
|
||||||
? total - refund
|
|
||||||
: total;
|
|
||||||
}},
|
|
||||||
{account: ASSETS.ACCOUNTS_RECEIVABLE.code, credit: function (ops) {
|
|
||||||
return ops.getIn(['customer_refund', 'enabled'])
|
|
||||||
? total - refund
|
|
||||||
: total;
|
|
||||||
}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
supplier_invoice: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Supplier Invoice",
|
|
||||||
depends: [],
|
|
||||||
operations: [
|
|
||||||
{account: EXPENSES.PURCHASES.code, debit: function () { return purchase; }},
|
|
||||||
{account: LIABILITIES.ACCOUNTS_PAYABLE.code, credit: function () { return purchase; }},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
supplier_invoice_paid: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Supplier Invoice Paid",
|
|
||||||
depends: ['supplier_invoice'],
|
|
||||||
operations: [
|
|
||||||
{account: LIABILITIES.ACCOUNTS_PAYABLE.code, debit: function () { return purchase; }},
|
|
||||||
{account: ASSETS.CASH.code, credit: function () { return purchase; }}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
inventory_reception: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Inventory Reception",
|
|
||||||
depends: ['supplier_invoice'],
|
|
||||||
// TODO: ???
|
|
||||||
operations: []
|
|
||||||
},
|
|
||||||
customer_delivery: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Customer Delivery",
|
|
||||||
depends: ['customer_invoice', 'inventory_reception'],
|
|
||||||
// TODO: ???
|
|
||||||
operations: [],
|
|
||||||
},
|
|
||||||
taxes: {
|
|
||||||
enabled: false,
|
|
||||||
label: "Pay Taxes Due",
|
|
||||||
depends: [],
|
|
||||||
// TODO: no taxes due if no customer invoice?
|
|
||||||
operations: [
|
|
||||||
{account: LIABILITIES.TAXES_PAYABLE.code, debit: function () { return tax; }},
|
|
||||||
{account: ASSETS.CASH.code, credit: function () { return tax; }}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var DOM = React.DOM;
|
var NULL = Immutable.Map({debit: 0, credit: 0});
|
||||||
|
|
||||||
var ASSETS = {
|
var ASSETS = {
|
||||||
code: 1,
|
code: 1,
|
||||||
label: "Assets",
|
label: "Assets",
|
||||||
@ -330,26 +161,73 @@
|
|||||||
label: "Expenses",
|
label: "Expenses",
|
||||||
PURCHASES: { code: 50100, label: "Purchases" }
|
PURCHASES: { code: 50100, label: "Purchases" }
|
||||||
};
|
};
|
||||||
var categories = [ASSETS, LIABILITIES, REVENUE, EXPENSES];
|
var categories = Immutable.fromJS([ASSETS, LIABILITIES, REVENUE, EXPENSES]);
|
||||||
var accounts = (function () {
|
var accounts = categories.toSeq().flatMap(function (cat) {
|
||||||
var acs = {};
|
return Immutable.Seq.of(cat.set('level', 0)).concat(cat.filter(function (v, k) {
|
||||||
categories.forEach(function (cat) {
|
return k.toUpperCase() === k;
|
||||||
acs[cat.code] = cat;
|
}).toIndexedSeq().map(function (acc) { return acc.set('level', 1) }));
|
||||||
accs(cat).forEach(function (acc) {
|
}).map(function (account) { // add accounts: Seq<AccountCode> to each account
|
||||||
acs[acc.code] = acc;
|
return account.set(
|
||||||
});
|
'accounts',
|
||||||
});
|
Immutable.Seq.of(account.get('code')).concat(
|
||||||
return acs;
|
account.toIndexedSeq().map(function (val) {
|
||||||
})();
|
return Immutable.Map.isMap(val) && val.get('code');
|
||||||
|
}).filter(function (val) { return !!val; })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
var sale = 100,
|
||||||
function accs(category) {
|
tax = sale * 0.09,
|
||||||
var out = [];
|
total = sale + tax,
|
||||||
for(var k in category) {
|
refund = sale * 0.1,
|
||||||
if (k.toUpperCase() === k) {
|
purchase = 80;
|
||||||
out.push(category[k]);
|
var operations = Immutable.fromJS([{
|
||||||
}
|
label: "Customer Invoice ($100 + 9% tax)",
|
||||||
}
|
operations: [
|
||||||
return out;
|
{account: ASSETS.ACCOUNTS_RECEIVABLE.code, debit: function () { return total; }},
|
||||||
|
{account: REVENUE.SALES.code, credit: function () { return sale; }},
|
||||||
|
{account: LIABILITIES.TAXES_PAYABLE.code, credit: function () { return tax; }}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: "Customer Refund 10%",
|
||||||
|
operations: [
|
||||||
|
{account: REVENUE.SALES.code, debit: function () { return refund; }},
|
||||||
|
{account: ASSETS.ACCOUNTS_RECEIVABLE.code, credit: function () { return refund; }}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: "Customer Payment",
|
||||||
|
operations: [
|
||||||
|
// TODO: depends of refund
|
||||||
|
{account: ASSETS.CASH.code, debit: function (ops) {
|
||||||
|
return ops.contains(operations.getIn(['customer_refund', 'operations']))
|
||||||
|
? total - refund
|
||||||
|
: total;
|
||||||
|
}},
|
||||||
|
{account: ASSETS.ACCOUNTS_RECEIVABLE.code, credit: function (ops) {
|
||||||
|
return ops.contains(operations.getIn(['customer_refund', 'operations']))
|
||||||
|
? total - refund
|
||||||
|
: total;
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: "Supplier Invoice",
|
||||||
|
operations: [
|
||||||
|
{account: EXPENSES.PURCHASES.code, debit: function () { return purchase; }},
|
||||||
|
{account: LIABILITIES.ACCOUNTS_PAYABLE.code, credit: function () { return purchase; }}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: "Supplier Invoice Paid",
|
||||||
|
operations: [
|
||||||
|
{account: LIABILITIES.ACCOUNTS_PAYABLE.code, debit: function () { return purchase; }},
|
||||||
|
{account: ASSETS.CASH.code, credit: function () { return purchase; }}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: "Pay Taxes Due",
|
||||||
|
operations: [
|
||||||
|
{account: LIABILITIES.TAXES_PAYABLE.code, debit: function () { return tax; }},
|
||||||
|
{account: ASSETS.CASH.code, credit: function () { return tax; }}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
]);
|
||||||
})();
|
})();
|
||||||
|
40
index.rst
40
index.rst
@ -69,6 +69,28 @@ them being consumed for the company to "work".
|
|||||||
What is owned has been financed through debts to reimburse or acquired
|
What is owned has been financed through debts to reimburse or acquired
|
||||||
assets (profits, capical).
|
assets (profits, capical).
|
||||||
|
|
||||||
|
Chart of Accounts
|
||||||
|
=================
|
||||||
|
|
||||||
|
The **chart of accounts** lists all the accounts used by the company, whether
|
||||||
|
they are balance sheet accounts (assets and liabilities) or P&L accounts
|
||||||
|
(revenues and expenses), and provides their state at a given moment (their
|
||||||
|
credit, debit and balance).
|
||||||
|
|
||||||
|
The accounts are used to organize and classify the finances of the company in
|
||||||
|
order to better understand its state and health, and the chart of accounts can
|
||||||
|
be used to get a snapshot of a company's financial period: because it includes
|
||||||
|
P&L, a chart of accounts is also generally viewed over a specific period.
|
||||||
|
|
||||||
|
.. rst-class:: force-right
|
||||||
|
|
||||||
|
Balance = debit - credit
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. h:div:: chart-of-accounts
|
||||||
|
|
||||||
|
Requires javascript
|
||||||
|
|
||||||
Journals
|
Journals
|
||||||
========
|
========
|
||||||
|
|
||||||
@ -141,24 +163,6 @@ T-accounts for the transactions
|
|||||||
|
|
||||||
needs javascript
|
needs javascript
|
||||||
|
|
||||||
Chart of Accounts
|
|
||||||
=================
|
|
||||||
|
|
||||||
The **chart of accounts** lists all balance sheet (assets, liabilities) and
|
|
||||||
P&L (revenue, expense) accounts. These accounts are used to organize and
|
|
||||||
classify the finances of the company to better understand the company's
|
|
||||||
financial state, and the chart can be used to get a snapshot of a company's
|
|
||||||
financial period.
|
|
||||||
|
|
||||||
.. rst-class:: force-right
|
|
||||||
|
|
||||||
Balance = debit - credit
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
.. h:div:: chart-of-accounts
|
|
||||||
|
|
||||||
Requires javascript
|
|
||||||
|
|
||||||
Debit and credit
|
Debit and credit
|
||||||
================
|
================
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user