diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/account.cc | 9 | ||||
-rw-r--r-- | src/chain.cc | 5 | ||||
-rw-r--r-- | src/filters.cc | 112 | ||||
-rw-r--r-- | src/filters.h | 24 | ||||
-rw-r--r-- | src/post.cc | 12 | ||||
-rw-r--r-- | src/post.h | 2 | ||||
-rw-r--r-- | src/report.h | 14 |
7 files changed, 131 insertions, 47 deletions
diff --git a/src/account.cc b/src/account.cc index d65b6911..9bc96564 100644 --- a/src/account.cc +++ b/src/account.cc @@ -196,6 +196,10 @@ namespace { return long(account.depth); } + value_t ignore(account_t&) { + return false; + } + value_t get_depth_spacer(account_t& account) { std::size_t depth = 0; @@ -259,6 +263,11 @@ expr_t::ptr_op_t account_t::lookup(const string& name) if (name == "total") return WRAP_FUNCTOR(get_wrapper<&get_total>); break; + + case 'u': + if (name == "use_direct_amount") + return WRAP_FUNCTOR(get_wrapper<&ignore>); + break; } return NULL; diff --git a/src/chain.cc b/src/chain.cc index 0ad1709f..d33742a5 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -79,9 +79,12 @@ post_handler_ptr chain_post_handlers(report_t& report, // the running total unpredictably. if (report.HANDLED(revalued)) handler.reset(new changed_value_posts - (handler, report.HANDLED(revalued_total_) ? + (handler, + report.HANDLER(display_amount_).expr, + report.HANDLED(revalued_total_) ? report.HANDLER(revalued_total_).expr : report.HANDLER(display_total_).expr, + report.HANDLER(display_total_).expr, report, report.HANDLED(revalued_only))); // calc_posts computes the running total. When this appears will diff --git a/src/filters.cc b/src/filters.cc index 7f305dd3..3071a951 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -213,14 +213,17 @@ void calc_posts::operator()(post_t& post) } namespace { - void handle_value(const value_t& value, - account_t * account, - xact_t * xact, - unsigned int flags, - std::list<post_t>& temps, - item_handler<post_t>& handler, - const date_t& date = date_t(), - const value_t& total = value_t()) + typedef function<void (post_t *)> post_functor_t; + + void handle_value(const value_t& value, + account_t * account, + xact_t * xact, + std::list<post_t>& temps, + item_handler<post_t>& handler, + const date_t& date = date_t(), + const value_t& total = value_t(), + const bool direct_amount = false, + const optional<post_functor_t>& functor = none) { temps.push_back(post_t(account)); post_t& post(temps.back()); @@ -259,7 +262,7 @@ namespace { case value_t::BALANCE: case value_t::SEQUENCE: xdata.value = temp; - flags |= POST_EXT_COMPOUND; + xdata.add_flags(POST_EXT_COMPOUND); break; case value_t::DATETIME: @@ -272,8 +275,13 @@ namespace { if (! total.is_null()) xdata.total = total; - if (flags) - xdata.add_flags(flags); + if (direct_amount) + xdata.add_flags(POST_EXT_DIRECT_AMT); + + if (functor) + (*functor)(&post); + + DEBUG("filter.changed_value.rounding", "post.amount = " << post.amount); handler(post); } @@ -314,7 +322,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, 0, post_temps, *handler); + handle_value(subtotal, &totals_account, &xact, post_temps, *handler); } component_posts.clear(); @@ -374,7 +382,7 @@ void related_posts::flush() item_handler<post_t>::flush(); } -void changed_value_posts::output_diff(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; @@ -391,36 +399,80 @@ void changed_value_posts::output_diff(post_t * post, const date_t& date) post->xdata().date = date_t(); DEBUG("filter.changed_value", - "output_diff(last_balance) = " << last_balance); + "output_revaluation(last_balance) = " << last_total); DEBUG("filter.changed_value", - "output_diff(repriced_total) = " << repriced_total); + "output_revaluation(repriced_total) = " << repriced_total); + + if (! last_total.is_null()) { + if (value_t diff = repriced_total - last_total) { + DEBUG("filter.changed_value", "output_revaluation(strip(diff)) = " + << diff.strip_annotations(report.what_to_keep())); + + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = _("Commodities revalued"); + xact._date = is_valid(date) ? date : post->date(); + + handle_value(diff, &revalued_account, &xact, post_temps, *handler, + *xact._date, repriced_total, false, + optional<post_functor_t> + (bind(&changed_value_posts::output_rounding, this, _1))); + } + } +} - if (value_t diff = repriced_total - last_balance) { - DEBUG("filter.changed_value", "output_diff(strip(diff)) = " - << diff.strip_annotations(report.what_to_keep())); +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)); - xact_temps.push_back(xact_t()); - xact_t& xact = xact_temps.back(); - xact.payee = _("Commodities revalued"); - xact._date = is_valid(date) ? date : post->date(); + DEBUG("filter.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("filter.changed_value.rounding", + "rounding.repriced_amount = " << repriced_amount); - handle_value(diff, &revalued_account, &xact, POST_EXT_NO_TOTAL, - post_temps, *handler, *xact._date, repriced_total); + value_t precise_display_total(new_display_total.truncated() - + repriced_amount.truncated()); + + DEBUG("filter.changed_value.rounding", + "rounding.precise_display_total = " << precise_display_total); + DEBUG("filter.changed_value.rounding", + "rounding.last_display_total = " << last_display_total); + + if (value_t diff = precise_display_total - last_display_total) { + DEBUG("filter.changed_value.rounding", + "rounding.diff = " << diff); + + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = _("Commodity rounding"); + xact._date = post->date(); + + handle_value(diff, &rounding_account, &xact, post_temps, + *handler, *xact._date, precise_display_total, true); + } + } } + last_display_total = new_display_total; } void changed_value_posts::operator()(post_t& post) { if (last_post) - output_diff(last_post, post.date()); + output_revaluation(last_post, post.date()); if (changed_values_only) post.xdata().add_flags(POST_EXT_DISPLAYED); + output_rounding(&post); + item_handler<post_t>::operator()(post); bind_scope_t bound_scope(report, post); - last_balance = total_expr.calc(bound_scope); + last_total = total_expr.calc(bound_scope); last_post = &post; } @@ -462,8 +514,8 @@ void subtotal_posts::report_subtotal(const char * spec_fmt, xact._date = range_start; foreach (values_map::value_type& pair, values) - handle_value(pair.second.value, pair.second.account, &xact, 0, - post_temps, *handler); + handle_value(pair.second.value, pair.second.account, &xact, post_temps, + *handler); values.clear(); } @@ -581,8 +633,8 @@ void posts_as_equity::report_subtotal() value_t total = 0L; foreach (values_map::value_type& pair, values) { - handle_value(pair.second.value, pair.second.account, &xact, 0, - post_temps, *handler); + handle_value(pair.second.value, pair.second.account, &xact, post_temps, + *handler); total += pair.second.value; } values.clear(); diff --git a/src/filters.h b/src/filters.h index 8bc121ba..9ac2a6b9 100644 --- a/src/filters.h +++ b/src/filters.h @@ -449,12 +449,16 @@ 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 display_amount_expr; expr_t total_expr; + expr_t display_total_expr; report_t& report; bool changed_values_only; post_t * last_post; - value_t last_balance; + value_t last_total; + value_t last_display_total; account_t revalued_account; + account_t rounding_account; std::list<xact_t> xact_temps; std::list<post_t> post_temps; @@ -463,14 +467,19 @@ class changed_value_posts : public item_handler<post_t> public: changed_value_posts(post_handler_ptr handler, + const expr_t& _display_amount_expr, const expr_t& _total_expr, + const expr_t& _display_total_expr, report_t& _report, bool _changed_values_only) - : item_handler<post_t>(handler), total_expr(_total_expr), - report(_report), changed_values_only(_changed_values_only), - last_post(NULL), revalued_account(NULL, _("<Revalued>")) { + : item_handler<post_t>(handler), + display_amount_expr(_display_amount_expr), total_expr(_total_expr), + display_total_expr(_display_total_expr), report(_report), + changed_values_only(_changed_values_only), last_post(NULL), + revalued_account(NULL, _("<Revalued>")), + rounding_account(NULL, _("<Rounding>")){ TRACE_CTOR(changed_value_posts, - "post_handler_ptr, const expr_t&, report_t&, bool"); + "post_handler_ptr, const expr_t&, const expr_t&, report_t&, bool"); } virtual ~changed_value_posts() { TRACE_DTOR(changed_value_posts); @@ -479,13 +488,14 @@ public: virtual void flush() { if (last_post && last_post->date() <= CURRENT_DATE()) { - output_diff(last_post, CURRENT_DATE()); + output_revaluation(last_post, CURRENT_DATE()); last_post = NULL; } item_handler<post_t>::flush(); } - void output_diff(post_t * post, const date_t& current); + void output_revaluation(post_t * post, const date_t& current); + void output_rounding(post_t * post); virtual void operator()(post_t& post); }; diff --git a/src/post.cc b/src/post.cc index b10ab81a..8293bfe4 100644 --- a/src/post.cc +++ b/src/post.cc @@ -158,6 +158,10 @@ namespace { } } + value_t get_use_direct_amount(post_t& post) { + return post.has_xdata() && post.xdata().has_flags(POST_EXT_DIRECT_AMT); + } + value_t get_commodity(post_t& post) { return string_value(post.amount.commodity().symbol()); } @@ -282,6 +286,11 @@ expr_t::ptr_op_t post_t::lookup(const string& name) return WRAP_FUNCTOR(get_wrapper<&get_total>); break; + case 'u': + if (name == "use_direct_amount") + return WRAP_FUNCTOR(get_wrapper<&get_use_direct_amount>); + break; + case 'v': if (name == "virtual") return WRAP_FUNCTOR(get_wrapper<&get_virtual>); @@ -333,8 +342,7 @@ void post_t::add_to_value(value_t& value, expr_t& expr) { if (xdata_ && xdata_->has_flags(POST_EXT_COMPOUND)) { add_or_set_value(value, xdata_->value); - } - else if (! xdata_ || ! xdata_->has_flags(POST_EXT_NO_TOTAL)) { + } else { bind_scope_t bound_scope(*expr.get_context(), *this); add_or_set_value(value, expr.calc(bound_scope)); } @@ -134,7 +134,7 @@ public: #define POST_EXT_HANDLED 0x02 #define POST_EXT_TO_DISPLAY 0x04 #define POST_EXT_DISPLAYED 0x08 -#define POST_EXT_NO_TOTAL 0x10 +#define POST_EXT_DIRECT_AMT 0x10 #define POST_EXT_SORT_CALC 0x20 #define POST_EXT_COMPOUND 0x40 #define POST_EXT_MATCHES 0x80 diff --git a/src/report.h b/src/report.h index 6839de0e..1d867c68 100644 --- a/src/report.h +++ b/src/report.h @@ -245,7 +245,7 @@ public: OPTION(report_t, base); OPTION_(report_t, basis, DO() { // -B - parent->HANDLER(revalued).off(); + parent->HANDLER(revalued).on_only(); parent->HANDLER(amount_).set_expr("rounded(cost)"); }); @@ -401,15 +401,17 @@ public: // Since we are displaying the amounts of revalued postings, they // will end up being composite totals, and hence a pair of pairs. parent->HANDLER(display_amount_) - .set_expr("is_seq(get_at(amount_expr, 0)) ?" - " get_at(get_at(amount_expr, 0), 0) :" - " market(get_at(amount_expr, 0), date, exchange) -" - " get_at(amount_expr, 1)"); + .set_expr("use_direct_amount ? amount :" + " (is_seq(get_at(amount_expr, 0)) ?" + " get_at(get_at(amount_expr, 0), 0) :" + " market(get_at(amount_expr, 0), date, exchange)" + " - get_at(amount_expr, 1))"); parent->HANDLER(revalued_total_) .set_expr("(market(get_at(total_expr, 0), date, exchange), " "get_at(total_expr, 1))"); parent->HANDLER(display_total_) - .set_expr("market(get_at(total_expr, 0), date, exchange)" + .set_expr("use_direct_amount ? total_expr :" + " market(get_at(total_expr, 0), date, exchange)" " - get_at(total_expr, 1)"); }); |