diff options
author | John Wiegley <johnw@newartisans.com> | 2010-05-30 20:49:50 -0600 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-05-30 20:49:50 -0600 |
commit | 5a2644c1b7220dc96e4de9cfb82f6d829cf34321 (patch) | |
tree | a865c62dd006ea595442b8ab2379d8a3cbf4d526 | |
parent | 58621a96a22de5c1453b7fac624e00dc7f3c402e (diff) | |
download | fork-ledger-5a2644c1b7220dc96e4de9cfb82f6d829cf34321.tar.gz fork-ledger-5a2644c1b7220dc96e4de9cfb82f6d829cf34321.tar.bz2 fork-ledger-5a2644c1b7220dc96e4de9cfb82f6d829cf34321.zip |
-V/-X options now take price history into account
-rw-r--r-- | src/filters.cc | 80 | ||||
-rw-r--r-- | src/filters.h | 2 | ||||
-rw-r--r-- | test/baseline/opt-price.test | 3 | ||||
-rw-r--r-- | test/regress/D943AE0F.test | 4 |
4 files changed, 84 insertions, 5 deletions
diff --git a/src/filters.cc b/src/filters.cc index eabf9834..bca8516e 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -503,6 +503,8 @@ changed_value_posts::changed_value_posts(post_handler_ptr handler, void changed_value_posts::flush() { if (last_post && last_post->date() <= report.terminus.date()) { + if (! for_accounts_report) + output_intermediate_prices(*last_post, report.terminus.date()); output_revaluation(*last_post, report.terminus.date()); last_post = NULL; } @@ -514,7 +516,6 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date) if (is_valid(date)) post.xdata().date = date; - value_t repriced_total; try { bind_scope_t bound_scope(report, post); repriced_total = total_expr.calc(bound_scope); @@ -573,6 +574,78 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date) } } +void changed_value_posts::output_intermediate_prices(post_t& post, + const date_t& current) +{ + // To fix BZ#199, examine the balance of last_post and determine whether the + // price of that amount changed after its date and before the new post's + // date. If so, generate an output_revaluation for that price change. + // Mostly this is only going to occur if the user has a series of pricing + // entries, since a posting-based revaluation would be seen here as a post. + assert(! last_total.is_null()); + + switch (last_total.type()) { + case value_t::INTEGER: + case value_t::SEQUENCE: + break; + case value_t::AMOUNT: + last_total.in_place_cast(value_t::BALANCE); + // fall through... + case value_t::BALANCE: { + commodity_t::history_map all_prices; + + foreach (const balance_t::amounts_map::value_type& amt_comm, + last_total.as_balance().amounts) { + if (optional<commodity_t::varied_history_t&> hist = + amt_comm.first->varied_history()) { + foreach + (const commodity_t::history_by_commodity_map::value_type& comm_hist, + hist->histories) { + foreach (const commodity_t::history_map::value_type& price, + comm_hist.second.prices) { + if (price.first.date() > post.date() && + price.first.date() < current) { + DEBUG("filters.revalued", post.date() << " < " + << price.first.date() << " < " << current); + DEBUG("filters.revalued", "inserting " + << price.second << " at " << price.first.date()); + all_prices.insert(price); + } + } + } + } + } + + // Choose the last price from each day as the price to use + typedef std::map<const date_t, + std::pair<const datetime_t, + amount_t> > history_by_date_map; + history_by_date_map all_prices_by_date; + + BOOST_REVERSE_FOREACH + (const commodity_t::history_map::value_type& price, all_prices) { + // This insert will fail if a later price has already been inserted + // for that date. + DEBUG("filters.revalued", + "re-inserting " << price.second << " at " << price.first.date()); + all_prices_by_date.insert(history_by_date_map::value_type + (price.first.date(), price)); + } + + // Go through the time-sorted prices list, outputting a revaluation for + // each price difference. + foreach (const history_by_date_map::value_type& price, all_prices_by_date) { + output_revaluation(post, price.first); + last_total = repriced_total; + } + break; + } + default: + assert(false); + break; + } +} + void changed_value_posts::output_rounding(post_t& post) { bind_scope_t bound_scope(report, post); @@ -612,8 +685,11 @@ void changed_value_posts::output_rounding(post_t& post) void changed_value_posts::operator()(post_t& post) { - if (last_post) + if (last_post) { + if (! for_accounts_report) + output_intermediate_prices(*last_post, post.date()); output_revaluation(*last_post, post.date()); + } if (changed_values_only) post.xdata().add_flags(POST_EXT_DISPLAYED); diff --git a/src/filters.h b/src/filters.h index dd6b3b1a..a66d8c47 100644 --- a/src/filters.h +++ b/src/filters.h @@ -499,6 +499,7 @@ class changed_value_posts : public item_handler<post_t> post_t * last_post; value_t last_total; value_t last_display_total; + value_t repriced_total; temporaries_t temps; account_t& revalued_account; account_t& rounding_account; @@ -521,6 +522,7 @@ public: virtual void flush(); void output_revaluation(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); diff --git a/test/baseline/opt-price.test b/test/baseline/opt-price.test index 06cc7751..bf302264 100644 --- a/test/baseline/opt-price.test +++ b/test/baseline/opt-price.test @@ -28,7 +28,8 @@ reg --end 2009/06/26 -V equities 08-Jan-01 Purchase Apple shares Equities $2000 $2000 08-Jun-30 Commodities revalued <Revalued> $500 $2500 08-Jun-30 Sell some Apple sha.. Equities $-1250 $1250 -09-Jun-26 Commodities revalued <Revalued> $750 $2000 +09-Jan-31 Commodities revalued <Revalued> $250 $1500 +09-Jun-26 Commodities revalued <Revalued> $500 $2000 >>>2 === 0 reg --end 2009/06/26 -G equities diff --git a/test/regress/D943AE0F.test b/test/regress/D943AE0F.test index 94a26df5..7a2e14d8 100644 --- a/test/regress/D943AE0F.test +++ b/test/regress/D943AE0F.test @@ -1,4 +1,4 @@ -reg -V --end=2009/06/16 +reg -V <<< D 1000.00 EUR @@ -10,6 +10,6 @@ P 2008/04/20 00:00:00 CAD 1.20 EUR >>>1 08-Apr-15 Paid expenses back .. Ex:Cie-Reimbursements 2200.00 EUR 2200.00 EUR Assets:Checking -2200.00 EUR 0 -09-Jun-16 Commodities revalued <Revalued> 200.00 EUR 200.00 EUR +08-Apr-20 Commodities revalued <Revalued> 200.00 EUR 200.00 EUR >>>2 === 0 |