Basic balance reports are working again!
This commit is contained in:
parent
65510c9a9f
commit
c9d575abce
13 changed files with 93 additions and 56 deletions
|
|
@ -30,6 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "account.h"
|
#include "account.h"
|
||||||
|
#include "report.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ account_t::~account_t()
|
||||||
}
|
}
|
||||||
|
|
||||||
account_t * account_t::find_account(const string& name,
|
account_t * account_t::find_account(const string& name,
|
||||||
const bool auto_create)
|
const bool auto_create)
|
||||||
{
|
{
|
||||||
accounts_map::const_iterator i = accounts.find(name);
|
accounts_map::const_iterator i = accounts.find(name);
|
||||||
if (i != accounts.end())
|
if (i != accounts.end())
|
||||||
|
|
@ -72,7 +73,7 @@ account_t * account_t::find_account(const string& name,
|
||||||
if (! auto_create)
|
if (! auto_create)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
account = new account_t(this, first);
|
account = new account_t(owner, this, first);
|
||||||
std::pair<accounts_map::iterator, bool> result
|
std::pair<accounts_map::iterator, bool> result
|
||||||
= accounts.insert(accounts_map::value_type(first, account));
|
= accounts.insert(accounts_map::value_type(first, account));
|
||||||
assert(result.second);
|
assert(result.second);
|
||||||
|
|
@ -113,11 +114,46 @@ std::ostream& operator<<(std::ostream& out, const account_t& account)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
value_t get_partial_name(account_t& account) {
|
||||||
|
string name;
|
||||||
|
|
||||||
|
for (account_t * acct = &account;
|
||||||
|
acct && acct->parent;
|
||||||
|
acct = acct->parent) {
|
||||||
|
if (acct->has_xdata() &&
|
||||||
|
acct->xdata().has_flags(ACCOUNT_EXT_DISPLAYED))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (name.empty())
|
||||||
|
name = acct->name;
|
||||||
|
else
|
||||||
|
name = acct->name + ":" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string_value(name);
|
||||||
|
}
|
||||||
|
|
||||||
value_t get_total(account_t& account) {
|
value_t get_total(account_t& account) {
|
||||||
assert(account.xdata_);
|
assert(account.xdata_);
|
||||||
return account.xdata_->total;
|
return account.xdata_->total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_t get_amount(account_t& account) {
|
||||||
|
assert(account.xdata_);
|
||||||
|
return account.xdata_->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_depth_spacer(account_t& account) {
|
||||||
|
std::ostringstream out;
|
||||||
|
for (account_t * acct = &account;
|
||||||
|
acct;
|
||||||
|
acct = acct->parent)
|
||||||
|
if (acct->has_xdata() &&
|
||||||
|
acct->xdata().has_flags(ACCOUNT_EXT_DISPLAYED))
|
||||||
|
out << " ";
|
||||||
|
return string_value(out.str());
|
||||||
|
}
|
||||||
|
|
||||||
template <value_t (*Func)(account_t&)>
|
template <value_t (*Func)(account_t&)>
|
||||||
value_t get_wrapper(call_scope_t& scope) {
|
value_t get_wrapper(call_scope_t& scope) {
|
||||||
return (*Func)(find_scope<account_t>(scope));
|
return (*Func)(find_scope<account_t>(scope));
|
||||||
|
|
@ -127,11 +163,20 @@ namespace {
|
||||||
expr_t::ptr_op_t account_t::lookup(const string& name)
|
expr_t::ptr_op_t account_t::lookup(const string& name)
|
||||||
{
|
{
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
|
case 'a':
|
||||||
|
if (name == "amount")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_amount>);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if (name.find("fmt_") == 0) {
|
if (name.find("fmt_") == 0) {
|
||||||
switch (name[4]) {
|
switch (name[4]) {
|
||||||
|
case '_':
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_depth_spacer>);
|
||||||
case 'T':
|
case 'T':
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_total>);
|
return WRAP_FUNCTOR(get_wrapper<&get_total>);
|
||||||
|
case 'a':
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_partial_name>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -173,26 +218,19 @@ void account_t::calculate_sums()
|
||||||
foreach (accounts_map::value_type& pair, accounts) {
|
foreach (accounts_map::value_type& pair, accounts) {
|
||||||
(*pair.second).calculate_sums();
|
(*pair.second).calculate_sums();
|
||||||
|
|
||||||
if (xd.total.is_null())
|
xdata_t& child_xd((*pair.second).xdata());
|
||||||
xd.total = (*pair.second).xdata().total;
|
add_or_set_value(xd.total, child_xd.total);
|
||||||
else
|
xd.total_count += child_xd.total_count + child_xd.count;
|
||||||
xd.total += (*pair.second).xdata().total;
|
|
||||||
|
|
||||||
xd.total_count += ((*pair.second).xdata().total_count +
|
|
||||||
(*pair.second).xdata().count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t result;
|
call_scope_t args(*this);
|
||||||
#if 0
|
value_t amount(owner->current_report->get_amount_expr(args));
|
||||||
compute_amount(result, details_t(account));
|
if (! amount.is_null()) {
|
||||||
#endif
|
add_or_set_value(xd.total, amount);
|
||||||
|
xd.total_count += xd.count;
|
||||||
if (xd.total.is_null())
|
} else {
|
||||||
xd.total = result;
|
assert(xd.count == 0);
|
||||||
else
|
}
|
||||||
xd.total += result;
|
|
||||||
|
|
||||||
xd.total_count += xd.count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ class account_t : public scope_t
|
||||||
public:
|
public:
|
||||||
typedef unsigned long ident_t;
|
typedef unsigned long ident_t;
|
||||||
|
|
||||||
|
session_t * owner;
|
||||||
account_t * parent;
|
account_t * parent;
|
||||||
string name;
|
string name;
|
||||||
optional<string> note;
|
optional<string> note;
|
||||||
|
|
@ -56,15 +57,17 @@ class account_t : public scope_t
|
||||||
mutable ident_t ident;
|
mutable ident_t ident;
|
||||||
mutable string _fullname;
|
mutable string _fullname;
|
||||||
|
|
||||||
account_t(account_t * _parent = NULL,
|
account_t(session_t * _owner,
|
||||||
|
account_t * _parent = NULL,
|
||||||
const string& _name = "",
|
const string& _name = "",
|
||||||
const optional<string>& _note = none)
|
const optional<string>& _note = none)
|
||||||
: scope_t(), parent(_parent), name(_name), note(_note),
|
: scope_t(), owner(_owner), parent(_parent), name(_name), note(_note),
|
||||||
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
|
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
|
||||||
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
|
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
|
||||||
}
|
}
|
||||||
account_t(const account_t& other)
|
account_t(const account_t& other)
|
||||||
: scope_t(),
|
: scope_t(),
|
||||||
|
owner(other.owner),
|
||||||
parent(other.parent),
|
parent(other.parent),
|
||||||
name(other.name),
|
name(other.name),
|
||||||
note(other.note),
|
note(other.note),
|
||||||
|
|
|
||||||
|
|
@ -413,17 +413,18 @@ bool compare_amount_commodities::operator()(const amount_t * left,
|
||||||
commodity_t& leftcomm(left->commodity());
|
commodity_t& leftcomm(left->commodity());
|
||||||
commodity_t& rightcomm(right->commodity());
|
commodity_t& rightcomm(right->commodity());
|
||||||
|
|
||||||
|
DEBUG("commodity.compare", " left symbol (" << leftcomm << ")");
|
||||||
|
DEBUG("commodity.compare", "right symbol (" << rightcomm << ")");
|
||||||
|
|
||||||
int cmp = leftcomm.base_symbol().compare(rightcomm.base_symbol());
|
int cmp = leftcomm.base_symbol().compare(rightcomm.base_symbol());
|
||||||
if (cmp != 0)
|
if (cmp != 0)
|
||||||
return cmp < 0;
|
return cmp < 0;
|
||||||
|
|
||||||
if (! leftcomm.annotated) {
|
if (! leftcomm.annotated) {
|
||||||
assert(rightcomm.annotated);
|
return rightcomm.annotated;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if (! rightcomm.annotated) {
|
else if (! rightcomm.annotated) {
|
||||||
assert(leftcomm.annotated);
|
return ! leftcomm.annotated;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm));
|
annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm));
|
||||||
|
|
|
||||||
21
src/entry.cc
21
src/entry.cc
|
|
@ -102,10 +102,7 @@ bool entry_base_t::finalize()
|
||||||
if (xact->must_balance()) {
|
if (xact->must_balance()) {
|
||||||
amount_t& p(xact->cost ? *xact->cost : xact->amount);
|
amount_t& p(xact->cost ? *xact->cost : xact->amount);
|
||||||
if (! p.is_null()) {
|
if (! p.is_null()) {
|
||||||
if (balance.is_null())
|
add_or_set_value(balance, p);
|
||||||
balance = p;
|
|
||||||
else
|
|
||||||
balance += p;
|
|
||||||
} else {
|
} else {
|
||||||
if (null_xact)
|
if (null_xact)
|
||||||
throw_(std::logic_error,
|
throw_(std::logic_error,
|
||||||
|
|
@ -283,12 +280,8 @@ bool entry_base_t::finalize()
|
||||||
entry ? entry->code : optional<string>());
|
entry ? entry->code : optional<string>());
|
||||||
|
|
||||||
if (xact->amount.is_annotated()) {
|
if (xact->amount.is_annotated()) {
|
||||||
if (ann_amount.annotation().price) {
|
if (ann_amount.annotation().price)
|
||||||
if (balance.is_null())
|
add_or_set_value(balance, basis_cost - final_cost);
|
||||||
balance = basis_cost - final_cost;
|
|
||||||
else
|
|
||||||
balance += basis_cost - final_cost;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
xact->amount = ann_amount;
|
xact->amount = ann_amount;
|
||||||
}
|
}
|
||||||
|
|
@ -324,14 +317,10 @@ bool entry_base_t::finalize()
|
||||||
|
|
||||||
if (dynamic_cast<entry_t *>(this)) {
|
if (dynamic_cast<entry_t *>(this)) {
|
||||||
foreach (xact_t * xact, xacts) {
|
foreach (xact_t * xact, xacts) {
|
||||||
account_t::xdata_t& xdata(xact->account->xdata());
|
|
||||||
|
|
||||||
// jww (2008-08-09): For now, this feature only works for
|
// jww (2008-08-09): For now, this feature only works for
|
||||||
// non-specific commodities.
|
// non-specific commodities.
|
||||||
if (xdata.value.is_null())
|
add_or_set_value(xact->account->xdata().value,
|
||||||
xdata.value = xact->amount.strip_annotations();
|
xact->amount.strip_annotations());
|
||||||
else
|
|
||||||
xdata.value += xact->amount.strip_annotations();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,10 +128,7 @@ void calc_xacts::operator()(xact_t& xact)
|
||||||
xact_t::xdata_t& xdata(xact.xdata());
|
xact_t::xdata_t& xdata(xact.xdata());
|
||||||
|
|
||||||
if (last_xact && last_xact->has_xdata()) {
|
if (last_xact && last_xact->has_xdata()) {
|
||||||
if (xdata.total.is_null())
|
add_or_set_value(xdata.total, last_xact->xdata().total);
|
||||||
xdata.total = last_xact->xdata().total;
|
|
||||||
else
|
|
||||||
xdata.total += last_xact->xdata().total;
|
|
||||||
xdata.index = last_xact->xdata().index + 1;
|
xdata.index = last_xact->xdata().index + 1;
|
||||||
} else {
|
} else {
|
||||||
xdata.index = 0;
|
xdata.index = 0;
|
||||||
|
|
|
||||||
|
|
@ -287,10 +287,10 @@ class collapse_xacts : public item_handler<xact_t>
|
||||||
collapse_xacts();
|
collapse_xacts();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
collapse_xacts(xact_handler_ptr handler)
|
collapse_xacts(xact_handler_ptr handler, session_t& session)
|
||||||
: item_handler<xact_t>(handler), count(0),
|
: item_handler<xact_t>(handler), count(0),
|
||||||
last_entry(NULL), last_xact(NULL),
|
last_entry(NULL), last_xact(NULL),
|
||||||
totals_account(NULL, "<Total>") {
|
totals_account(&session, NULL, "<Total>") {
|
||||||
TRACE_CTOR(collapse_xacts, "xact_handler_ptr");
|
TRACE_CTOR(collapse_xacts, "xact_handler_ptr");
|
||||||
}
|
}
|
||||||
virtual ~collapse_xacts() {
|
virtual ~collapse_xacts() {
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ static enum action_t {
|
||||||
static void startElement(void *, const char *name, const char **)
|
static void startElement(void *, const char *name, const char **)
|
||||||
{
|
{
|
||||||
if (std::strcmp(name, "gnc:account") == 0) {
|
if (std::strcmp(name, "gnc:account") == 0) {
|
||||||
curr_account = new account_t(master_account);
|
curr_account = new account_t(master_account->owner, master_account);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "act:name") == 0)
|
else if (std::strcmp(name, "act:name") == 0)
|
||||||
action = ACCOUNT_NAME;
|
action = ACCOUNT_NAME;
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,8 @@ int ofx_proc_account_cb(struct OfxAccountData data, void *)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
DEBUG("ledger.ofx.parse", "account " << data.account_name);
|
DEBUG("ledger.ofx.parse", "account " << data.account_name);
|
||||||
account_t * account = new account_t(master_account, data.account_name);
|
account_t * account = new account_t(master_account->owner, master_account,
|
||||||
|
data.account_name);
|
||||||
curr_journal->add_account(account);
|
curr_journal->add_account(account);
|
||||||
ofx_accounts.insert(accounts_pair(data.account_id, account));
|
ofx_accounts.insert(accounts_pair(data.account_id, account));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ format_equity::format_equity(report_t& _report,
|
||||||
|
|
||||||
void format_equity::flush()
|
void format_equity::flush()
|
||||||
{
|
{
|
||||||
account_t summary(NULL, "Equity:Opening Balances");
|
account_t summary(&report.session, NULL, "Equity:Opening Balances");
|
||||||
|
|
||||||
account_t::xdata_t& xdata(summary.xdata());
|
account_t::xdata_t& xdata(summary.xdata());
|
||||||
std::ostream& out(*report.output_stream);
|
std::ostream& out(*report.output_stream);
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ report_t::chain_xact_handlers(xact_handler_ptr base_handler,
|
||||||
// to appear as entries with a subtotaled xact for each
|
// to appear as entries with a subtotaled xact for each
|
||||||
// commodity used.
|
// commodity used.
|
||||||
if (show_collapsed)
|
if (show_collapsed)
|
||||||
handler.reset(new collapse_xacts(handler));
|
handler.reset(new collapse_xacts(handler, session));
|
||||||
|
|
||||||
// subtotal_xacts combines all the xacts it receives
|
// subtotal_xacts combines all the xacts it receives
|
||||||
// into one subtotal entry, which has one xact for each
|
// into one subtotal entry, which has one xact for each
|
||||||
|
|
@ -327,7 +327,6 @@ void report_t::sum_all_accounts()
|
||||||
pass_down_xacts
|
pass_down_xacts
|
||||||
(chain_xact_handlers(xact_handler_ptr(new set_account_value), false),
|
(chain_xact_handlers(xact_handler_ptr(new set_account_value), false),
|
||||||
walker);
|
walker);
|
||||||
// no flush() needed with set_account_value
|
|
||||||
session.master->calculate_sums();
|
session.master->calculate_sums();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ session_t::session_t()
|
||||||
print_format
|
print_format
|
||||||
("\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n"),
|
("\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n"),
|
||||||
balance_format
|
balance_format
|
||||||
("%20T %2_%-a\n"),
|
("%20T %_%-a\n"),
|
||||||
equity_format
|
equity_format
|
||||||
("\n%D %Y%C%P\n%/ %-34W %12t\n"),
|
("\n%D %Y%C%P\n%/ %-34W %12t\n"),
|
||||||
plot_amount_format
|
plot_amount_format
|
||||||
|
|
@ -111,7 +111,7 @@ session_t::session_t()
|
||||||
ansi_codes(false),
|
ansi_codes(false),
|
||||||
ansi_invert(false),
|
ansi_invert(false),
|
||||||
|
|
||||||
master(new account_t(NULL, ""))
|
master(new account_t(this, NULL, ""))
|
||||||
{
|
{
|
||||||
TRACE_CTOR(session_t, "");
|
TRACE_CTOR(session_t, "");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -923,6 +923,15 @@ inline string value_context(const value_t& val) {
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline value_t& add_or_set_value(value_t& lhs, const T& rhs) {
|
||||||
|
if (lhs.is_null())
|
||||||
|
lhs = rhs;
|
||||||
|
else
|
||||||
|
lhs += rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _VALUE_H
|
#endif // _VALUE_H
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ xact_context::xact_context(const xact_t& _xact, const string& desc) throw()
|
||||||
void xact_t::add_to_value(value_t& value)
|
void xact_t::add_to_value(value_t& value)
|
||||||
{
|
{
|
||||||
if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) {
|
if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) {
|
||||||
value += xdata_->value;
|
add_or_set_value(value, xdata_->value);
|
||||||
}
|
}
|
||||||
else if (cost || (! value.is_null() && ! value.is_realzero())) {
|
else if (cost || (! value.is_null() && ! value.is_realzero())) {
|
||||||
if (value.is_null())
|
if (value.is_null())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue