From ae8b57f15785f0fbe300e7d6d2b709b4730556d1 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 18 Nov 2009 23:24:53 -0500 Subject: Renamed bool controlling running total calculations It used to be "account_wise", since it only happens for non-account-wise reports. Now it's called just "calc_running_total", so anyone can request it. --- src/filters.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/filters.h') diff --git a/src/filters.h b/src/filters.h index 57b3edd2..40119d6d 100644 --- a/src/filters.h +++ b/src/filters.h @@ -280,16 +280,16 @@ class calc_posts : public item_handler { post_t * last_post; expr_t& amount_expr; - bool account_wise; + bool calc_running_total; calc_posts(); public: calc_posts(post_handler_ptr handler, expr_t& _amount_expr, - bool _account_wise = false) + bool _calc_running_total = false) : item_handler(handler), last_post(NULL), - amount_expr(_amount_expr), account_wise(_account_wise) { + amount_expr(_amount_expr), calc_running_total(_calc_running_total) { TRACE_CTOR(calc_posts, "post_handler_ptr, expr_t&, bool"); } virtual ~calc_posts() { -- cgit v1.2.3 From 20965d9fa3c2b355280f25520f0cd74cafcf5fbc Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 19 Nov 2009 00:54:19 -0500 Subject: Changed several pointers to references in filters --- src/chain.cc | 9 +------- src/filters.cc | 67 ++++++++++++++++++++++++++++++++++++---------------------- src/filters.h | 22 +++++-------------- 3 files changed, 48 insertions(+), 50 deletions(-) (limited to 'src/filters.h') diff --git a/src/chain.cc b/src/chain.cc index 06bcdf27..a3695923 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -82,14 +82,7 @@ post_handler_ptr chain_post_handlers(report_t& report, // changes in market value of commodities, which otherwise would affect // the running total unpredictably. if (report.HANDLED(revalued)) - handler.reset(new changed_value_posts - (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))); + handler.reset(new changed_value_posts(handler, report)); } // calc_posts computes the running total. When this appears will determine, diff --git a/src/filters.cc b/src/filters.cc index 4c69dd78..4ac3de4c 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -239,19 +239,20 @@ void calc_posts::operator()(post_t& post) } namespace { - typedef function post_functor_t; + typedef function post_functor_t; void handle_value(const value_t& value, - account_t * account, + account_t * account, xact_t * xact, temporaries_t& temps, - item_handler& 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 optional& 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 +303,11 @@ 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); } } @@ -344,7 +345,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 +405,46 @@ void related_posts::flush() item_handler::flush(); } +changed_value_posts::changed_value_posts(post_handler_ptr handler, + report_t& _report) + : item_handler(handler), report(_report), last_post(NULL), + revalued_account(temps.create_account(_(""))), + rounding_account(temps.create_account(_(""))) +{ + 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); +} + 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::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,9 +458,9 @@ 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(); + xact._date = is_valid(date) ? date : post.date(); - handle_value(diff, &revalued_account, &xact, temps, *handler, + handle_value(diff, &revalued_account, &xact, temps, handler, *xact._date, repriced_total, false, optional (bind(&changed_value_posts::output_rounding, this, _1))); @@ -451,9 +468,9 @@ void changed_value_posts::output_revaluation(post_t * post, const date_t& date) } } -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 +495,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,12 +508,12 @@ 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); + output_rounding(post); item_handler::operator()(post); @@ -543,7 +560,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(); } @@ -653,10 +670,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; } diff --git a/src/filters.h b/src/filters.h index 40119d6d..2222878e 100644 --- a/src/filters.h +++ b/src/filters.h @@ -382,7 +382,7 @@ class changed_value_posts : public item_handler post_t * last_post; value_t last_total; value_t last_display_total; - temporaries_t temps; + temporaries_t temps; account_t& revalued_account; account_t& rounding_account; @@ -390,28 +390,16 @@ class changed_value_posts : public item_handler 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(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(temps.create_account(_(""))), - rounding_account(temps.create_account(_(""))) { - TRACE_CTOR(changed_value_posts, - "post_handler_ptr, const expr_t&, const expr_t&, report_t&, bool"); - } + report_t& _report); + virtual ~changed_value_posts() { TRACE_DTOR(changed_value_posts); } virtual void flush(); - void output_revaluation(post_t * post, const date_t& current); - void output_rounding(post_t * post); + void output_revaluation(post_t& post, const date_t& current); + void output_rounding(post_t& post); virtual void operator()(post_t& post); }; -- cgit v1.2.3 From 3f1861fb1e9e374fb7756117638edcb6fb1e73fb Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 19 Nov 2009 01:27:10 -0500 Subject: Fixed a debug string --- src/filters.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/filters.h') diff --git a/src/filters.h b/src/filters.h index 2222878e..f9412407 100644 --- a/src/filters.h +++ b/src/filters.h @@ -241,8 +241,7 @@ public: const predicate_t& predicate, scope_t& _context) : item_handler(handler), pred(predicate), context(_context) { - TRACE_CTOR(filter_posts, - "post_handler_ptr, const predicate_t&, scope_t&"); + TRACE_CTOR(filter_posts, "post_handler_ptr, predicate_t, scope_t&"); } virtual ~filter_posts() { TRACE_DTOR(filter_posts); -- cgit v1.2.3 From 63fee4c83775f79364199ea547dbc7e068b0abc8 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 19 Nov 2009 02:00:10 -0500 Subject: Added an --unrealized option, for use with bal -V When this option is on, then in balance report which show market values, any gains or losses in value will be balanced into a pair of accounts called Equity:Unrealized Gains and Equity:Unrealized Losses. --- src/chain.cc | 19 ++++++++----- src/filters.cc | 58 ++++++++++++++++++++++++++++++++++----- src/filters.h | 8 +++++- src/report.cc | 1 + src/report.h | 3 ++ test/baseline/opt-unrealized.test | 20 ++++++++++++++ 6 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 test/baseline/opt-unrealized.test (limited to 'src/filters.h') diff --git a/src/chain.cc b/src/chain.cc index 9ab26bd6..113a71d8 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -77,18 +77,23 @@ post_handler_ptr chain_post_handlers(report_t& report, report.what_to_keep()); handler.reset(new filter_posts(handler, display_predicate, report)); } - - // 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)) - handler.reset(new changed_value_posts(handler, report)); } + // 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) && (! for_accounts_report || + report.HANDLED(unrealized))) + handler.reset(new changed_value_posts(handler, report, + for_accounts_report, + report.HANDLED(unrealized))); + // calc_posts computes the running total. When this appears will determine, // for example, whether filtered posts are included or excluded from the // running total. - handler.reset(new calc_posts(handler, expr, ! for_accounts_report)); + handler.reset(new calc_posts(handler, expr, (! for_accounts_report || + (report.HANDLED(revalued) && + report.HANDLED(unrealized))))); // filter_posts will only pass through posts matching the // `secondary_predicate'. diff --git a/src/filters.cc b/src/filters.cc index 4ac3de4c..39097c58 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -249,6 +249,7 @@ namespace { const date_t& date = date_t(), const value_t& total = value_t(), const bool direct_amount = false, + const bool mark_visited = false, const optional& functor = none) { post_t& post = temps.create_post(*xact, account); @@ -308,6 +309,11 @@ namespace { DEBUG("filter.changed_value.rounding", "post.amount = " << post.amount); (*handler)(post); + + if (mark_visited) { + post.xdata().add_flags(POST_EXT_VISITED); + post.account->xdata().add_flags(ACCOUNT_EXT_VISITED); + } } } @@ -406,8 +412,12 @@ void related_posts::flush() } changed_value_posts::changed_value_posts(post_handler_ptr handler, - report_t& _report) - : item_handler(handler), report(_report), last_post(NULL), + report_t& _report, + bool _for_accounts_report, + bool _show_unrealized) + : item_handler(handler), report(_report), + for_accounts_report(_for_accounts_report), + show_unrealized(_show_unrealized), last_post(NULL), revalued_account(temps.create_account(_(""))), rounding_account(temps.create_account(_(""))) { @@ -419,6 +429,14 @@ changed_value_posts::changed_value_posts(post_handler_ptr handler, 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() @@ -460,10 +478,35 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date) 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 - (bind(&changed_value_posts::output_rounding, this, _1))); + 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 + (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); + } } } } @@ -513,7 +556,8 @@ void changed_value_posts::operator()(post_t& post) if (changed_values_only) post.xdata().add_flags(POST_EXT_DISPLAYED); - output_rounding(post); + if (! for_accounts_report) + output_rounding(post); item_handler::operator()(post); diff --git a/src/filters.h b/src/filters.h index f9412407..92148dbe 100644 --- a/src/filters.h +++ b/src/filters.h @@ -378,18 +378,24 @@ class changed_value_posts : public item_handler expr_t display_total_expr; report_t& report; bool changed_values_only; + bool for_accounts_report; + bool show_unrealized; post_t * last_post; value_t last_total; value_t last_display_total; temporaries_t temps; account_t& revalued_account; account_t& rounding_account; + account_t * gains_equity_account; + account_t * losses_equity_account; changed_value_posts(); public: changed_value_posts(post_handler_ptr handler, - report_t& _report); + report_t& _report, + bool _for_accounts_report, + bool _show_unrealized); virtual ~changed_value_posts() { TRACE_DTOR(changed_value_posts); diff --git a/src/report.cc b/src/report.cc index 92525565..7da44f8c 100644 --- a/src/report.cc +++ b/src/report.cc @@ -887,6 +887,7 @@ option_t * report_t::lookup_option(const char * p) case 'u': OPT(unbudgeted); else OPT(uncleared); + else OPT(unrealized); else OPT(unround); else OPT(unsorted); break; diff --git a/src/report.h b/src/report.h index 0b1baff1..354e31b6 100644 --- a/src/report.h +++ b/src/report.h @@ -301,6 +301,7 @@ public: HANDLER(truncate_).report(out); HANDLER(unbudgeted).report(out); HANDLER(uncleared).report(out); + HANDLER(unrealized).report(out); HANDLER(unround).report(out); HANDLER(unsorted).report(out); HANDLER(weekly).report(out); @@ -873,6 +874,8 @@ public: parent->HANDLER(limit_).on(string("--uncleared"), "uncleared|pending"); }); + OPTION(report_t, unrealized); + OPTION_(report_t, unround, DO() { parent->HANDLER(display_amount_) .set_expr(string("--unround"), "unrounded(amount_expr)"); diff --git a/test/baseline/opt-unrealized.test b/test/baseline/opt-unrealized.test new file mode 100644 index 00000000..7d5d20fb --- /dev/null +++ b/test/baseline/opt-unrealized.test @@ -0,0 +1,20 @@ +bal -V --unrealized +<<< +2008/10/01 Sample + Assets:Brokerage 10 AAPL + Assets:Checking $-200.00 + +P 2008/10/20 12:00:00 AAPL $30.00 + +; 2008/10/20 +; Assets:Brokerage $100 +; Equity:Unrealized Gains +>>>1 + $100.00 Assets + $300.00 Brokerage + $-200.00 Checking + $-100.00 Equity:Unrealized Gains +-------------------- + 0 +>>>2 +=== 0 -- cgit v1.2.3