Merge branch 'next'
This commit is contained in:
commit
e8ffbd6f2f
12 changed files with 213 additions and 137 deletions
|
|
@ -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':
|
||||||
|
|
|
||||||
34
src/chain.cc
34
src/chain.cc
|
|
@ -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)));
|
||||||
|
|
||||||
|
|
|
||||||
16
src/chain.h
16
src/chain.h
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
156
src/filters.cc
156
src/filters.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 (...) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue