Fixed interaction with -V/X and grouped postings
With -s, -M/Y/D, -n, and a few other flags, postings get "grouped" into meta-transactions that contain more postings than before. In all these cases, -V use the date of the *earliest* posting in that group, which makes little sense and caused breakages with -J. It now uses the latest date. Fixes #197 / 68EAF363-D0FE-4127-866E-A5AEBACB65D6
This commit is contained in:
parent
524c98244e
commit
fc09b69fb7
6 changed files with 102 additions and 55 deletions
116
src/filters.cc
116
src/filters.cc
|
|
@ -289,18 +289,16 @@ void calc_posts::operator()(post_t& post)
|
|||
}
|
||||
|
||||
namespace {
|
||||
typedef function<void (post_t&)> post_functor_t;
|
||||
|
||||
void handle_value(const value_t& value,
|
||||
account_t * account,
|
||||
xact_t * xact,
|
||||
temporaries_t& temps,
|
||||
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)
|
||||
void handle_value(const value_t& value,
|
||||
account_t * account,
|
||||
xact_t * xact,
|
||||
temporaries_t& temps,
|
||||
post_handler_ptr handler,
|
||||
const date_t& date = date_t(),
|
||||
const bool act_date_p = true,
|
||||
const value_t& total = value_t(),
|
||||
const bool direct_amount = false,
|
||||
const bool mark_visited = false)
|
||||
{
|
||||
post_t& post = temps.create_post(*xact, account);
|
||||
post.add_flags(ITEM_GENERATED);
|
||||
|
|
@ -319,8 +317,12 @@ namespace {
|
|||
|
||||
post_t::xdata_t& xdata(post.xdata());
|
||||
|
||||
if (is_valid(date))
|
||||
xdata.date = date;
|
||||
if (is_valid(date)) {
|
||||
if (act_date_p)
|
||||
xdata.date = date;
|
||||
else
|
||||
xdata.value_date = date;
|
||||
}
|
||||
|
||||
value_t temp(value);
|
||||
|
||||
|
|
@ -353,9 +355,6 @@ namespace {
|
|||
if (direct_amount)
|
||||
xdata.add_flags(POST_EXT_DIRECT_AMT);
|
||||
|
||||
if (functor)
|
||||
(*functor)(post);
|
||||
|
||||
DEBUG("filters.changed_value.rounding", "post.amount = " << post.amount);
|
||||
|
||||
(*handler)(post);
|
||||
|
|
@ -388,12 +387,15 @@ void collapse_posts::report_subtotal()
|
|||
}
|
||||
else {
|
||||
date_t earliest_date;
|
||||
date_t latest_date;
|
||||
|
||||
foreach (post_t * post, component_posts) {
|
||||
date_t reported = post->date();
|
||||
if (! is_valid(earliest_date) ||
|
||||
reported < earliest_date)
|
||||
earliest_date = reported;
|
||||
date_t date = post->date();
|
||||
date_t value_date = post->value_date();
|
||||
if (! is_valid(earliest_date) || date < earliest_date)
|
||||
earliest_date = date;
|
||||
if (! is_valid(latest_date) || value_date > latest_date)
|
||||
latest_date = value_date;
|
||||
}
|
||||
|
||||
xact_t& xact = temps.create_xact();
|
||||
|
|
@ -401,12 +403,16 @@ void collapse_posts::report_subtotal()
|
|||
xact._date = (is_valid(earliest_date) ?
|
||||
earliest_date : last_xact->_date);
|
||||
DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date);
|
||||
DEBUG("filters.collapse", "earliest date = " << earliest_date);
|
||||
DEBUG("filters.collapse", "latest date = " << latest_date);
|
||||
|
||||
handle_value(/* value= */ subtotal,
|
||||
/* account= */ &totals_account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler);
|
||||
handle_value(/* value= */ subtotal,
|
||||
/* account= */ &totals_account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ latest_date,
|
||||
/* act_date_p= */ false);
|
||||
}
|
||||
|
||||
component_posts.clear();
|
||||
|
|
@ -526,6 +532,7 @@ bool display_filter_posts::output_rounding(post_t& post)
|
|||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ *xact._date,
|
||||
/* act_date_p= */ true,
|
||||
/* total= */ precise_display_total,
|
||||
/* direct_amount= */ true);
|
||||
}
|
||||
|
|
@ -627,7 +634,7 @@ 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.value_date();
|
||||
|
||||
if (! for_accounts_report) {
|
||||
handle_value
|
||||
|
|
@ -637,6 +644,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
|
|||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ *xact._date,
|
||||
/* act_date_p= */ true,
|
||||
/* total= */ repriced_total);
|
||||
}
|
||||
else if (show_unrealized) {
|
||||
|
|
@ -649,6 +657,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
|
|||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ *xact._date,
|
||||
/* act_date_p= */ true,
|
||||
/* total= */ value_t(),
|
||||
/* direct_amount= */ false,
|
||||
/* mark_visited= */ true);
|
||||
|
|
@ -672,7 +681,7 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
|
|||
xact_t& xact(temps.create_xact());
|
||||
|
||||
xact.payee = _("Commodities revalued");
|
||||
xact._date = is_valid(current) ? current : post.date();
|
||||
xact._date = is_valid(current) ? current : post.value_date();
|
||||
|
||||
post_t& temp(temps.copy_post(post, xact));
|
||||
temp.add_flags(ITEM_GENERATED);
|
||||
|
|
@ -734,9 +743,9 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
|
|||
hist->histories) {
|
||||
foreach (const commodity_t::history_map::value_type& price,
|
||||
comm_hist.second.prices) {
|
||||
if (price.first.date() > post.date() &&
|
||||
if (price.first.date() > post.value_date() &&
|
||||
price.first.date() < current) {
|
||||
DEBUG("filters.revalued", post.date() << " < "
|
||||
DEBUG("filters.revalued", post.value_date() << " < "
|
||||
<< price.first.date() << " < " << current);
|
||||
DEBUG("filters.revalued", "inserting "
|
||||
<< price.second << " at " << price.first.date());
|
||||
|
|
@ -778,8 +787,8 @@ void changed_value_posts::operator()(post_t& post)
|
|||
{
|
||||
if (last_post) {
|
||||
if (! for_accounts_report)
|
||||
output_intermediate_prices(*last_post, post.date());
|
||||
output_revaluation(*last_post, post.date());
|
||||
output_intermediate_prices(*last_post, post.value_date());
|
||||
output_revaluation(*last_post, post.value_date());
|
||||
}
|
||||
|
||||
if (changed_values_only)
|
||||
|
|
@ -803,11 +812,12 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
|
|||
|
||||
if (! range_start || ! range_finish) {
|
||||
foreach (post_t * post, component_posts) {
|
||||
date_t date = post->date();
|
||||
date_t date = post->date();
|
||||
date_t value_date = post->value_date();
|
||||
if (! range_start || date < *range_start)
|
||||
range_start = date;
|
||||
if (! range_finish || date > *range_finish)
|
||||
range_finish = date;
|
||||
if (! range_finish || value_date > *range_finish)
|
||||
range_finish = value_date;
|
||||
}
|
||||
}
|
||||
component_posts.clear();
|
||||
|
|
@ -829,11 +839,13 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
|
|||
xact._date = *range_start;
|
||||
|
||||
foreach (values_map::value_type& pair, values)
|
||||
handle_value(/* value= */ pair.second.value,
|
||||
/* account= */ pair.second.account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler);
|
||||
handle_value(/* value= */ pair.second.value,
|
||||
/* account= */ pair.second.account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ *range_finish,
|
||||
/* act_date_p= */ false);
|
||||
|
||||
values.clear();
|
||||
}
|
||||
|
|
@ -942,17 +954,21 @@ void posts_as_equity::report_subtotal()
|
|||
if (pair.second.value.is_balance()) {
|
||||
foreach (const balance_t::amounts_map::value_type& amount_pair,
|
||||
pair.second.value.as_balance().amounts)
|
||||
handle_value(/* value= */ amount_pair.second,
|
||||
/* account= */ pair.second.account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler);
|
||||
handle_value(/* value= */ amount_pair.second,
|
||||
/* account= */ pair.second.account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ finish,
|
||||
/* act_date_p= */ false);
|
||||
} else {
|
||||
handle_value(/* value= */ pair.second.value,
|
||||
/* account= */ pair.second.account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler);
|
||||
handle_value(/* value= */ pair.second.value,
|
||||
/* account= */ pair.second.account,
|
||||
/* xact= */ &xact,
|
||||
/* temps= */ temps,
|
||||
/* handler= */ handler,
|
||||
/* date= */ finish,
|
||||
/* act_date_p= */ false);
|
||||
}
|
||||
total += pair.second.value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -465,6 +465,11 @@ expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
|
|||
return WRAP_FUNCTOR(get_wrapper<&get_uncleared>);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
if (name == "value_date")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (name[1] == '\0')
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_actual>);
|
||||
|
|
|
|||
17
src/post.cc
17
src/post.cc
|
|
@ -78,6 +78,13 @@ optional<string> post_t::get_tag(const mask_t& tag_mask,
|
|||
return none;
|
||||
}
|
||||
|
||||
date_t post_t::value_date() const
|
||||
{
|
||||
if (xdata_ && is_valid(xdata_->value_date))
|
||||
return xdata_->value_date;
|
||||
return date();
|
||||
}
|
||||
|
||||
date_t post_t::date() const
|
||||
{
|
||||
if (xdata_ && is_valid(xdata_->date))
|
||||
|
|
@ -319,6 +326,14 @@ namespace {
|
|||
return long(post.reported_account()->depth);
|
||||
}
|
||||
|
||||
value_t get_value_date(post_t& post) {
|
||||
if (post.has_xdata()) {
|
||||
post_t::xdata_t& xdata(post.xdata());
|
||||
if (! xdata.value_date.is_not_a_date())
|
||||
return xdata.value_date;
|
||||
}
|
||||
return post.date();
|
||||
}
|
||||
value_t get_datetime(post_t& post) {
|
||||
return post.xdata().datetime;
|
||||
}
|
||||
|
|
@ -479,6 +494,8 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
|
|||
case 'v':
|
||||
if (name == "virtual")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_virtual>);
|
||||
else if (name == "value_date")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_value_date>);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ public:
|
|||
virtual optional<string> get_tag(const mask_t& tag_mask,
|
||||
const optional<mask_t>& value_mask = none) const;
|
||||
|
||||
virtual date_t value_date() const;
|
||||
virtual date_t date() const;
|
||||
virtual date_t actual_date() const;
|
||||
virtual optional<date_t> effective_date() const;
|
||||
|
|
@ -141,6 +142,7 @@ public:
|
|||
value_t total;
|
||||
std::size_t count;
|
||||
date_t date;
|
||||
date_t value_date;
|
||||
datetime_t datetime;
|
||||
account_t * account;
|
||||
|
||||
|
|
|
|||
|
|
@ -1308,6 +1308,11 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
|||
return MAKE_FUNCTOR(report_t::fn_unrounded);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
if (is_eq(p, "value_date"))
|
||||
return MAKE_FUNCTOR(report_t::fn_now);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (is_eq(p, "white"))
|
||||
return WRAP_FUNCTOR(fn_white);
|
||||
|
|
|
|||
12
src/report.h
12
src/report.h
|
|
@ -586,16 +586,16 @@ public:
|
|||
"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)"
|
||||
" market(get_at(amount_expr, 0), value_date, exchange)"
|
||||
" - get_at(amount_expr, 1))");
|
||||
parent->HANDLER(revalued_total_)
|
||||
.set_expr(string("--gain"),
|
||||
"(market(get_at(total_expr, 0), date, exchange), "
|
||||
"(market(get_at(total_expr, 0), value_date, exchange), "
|
||||
"get_at(total_expr, 1))");
|
||||
parent->HANDLER(display_total_)
|
||||
.set_expr(string("--gain"),
|
||||
"use_direct_amount ? total_expr :"
|
||||
" market(get_at(total_expr, 0), date, exchange)"
|
||||
" market(get_at(total_expr, 0), value_date, exchange)"
|
||||
" - get_at(total_expr, 1)");
|
||||
});
|
||||
|
||||
|
|
@ -642,9 +642,11 @@ public:
|
|||
OPTION_(report_t, market, DO() { // -V
|
||||
parent->HANDLER(revalued).on_only(string("--market"));
|
||||
parent->HANDLER(display_amount_)
|
||||
.set_expr(string("--market"), "market(amount_expr, date, exchange)");
|
||||
.set_expr(string("--market"),
|
||||
"market(amount_expr, value_date, exchange)");
|
||||
parent->HANDLER(display_total_)
|
||||
.set_expr(string("--market"), "market(total_expr, date, exchange)");
|
||||
.set_expr(string("--market"),
|
||||
"market(total_expr, value_date, exchange)");
|
||||
});
|
||||
|
||||
OPTION(report_t, meta_);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue