summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/balance.cc17
-rw-r--r--src/chain.cc18
-rw-r--r--src/filters.cc60
-rw-r--r--src/filters.h25
-rw-r--r--src/output.cc10
-rw-r--r--src/report.cc10
-rw-r--r--src/report.h2
-rw-r--r--src/xact.cc3
-rw-r--r--src/xact.h6
-rw-r--r--test/baseline/opt-exchange.test20
-rw-r--r--test/baseline/opt-market.test6
11 files changed, 106 insertions, 71 deletions
diff --git a/src/balance.cc b/src/balance.cc
index 70e83362..39392aa3 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -163,18 +163,19 @@ balance_t::value(const bool primary_only,
const optional<datetime_t>& moment,
const optional<commodity_t&>& in_terms_of) const
{
- optional<balance_t> temp;
+ balance_t temp;
+ bool resolved = false;
foreach (const amounts_map::value_type& pair, amounts) {
- if (! temp)
- temp = balance_t();
if (optional<amount_t> val = pair.second.value(primary_only, moment,
- in_terms_of))
- *temp += *val;
- else
- *temp += pair.second;
+ in_terms_of)) {
+ temp += *val;
+ resolved = true;
+ } else {
+ temp += pair.second;
+ }
}
- return temp;
+ return resolved ? temp : optional<balance_t>();
}
optional<amount_t>
diff --git a/src/chain.cc b/src/chain.cc
index 8d51d11c..2a494fda 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -74,6 +74,15 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
handler.reset(new filter_xacts(handler, display_predicate, report));
}
+ // changed_value_xacts adds virtual xacts 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_xacts(handler,
+ report.HANDLER(display_total_).expr,
+ report,
+ report.HANDLED(revalued_only)));
+
// calc_xacts computes the running total. When this appears will
// determine, for example, whether filtered xacts are included or excluded
// from the running total.
@@ -98,14 +107,6 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
handler.reset(new sort_xacts(handler, report.HANDLER(sort_).str()));
}
- // changed_value_xacts adds virtual xacts 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_xacts(handler,
- report.HANDLER(total_).expr,
- report.HANDLED(revalued_only)));
-
// collapse_xacts causes entries with multiple xacts to appear as entries
// with a subtotaled xact for each commodity used.
if (report.HANDLED(collapse))
@@ -137,7 +138,6 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
if (report.HANDLED(period_)) {
handler.reset(new interval_xacts(handler, expr,
report.HANDLER(period_).str(),
- report.session.master.get(),
report.HANDLED(exact),
report.HANDLED(empty)));
handler.reset(new sort_xacts(handler, "date"));
diff --git a/src/filters.cc b/src/filters.cc
index c6ab5c4e..c58d6618 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -33,6 +33,7 @@
#include "iterators.h"
#include "compare.h"
#include "format.h"
+#include "report.h"
namespace ledger {
@@ -218,7 +219,8 @@ namespace {
unsigned int flags,
std::list<xact_t>& temps,
item_handler<xact_t>& handler,
- const date_t& date = date_t())
+ const date_t& date = date_t(),
+ const value_t& total = value_t())
{
temps.push_back(xact_t(account));
xact_t& xact(temps.back());
@@ -266,6 +268,9 @@ namespace {
break;
}
+ if (! total.is_null())
+ xdata.total = total;
+
if (flags)
xdata.add_flags(flags);
@@ -294,7 +299,7 @@ void collapse_xacts::report_subtotal()
date_t earliest_date;
foreach (xact_t * xact, component_xacts) {
- date_t reported = xact->reported_date();
+ date_t reported = xact->date();
if (! is_valid(earliest_date) ||
reported < earliest_date)
earliest_date = reported;
@@ -367,36 +372,55 @@ void related_xacts::flush()
item_handler<xact_t>::flush();
}
-void changed_value_xacts::output_diff(const date_t& date)
+void changed_value_xacts::output_diff(xact_t * xact, const date_t& date)
{
- value_t cur_bal;
+ if (is_valid(date))
+ xact->xdata().date = date;
+
+ value_t repriced_total;
+ try {
+ bind_scope_t bound_scope(report, *xact);
+ repriced_total = total_expr.calc(bound_scope);
+ }
+ catch (...) {
+ xact->xdata().date = date_t();
+ throw;
+ }
+ xact->xdata().date = date_t();
- last_xact->xdata().date = date;
- cur_bal = total_expr.calc(*last_xact).rounded();
+ DEBUG("filter.changed_value",
+ "output_diff(last_balance) = " << last_balance);
+ DEBUG("filter.changed_value",
+ "output_diff(repriced_total) = " << repriced_total);
+
+ if (value_t diff = repriced_total - last_balance) {
+ DEBUG("filter.changed_value", "output_diff(strip(diff)) = "
+ << diff.strip_annotations(report.what_to_keep()));
- if (value_t diff = cur_bal - last_balance) {
entry_temps.push_back(entry_t());
entry_t& entry = entry_temps.back();
entry.payee = "Commodities revalued";
- entry._date = date;
+ entry._date = is_valid(date) ? date : xact->date();
- handle_value(diff, NULL, &entry, XACT_EXT_NO_TOTAL, xact_temps,
- *handler);
+ handle_value(diff, &revalued_account, &entry, XACT_EXT_NO_TOTAL,
+ xact_temps, *handler, *entry._date, repriced_total);
}
}
void changed_value_xacts::operator()(xact_t& xact)
{
if (last_xact)
- output_diff(last_xact->reported_date());
+ output_diff(last_xact, xact.date());
if (changed_values_only)
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
item_handler<xact_t>::operator()(xact);
- last_balance = total_expr.calc(xact).rounded();
- last_xact = &xact;
+ bind_scope_t bound_scope(report, xact);
+ last_balance = total_expr.calc(bound_scope);
+
+ last_xact = &xact;
}
void subtotal_xacts::report_subtotal(const char * spec_fmt,
@@ -409,7 +433,7 @@ void subtotal_xacts::report_subtotal(const char * spec_fmt,
date_t range_start = start;
date_t range_finish = finish;
foreach (xact_t * xact, component_xacts) {
- date_t date = xact->reported_date();
+ date_t date = xact->date();
if (! is_valid(range_start) || date < range_start)
range_start = date;
if (! is_valid(range_finish) || date > range_finish)
@@ -437,7 +461,7 @@ void subtotal_xacts::report_subtotal(const char * spec_fmt,
foreach (values_map::value_type& pair, values)
handle_value(pair.second.value, pair.second.account, &entry, 0,
- xact_temps, *handler, range_finish);
+ xact_temps, *handler);
values.clear();
}
@@ -484,7 +508,7 @@ void interval_xacts::report_subtotal(const date_t& finish)
void interval_xacts::operator()(xact_t& xact)
{
- date_t date = xact.reported_date();
+ date_t date = xact.date();
if ((is_valid(interval.begin) && date < interval.begin) ||
(is_valid(interval.end) && date >= interval.end))
@@ -542,7 +566,7 @@ void xacts_as_equity::report_subtotal()
{
date_t finish;
foreach (xact_t * xact, component_xacts) {
- date_t date = xact->reported_date();
+ date_t date = xact->date();
if (! is_valid(finish) || date > finish)
finish = date;
}
@@ -614,7 +638,7 @@ void transfer_details::operator()(xact_t& xact)
{
entry_temps.push_back(*xact.entry);
entry_t& entry = entry_temps.back();
- entry._date = xact.reported_date();
+ entry._date = xact.date();
xact_temps.push_back(xact);
xact_t& temp = xact_temps.back();
diff --git a/src/filters.h b/src/filters.h
index 81039125..3a8a5ab5 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -449,10 +449,12 @@ class changed_value_xacts : public item_handler<xact_t>
// This filter requires that calc_xacts be used at some point
// later in the chain.
- expr_t total_expr;
- bool changed_values_only;
- xact_t * last_xact;
- value_t last_balance;
+ expr_t total_expr;
+ report_t& report;
+ bool changed_values_only;
+ xact_t * last_xact;
+ value_t last_balance;
+ account_t revalued_account;
std::list<entry_t> entry_temps;
std::list<xact_t> xact_temps;
@@ -462,11 +464,13 @@ class changed_value_xacts : public item_handler<xact_t>
public:
changed_value_xacts(xact_handler_ptr handler,
const expr_t& _total_expr,
+ report_t& _report,
bool _changed_values_only)
: item_handler<xact_t>(handler), total_expr(_total_expr),
- changed_values_only(_changed_values_only), last_xact(NULL) {
+ report(_report), changed_values_only(_changed_values_only),
+ last_xact(NULL), revalued_account(NULL, "<Revalued>") {
TRACE_CTOR(changed_value_xacts,
- "xact_handler_ptr, bool");
+ "xact_handler_ptr, const expr_t&, report_t&, bool");
}
virtual ~changed_value_xacts() {
TRACE_DTOR(changed_value_xacts);
@@ -474,14 +478,14 @@ public:
}
virtual void flush() {
- if (last_xact) {
- output_diff(CURRENT_DATE());
+ if (last_xact && last_xact->date() <= CURRENT_DATE()) {
+ output_diff(last_xact, CURRENT_DATE());
last_xact = NULL;
}
item_handler<xact_t>::flush();
}
- void output_diff(const date_t& current);
+ void output_diff(xact_t * xact, const date_t& current);
virtual void operator()(xact_t& xact);
};
@@ -576,11 +580,10 @@ public:
interval_xacts(xact_handler_ptr _handler,
expr_t& amount_expr,
const interval_t& _interval,
- account_t * master = NULL,
bool _exact_periods = false,
bool _generate_empty_xacts = false)
: subtotal_xacts(_handler, amount_expr), interval(_interval),
- last_xact(NULL), empty_account(master, "<None>"),
+ last_xact(NULL), empty_account(NULL, "<None>"),
exact_periods(_exact_periods),
generate_empty_xacts(_generate_empty_xacts) {
TRACE_CTOR(interval_xacts,
diff --git a/src/output.cc b/src/output.cc
index fd27e2bb..e33ae627 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -170,7 +170,7 @@ void gather_statistics::operator()(xact_t& xact)
statistics.filenames.insert(xact.pathname);
- date_t date = xact.reported_date();
+ date_t date = xact.date();
if (date.year() == CURRENT_DATE().year() &&
date.month() == CURRENT_DATE().month())
@@ -185,11 +185,11 @@ void gather_statistics::operator()(xact_t& xact)
statistics.total_uncleared_xacts++;
if (! is_valid(statistics.earliest_xact) ||
- xact.reported_date() < statistics.earliest_xact)
- statistics.earliest_xact = xact.reported_date();
+ xact.date() < statistics.earliest_xact)
+ statistics.earliest_xact = xact.date();
if (! is_valid(statistics.latest_xact) ||
- xact.reported_date() > statistics.latest_xact)
- statistics.latest_xact = xact.reported_date();
+ xact.date() > statistics.latest_xact)
+ statistics.latest_xact = xact.date();
statistics.accounts_referenced.insert(xact.account->fullname());
statistics.payees_referenced.insert(xact.entry->payee);
diff --git a/src/report.cc b/src/report.cc
index 22ed926c..b8eecdfa 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -120,7 +120,7 @@ value_t report_t::fn_display_total(call_scope_t& scope)
return HANDLER(display_total_).expr.calc(scope);
}
-value_t report_t::fn_market_value(call_scope_t& scope)
+value_t report_t::fn_market(call_scope_t& scope)
{
interactive_t args(scope, "a&ts");
@@ -132,12 +132,16 @@ value_t report_t::fn_market_value(call_scope_t& scope)
p;
p = std::strtok(NULL, ",")) {
if (commodity_t * commodity = amount_t::current_pool->find(trim_ws(p))) {
+ DEBUG("report.market", "Searching for value of " << args.value_at(0)
+ << " in terms of commodity " << commodity->symbol());
value_t result =
args.value_at(0).value(false, args.has(1) ?
args.get<datetime_t>(1) :
optional<datetime_t>(), *commodity);
- if (! result.is_null())
+ if (! result.is_null()) {
+ DEBUG("report.market", "Market value is = " << result);
return result;
+ }
}
}
} else {
@@ -621,7 +625,7 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
case 'm':
if (is_eq(p, "market"))
- return MAKE_FUNCTOR(report_t::fn_market_value);
+ return MAKE_FUNCTOR(report_t::fn_market);
break;
case 'o':
diff --git a/src/report.h b/src/report.h
index 5494db7f..778848dd 100644
--- a/src/report.h
+++ b/src/report.h
@@ -132,7 +132,7 @@ public:
value_t fn_total_expr(call_scope_t& scope);
value_t fn_display_amount(call_scope_t& scope);
value_t fn_display_total(call_scope_t& scope);
- value_t fn_market_value(call_scope_t& scope);
+ value_t fn_market(call_scope_t& scope);
value_t fn_strip(call_scope_t& scope);
value_t fn_scrub(call_scope_t& scope);
value_t fn_quantity(call_scope_t& scope);
diff --git a/src/xact.cc b/src/xact.cc
index 5818b687..14464c6f 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -77,6 +77,9 @@ optional<string> xact_t::get_tag(const mask_t& tag_mask,
date_t xact_t::date() const
{
+ if (xdata_ && is_valid(xdata_->date))
+ return xdata_->date;
+
if (item_t::use_effective_date) {
if (_date_eff)
return *_date_eff;
diff --git a/src/xact.h b/src/xact.h
index b766383b..43f49823 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -189,12 +189,6 @@ public:
void add_to_value(value_t& value, expr_t& expr);
- date_t reported_date() const {
- if (xdata_ && is_valid(xdata_->date))
- return xdata_->date;
- return date();
- }
-
account_t * reported_account() {
if (xdata_)
if (account_t * acct = xdata_->account)
diff --git a/test/baseline/opt-exchange.test b/test/baseline/opt-exchange.test
index 78699082..9ed46c12 100644
--- a/test/baseline/opt-exchange.test
+++ b/test/baseline/opt-exchange.test
@@ -49,16 +49,12 @@ reg --exchange=' C, A '
Assets:Brokerage -155 A [2009/01/06]
>>>1
09-Jan-01 January 1st, 2009 (1) Assets:Brokerage 100 A 100 A
- Assets:Brokerage -50 A 100 A
- -200 B
-09-Jan-01 January 1st, 2009 (2) Assets:Brokerage 100 A 200 A
- -200 B
- Assets:Brokerage -75 A 200 A
- -500 B
-09-Jan-01 January 1st, 2009 (3) Assets:Brokerage 100 A 300 A
- -500 B
- Assets:Brokerage -100 A 300 A
- -900 B
+ Assets:Brokerage -50 A 50 A
+09-Jan-01 January 1st, 2009 (2) Assets:Brokerage 100 A 150 A
+ Assets:Brokerage -75 A 75 A
+09-Jan-01 January 1st, 2009 (3) Assets:Brokerage 100 A 175 A
+ Assets:Brokerage -100 A 75 A
+09-Jan-02 Commodities revalued <Revalued> 0 600 C
09-Jan-02 January 2nd, 2009 Assets:Brokerage 500 C 1100 C
Assets:Brokerage -500 C 600 C
09-Jan-03 January 3rd, 2009 Assets:Brokerage 600 C 1200 C
@@ -67,12 +63,16 @@ reg --exchange=' C, A '
Assets:Brokerage -2400 C 600 C
09-Jan-05 January 5th, 2009 Assets:Brokerage 1280 C 1880 C
Assets:Brokerage -1280 C 600 C
+09-Jan-06 Commodities revalued <Revalued> -2040 C -1440 C
09-Jan-06 January 6th, 2009 Assets:Brokerage 186 C -1254 C
Assets:Brokerage -186 C -1440 C
+09-Jan-07 Commodities revalued <Revalued> -18 C -1458 C
09-Jan-07 January 7th, 2009 Assets:Brokerage 200 C -1258 C
Assets:Brokerage -200 C -1458 C
+09-Jan-08 Commodities revalued <Revalued> -5613 C -7071 C
09-Jan-08 January 8th, 2009 Assets:Brokerage 200 C -6871 C
Assets:Brokerage -200 C -7071 C
+09-Jan-09 Commodities revalued <Revalued> -2800 C -9871 C
09-Jan-09 January 9th, 2009 Assets:Brokerage 200 C -9671 C
Assets:Brokerage -200 C -9871 C
09-Jan-10 January 10th, 2009 Assets:Brokerage 200 C -9671 C
diff --git a/test/baseline/opt-market.test b/test/baseline/opt-market.test
index 1d68fe3a..b6c0ed6d 100644
--- a/test/baseline/opt-market.test
+++ b/test/baseline/opt-market.test
@@ -50,11 +50,17 @@ P 2010/03/01 00:00:00 S 8 P
P 2010/04/01 00:00:00 S 16 P
>>>1
09-Jan-01 Sample 1a As:Brokerage:Stocks 200 P 200 P
+09-Feb-01 Commodities revalued <Revalued> 200 P 400 P
09-Feb-01 Sample 2a As:Brokerage:Stocks 400 P 800 P
+09-Mar-01 Commodities revalued <Revalued> 800 P 1600 P
09-Mar-01 Sample 3a As:Brokerage:Stocks 800 P 2400 P
+09-Apr-01 Commodities revalued <Revalued> 2400 P 4800 P
09-Apr-01 Sample 4a As:Brokerage:Stocks -1600 P 3200 P
+10-Feb-01 Commodities revalued <Revalued> -2400 P 800 P
10-Feb-01 Sample 2b As:Brokerage:Stocks 400 P 1200 P
+10-Mar-01 Commodities revalued <Revalued> 1200 P 2400 P
10-Mar-01 Sample 3b As:Brokerage:Stocks 800 P 3200 P
+10-Apr-01 Commodities revalued <Revalued> 3200 P 6400 P
10-Apr-01 Sample 4b As:Brokerage:Stocks -1600 P 4800 P
>>>2
=== 0