summaryrefslogtreecommitdiff
path: root/src/filters.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/filters.cc')
-rw-r--r--src/filters.cc146
1 files changed, 104 insertions, 42 deletions
diff --git a/src/filters.cc b/src/filters.cc
index bef4dc24..39097c58 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -217,7 +217,7 @@ void calc_posts::operator()(post_t& post)
if (last_post) {
assert(last_post->has_xdata());
- if (! account_wise)
+ if (calc_running_total)
xdata.total = last_post->xdata().total;
xdata.count = last_post->xdata().count + 1;
} else {
@@ -230,7 +230,7 @@ void calc_posts::operator()(post_t& post)
account_t * acct = post.reported_account();
acct->xdata().add_flags(ACCOUNT_EXT_VISITED);
- if (! account_wise)
+ if (calc_running_total)
add_or_set_value(xdata.total, xdata.visited_value);
item_handler<post_t>::operator()(post);
@@ -239,19 +239,21 @@ void calc_posts::operator()(post_t& post)
}
namespace {
- typedef function<void (post_t *)> post_functor_t;
+ typedef function<void (post_t&)> post_functor_t;
void handle_value(const value_t& value,
- account_t * account,
+ account_t * account,
xact_t * xact,
temporaries_t& temps,
- item_handler<post_t>& handler,
- const date_t& date = date_t(),
- const value_t& total = value_t(),
+ post_handler_ptr handler,
+ const date_t& date = date_t(),
+ const value_t& total = value_t(),
const bool direct_amount = false,
+ const bool mark_visited = false,
const optional<post_functor_t>& functor = none)
{
post_t& post = temps.create_post(*xact, account);
+ post.add_flags(ITEM_GENERATED);
// If the account for this post is all virtual, then report the post as
// such. This allows subtotal reports to show "(Account)" for accounts
@@ -302,11 +304,16 @@ namespace {
xdata.add_flags(POST_EXT_DIRECT_AMT);
if (functor)
- (*functor)(&post);
+ (*functor)(post);
DEBUG("filter.changed_value.rounding", "post.amount = " << post.amount);
- handler(post);
+ (*handler)(post);
+
+ if (mark_visited) {
+ post.xdata().add_flags(POST_EXT_VISITED);
+ post.account->xdata().add_flags(ACCOUNT_EXT_VISITED);
+ }
}
}
@@ -344,7 +351,7 @@ void collapse_posts::report_subtotal()
earliest_date : last_xact->_date);
DEBUG("filter.collapse", "Pseudo-xact date = " << *xact._date);
- handle_value(subtotal, &totals_account, &xact, temps, *handler);
+ handle_value(subtotal, &totals_account, &xact, temps, handler);
}
component_posts.clear();
@@ -404,30 +411,58 @@ void related_posts::flush()
item_handler<post_t>::flush();
}
+changed_value_posts::changed_value_posts(post_handler_ptr handler,
+ report_t& _report,
+ bool _for_accounts_report,
+ bool _show_unrealized)
+ : item_handler<post_t>(handler), report(_report),
+ for_accounts_report(_for_accounts_report),
+ show_unrealized(_show_unrealized), last_post(NULL),
+ revalued_account(temps.create_account(_("<Revalued>"))),
+ rounding_account(temps.create_account(_("<Rounding>")))
+{
+ 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_) ?
+ report.HANDLER(revalued_total_).expr :
+ report.HANDLER(display_total_).expr);
+ display_total_expr = report.HANDLER(display_total_).expr;
+ changed_values_only = report.HANDLED(revalued_only);
+
+ gains_equity_account =
+ report.session.journal->master->find_account(_("Equity:Unrealized Gains"));
+ gains_equity_account->add_flags(ACCOUNT_GENERATED);
+
+ losses_equity_account =
+ report.session.journal->master->find_account(_("Equity:Unrealized Losses"));
+ losses_equity_account->add_flags(ACCOUNT_GENERATED);
+}
+
void changed_value_posts::flush()
{
if (last_post && last_post->date() <= report.terminus.date()) {
- output_revaluation(last_post, report.terminus.date());
+ output_revaluation(*last_post, report.terminus.date());
last_post = NULL;
}
item_handler<post_t>::flush();
}
-void changed_value_posts::output_revaluation(post_t * post, const date_t& date)
+void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
{
if (is_valid(date))
- post->xdata().date = date;
+ post.xdata().date = date;
value_t repriced_total;
try {
- bind_scope_t bound_scope(report, *post);
+ bind_scope_t bound_scope(report, post);
repriced_total = total_expr.calc(bound_scope);
}
catch (...) {
- post->xdata().date = date_t();
+ post.xdata().date = date_t();
throw;
}
- post->xdata().date = date_t();
+ post.xdata().date = date_t();
DEBUG("filter.changed_value",
"output_revaluation(last_balance) = " << last_total);
@@ -441,19 +476,44 @@ void changed_value_posts::output_revaluation(post_t * post, const date_t& date)
xact_t& xact = temps.create_xact();
xact.payee = _("Commodities revalued");
- xact._date = is_valid(date) ? date : post->date();
-
- handle_value(diff, &revalued_account, &xact, temps, *handler,
- *xact._date, repriced_total, false,
- optional<post_functor_t>
- (bind(&changed_value_posts::output_rounding, this, _1)));
+ xact._date = is_valid(date) ? date : post.date();
+
+ if (! for_accounts_report) {
+ handle_value
+ (/* value= */ diff,
+ /* account= */ &revalued_account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler,
+ /* date= */ *xact._date,
+ /* total= */ repriced_total,
+ /* direct_amount= */ false,
+ /* mark_visited= */ false,
+ /* functor= */ (optional<post_functor_t>
+ (bind(&changed_value_posts::output_rounding,
+ this, _1))));
+ }
+ else if (show_unrealized) {
+ handle_value
+ (/* value= */ - diff,
+ /* account= */ (diff < 0L ?
+ losses_equity_account :
+ gains_equity_account),
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler,
+ /* date= */ *xact._date,
+ /* total= */ value_t(),
+ /* direct_amount= */ false,
+ /* mark_visited= */ true);
+ }
}
}
}
-void changed_value_posts::output_rounding(post_t * post)
+void changed_value_posts::output_rounding(post_t& post)
{
- bind_scope_t bound_scope(report, *post);
+ bind_scope_t bound_scope(report, post);
value_t new_display_total(display_total_expr.calc(bound_scope));
DEBUG("filter.changed_value.rounding",
@@ -478,9 +538,9 @@ void changed_value_posts::output_rounding(post_t * post)
xact_t& xact = temps.create_xact();
xact.payee = _("Commodity rounding");
- xact._date = post->date();
+ xact._date = post.date();
- handle_value(diff, &rounding_account, &xact, temps, *handler,
+ handle_value(diff, &rounding_account, &xact, temps, handler,
*xact._date, precise_display_total, true);
}
}
@@ -491,19 +551,19 @@ void changed_value_posts::output_rounding(post_t * post)
void changed_value_posts::operator()(post_t& post)
{
if (last_post)
- output_revaluation(last_post, post.date());
+ output_revaluation(*last_post, post.date());
if (changed_values_only)
post.xdata().add_flags(POST_EXT_DISPLAYED);
- output_rounding(&post);
+ if (! for_accounts_report)
+ output_rounding(post);
item_handler<post_t>::operator()(post);
bind_scope_t bound_scope(report, post);
last_total = total_expr.calc(bound_scope);
-
- last_post = &post;
+ last_post = &post;
}
void subtotal_posts::report_subtotal(const char * spec_fmt,
@@ -515,12 +575,14 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
optional<date_t> range_start = interval ? interval->start : none;
optional<date_t> range_finish = interval ? interval->inclusive_end() : none;
- foreach (post_t * post, component_posts) {
- date_t date = post->date();
- if (! range_start || date < *range_start)
- range_start = date;
- if (! range_finish || date > *range_finish)
- range_finish = date;
+ if (! range_start || ! range_finish) {
+ foreach (post_t * post, component_posts) {
+ date_t date = post->date();
+ if (! range_start || date < *range_start)
+ range_start = date;
+ if (! range_finish || date > *range_finish)
+ range_finish = date;
+ }
}
component_posts.clear();
@@ -542,7 +604,7 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
foreach (values_map::value_type& pair, values)
handle_value(pair.second.value, pair.second.account, &xact, temps,
- *handler);
+ handler);
values.clear();
}
@@ -652,10 +714,10 @@ void posts_as_equity::report_subtotal()
foreach (balance_t::amounts_map::value_type amount_pair,
pair.second.value.as_balance().amounts)
handle_value(amount_pair.second, pair.second.account, &xact, temps,
- *handler);
+ handler);
} else {
handle_value(pair.second.value, pair.second.account, &xact, temps,
- *handler);
+ handler);
}
total += pair.second.value;
}
@@ -784,7 +846,7 @@ void budget_posts::report_budget_items(const date_t& date)
assert(begin);
if (*begin <= date &&
- (! pair.first.end || *begin < *pair.first.end)) {
+ (! pair.first.finish || *begin < *pair.first.finish)) {
post_t& post = *pair.second;
DEBUG("budget.generate", "Reporting budget for "
@@ -905,8 +967,8 @@ void forecast_posts::flush()
}
date_t& begin = *(*least).first.start;
- if ((*least).first.end)
- assert(begin < *(*least).first.end);
+ if ((*least).first.finish)
+ assert(begin < *(*least).first.finish);
// If the next date in the series for this periodic posting is more than 5
// years beyond the last valid post we generated, drop it from further