diff options
author | John Wiegley <johnw@newartisans.com> | 2008-08-10 00:57:29 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-08-10 00:57:29 -0400 |
commit | c9d575abceb672d1c23383d973adee40daeecda8 (patch) | |
tree | dea80d45787359712e582cc7bf5d700a4419ec30 | |
parent | 65510c9a9f0d588a8d0285072dfc2e2a153e5253 (diff) | |
download | fork-ledger-c9d575abceb672d1c23383d973adee40daeecda8.tar.gz fork-ledger-c9d575abceb672d1c23383d973adee40daeecda8.tar.bz2 fork-ledger-c9d575abceb672d1c23383d973adee40daeecda8.zip |
Basic balance reports are working again!
-rw-r--r-- | src/account.cc | 78 | ||||
-rw-r--r-- | src/account.h | 7 | ||||
-rw-r--r-- | src/commodity.cc | 9 | ||||
-rw-r--r-- | src/entry.cc | 21 | ||||
-rw-r--r-- | src/filters.cc | 5 | ||||
-rw-r--r-- | src/filters.h | 4 | ||||
-rw-r--r-- | src/gnucash.cc | 2 | ||||
-rw-r--r-- | src/ofx.cc | 3 | ||||
-rw-r--r-- | src/output.cc | 2 | ||||
-rw-r--r-- | src/report.cc | 3 | ||||
-rw-r--r-- | src/session.cc | 4 | ||||
-rw-r--r-- | src/value.h | 9 | ||||
-rw-r--r-- | src/xact.cc | 2 |
13 files changed, 93 insertions, 56 deletions
diff --git a/src/account.cc b/src/account.cc index d3b19ad0..6c1f81a0 100644 --- a/src/account.cc +++ b/src/account.cc @@ -30,6 +30,7 @@ */ #include "account.h" +#include "report.h" namespace ledger { @@ -42,7 +43,7 @@ account_t::~account_t() } 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); if (i != accounts.end()) @@ -72,7 +73,7 @@ account_t * account_t::find_account(const string& name, if (! auto_create) return NULL; - account = new account_t(this, first); + account = new account_t(owner, this, first); std::pair<accounts_map::iterator, bool> result = accounts.insert(accounts_map::value_type(first, account)); assert(result.second); @@ -113,11 +114,46 @@ std::ostream& operator<<(std::ostream& out, const account_t& account) } 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) { assert(account.xdata_); 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&)> value_t get_wrapper(call_scope_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) { switch (name[0]) { + case 'a': + if (name == "amount") + return WRAP_FUNCTOR(get_wrapper<&get_amount>); + break; + case 'f': if (name.find("fmt_") == 0) { switch (name[4]) { + case '_': + return WRAP_FUNCTOR(get_wrapper<&get_depth_spacer>); case 'T': return WRAP_FUNCTOR(get_wrapper<&get_total>); + case 'a': + return WRAP_FUNCTOR(get_wrapper<&get_partial_name>); } } break; @@ -173,26 +218,19 @@ void account_t::calculate_sums() foreach (accounts_map::value_type& pair, accounts) { (*pair.second).calculate_sums(); - if (xd.total.is_null()) - xd.total = (*pair.second).xdata().total; - else - xd.total += (*pair.second).xdata().total; - - xd.total_count += ((*pair.second).xdata().total_count + - (*pair.second).xdata().count); + xdata_t& child_xd((*pair.second).xdata()); + add_or_set_value(xd.total, child_xd.total); + xd.total_count += child_xd.total_count + child_xd.count; } - value_t result; -#if 0 - compute_amount(result, details_t(account)); -#endif - - if (xd.total.is_null()) - xd.total = result; - else - xd.total += result; - - xd.total_count += xd.count; + call_scope_t args(*this); + value_t amount(owner->current_report->get_amount_expr(args)); + if (! amount.is_null()) { + add_or_set_value(xd.total, amount); + xd.total_count += xd.count; + } else { + assert(xd.count == 0); + } } } // namespace ledger diff --git a/src/account.h b/src/account.h index 7d35593c..83242583 100644 --- a/src/account.h +++ b/src/account.h @@ -46,6 +46,7 @@ class account_t : public scope_t public: typedef unsigned long ident_t; + session_t * owner; account_t * parent; string name; optional<string> note; @@ -56,15 +57,17 @@ class account_t : public scope_t mutable ident_t ident; mutable string _fullname; - account_t(account_t * _parent = NULL, + account_t(session_t * _owner, + account_t * _parent = NULL, const string& _name = "", 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) { TRACE_CTOR(account_t, "account_t *, const string&, const string&"); } account_t(const account_t& other) : scope_t(), + owner(other.owner), parent(other.parent), name(other.name), note(other.note), diff --git a/src/commodity.cc b/src/commodity.cc index a1c1e2c9..7bb41651 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -413,17 +413,18 @@ bool compare_amount_commodities::operator()(const amount_t * left, commodity_t& leftcomm(left->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()); if (cmp != 0) return cmp < 0; if (! leftcomm.annotated) { - assert(rightcomm.annotated); - return true; + return rightcomm.annotated; } else if (! rightcomm.annotated) { - assert(leftcomm.annotated); - return false; + return ! leftcomm.annotated; } else { annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm)); diff --git a/src/entry.cc b/src/entry.cc index 1a906cc4..97bc90f1 100644 --- a/src/entry.cc +++ b/src/entry.cc @@ -102,10 +102,7 @@ bool entry_base_t::finalize() if (xact->must_balance()) { amount_t& p(xact->cost ? *xact->cost : xact->amount); if (! p.is_null()) { - if (balance.is_null()) - balance = p; - else - balance += p; + add_or_set_value(balance, p); } else { if (null_xact) throw_(std::logic_error, @@ -283,12 +280,8 @@ bool entry_base_t::finalize() entry ? entry->code : optional<string>()); if (xact->amount.is_annotated()) { - if (ann_amount.annotation().price) { - if (balance.is_null()) - balance = basis_cost - final_cost; - else - balance += basis_cost - final_cost; - } + if (ann_amount.annotation().price) + add_or_set_value(balance, basis_cost - final_cost); } else { xact->amount = ann_amount; } @@ -324,14 +317,10 @@ bool entry_base_t::finalize() if (dynamic_cast<entry_t *>(this)) { foreach (xact_t * xact, xacts) { - account_t::xdata_t& xdata(xact->account->xdata()); - // jww (2008-08-09): For now, this feature only works for // non-specific commodities. - if (xdata.value.is_null()) - xdata.value = xact->amount.strip_annotations(); - else - xdata.value += xact->amount.strip_annotations(); + add_or_set_value(xact->account->xdata().value, + xact->amount.strip_annotations()); } } diff --git a/src/filters.cc b/src/filters.cc index e5455423..f9115c37 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -128,10 +128,7 @@ void calc_xacts::operator()(xact_t& xact) xact_t::xdata_t& xdata(xact.xdata()); if (last_xact && last_xact->has_xdata()) { - if (xdata.total.is_null()) - xdata.total = last_xact->xdata().total; - else - xdata.total += last_xact->xdata().total; + add_or_set_value(xdata.total, last_xact->xdata().total); xdata.index = last_xact->xdata().index + 1; } else { xdata.index = 0; diff --git a/src/filters.h b/src/filters.h index 7f67cbd8..093f2de7 100644 --- a/src/filters.h +++ b/src/filters.h @@ -287,10 +287,10 @@ class collapse_xacts : public item_handler<xact_t> collapse_xacts(); public: - collapse_xacts(xact_handler_ptr handler) + collapse_xacts(xact_handler_ptr handler, session_t& session) : item_handler<xact_t>(handler), count(0), last_entry(NULL), last_xact(NULL), - totals_account(NULL, "<Total>") { + totals_account(&session, NULL, "<Total>") { TRACE_CTOR(collapse_xacts, "xact_handler_ptr"); } virtual ~collapse_xacts() { diff --git a/src/gnucash.cc b/src/gnucash.cc index 5a171ace..6b9b5211 100644 --- a/src/gnucash.cc +++ b/src/gnucash.cc @@ -89,7 +89,7 @@ static enum action_t { static void startElement(void *, const char *name, const char **) { 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) action = ACCOUNT_NAME; @@ -61,7 +61,8 @@ int ofx_proc_account_cb(struct OfxAccountData data, void *) return -1; 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); ofx_accounts.insert(accounts_pair(data.account_id, account)); diff --git a/src/output.cc b/src/output.cc index 324a20e4..b05f5815 100644 --- a/src/output.cc +++ b/src/output.cc @@ -249,7 +249,7 @@ format_equity::format_equity(report_t& _report, 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()); std::ostream& out(*report.output_stream); diff --git a/src/report.cc b/src/report.cc index 92f20d4f..03b519ab 100644 --- a/src/report.cc +++ b/src/report.cc @@ -207,7 +207,7 @@ report_t::chain_xact_handlers(xact_handler_ptr base_handler, // to appear as entries with a subtotaled xact for each // commodity used. if (show_collapsed) - handler.reset(new collapse_xacts(handler)); + handler.reset(new collapse_xacts(handler, session)); // subtotal_xacts combines all the xacts it receives // into one subtotal entry, which has one xact for each @@ -327,7 +327,6 @@ void report_t::sum_all_accounts() pass_down_xacts (chain_xact_handlers(xact_handler_ptr(new set_account_value), false), walker); - // no flush() needed with set_account_value session.master->calculate_sums(); } diff --git a/src/session.cc b/src/session.cc index 06288444..f634c855 100644 --- a/src/session.cc +++ b/src/session.cc @@ -79,7 +79,7 @@ session_t::session_t() print_format ("\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n"), balance_format - ("%20T %2_%-a\n"), + ("%20T %_%-a\n"), equity_format ("\n%D %Y%C%P\n%/ %-34W %12t\n"), plot_amount_format @@ -111,7 +111,7 @@ session_t::session_t() ansi_codes(false), ansi_invert(false), - master(new account_t(NULL, "")) + master(new account_t(this, NULL, "")) { TRACE_CTOR(session_t, ""); } diff --git a/src/value.h b/src/value.h index 7c82efaf..8d638657 100644 --- a/src/value.h +++ b/src/value.h @@ -923,6 +923,15 @@ inline string value_context(const value_t& val) { 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 #endif // _VALUE_H diff --git a/src/xact.cc b/src/xact.cc index ce4da0d7..22dd1742 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -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) { 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())) { if (value.is_null()) |