Merge branch 'next'

This commit is contained in:
John Wiegley 2010-06-06 13:04:44 -04:00
commit e8ffbd6f2f
12 changed files with 213 additions and 137 deletions

View file

@ -205,6 +205,10 @@ namespace {
value_t get_count(account_t& account) { value_t get_count(account_t& account) {
return long(account.family_details().posts_count); return long(account.family_details().posts_count);
} }
value_t get_cost(account_t&) {
throw_(calc_error, _("An account does not have a 'cost' value"));
return false;
}
value_t get_depth(account_t& account) { value_t get_depth(account_t& account) {
return long(account.depth); return long(account.depth);
@ -311,6 +315,8 @@ expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
case 'c': case 'c':
if (name == "count") if (name == "count")
return WRAP_FUNCTOR(get_wrapper<&get_count>); return WRAP_FUNCTOR(get_wrapper<&get_count>);
else if (name == "cost")
return WRAP_FUNCTOR(get_wrapper<&get_cost>);
break; break;
case 'd': case 'd':

View file

@ -39,8 +39,8 @@
namespace ledger { namespace ledger {
post_handler_ptr chain_pre_post_handlers(report_t& report, post_handler_ptr chain_pre_post_handlers(post_handler_ptr base_handler,
post_handler_ptr base_handler) report_t& report)
{ {
post_handler_ptr handler(base_handler); post_handler_ptr handler(base_handler);
@ -106,13 +106,14 @@ post_handler_ptr chain_pre_post_handlers(report_t& report,
return handler; return handler;
} }
post_handler_ptr chain_post_handlers(report_t& report, post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
post_handler_ptr base_handler, report_t& report,
bool for_accounts_report) bool for_accounts_report)
{ {
post_handler_ptr handler(base_handler); post_handler_ptr handler(base_handler);
predicate_t display_predicate; predicate_t display_predicate;
predicate_t only_predicate; predicate_t only_predicate;
rounding_error_posts * rounding_handler = NULL;
assert(report.HANDLED(amount_)); assert(report.HANDLED(amount_));
expr_t& expr(report.HANDLER(amount_).expr); expr_t& expr(report.HANDLER(amount_).expr);
@ -137,6 +138,14 @@ post_handler_ptr chain_post_handlers(report_t& report,
report.HANDLED(tail_) ? report.HANDLED(tail_) ?
report.HANDLER(tail_).value.to_int() : 0)); report.HANDLER(tail_).value.to_int() : 0));
// changed_value_posts adds virtual posts to the list to account for changes
// in market value of commodities, which otherwise would affect the running
// total unpredictably.
if (report.HANDLED(revalued) && ! report.HANDLED(no_rounding)) {
rounding_handler = new rounding_error_posts(handler, report);
handler.reset(rounding_handler);
}
// filter_posts will only pass through posts matching the // filter_posts will only pass through posts matching the
// `display_predicate'. // `display_predicate'.
if (report.HANDLED(display_)) { if (report.HANDLED(display_)) {
@ -149,12 +158,11 @@ post_handler_ptr chain_post_handlers(report_t& report,
// changed_value_posts adds virtual posts to the list to account for changes // changed_value_posts adds virtual posts to the list to account for changes
// in market value of commodities, which otherwise would affect the running // in market value of commodities, which otherwise would affect the running
// total unpredictably. // total unpredictably.
if (report.HANDLED(revalued) && (! for_accounts_report || if (report.HANDLED(revalued) &&
report.HANDLED(unrealized))) (! for_accounts_report || report.HANDLED(unrealized)))
handler.reset(new changed_value_posts(handler, report, handler.reset(new changed_value_posts(handler, report, for_accounts_report,
for_accounts_report,
report.HANDLED(unrealized), report.HANDLED(unrealized),
! report.HANDLED(no_rounding))); rounding_handler));
// calc_posts computes the running total. When this appears will determine, // calc_posts computes the running total. When this appears will determine,
// for example, whether filtered posts are included or excluded from the // for example, whether filtered posts are included or excluded from the
@ -190,7 +198,7 @@ post_handler_ptr chain_post_handlers(report_t& report,
// collapse_posts causes xacts with multiple posts to appear as xacts // collapse_posts causes xacts with multiple posts to appear as xacts
// with a subtotaled post for each commodity used. // with a subtotaled post for each commodity used.
if (report.HANDLED(collapse)) if (report.HANDLED(collapse))
handler.reset(new collapse_posts(handler, expr, handler.reset(new collapse_posts(handler, report, expr,
display_predicate, only_predicate, display_predicate, only_predicate,
report.HANDLED(collapse_if_zero))); report.HANDLED(collapse_if_zero)));

View file

@ -93,20 +93,20 @@ typedef shared_ptr<item_handler<account_t> > acct_handler_ptr;
class report_t; class report_t;
post_handler_ptr post_handler_ptr
chain_pre_post_handlers(report_t& report, chain_pre_post_handlers(post_handler_ptr base_handler,
post_handler_ptr base_handler); report_t& report);
post_handler_ptr post_handler_ptr
chain_post_handlers(report_t& report, chain_post_handlers(post_handler_ptr base_handler,
post_handler_ptr base_handler, report_t& report,
bool for_accounts_report = false); bool for_accounts_report = false);
inline post_handler_ptr inline post_handler_ptr
chain_handlers(report_t& report, chain_handlers(post_handler_ptr handler,
post_handler_ptr handler, report_t& report,
bool for_accounts_report = false) { bool for_accounts_report = false) {
handler = chain_post_handlers(report, handler, for_accounts_report); handler = chain_post_handlers(handler, report, for_accounts_report);
handler = chain_pre_post_handlers(report, handler); handler = chain_pre_post_handlers(handler, report);
return handler; return handler;
} }

View file

@ -374,7 +374,8 @@ void collapse_posts::report_subtotal()
std::size_t displayed_count = 0; std::size_t displayed_count = 0;
foreach (post_t * post, component_posts) { foreach (post_t * post, component_posts) {
if (only_predicate(*post) && display_predicate(*post)) bind_scope_t bound_scope(report, *post);
if (only_predicate(bound_scope) && display_predicate(bound_scope))
displayed_count++; displayed_count++;
} }
@ -401,7 +402,11 @@ void collapse_posts::report_subtotal()
earliest_date : last_xact->_date); earliest_date : last_xact->_date);
DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date); DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date);
handle_value(subtotal, &totals_account, &xact, temps, handler); handle_value(/* value= */ subtotal,
/* account= */ &totals_account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
} }
component_posts.clear(); component_posts.clear();
@ -461,21 +466,81 @@ void related_posts::flush()
item_handler<post_t>::flush(); item_handler<post_t>::flush();
} }
changed_value_posts::changed_value_posts(post_handler_ptr handler, rounding_error_posts::rounding_error_posts(post_handler_ptr handler,
report_t& _report, report_t& _report)
bool _for_accounts_report, : item_handler<post_t>(handler), report(_report),
bool _show_unrealized, rounding_account(temps.create_account(_("<Rounding>")))
bool _show_rounding) {
TRACE_CTOR(rounding_error_posts, "post_handler_ptr, report_t&");
display_amount_expr = report.HANDLER(display_amount_).expr;
display_total_expr = report.HANDLER(display_total_).expr;
}
void rounding_error_posts::output_rounding(post_t& post)
{
bind_scope_t bound_scope(report, post);
value_t new_display_total(display_total_expr.calc(bound_scope));
DEBUG("filters.changed_value.rounding",
"rounding.new_display_total = " << new_display_total);
if (! last_display_total.is_null()) {
if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
DEBUG("filters.changed_value.rounding",
"rounding.repriced_amount = " << repriced_amount);
value_t precise_display_total(new_display_total.truncated() -
repriced_amount.truncated());
DEBUG("filters.changed_value.rounding",
"rounding.precise_display_total = " << precise_display_total);
DEBUG("filters.changed_value.rounding",
"rounding.last_display_total = " << last_display_total);
if (value_t diff = precise_display_total - last_display_total) {
DEBUG("filters.changed_value.rounding",
"rounding.diff = " << diff);
xact_t& xact = temps.create_xact();
xact.payee = _("Commodity rounding");
xact._date = post.date();
handle_value(/* value= */ diff,
/* account= */ &rounding_account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler,
/* date= */ *xact._date,
/* total= */ precise_display_total,
/* direct_amount= */ true);
}
}
}
last_display_total = new_display_total;
}
void rounding_error_posts::operator()(post_t& post)
{
output_rounding(post);
item_handler<post_t>::operator()(post);
}
changed_value_posts::changed_value_posts
(post_handler_ptr handler,
report_t& _report,
bool _for_accounts_report,
bool _show_unrealized,
rounding_error_posts * _rounding_handler)
: item_handler<post_t>(handler), report(_report), : item_handler<post_t>(handler), report(_report),
for_accounts_report(_for_accounts_report), for_accounts_report(_for_accounts_report),
show_unrealized(_show_unrealized), show_unrealized(_show_unrealized), last_post(NULL),
show_rounding(_show_rounding), last_post(NULL),
revalued_account(temps.create_account(_("<Revalued>"))), revalued_account(temps.create_account(_("<Revalued>"))),
rounding_account(temps.create_account(_("<Rounding>"))) rounding_handler(_rounding_handler)
{ {
TRACE_CTOR(changed_value_posts, "post_handler_ptr, report_t&, bool"); TRACE_CTOR(changed_value_posts, "post_handler_ptr, report_t&, bool");
display_amount_expr = report.HANDLER(display_amount_).expr;
total_expr = (report.HANDLED(revalued_total_) ? total_expr = (report.HANDLED(revalued_total_) ?
report.HANDLER(revalued_total_).expr : report.HANDLER(revalued_total_).expr :
report.HANDLER(display_total_).expr); report.HANDLER(display_total_).expr);
@ -549,13 +614,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler, /* handler= */ handler,
/* date= */ *xact._date, /* date= */ *xact._date,
/* total= */ repriced_total, /* total= */ repriced_total);
/* direct_amount= */ false,
/* mark_visited= */ false,
/* functor= */ (show_rounding ?
optional<post_functor_t>
(bind(&changed_value_posts::output_rounding,
this, _1)) : none));
} }
else if (show_unrealized) { else if (show_unrealized) {
handle_value handle_value
@ -692,43 +751,6 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
} }
} }
void changed_value_posts::output_rounding(post_t& post)
{
bind_scope_t bound_scope(report, post);
value_t new_display_total(display_total_expr.calc(bound_scope));
DEBUG("filters.changed_value.rounding",
"rounding.new_display_total = " << new_display_total);
if (! last_display_total.is_null()) {
if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
DEBUG("filters.changed_value.rounding",
"rounding.repriced_amount = " << repriced_amount);
value_t precise_display_total(new_display_total.truncated() -
repriced_amount.truncated());
DEBUG("filters.changed_value.rounding",
"rounding.precise_display_total = " << precise_display_total);
DEBUG("filters.changed_value.rounding",
"rounding.last_display_total = " << last_display_total);
if (value_t diff = precise_display_total - last_display_total) {
DEBUG("filters.changed_value.rounding",
"rounding.diff = " << diff);
xact_t& xact = temps.create_xact();
xact.payee = _("Commodity rounding");
xact._date = post.date();
handle_value(diff, &rounding_account, &xact, temps, handler,
*xact._date, precise_display_total, true);
}
}
}
last_display_total = new_display_total;
}
void changed_value_posts::operator()(post_t& post) void changed_value_posts::operator()(post_t& post)
{ {
if (last_post) { if (last_post) {
@ -740,9 +762,6 @@ void changed_value_posts::operator()(post_t& post)
if (changed_values_only) if (changed_values_only)
post.xdata().add_flags(POST_EXT_DISPLAYED); post.xdata().add_flags(POST_EXT_DISPLAYED);
if (! for_accounts_report && show_rounding)
output_rounding(post);
item_handler<post_t>::operator()(post); item_handler<post_t>::operator()(post);
bind_scope_t bound_scope(report, post); bind_scope_t bound_scope(report, post);
@ -787,8 +806,11 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
xact._date = *range_start; xact._date = *range_start;
foreach (values_map::value_type& pair, values) foreach (values_map::value_type& pair, values)
handle_value(pair.second.value, pair.second.account, &xact, temps, handle_value(/* value= */ pair.second.value,
handler); /* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
values.clear(); values.clear();
} }
@ -897,11 +919,17 @@ void posts_as_equity::report_subtotal()
if (pair.second.value.is_balance()) { if (pair.second.value.is_balance()) {
foreach (const balance_t::amounts_map::value_type& amount_pair, foreach (const balance_t::amounts_map::value_type& amount_pair,
pair.second.value.as_balance().amounts) pair.second.value.as_balance().amounts)
handle_value(amount_pair.second, pair.second.account, &xact, temps, handle_value(/* value= */ amount_pair.second,
handler); /* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
} else { } else {
handle_value(pair.second.value, pair.second.account, &xact, temps, handle_value(/* value= */ pair.second.value,
handler); /* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
} }
total += pair.second.value; total += pair.second.value;
} }

View file

@ -63,17 +63,17 @@ public:
protected: protected:
value_to_posts_map posts_map; value_to_posts_map posts_map;
report_t& report;
post_handler_ptr post_chain; post_handler_ptr post_chain;
report_t& report;
expr_t group_by_expr; expr_t group_by_expr;
custom_flusher_t preflush_func; custom_flusher_t preflush_func;
optional<custom_flusher_t> postflush_func; optional<custom_flusher_t> postflush_func;
public: public:
post_splitter(report_t& _report, post_splitter(post_handler_ptr _post_chain,
post_handler_ptr _post_chain, report_t& _report,
expr_t _group_by_expr) expr_t _group_by_expr)
: report(_report), post_chain(_post_chain), : post_chain(_post_chain), report(_report),
group_by_expr(_group_by_expr), group_by_expr(_group_by_expr),
preflush_func(bind(&post_splitter::print_title, this, _1)) { preflush_func(bind(&post_splitter::print_title, this, _1)) {
TRACE_CTOR(post_splitter, "scope_t&, post_handler_ptr, expr_t"); TRACE_CTOR(post_splitter, "scope_t&, post_handler_ptr, expr_t");
@ -401,11 +401,13 @@ class collapse_posts : public item_handler<post_t>
account_t& totals_account; account_t& totals_account;
bool only_collapse_if_zero; bool only_collapse_if_zero;
std::list<post_t *> component_posts; std::list<post_t *> component_posts;
report_t& report;
collapse_posts(); collapse_posts();
public: public:
collapse_posts(post_handler_ptr handler, collapse_posts(post_handler_ptr handler,
report_t& _report,
expr_t& _amount_expr, expr_t& _amount_expr,
predicate_t _display_predicate, predicate_t _display_predicate,
predicate_t _only_predicate, predicate_t _only_predicate,
@ -415,8 +417,8 @@ public:
only_predicate(_only_predicate), count(0), only_predicate(_only_predicate), count(0),
last_xact(NULL), last_post(NULL), last_xact(NULL), last_post(NULL),
totals_account(temps.create_account(_("<Total>"))), totals_account(temps.create_account(_("<Total>"))),
only_collapse_if_zero(_only_collapse_if_zero) { only_collapse_if_zero(_only_collapse_if_zero), report(_report) {
TRACE_CTOR(collapse_posts, "post_handler_ptr"); TRACE_CTOR(collapse_posts, "post_handler_ptr, ...");
} }
virtual ~collapse_posts() { virtual ~collapse_posts() {
TRACE_DTOR(collapse_posts); TRACE_DTOR(collapse_posts);
@ -479,37 +481,73 @@ public:
} }
}; };
class changed_value_posts : public item_handler<post_t> class rounding_error_posts : public item_handler<post_t>
{ {
// This filter requires that calc_posts be used at some point // This filter requires that calc_posts be used at some point
// later in the chain. // later in the chain.
expr_t display_amount_expr; expr_t display_amount_expr;
expr_t display_total_expr;
report_t& report;
value_t last_display_total;
temporaries_t temps;
account_t& rounding_account;
rounding_error_posts();
public:
rounding_error_posts(post_handler_ptr handler,
report_t& _report);
virtual ~rounding_error_posts() {
TRACE_DTOR(rounding_error_posts);
}
void output_rounding(post_t& post);
virtual void operator()(post_t& post);
virtual void clear() {
display_amount_expr.mark_uncompiled();
display_total_expr.mark_uncompiled();
last_display_total = value_t();
temps.clear();
item_handler<post_t>::clear();
}
};
class changed_value_posts : public item_handler<post_t>
{
// This filter requires that calc_posts be used at some point
// later in the chain.
expr_t total_expr; expr_t total_expr;
expr_t display_total_expr; expr_t display_total_expr;
report_t& report; report_t& report;
bool changed_values_only; bool changed_values_only;
bool for_accounts_report; bool for_accounts_report;
bool show_unrealized; bool show_unrealized;
bool show_rounding;
post_t * last_post; post_t * last_post;
value_t last_total; value_t last_total;
value_t last_display_total;
value_t repriced_total; value_t repriced_total;
temporaries_t temps; temporaries_t temps;
account_t& revalued_account; account_t& revalued_account;
account_t& rounding_account;
account_t * gains_equity_account; account_t * gains_equity_account;
account_t * losses_equity_account; account_t * losses_equity_account;
rounding_error_posts * rounding_handler;
changed_value_posts(); changed_value_posts();
public: public:
changed_value_posts(post_handler_ptr handler, changed_value_posts(post_handler_ptr handler,
report_t& _report, report_t& _report,
bool _for_accounts_report, bool _for_accounts_report,
bool _show_unrealized, bool _show_unrealized,
bool _show_rounding); rounding_error_posts * _rounding_handler);
virtual ~changed_value_posts() { virtual ~changed_value_posts() {
TRACE_DTOR(changed_value_posts); TRACE_DTOR(changed_value_posts);
@ -519,18 +557,15 @@ public:
void output_revaluation(post_t& post, const date_t& current); void output_revaluation(post_t& post, const date_t& current);
void output_intermediate_prices(post_t& post, const date_t& current); void output_intermediate_prices(post_t& post, const date_t& current);
void output_rounding(post_t& post);
virtual void operator()(post_t& post); virtual void operator()(post_t& post);
virtual void clear() { virtual void clear() {
display_amount_expr.mark_uncompiled();
total_expr.mark_uncompiled(); total_expr.mark_uncompiled();
display_total_expr.mark_uncompiled(); display_total_expr.mark_uncompiled();
last_post = NULL; last_post = NULL;
last_total = value_t(); last_total = value_t();
last_display_total = value_t();
temps.clear(); temps.clear();

View file

@ -190,8 +190,8 @@ namespace {
journal_posts_iterator walker(coll->journal); journal_posts_iterator walker(coll->journal);
coll->chain = coll->chain =
chain_post_handlers(coll->report, chain_post_handlers(post_handler_ptr(coll->posts_collector),
post_handler_ptr(coll->posts_collector)); coll->report);
pass_down_posts(coll->chain, walker); pass_down_posts(coll->chain, walker);
} }
catch (...) { catch (...) {

View file

@ -141,7 +141,9 @@ void report_t::normalize_options(const string& verb)
HANDLER(limit_).on(string("?normalize"), "actual"); HANDLER(limit_).on(string("?normalize"), "actual");
if (! HANDLED(empty)) if (! HANDLED(empty))
HANDLER(display_).on(string("?normalize"), "amount|(!post&total)"); HANDLER(display_).on(string("?normalize"),
string("(post?(display_amount|account=\"") +
_("<Revalued>") + "\"):display_total)");
if (verb[0] != 'b' && verb[0] != 'r') if (verb[0] != 'b' && verb[0] != 'r')
HANDLER(base).on_only(string("?normalize")); HANDLER(base).on_only(string("?normalize"));
@ -284,11 +286,11 @@ void report_t::parse_query_args(const value_t& args, const string& whence)
namespace { namespace {
struct posts_flusher struct posts_flusher
{ {
report_t& report;
post_handler_ptr handler; post_handler_ptr handler;
report_t& report;
posts_flusher(report_t& _report, post_handler_ptr _handler) posts_flusher(post_handler_ptr _handler, report_t& _report)
: report(_report), handler(_handler) {} : handler(_handler), report(_report) {}
void operator()(const value_t&) { void operator()(const value_t&) {
report.session.journal->clear_xdata(); report.session.journal->clear_xdata();
@ -298,27 +300,27 @@ namespace {
void report_t::posts_report(post_handler_ptr handler) void report_t::posts_report(post_handler_ptr handler)
{ {
handler = chain_post_handlers(*this, handler); handler = chain_post_handlers(handler, *this);
if (HANDLED(group_by_)) { if (HANDLED(group_by_)) {
std::auto_ptr<post_splitter> std::auto_ptr<post_splitter>
splitter(new post_splitter(*this, handler, HANDLER(group_by_).expr)); splitter(new post_splitter(handler, *this, HANDLER(group_by_).expr));
splitter->set_postflush_func(posts_flusher(*this, handler)); splitter->set_postflush_func(posts_flusher(handler, *this));
handler = post_handler_ptr(splitter.release()); handler = post_handler_ptr(splitter.release());
} }
handler = chain_pre_post_handlers(*this, handler); handler = chain_pre_post_handlers(handler, *this);
journal_posts_iterator walker(*session.journal.get()); journal_posts_iterator walker(*session.journal.get());
pass_down_posts(handler, walker); pass_down_posts(handler, walker);
if (! HANDLED(group_by_)) if (! HANDLED(group_by_))
posts_flusher(*this, handler)(value_t()); posts_flusher(handler, *this)(value_t());
} }
void report_t::generate_report(post_handler_ptr handler) void report_t::generate_report(post_handler_ptr handler)
{ {
HANDLER(limit_).on(string("#generate"), "actual"); HANDLER(limit_).on(string("#generate"), "actual");
handler = chain_handlers(*this, handler); handler = chain_handlers(handler, *this);
generate_posts_iterator walker generate_posts_iterator walker
(session, HANDLED(seed_) ? (session, HANDLED(seed_) ?
@ -331,7 +333,7 @@ void report_t::generate_report(post_handler_ptr handler)
void report_t::xact_report(post_handler_ptr handler, xact_t& xact) void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
{ {
handler = chain_handlers(*this, handler); handler = chain_handlers(handler, *this);
xact_posts_iterator walker(xact); xact_posts_iterator walker(xact);
pass_down_posts(handler, walker); pass_down_posts(handler, walker);
@ -342,11 +344,11 @@ void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
namespace { namespace {
struct accounts_title_printer struct accounts_title_printer
{ {
report_t& report;
acct_handler_ptr handler; acct_handler_ptr handler;
report_t& report;
accounts_title_printer(report_t& _report, acct_handler_ptr _handler) accounts_title_printer(acct_handler_ptr _handler, report_t& _report)
: report(_report), handler(_handler) {} : handler(_handler), report(_report) {}
void operator()(const value_t& val) void operator()(const value_t& val)
{ {
@ -360,11 +362,11 @@ namespace {
struct accounts_flusher struct accounts_flusher
{ {
report_t& report;
acct_handler_ptr handler; acct_handler_ptr handler;
report_t& report;
accounts_flusher(report_t& _report, acct_handler_ptr _handler) accounts_flusher(acct_handler_ptr _handler, report_t& _report)
: report(_report), handler(_handler) {} : handler(_handler), report(_report) {}
void operator()(const value_t&) void operator()(const value_t&)
{ {
@ -403,18 +405,18 @@ namespace {
void report_t::accounts_report(acct_handler_ptr handler) void report_t::accounts_report(acct_handler_ptr handler)
{ {
post_handler_ptr chain = post_handler_ptr chain =
chain_post_handlers(*this, post_handler_ptr(new ignore_posts), chain_post_handlers(post_handler_ptr(new ignore_posts), *this,
/* for_accounts_report= */ true); /* for_accounts_report= */ true);
if (HANDLED(group_by_)) { if (HANDLED(group_by_)) {
std::auto_ptr<post_splitter> std::auto_ptr<post_splitter>
splitter(new post_splitter(*this, chain, HANDLER(group_by_).expr)); splitter(new post_splitter(chain, *this, HANDLER(group_by_).expr));
splitter->set_preflush_func(accounts_title_printer(*this, handler)); splitter->set_preflush_func(accounts_title_printer(handler, *this));
splitter->set_postflush_func(accounts_flusher(*this, handler)); splitter->set_postflush_func(accounts_flusher(handler, *this));
chain = post_handler_ptr(splitter.release()); chain = post_handler_ptr(splitter.release());
} }
chain = chain_pre_post_handlers(*this, chain); chain = chain_pre_post_handlers(chain, *this);
// The lifetime of the chain object controls the lifetime of all temporary // The lifetime of the chain object controls the lifetime of all temporary
// objects created within it during the call to pass_down_posts, which will // objects created within it during the call to pass_down_posts, which will
@ -423,12 +425,12 @@ void report_t::accounts_report(acct_handler_ptr handler)
pass_down_posts(chain, walker); pass_down_posts(chain, walker);
if (! HANDLED(group_by_)) if (! HANDLED(group_by_))
accounts_flusher(*this, handler)(value_t()); accounts_flusher(handler, *this)(value_t());
} }
void report_t::commodities_report(post_handler_ptr handler) void report_t::commodities_report(post_handler_ptr handler)
{ {
handler = chain_handlers(*this, handler); handler = chain_handlers(handler, *this);
posts_commodities_iterator walker(*session.journal.get()); posts_commodities_iterator walker(*session.journal.get());
pass_down_posts(handler, walker); pass_down_posts(handler, walker);

View file

@ -735,7 +735,7 @@ public:
OPTION_(report_t, percent, DO() { // -% OPTION_(report_t, percent, DO() { // -%
parent->HANDLER(total_) parent->HANDLER(total_)
.set_expr(string("--percent"), .set_expr(string("--percent"),
"is_account&parent&parent.total&percent(total, parent.total)"); "((is_account&parent&parent.total)?percent(total, parent.total):0");
}); });
OPTION__ OPTION__

View file

@ -285,6 +285,7 @@ class date_specifier_t
{ {
friend class date_parser_t; friend class date_parser_t;
public:
#if 0 #if 0
typedef date_t::year_type year_type; typedef date_t::year_type year_type;
#else #else
@ -294,6 +295,7 @@ class date_specifier_t
typedef date_t::day_type day_type; typedef date_t::day_type day_type;
typedef date_t::day_of_week_type day_of_week_type; typedef date_t::day_of_week_type day_of_week_type;
protected:
optional<year_type> year; optional<year_type> year;
optional<month_type> month; optional<month_type> month;
optional<day_type> day; optional<day_type> day;

View file

@ -685,16 +685,15 @@ void auto_xact_t::extend_xact(xact_base_t& xact)
else else
amt = post_amount; amt = post_amount;
#if defined(DEBUG_ON)
IF_DEBUG("xact.extend") { IF_DEBUG("xact.extend") {
DEBUG("xact.extend", DEBUG("xact.extend",
"Initial post on line " << initial_post->pos->beg_line << ": " "Initial post on line " << initial_post->pos->beg_line << ": "
<< "amount " << initial_post->amount << " (precision " << "amount " << initial_post->amount << " (precision "
<< initial_post->amount.precision() << ")"); << initial_post->amount.precision() << ")");
#if defined(DEBUG_ON)
if (initial_post->amount.keep_precision()) if (initial_post->amount.keep_precision())
DEBUG("xact.extend", " precision is kept"); DEBUG("xact.extend", " precision is kept");
#endif
DEBUG("xact.extend", DEBUG("xact.extend",
"Posting on line " << post->pos->beg_line << ": " "Posting on line " << post->pos->beg_line << ": "
@ -702,13 +701,12 @@ void auto_xact_t::extend_xact(xact_base_t& xact)
<< " (precision " << post_amount.precision() << " (precision " << post_amount.precision()
<< " != " << amt.precision() << ")"); << " != " << amt.precision() << ")");
#if defined(DEBUG_ON)
if (post_amount.keep_precision()) if (post_amount.keep_precision())
DEBUG("xact.extend", " precision is kept"); DEBUG("xact.extend", " precision is kept");
if (amt.keep_precision()) if (amt.keep_precision())
DEBUG("xact.extend", " amt precision is kept"); DEBUG("xact.extend", " amt precision is kept");
#endif
} }
#endif // defined(DEBUG_ON)
account_t * account = post->account; account_t * account = post->account;
string fullname = account->fullname(); string fullname = account->fullname();

View file

@ -49,7 +49,6 @@ P 2010/03/01 00:00:00 S 8 P
P 2010/04/01 00:00:00 S 16 P P 2010/04/01 00:00:00 S 16 P
>>>1 >>>1
09-Jan-01 Sample 1a As:Brokerage:Stocks 0 0
09-Jan-15 Commodities revalued <Revalued> 100 P 100 P 09-Jan-15 Commodities revalued <Revalued> 100 P 100 P
09-Feb-01 Commodities revalued <Revalued> 200 P 300 P 09-Feb-01 Commodities revalued <Revalued> 200 P 300 P
09-Feb-01 Sample 2a As:Brokerage:Stocks 300 P 600 P 09-Feb-01 Sample 2a As:Brokerage:Stocks 300 P 600 P

View file

@ -34,9 +34,7 @@ reg --end 2009/06/26 -V equities
=== 0 === 0
reg --end 2009/06/26 -G equities reg --end 2009/06/26 -G equities
>>>1 >>>1
08-Jan-01 Purchase Apple shares Equities 0 0
08-Jun-30 Commodities revalued <Revalued> $500 $500 08-Jun-30 Commodities revalued <Revalued> $500 $500
08-Jun-30 Sell some Apple sha.. Equities 0 $500
09-Jan-31 Commodities revalued <Revalued> $250 $750 09-Jan-31 Commodities revalued <Revalued> $250 $750
09-Jun-26 Commodities revalued <Revalued> $500 $1250 09-Jun-26 Commodities revalued <Revalued> $500 $1250
>>>2 >>>2