summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-08-10 00:57:29 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-08-10 00:57:29 -0400
commitc9d575abceb672d1c23383d973adee40daeecda8 (patch)
treedea80d45787359712e582cc7bf5d700a4419ec30
parent65510c9a9f0d588a8d0285072dfc2e2a153e5253 (diff)
downloadfork-ledger-c9d575abceb672d1c23383d973adee40daeecda8.tar.gz
fork-ledger-c9d575abceb672d1c23383d973adee40daeecda8.tar.bz2
fork-ledger-c9d575abceb672d1c23383d973adee40daeecda8.zip
Basic balance reports are working again!
-rw-r--r--src/account.cc78
-rw-r--r--src/account.h7
-rw-r--r--src/commodity.cc9
-rw-r--r--src/entry.cc21
-rw-r--r--src/filters.cc5
-rw-r--r--src/filters.h4
-rw-r--r--src/gnucash.cc2
-rw-r--r--src/ofx.cc3
-rw-r--r--src/output.cc2
-rw-r--r--src/report.cc3
-rw-r--r--src/session.cc4
-rw-r--r--src/value.h9
-rw-r--r--src/xact.cc2
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;
diff --git a/src/ofx.cc b/src/ofx.cc
index 8940f62a..0bc917e8 100644
--- a/src/ofx.cc
+++ b/src/ofx.cc
@@ -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())