summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2012-03-23 16:46:11 -0500
committerJohn Wiegley <johnw@newartisans.com>2012-03-23 16:46:11 -0500
commit4b057599626538a0d1463c63f2110d2fe5baa2e6 (patch)
tree1934a6b1bd6c47ff3599c9aaaeb211fb2303c86f
parent38813bc635e587f0979ef142511c5e7655fd88f1 (diff)
downloadfork-ledger-4b057599626538a0d1463c63f2110d2fe5baa2e6.tar.gz
fork-ledger-4b057599626538a0d1463c63f2110d2fe5baa2e6.tar.bz2
fork-ledger-4b057599626538a0d1463c63f2110d2fe5baa2e6.zip
Fixed sorting of equity output
-rw-r--r--src/balance.cc102
-rw-r--r--src/balance.h8
-rw-r--r--src/filters.cc56
-rw-r--r--test/baseline/opt-equity.test4
4 files changed, 121 insertions, 49 deletions
diff --git a/src/balance.cc b/src/balance.cc
index 5c57cd99..cd25eede 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -240,17 +240,8 @@ balance_t::strip_annotations(const keep_details_t& what_to_keep) const
return temp;
}
-void balance_t::print(std::ostream& out,
- const int first_width,
- const int latter_width,
- const uint_least8_t flags) const
+void balance_t::map_sorted_amounts(function<void(const amount_t&)> fn) const
{
- bool first = true;
- int lwidth = latter_width;
-
- if (lwidth == -1)
- lwidth = first_width;
-
typedef std::vector<const amount_t *> amounts_array;
amounts_array sorted;
@@ -261,30 +252,79 @@ void balance_t::print(std::ostream& out,
std::stable_sort(sorted.begin(), sorted.end(),
commodity_t::compare_by_commodity());
- foreach (const amount_t * amount, sorted) {
- int width;
- if (! first) {
- out << std::endl;
- width = lwidth;
- } else {
- first = false;
- width = first_width;
+ foreach (const amount_t * amount, sorted)
+ fn(*amount);
+}
+
+namespace {
+ struct print_amount_from_balance
+ {
+ std::ostream& out;
+ bool& first;
+ int fwidth;
+ int lwidth;
+ uint_least8_t flags;
+
+ explicit print_amount_from_balance(std::ostream& _out,
+ bool& _first,
+ int _fwidth, int _lwidth,
+ uint_least8_t _flags)
+ : out(_out), first(_first), fwidth(_fwidth), lwidth(_lwidth),
+ flags(_flags) {
+ TRACE_CTOR(print_amount_from_balance,
+ "ostream&, int, int, uint_least8_t");
+ }
+ print_amount_from_balance(const print_amount_from_balance& other)
+ : out(other.out), first(other.first), fwidth(other.fwidth),
+ lwidth(other.lwidth), flags(other.flags) {
+ TRACE_CTOR(print_amount_from_balance, "copy");
+ }
+ ~print_amount_from_balance() throw() {
+ TRACE_DTOR(print_amount_from_balance);
}
- std::ostringstream buf;
- amount->print(buf, flags);
- justify(out, buf.str(), width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY,
- flags & AMOUNT_PRINT_COLORIZE && amount->sign() < 0);
- }
+ void operator()(const amount_t& amount) {
+ int width;
+ if (! first) {
+ out << std::endl;
+ width = lwidth;
+ } else {
+ first = false;
+ width = fwidth;
+ }
+
+ std::ostringstream buf;
+ amount.print(buf, flags);
+
+ justify(out, buf.str(), width,
+ flags & AMOUNT_PRINT_RIGHT_JUSTIFY,
+ flags & AMOUNT_PRINT_COLORIZE && amount.sign() < 0);
+ }
- if (first) {
- out.width(first_width);
- if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY)
- out << std::right;
- else
- out << std::left;
- out << 0;
- }
+ void close() {
+ out.width(fwidth);
+ if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY)
+ out << std::right;
+ else
+ out << std::left;
+ out << 0;
+ }
+ };
+}
+
+void balance_t::print(std::ostream& out,
+ const int first_width,
+ const int latter_width,
+ const uint_least8_t flags) const
+{
+ bool first = true;
+ print_amount_from_balance
+ amount_printer(out, first, first_width,
+ latter_width == 1 ? first_width : latter_width, flags);
+ map_sorted_amounts(amount_printer);
+
+ if (first)
+ amount_printer.close();
}
void to_xml(std::ostream& out, const balance_t& bal)
diff --git a/src/balance.h b/src/balance.h
index 11c370bb..704b4072 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -507,6 +507,14 @@ public:
balance_t strip_annotations(const keep_details_t& what_to_keep) const;
/**
+ * Iteration primitives. `map_sorted_amounts' allows one to visit
+ * each amount in balance in the proper order for displaying to the
+ * user. Mostly used by `print' and other routinse where the sort
+ * order of the amounts' commodities is significant.
+ */
+ void map_sorted_amounts(function<void(const amount_t&)> fn) const;
+
+ /**
* Printing methods. A balance may be output to a stream using the
* `print' method. There is also a global operator<< defined which
* simply calls print for a balance on the given stream. There is
diff --git a/src/filters.cc b/src/filters.cc
index 32b3ec3a..a665f9e6 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -1030,6 +1030,40 @@ void interval_posts::flush()
subtotal_posts::flush();
}
+namespace {
+ struct create_post_from_amount
+ {
+ post_handler_ptr handler;
+ xact_t& xact;
+ account_t& balance_account;
+ temporaries_t& temps;
+
+ explicit create_post_from_amount(post_handler_ptr _handler,
+ xact_t& _xact,
+ account_t& _balance_account,
+ temporaries_t& _temps)
+ : handler(_handler), xact(_xact),
+ balance_account(_balance_account), temps(_temps) {
+ TRACE_CTOR(create_post_from_amount,
+ "post_handler_ptr, xact_t&, account_t&, temporaries_t&");
+ }
+ create_post_from_amount(const create_post_from_amount& other)
+ : handler(other.handler), xact(other.xact),
+ balance_account(other.balance_account), temps(other.temps) {
+ TRACE_CTOR(create_post_from_amount, "copy");
+ }
+ ~create_post_from_amount() throw() {
+ TRACE_DTOR(create_post_from_amount);
+ }
+
+ void operator()(const amount_t& amount) {
+ post_t& balance_post = temps.create_post(xact, &balance_account);
+ balance_post.amount = - amount;
+ (*handler)(balance_post);
+ }
+ };
+}
+
void posts_as_equity::report_subtotal()
{
date_t finish;
@@ -1076,28 +1110,18 @@ void posts_as_equity::report_subtotal()
}
values.clear();
-#if 1
// This last part isn't really needed, since an Equity:Opening
// Balances posting with a null amount will automatically balance with
// all the other postings generated. But it does make the full
// balancing amount clearer to the user.
if (! total.is_zero()) {
- if (total.is_balance()) {
- foreach (const balance_t::amounts_map::value_type& pair,
- total.as_balance().amounts) {
- if (! pair.second.is_zero()) {
- post_t& balance_post = temps.create_post(xact, balance_account);
- balance_post.amount = - pair.second;
- (*handler)(balance_post);
- }
- }
- } else {
- post_t& balance_post = temps.create_post(xact, balance_account);
- balance_post.amount = - total.to_amount();
- (*handler)(balance_post);
- }
+ create_post_from_amount post_creator(handler, xact,
+ *balance_account, temps);
+ if (total.is_balance())
+ total.as_balance_lval().map_sorted_amounts(post_creator);
+ else
+ post_creator(total.to_amount());
}
-#endif
}
void by_payee_posts::flush()
diff --git a/test/baseline/opt-equity.test b/test/baseline/opt-equity.test
index 511333cc..35ea6b1e 100644
--- a/test/baseline/opt-equity.test
+++ b/test/baseline/opt-equity.test
@@ -41,9 +41,9 @@ test equity --lot-prices
Assets:Bank -3.80 GBP
Assets:Broker 2 AAA {0.90 GBP}
Assets:Broker 2 AAA {1.00 GBP}
- Equity:Opening Balances 3.80 GBP
Equity:Opening Balances -2 AAA {0.90 GBP}
Equity:Opening Balances -2 AAA {1.00 GBP}
+ Equity:Opening Balances 3.80 GBP
end test
test equity --lots
@@ -51,8 +51,8 @@ test equity --lots
Assets:Bank -3.80 GBP
Assets:Broker 2 AAA {0.90 GBP} [2011/03/04]
Assets:Broker 2 AAA {1.00 GBP} [2011/03/05]
- Equity:Opening Balances 3.80 GBP
Equity:Opening Balances -2 AAA {0.90 GBP} [2011/03/04]
Equity:Opening Balances -2 AAA {1.00 GBP} [2011/03/05]
+ Equity:Opening Balances 3.80 GBP
end test