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 "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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
21
src/entry.cc
21
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, "");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue