summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-05-30 20:49:50 -0600
committerJohn Wiegley <johnw@newartisans.com>2010-05-30 20:49:50 -0600
commit5a2644c1b7220dc96e4de9cfb82f6d829cf34321 (patch)
treea865c62dd006ea595442b8ab2379d8a3cbf4d526
parent58621a96a22de5c1453b7fac624e00dc7f3c402e (diff)
downloadfork-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.cc80
-rw-r--r--src/filters.h2
-rw-r--r--test/baseline/opt-price.test3
-rw-r--r--test/regress/D943AE0F.test4
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