summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-06-06 06:20:07 -0400
committerJohn Wiegley <johnw@newartisans.com>2010-06-06 06:20:07 -0400
commit39f9854e2c1f807f6e9c90d80e1eec2bf9b90017 (patch)
treeb72e9a1454b6721d59e3844d71a91880c94e2cae
parent4197c8851120e5c5ac7426cdca209a49049e9363 (diff)
downloadfork-ledger-39f9854e2c1f807f6e9c90d80e1eec2bf9b90017.tar.gz
fork-ledger-39f9854e2c1f807f6e9c90d80e1eec2bf9b90017.tar.bz2
fork-ledger-39f9854e2c1f807f6e9c90d80e1eec2bf9b90017.zip
Reworked the way that <Rounding> entries are shown
Fixes #188 / 53BCED29-F3B9-4E02-9A35-6C739ABB9662
-rw-r--r--src/chain.cc34
-rw-r--r--src/chain.h16
-rw-r--r--src/filters.cc156
-rw-r--r--src/filters.h71
-rw-r--r--src/py_journal.cc4
-rw-r--r--src/report.cc50
-rw-r--r--test/baseline/opt-gain.test1
-rw-r--r--test/baseline/opt-price.test2
8 files changed, 202 insertions, 132 deletions
diff --git a/src/chain.cc b/src/chain.cc
index b8c2eb0a..86d35f14 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -39,8 +39,8 @@
namespace ledger {
-post_handler_ptr chain_pre_post_handlers(report_t& report,
- post_handler_ptr base_handler)
+post_handler_ptr chain_pre_post_handlers(post_handler_ptr base_handler,
+ report_t& report)
{
post_handler_ptr handler(base_handler);
@@ -106,13 +106,14 @@ post_handler_ptr chain_pre_post_handlers(report_t& report,
return handler;
}
-post_handler_ptr chain_post_handlers(report_t& report,
- post_handler_ptr base_handler,
+post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
+ report_t& report,
bool for_accounts_report)
{
- post_handler_ptr handler(base_handler);
- predicate_t display_predicate;
- predicate_t only_predicate;
+ post_handler_ptr handler(base_handler);
+ predicate_t display_predicate;
+ predicate_t only_predicate;
+ rounding_error_posts * rounding_handler = NULL;
assert(report.HANDLED(amount_));
expr_t& expr(report.HANDLER(amount_).expr);
@@ -137,6 +138,14 @@ post_handler_ptr chain_post_handlers(report_t& report,
report.HANDLED(tail_) ?
report.HANDLER(tail_).value.to_int() : 0));
+ // 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) && ! report.HANDLED(no_rounding)) {
+ rounding_handler = new rounding_error_posts(handler, report);
+ handler.reset(rounding_handler);
+ }
+
// filter_posts will only pass through posts matching the
// `display_predicate'.
if (report.HANDLED(display_)) {
@@ -149,12 +158,11 @@ post_handler_ptr chain_post_handlers(report_t& 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,
+ if (report.HANDLED(revalued) &&
+ (! for_accounts_report || report.HANDLED(unrealized)))
+ handler.reset(new changed_value_posts(handler, report, for_accounts_report,
report.HANDLED(unrealized),
- ! report.HANDLED(no_rounding)));
+ rounding_handler));
// calc_posts computes the running total. When this appears will determine,
// for example, whether filtered posts are included or excluded from the
@@ -190,7 +198,7 @@ post_handler_ptr chain_post_handlers(report_t& report,
// collapse_posts causes xacts with multiple posts to appear as xacts
// with a subtotaled post for each commodity used.
if (report.HANDLED(collapse))
- handler.reset(new collapse_posts(handler, expr,
+ handler.reset(new collapse_posts(handler, report, expr,
display_predicate, only_predicate,
report.HANDLED(collapse_if_zero)));
diff --git a/src/chain.h b/src/chain.h
index 59b04eb8..1a50a077 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -93,20 +93,20 @@ typedef shared_ptr<item_handler<account_t> > acct_handler_ptr;
class report_t;
post_handler_ptr
-chain_pre_post_handlers(report_t& report,
- post_handler_ptr base_handler);
+chain_pre_post_handlers(post_handler_ptr base_handler,
+ report_t& report);
post_handler_ptr
-chain_post_handlers(report_t& report,
- post_handler_ptr base_handler,
+chain_post_handlers(post_handler_ptr base_handler,
+ report_t& report,
bool for_accounts_report = false);
inline post_handler_ptr
-chain_handlers(report_t& report,
- post_handler_ptr handler,
+chain_handlers(post_handler_ptr handler,
+ report_t& report,
bool for_accounts_report = false) {
- handler = chain_post_handlers(report, handler, for_accounts_report);
- handler = chain_pre_post_handlers(report, handler);
+ handler = chain_post_handlers(handler, report, for_accounts_report);
+ handler = chain_pre_post_handlers(handler, report);
return handler;
}
diff --git a/src/filters.cc b/src/filters.cc
index 07278500..e5c5275c 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -374,7 +374,8 @@ void collapse_posts::report_subtotal()
std::size_t displayed_count = 0;
foreach (post_t * post, component_posts) {
- if (only_predicate(*post) && display_predicate(*post))
+ bind_scope_t bound_scope(report, *post);
+ if (only_predicate(bound_scope) && display_predicate(bound_scope))
displayed_count++;
}
@@ -401,7 +402,11 @@ void collapse_posts::report_subtotal()
earliest_date : last_xact->_date);
DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date);
- handle_value(subtotal, &totals_account, &xact, temps, handler);
+ handle_value(/* value= */ subtotal,
+ /* account= */ &totals_account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler);
}
component_posts.clear();
@@ -461,21 +466,81 @@ void related_posts::flush()
item_handler<post_t>::flush();
}
-changed_value_posts::changed_value_posts(post_handler_ptr handler,
- report_t& _report,
- bool _for_accounts_report,
- bool _show_unrealized,
- bool _show_rounding)
+rounding_error_posts::rounding_error_posts(post_handler_ptr handler,
+ report_t& _report)
+ : item_handler<post_t>(handler), report(_report),
+ rounding_account(temps.create_account(_("<Rounding>")))
+{
+ TRACE_CTOR(rounding_error_posts, "post_handler_ptr, report_t&");
+
+ display_amount_expr = report.HANDLER(display_amount_).expr;
+ display_total_expr = report.HANDLER(display_total_).expr;
+}
+
+void rounding_error_posts::output_rounding(post_t& post)
+{
+ bind_scope_t bound_scope(report, post);
+ value_t new_display_total(display_total_expr.calc(bound_scope));
+
+ DEBUG("filters.changed_value.rounding",
+ "rounding.new_display_total = " << new_display_total);
+
+ if (! last_display_total.is_null()) {
+ if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
+ DEBUG("filters.changed_value.rounding",
+ "rounding.repriced_amount = " << repriced_amount);
+
+ value_t precise_display_total(new_display_total.truncated() -
+ repriced_amount.truncated());
+
+ DEBUG("filters.changed_value.rounding",
+ "rounding.precise_display_total = " << precise_display_total);
+ DEBUG("filters.changed_value.rounding",
+ "rounding.last_display_total = " << last_display_total);
+
+ if (value_t diff = precise_display_total - last_display_total) {
+ DEBUG("filters.changed_value.rounding",
+ "rounding.diff = " << diff);
+
+ xact_t& xact = temps.create_xact();
+ xact.payee = _("Commodity rounding");
+ xact._date = post.date();
+
+ handle_value(/* value= */ diff,
+ /* account= */ &rounding_account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler,
+ /* date= */ *xact._date,
+ /* total= */ precise_display_total,
+ /* direct_amount= */ true);
+ }
+ }
+ }
+ last_display_total = new_display_total;
+}
+
+void rounding_error_posts::operator()(post_t& post)
+{
+ output_rounding(post);
+
+ item_handler<post_t>::operator()(post);
+}
+
+changed_value_posts::changed_value_posts
+ (post_handler_ptr handler,
+ report_t& _report,
+ bool _for_accounts_report,
+ bool _show_unrealized,
+ rounding_error_posts * _rounding_handler)
: item_handler<post_t>(handler), report(_report),
for_accounts_report(_for_accounts_report),
- show_unrealized(_show_unrealized),
- show_rounding(_show_rounding), last_post(NULL),
+ show_unrealized(_show_unrealized), last_post(NULL),
revalued_account(temps.create_account(_("<Revalued>"))),
- rounding_account(temps.create_account(_("<Rounding>")))
+ rounding_handler(_rounding_handler)
{
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);
@@ -549,13 +614,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
/* temps= */ temps,
/* handler= */ handler,
/* date= */ *xact._date,
- /* total= */ repriced_total,
- /* direct_amount= */ false,
- /* mark_visited= */ false,
- /* functor= */ (show_rounding ?
- optional<post_functor_t>
- (bind(&changed_value_posts::output_rounding,
- this, _1)) : none));
+ /* total= */ repriced_total);
}
else if (show_unrealized) {
handle_value
@@ -692,43 +751,6 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
}
}
-void changed_value_posts::output_rounding(post_t& post)
-{
- bind_scope_t bound_scope(report, post);
- value_t new_display_total(display_total_expr.calc(bound_scope));
-
- DEBUG("filters.changed_value.rounding",
- "rounding.new_display_total = " << new_display_total);
-
- if (! last_display_total.is_null()) {
- if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
- DEBUG("filters.changed_value.rounding",
- "rounding.repriced_amount = " << repriced_amount);
-
- value_t precise_display_total(new_display_total.truncated() -
- repriced_amount.truncated());
-
- DEBUG("filters.changed_value.rounding",
- "rounding.precise_display_total = " << precise_display_total);
- DEBUG("filters.changed_value.rounding",
- "rounding.last_display_total = " << last_display_total);
-
- if (value_t diff = precise_display_total - last_display_total) {
- DEBUG("filters.changed_value.rounding",
- "rounding.diff = " << diff);
-
- xact_t& xact = temps.create_xact();
- xact.payee = _("Commodity rounding");
- xact._date = post.date();
-
- handle_value(diff, &rounding_account, &xact, temps, handler,
- *xact._date, precise_display_total, true);
- }
- }
- }
- last_display_total = new_display_total;
-}
-
void changed_value_posts::operator()(post_t& post)
{
if (last_post) {
@@ -740,9 +762,6 @@ void changed_value_posts::operator()(post_t& post)
if (changed_values_only)
post.xdata().add_flags(POST_EXT_DISPLAYED);
- if (! for_accounts_report && show_rounding)
- output_rounding(post);
-
item_handler<post_t>::operator()(post);
bind_scope_t bound_scope(report, post);
@@ -787,8 +806,11 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
xact._date = *range_start;
foreach (values_map::value_type& pair, values)
- handle_value(pair.second.value, pair.second.account, &xact, temps,
- handler);
+ handle_value(/* value= */ pair.second.value,
+ /* account= */ pair.second.account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler);
values.clear();
}
@@ -897,11 +919,17 @@ 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(amount_pair.second, pair.second.account, &xact, temps,
- handler);
+ handle_value(/* value= */ amount_pair.second,
+ /* account= */ pair.second.account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler);
} else {
- handle_value(pair.second.value, pair.second.account, &xact, temps,
- handler);
+ handle_value(/* value= */ pair.second.value,
+ /* account= */ pair.second.account,
+ /* xact= */ &xact,
+ /* temps= */ temps,
+ /* handler= */ handler);
}
total += pair.second.value;
}
diff --git a/src/filters.h b/src/filters.h
index 327499fb..22b27c5d 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -63,17 +63,17 @@ public:
protected:
value_to_posts_map posts_map;
- report_t& report;
post_handler_ptr post_chain;
+ report_t& report;
expr_t group_by_expr;
custom_flusher_t preflush_func;
optional<custom_flusher_t> postflush_func;
public:
- post_splitter(report_t& _report,
- post_handler_ptr _post_chain,
+ post_splitter(post_handler_ptr _post_chain,
+ report_t& _report,
expr_t _group_by_expr)
- : report(_report), post_chain(_post_chain),
+ : post_chain(_post_chain), report(_report),
group_by_expr(_group_by_expr),
preflush_func(bind(&post_splitter::print_title, this, _1)) {
TRACE_CTOR(post_splitter, "scope_t&, post_handler_ptr, expr_t");
@@ -401,11 +401,13 @@ class collapse_posts : public item_handler<post_t>
account_t& totals_account;
bool only_collapse_if_zero;
std::list<post_t *> component_posts;
+ report_t& report;
collapse_posts();
public:
collapse_posts(post_handler_ptr handler,
+ report_t& _report,
expr_t& _amount_expr,
predicate_t _display_predicate,
predicate_t _only_predicate,
@@ -415,8 +417,8 @@ public:
only_predicate(_only_predicate), count(0),
last_xact(NULL), last_post(NULL),
totals_account(temps.create_account(_("<Total>"))),
- only_collapse_if_zero(_only_collapse_if_zero) {
- TRACE_CTOR(collapse_posts, "post_handler_ptr");
+ only_collapse_if_zero(_only_collapse_if_zero), report(_report) {
+ TRACE_CTOR(collapse_posts, "post_handler_ptr, ...");
}
virtual ~collapse_posts() {
TRACE_DTOR(collapse_posts);
@@ -479,37 +481,73 @@ public:
}
};
-class changed_value_posts : public item_handler<post_t>
+class rounding_error_posts : public item_handler<post_t>
{
// This filter requires that calc_posts be used at some point
// later in the chain.
expr_t display_amount_expr;
+ expr_t display_total_expr;
+ report_t& report;
+ value_t last_display_total;
+ temporaries_t temps;
+ account_t& rounding_account;
+
+ rounding_error_posts();
+
+public:
+ rounding_error_posts(post_handler_ptr handler,
+ report_t& _report);
+
+ virtual ~rounding_error_posts() {
+ TRACE_DTOR(rounding_error_posts);
+ }
+
+ void output_rounding(post_t& post);
+
+ virtual void operator()(post_t& post);
+
+ virtual void clear() {
+ display_amount_expr.mark_uncompiled();
+ display_total_expr.mark_uncompiled();
+
+ last_display_total = value_t();
+
+ temps.clear();
+
+ item_handler<post_t>::clear();
+ }
+};
+
+class changed_value_posts : public item_handler<post_t>
+{
+ // This filter requires that calc_posts be used at some point
+ // later in the chain.
+
expr_t total_expr;
expr_t display_total_expr;
report_t& report;
bool changed_values_only;
bool for_accounts_report;
bool show_unrealized;
- bool show_rounding;
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;
account_t * gains_equity_account;
account_t * losses_equity_account;
+ rounding_error_posts * rounding_handler;
+
changed_value_posts();
public:
- changed_value_posts(post_handler_ptr handler,
- report_t& _report,
- bool _for_accounts_report,
- bool _show_unrealized,
- bool _show_rounding);
+ changed_value_posts(post_handler_ptr handler,
+ report_t& _report,
+ bool _for_accounts_report,
+ bool _show_unrealized,
+ rounding_error_posts * _rounding_handler);
virtual ~changed_value_posts() {
TRACE_DTOR(changed_value_posts);
@@ -519,18 +557,15 @@ public:
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);
virtual void clear() {
- display_amount_expr.mark_uncompiled();
total_expr.mark_uncompiled();
display_total_expr.mark_uncompiled();
last_post = NULL;
last_total = value_t();
- last_display_total = value_t();
temps.clear();
diff --git a/src/py_journal.cc b/src/py_journal.cc
index 1848adc4..cd25d134 100644
--- a/src/py_journal.cc
+++ b/src/py_journal.cc
@@ -190,8 +190,8 @@ namespace {
journal_posts_iterator walker(coll->journal);
coll->chain =
- chain_post_handlers(coll->report,
- post_handler_ptr(coll->posts_collector));
+ chain_post_handlers(post_handler_ptr(coll->posts_collector),
+ coll->report);
pass_down_posts(coll->chain, walker);
}
catch (...) {
diff --git a/src/report.cc b/src/report.cc
index f0923b33..4302187e 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -141,7 +141,9 @@ void report_t::normalize_options(const string& verb)
HANDLER(limit_).on(string("?normalize"), "actual");
if (! HANDLED(empty))
- HANDLER(display_).on(string("?normalize"), "amount|(!post&total)");
+ HANDLER(display_).on(string("?normalize"),
+ string("(post?(display_amount|account=\"") +
+ _("<Revalued>") + "\"):display_total)");
if (verb[0] != 'b' && verb[0] != 'r')
HANDLER(base).on_only(string("?normalize"));
@@ -284,11 +286,11 @@ void report_t::parse_query_args(const value_t& args, const string& whence)
namespace {
struct posts_flusher
{
- report_t& report;
post_handler_ptr handler;
+ report_t& report;
- posts_flusher(report_t& _report, post_handler_ptr _handler)
- : report(_report), handler(_handler) {}
+ posts_flusher(post_handler_ptr _handler, report_t& _report)
+ : handler(_handler), report(_report) {}
void operator()(const value_t&) {
report.session.journal->clear_xdata();
@@ -298,27 +300,27 @@ namespace {
void report_t::posts_report(post_handler_ptr handler)
{
- handler = chain_post_handlers(*this, handler);
+ handler = chain_post_handlers(handler, *this);
if (HANDLED(group_by_)) {
std::auto_ptr<post_splitter>
- splitter(new post_splitter(*this, handler, HANDLER(group_by_).expr));
- splitter->set_postflush_func(posts_flusher(*this, handler));
+ splitter(new post_splitter(handler, *this, HANDLER(group_by_).expr));
+ splitter->set_postflush_func(posts_flusher(handler, *this));
handler = post_handler_ptr(splitter.release());
}
- handler = chain_pre_post_handlers(*this, handler);
+ handler = chain_pre_post_handlers(handler, *this);
journal_posts_iterator walker(*session.journal.get());
pass_down_posts(handler, walker);
if (! HANDLED(group_by_))
- posts_flusher(*this, handler)(value_t());
+ posts_flusher(handler, *this)(value_t());
}
void report_t::generate_report(post_handler_ptr handler)
{
HANDLER(limit_).on(string("#generate"), "actual");
- handler = chain_handlers(*this, handler);
+ handler = chain_handlers(handler, *this);
generate_posts_iterator walker
(session, HANDLED(seed_) ?
@@ -331,7 +333,7 @@ void report_t::generate_report(post_handler_ptr handler)
void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
{
- handler = chain_handlers(*this, handler);
+ handler = chain_handlers(handler, *this);
xact_posts_iterator walker(xact);
pass_down_posts(handler, walker);
@@ -342,11 +344,11 @@ void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
namespace {
struct accounts_title_printer
{
- report_t& report;
acct_handler_ptr handler;
+ report_t& report;
- accounts_title_printer(report_t& _report, acct_handler_ptr _handler)
- : report(_report), handler(_handler) {}
+ accounts_title_printer(acct_handler_ptr _handler, report_t& _report)
+ : handler(_handler), report(_report) {}
void operator()(const value_t& val)
{
@@ -360,11 +362,11 @@ namespace {
struct accounts_flusher
{
- report_t& report;
acct_handler_ptr handler;
+ report_t& report;
- accounts_flusher(report_t& _report, acct_handler_ptr _handler)
- : report(_report), handler(_handler) {}
+ accounts_flusher(acct_handler_ptr _handler, report_t& _report)
+ : handler(_handler), report(_report) {}
void operator()(const value_t&)
{
@@ -403,18 +405,18 @@ namespace {
void report_t::accounts_report(acct_handler_ptr handler)
{
post_handler_ptr chain =
- chain_post_handlers(*this, post_handler_ptr(new ignore_posts),
+ chain_post_handlers(post_handler_ptr(new ignore_posts), *this,
/* for_accounts_report= */ true);
if (HANDLED(group_by_)) {
std::auto_ptr<post_splitter>
- splitter(new post_splitter(*this, chain, HANDLER(group_by_).expr));
+ splitter(new post_splitter(chain, *this, HANDLER(group_by_).expr));
- splitter->set_preflush_func(accounts_title_printer(*this, handler));
- splitter->set_postflush_func(accounts_flusher(*this, handler));
+ splitter->set_preflush_func(accounts_title_printer(handler, *this));
+ splitter->set_postflush_func(accounts_flusher(handler, *this));
chain = post_handler_ptr(splitter.release());
}
- chain = chain_pre_post_handlers(*this, chain);
+ chain = chain_pre_post_handlers(chain, *this);
// The lifetime of the chain object controls the lifetime of all temporary
// objects created within it during the call to pass_down_posts, which will
@@ -423,12 +425,12 @@ void report_t::accounts_report(acct_handler_ptr handler)
pass_down_posts(chain, walker);
if (! HANDLED(group_by_))
- accounts_flusher(*this, handler)(value_t());
+ accounts_flusher(handler, *this)(value_t());
}
void report_t::commodities_report(post_handler_ptr handler)
{
- handler = chain_handlers(*this, handler);
+ handler = chain_handlers(handler, *this);
posts_commodities_iterator walker(*session.journal.get());
pass_down_posts(handler, walker);
diff --git a/test/baseline/opt-gain.test b/test/baseline/opt-gain.test
index 63055d5f..6d139c79 100644
--- a/test/baseline/opt-gain.test
+++ b/test/baseline/opt-gain.test
@@ -49,7 +49,6 @@ 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 0 0
09-Jan-15 Commodities revalued <Revalued> 100 P 100 P
09-Feb-01 Commodities revalued <Revalued> 200 P 300 P
09-Feb-01 Sample 2a As:Brokerage:Stocks 300 P 600 P
diff --git a/test/baseline/opt-price.test b/test/baseline/opt-price.test
index 133b2155..67f8161b 100644
--- a/test/baseline/opt-price.test
+++ b/test/baseline/opt-price.test
@@ -34,9 +34,7 @@ reg --end 2009/06/26 -V equities
=== 0
reg --end 2009/06/26 -G equities
>>>1
-08-Jan-01 Purchase Apple shares Equities 0 0
08-Jun-30 Commodities revalued <Revalued> $500 $500
-08-Jun-30 Sell some Apple sha.. Equities 0 $500
09-Jan-31 Commodities revalued <Revalued> $250 $750
09-Jun-26 Commodities revalued <Revalued> $500 $1250
>>>2